Add manual auto-update fallback
This commit is contained in:
@@ -1,14 +1,17 @@
|
|||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import { connect } from 'react-redux'
|
|
||||||
import * as q from '../../backend/src/Model'
|
import * as q from '../../backend/src/Model'
|
||||||
import CssBaseline from '@material-ui/core/CssBaseline'
|
|
||||||
import { withStyles, Theme } from '@material-ui/core/styles'
|
import { Theme, withStyles } from '@material-ui/core/styles'
|
||||||
import Tree from './components/Tree/Tree'
|
|
||||||
import TitleBar from './components/TitleBar'
|
|
||||||
import Sidebar from './components/Sidebar/Sidebar'
|
|
||||||
import Connection from './components/ConnectionSetup/Connection'
|
|
||||||
import Settings from './components/Settings'
|
|
||||||
import { AppState } from './reducers'
|
import { AppState } from './reducers'
|
||||||
|
import Connection from './components/ConnectionSetup/Connection'
|
||||||
|
import CssBaseline from '@material-ui/core/CssBaseline'
|
||||||
|
import Settings from './components/Settings'
|
||||||
|
import Sidebar from './components/Sidebar/Sidebar'
|
||||||
|
import TitleBar from './components/TitleBar'
|
||||||
|
import Tree from './components/Tree/Tree'
|
||||||
|
import UpdateNotifier from './UpdateNotifier'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
selectedNode?: q.TreeNode,
|
selectedNode?: q.TreeNode,
|
||||||
@@ -79,24 +82,27 @@ class App extends React.Component<Props, State> {
|
|||||||
public render() {
|
public render() {
|
||||||
const { settingsVisible } = this.props
|
const { settingsVisible } = this.props
|
||||||
const { content, contentShift, centerContent } = this.getStyles()
|
const { content, contentShift, centerContent } = this.getStyles()
|
||||||
return <div style={centerContent}>
|
return (
|
||||||
<CssBaseline />
|
<div style={centerContent}>
|
||||||
<Settings />
|
<CssBaseline />
|
||||||
<div style={settingsVisible ? contentShift : content}>
|
<Settings />
|
||||||
<TitleBar />
|
<div style={settingsVisible ? contentShift : content}>
|
||||||
<div style={centerContent}>
|
<TitleBar />
|
||||||
<div style={this.getStyles().left}>
|
<div style={centerContent}>
|
||||||
<Tree connectionId={this.state.connectionId} didSelectNode={(node: q.TreeNode) => {
|
<div style={this.getStyles().left}>
|
||||||
this.setState({ selectedNode: node })
|
<Tree connectionId={this.state.connectionId} didSelectNode={(node: q.TreeNode) => {
|
||||||
}} />
|
this.setState({ selectedNode: node })
|
||||||
|
}} />
|
||||||
|
</div>
|
||||||
|
<div style={this.getStyles().right}>
|
||||||
|
<Sidebar connectionId={this.state.connectionId} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={this.getStyles().right}>
|
</div>
|
||||||
<Sidebar connectionId={this.state.connectionId} />
|
<UpdateNotifier />
|
||||||
</div>
|
<Connection onConnection={(connectionId: string) => this.setState({ connectionId })}/>
|
||||||
</div>
|
</div >
|
||||||
</div>
|
)
|
||||||
<Connection onConnection={(connectionId: string) => this.setState({ connectionId })}/>
|
|
||||||
</div >
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
212
app/src/UpdateNotifier.tsx
Normal file
212
app/src/UpdateNotifier.tsx
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
import * as React from 'react'
|
||||||
|
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
IconButton,
|
||||||
|
Modal,
|
||||||
|
Paper,
|
||||||
|
Snackbar,
|
||||||
|
SnackbarContent,
|
||||||
|
Typography,
|
||||||
|
} from '@material-ui/core'
|
||||||
|
import { Theme, withStyles } from '@material-ui/core/styles'
|
||||||
|
import { UpdateInfo, checkForUpdates, rendererEvents, updateAvailable } from '../../events'
|
||||||
|
import { green, red } from '@material-ui/core/colors'
|
||||||
|
|
||||||
|
import { AppState } from './reducers'
|
||||||
|
import Close from '@material-ui/icons/Close'
|
||||||
|
import CloudDownload from '@material-ui/icons/CloudDownload'
|
||||||
|
import { UpdateFileInfo } from 'builder-util-runtime'
|
||||||
|
import { bindActionCreators } from 'redux'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
import { updateNotifierActions } from './actions'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
showUpdateNotification: boolean
|
||||||
|
showUpdateDetails: boolean
|
||||||
|
classes: any
|
||||||
|
actions: any
|
||||||
|
}
|
||||||
|
|
||||||
|
class UpdateNotifier extends React.Component<Props, {}> {
|
||||||
|
private updateInfo?: UpdateInfo
|
||||||
|
constructor(props: any) {
|
||||||
|
super(props)
|
||||||
|
this.state = {
|
||||||
|
selectedNode: undefined,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public componentDidMount() {
|
||||||
|
rendererEvents.emit(checkForUpdates, undefined)
|
||||||
|
rendererEvents.subscribe(updateAvailable, this.handleUpdate)
|
||||||
|
}
|
||||||
|
|
||||||
|
public componentWillUnmount() {
|
||||||
|
rendererEvents.unsubscribeAll(updateAvailable)
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleUpdate = (updateInfo: UpdateInfo) => {
|
||||||
|
this.updateInfo = updateInfo
|
||||||
|
this.props.actions.showUpdateNotification(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
private closeNotification = () => {
|
||||||
|
this.props.actions.showUpdateNotification(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
private showDetails = () => {
|
||||||
|
this.closeNotification()
|
||||||
|
this.props.actions.showUpdateDetails(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
private hideDetails = () => {
|
||||||
|
this.props.actions.showUpdateDetails(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{this.renderUpdateNotification()}
|
||||||
|
{this.renderUpdateDetails()}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderUpdateNotification() {
|
||||||
|
const snackbarAnchor = {
|
||||||
|
vertical: 'top',
|
||||||
|
horizontal: 'right',
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Snackbar
|
||||||
|
anchorOrigin={snackbarAnchor}
|
||||||
|
open={this.props.showUpdateNotification}
|
||||||
|
autoHideDuration={6000}
|
||||||
|
onClose={this.closeNotification}
|
||||||
|
>
|
||||||
|
<SnackbarContent
|
||||||
|
className={this.props.classes.success}
|
||||||
|
message="Update available"
|
||||||
|
action={this.notificationActions()}
|
||||||
|
/>
|
||||||
|
</Snackbar>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private notificationActions() {
|
||||||
|
return [(
|
||||||
|
<Button key="undo" size="small" onClick={this.showDetails}>
|
||||||
|
Download
|
||||||
|
</Button>
|
||||||
|
), (
|
||||||
|
<IconButton
|
||||||
|
key="close"
|
||||||
|
aria-label="Close"
|
||||||
|
color="inherit"
|
||||||
|
className={this.props.classes.close}
|
||||||
|
onClick={this.closeNotification}
|
||||||
|
>
|
||||||
|
<Close />
|
||||||
|
</IconButton>
|
||||||
|
),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderUpdateDetails() {
|
||||||
|
if (!this.updateInfo) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const releaseNotes = (this.updateInfo.releaseNotes as string) || ''
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
open={this.props.showUpdateDetails}
|
||||||
|
disableAutoFocus={true}
|
||||||
|
onClose={this.hideDetails}
|
||||||
|
>
|
||||||
|
<Paper className={this.props.classes.root}>
|
||||||
|
<Typography variant="h6" className={this.props.classes.title}>Version {this.updateInfo.version}</Typography>
|
||||||
|
<Typography className={this.props.classes.title}>Changelog</Typography>
|
||||||
|
<div className={this.props.classes.releaseNotes} dangerouslySetInnerHTML={{ __html: releaseNotes }} />
|
||||||
|
{this.renderDownloads(this.updateInfo)}
|
||||||
|
<Button className={this.props.classes.closeButton} color="secondary" onClick={this.hideDetails}>Close</Button>
|
||||||
|
</Paper>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private urlToFilename(url: string) {
|
||||||
|
const parts = url.split('/')
|
||||||
|
|
||||||
|
return parts[parts.length - 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderDownloads(updateInfo: UpdateInfo) {
|
||||||
|
console.log(updateInfo)
|
||||||
|
return updateInfo.files
|
||||||
|
.map((file: UpdateFileInfo, index: number) => (
|
||||||
|
<div key={index}>
|
||||||
|
<Button
|
||||||
|
className={this.props.classes.download}
|
||||||
|
href={file.url}
|
||||||
|
>
|
||||||
|
<IconButton><CloudDownload /></IconButton>{this.urlToFilename(file.url)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = (theme: Theme) => ({
|
||||||
|
success: {
|
||||||
|
backgroundColor: green[600],
|
||||||
|
color: theme.typography.button.color,
|
||||||
|
},
|
||||||
|
close: {
|
||||||
|
padding: theme.spacing.unit / 2,
|
||||||
|
},
|
||||||
|
root: {
|
||||||
|
minWidth: '350px',
|
||||||
|
maxWidth: '500px',
|
||||||
|
backgroundColor: theme.palette.background.default,
|
||||||
|
margin: '20vh auto auto auto',
|
||||||
|
padding: `${2 * theme.spacing.unit}px`,
|
||||||
|
outline: 'none',
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
color: theme.palette.text.primary,
|
||||||
|
},
|
||||||
|
releaseNotes: {
|
||||||
|
overflow: 'auto scroll',
|
||||||
|
color: theme.palette.text.secondary,
|
||||||
|
backgroundColor: 'rgba(60, 60, 60, 0.6)',
|
||||||
|
maxHeight: '28vh',
|
||||||
|
},
|
||||||
|
paper: {
|
||||||
|
padding: `${theme.spacing.unit * 2}px`,
|
||||||
|
color: theme.palette.text.secondary,
|
||||||
|
},
|
||||||
|
download: {
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
closeButton: {
|
||||||
|
display: 'block',
|
||||||
|
margin: '0 0 0 auto',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapStateToProps = (state: AppState) => {
|
||||||
|
return {
|
||||||
|
showUpdateNotification: state.showUpdateNotification,
|
||||||
|
showUpdateDetails: state.showUpdateDetails,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch: any) => {
|
||||||
|
return {
|
||||||
|
actions: bindActionCreators(updateNotifierActions, dispatch),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withStyles(styles, { withTheme: true })(connect(mapStateToProps, mapDispatchToProps)(UpdateNotifier))
|
||||||
15
app/src/actions/UpdateNotifier.ts
Normal file
15
app/src/actions/UpdateNotifier.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { ActionTypes, CustomAction } from '../reducers'
|
||||||
|
|
||||||
|
export const showUpdateNotification = (show: boolean): CustomAction => {
|
||||||
|
return {
|
||||||
|
type: ActionTypes.showUpdateNotification,
|
||||||
|
showUpdateNotification: show,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const showUpdateDetails = (show: boolean): CustomAction => {
|
||||||
|
return {
|
||||||
|
type: ActionTypes.showUpdateDetails,
|
||||||
|
showUpdateDetails: show,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import * as settingsActions from './Settings'
|
import * as settingsActions from './Settings'
|
||||||
import * as treeActions from './Tree'
|
|
||||||
import * as sidebarActions from './Sidebar'
|
import * as sidebarActions from './Sidebar'
|
||||||
|
import * as treeActions from './Tree'
|
||||||
|
import * as updateNotifierActions from './UpdateNotifier'
|
||||||
|
|
||||||
export { settingsActions, treeActions, sidebarActions }
|
export { settingsActions, treeActions, sidebarActions, updateNotifierActions }
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ const initialAppState: AppState = {
|
|||||||
},
|
},
|
||||||
sidebar: {},
|
sidebar: {},
|
||||||
selectedTopic: undefined,
|
selectedTopic: undefined,
|
||||||
|
showUpdateDetails: false,
|
||||||
}
|
}
|
||||||
const store = createStore(reducers, initialAppState)
|
const store = createStore(reducers, initialAppState)
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ export enum ActionTypes {
|
|||||||
selectTopic = 'SELECT_TOPIC',
|
selectTopic = 'SELECT_TOPIC',
|
||||||
setPublishTopic = 'SET_PUBLISH_TOPIC',
|
setPublishTopic = 'SET_PUBLISH_TOPIC',
|
||||||
setPublishPayload = 'SET_PUBLISH_PAYLOAD',
|
setPublishPayload = 'SET_PUBLISH_PAYLOAD',
|
||||||
|
showUpdateNotification = 'SHOW_UPDATE_NOTIFICATION',
|
||||||
|
showUpdateDetails = 'SHOW_UPDATE_DETAILS',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CustomAction extends Action {
|
export interface CustomAction extends Action {
|
||||||
@@ -20,6 +22,8 @@ export interface CustomAction extends Action {
|
|||||||
selectedTopic?: q.TreeNode
|
selectedTopic?: q.TreeNode
|
||||||
publishTopic?: string
|
publishTopic?: string
|
||||||
publishPayload?: string
|
publishPayload?: string
|
||||||
|
showUpdateNotification?: boolean
|
||||||
|
showUpdateDetails?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SidebarState {
|
export interface SidebarState {
|
||||||
@@ -31,6 +35,8 @@ export interface AppState {
|
|||||||
settings: SettingsState,
|
settings: SettingsState,
|
||||||
selectedTopic?: q.TreeNode
|
selectedTopic?: q.TreeNode
|
||||||
sidebar: SidebarState
|
sidebar: SidebarState
|
||||||
|
showUpdateNotification?: boolean
|
||||||
|
showUpdateDetails: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SettingsState {
|
export interface SettingsState {
|
||||||
@@ -51,7 +57,7 @@ const reducer: Reducer<AppState | undefined, CustomAction> = (state, action) =>
|
|||||||
throw Error('No initial state')
|
throw Error('No initial state')
|
||||||
}
|
}
|
||||||
trackEvent(action.type)
|
trackEvent(action.type)
|
||||||
|
console.log(action, state)
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case ActionTypes.setAutoExpandLimit:
|
case ActionTypes.setAutoExpandLimit:
|
||||||
if (action.autoExpandLimit === undefined) {
|
if (action.autoExpandLimit === undefined) {
|
||||||
@@ -98,6 +104,19 @@ const reducer: Reducer<AppState | undefined, CustomAction> = (state, action) =>
|
|||||||
...state,
|
...state,
|
||||||
settings: { ...state.settings, nodeOrder: action.nodeOrder },
|
settings: { ...state.settings, nodeOrder: action.nodeOrder },
|
||||||
}
|
}
|
||||||
|
case ActionTypes.showUpdateNotification:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
showUpdateNotification: action.showUpdateNotification,
|
||||||
|
}
|
||||||
|
case ActionTypes.showUpdateDetails:
|
||||||
|
if (action.showUpdateDetails === undefined) {
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
showUpdateDetails: action.showUpdateDetails,
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,21 @@
|
|||||||
import {
|
import {
|
||||||
addMqttConnectionEvent, backendEvents,
|
AddMqttConnection,
|
||||||
makeConnectionStateEvent, removeConnection,
|
EventDispatcher,
|
||||||
makeConnectionMessageEvent, makePublishEvent, AddMqttConnection, Message,
|
Message,
|
||||||
|
addMqttConnectionEvent,
|
||||||
|
backendEvents,
|
||||||
|
checkForUpdates,
|
||||||
|
makeConnectionMessageEvent,
|
||||||
|
makeConnectionStateEvent,
|
||||||
|
makePublishEvent,
|
||||||
|
removeConnection,
|
||||||
|
updateAvailable,
|
||||||
} from '../../events'
|
} from '../../events'
|
||||||
import { MqttSource, DataSource } from './DataSource'
|
import { DataSource, MqttSource } from './DataSource'
|
||||||
|
|
||||||
class ConnectionManager {
|
import { UpdateInfo } from 'builder-util-runtime'
|
||||||
|
|
||||||
|
export class ConnectionManager {
|
||||||
private connections: {[s: string]: DataSource<any>} = {}
|
private connections: {[s: string]: DataSource<any>} = {}
|
||||||
|
|
||||||
public manageConnections() {
|
public manageConnections() {
|
||||||
@@ -49,5 +59,16 @@ class ConnectionManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const connectionManager = new ConnectionManager()
|
class UpdateNotifier {
|
||||||
connectionManager.manageConnections()
|
public onCheckUpdateRequest = new EventDispatcher<void, UpdateNotifier>(this)
|
||||||
|
constructor() {
|
||||||
|
backendEvents.subscribe(checkForUpdates, () => {
|
||||||
|
this.onCheckUpdateRequest.dispatch()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
public notify(updateInfo: UpdateInfo) {
|
||||||
|
backendEvents.emit(updateAvailable, updateInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const updateNotifier = new UpdateNotifier()
|
||||||
|
|||||||
66
electron.js
66
electron.js
@@ -1,17 +1,15 @@
|
|||||||
|
const { app, BrowserWindow } = require('electron')
|
||||||
const { autoUpdater } = require("electron-updater")
|
const { autoUpdater } = require("electron-updater")
|
||||||
const log = require('electron-log');
|
const log = require('electron-log');
|
||||||
|
const { ConnectionManager, updateNotifier } = require('./backend/build/backend/src/index.js')
|
||||||
|
|
||||||
autoUpdater.logger = log;
|
autoUpdater.logger = log;
|
||||||
autoUpdater.logger.transports.file.level = 'info';
|
autoUpdater.logger.transports.file.level = 'info';
|
||||||
log.info('App starting...');
|
log.info('App starting...');
|
||||||
|
|
||||||
// Modules to control application life and create native browser window
|
const connectionManager = new ConnectionManager()
|
||||||
const { app, BrowserWindow, Notification } = require('electron')
|
connectionManager.manageConnections()
|
||||||
try {
|
|
||||||
require('./backend/build/backend/src/index.js')
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err)
|
|
||||||
}
|
|
||||||
// Keep a global reference of the window object, if you don't, the window will
|
// Keep a global reference of the window object, if you don't, the window will
|
||||||
// be closed automatically when the JavaScript object is garbage collected.
|
// be closed automatically when the JavaScript object is garbage collected.
|
||||||
let mainWindow
|
let mainWindow
|
||||||
@@ -29,31 +27,6 @@ function createWindow () {
|
|||||||
// and load the index.html of the app.
|
// and load the index.html of the app.
|
||||||
mainWindow.loadFile('app/index.html')
|
mainWindow.loadFile('app/index.html')
|
||||||
|
|
||||||
mainWindow.webContents.once('dom-ready', () => {
|
|
||||||
|
|
||||||
console.log('window loaded, check for updates')
|
|
||||||
let updateInfo
|
|
||||||
|
|
||||||
autoUpdater.on('update-available', (info) => {
|
|
||||||
updateInfo = info
|
|
||||||
})
|
|
||||||
|
|
||||||
autoUpdater.on('error', () => {
|
|
||||||
const version = updateInfo ? ` (${updateInfo.version})` : ''
|
|
||||||
const releaseNotes = ((updateInfo && updateInfo.releaseNotes) ? `${updateInfo.releaseNotes}\n` : '')
|
|
||||||
let notification = new Notification({
|
|
||||||
title: 'Update available' + version,
|
|
||||||
silent: true,
|
|
||||||
body: releaseNotes + 'https://github.com/thomasnordquist/MQTT-Explorer/releases'
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
})
|
|
||||||
try {
|
|
||||||
autoUpdater.checkForUpdatesAndNotify()
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// Open the DevTools.
|
// Open the DevTools.
|
||||||
// mainWindow.webContents.openDevTools()
|
// mainWindow.webContents.openDevTools()
|
||||||
|
|
||||||
@@ -72,6 +45,35 @@ function createWindow () {
|
|||||||
// Some APIs can only be used after this event occurs.
|
// Some APIs can only be used after this event occurs.
|
||||||
app.on('ready', () => {
|
app.on('ready', () => {
|
||||||
createWindow()
|
createWindow()
|
||||||
|
|
||||||
|
let updateInfo
|
||||||
|
autoUpdater.on('update-available', (info) => {
|
||||||
|
updateInfo = info
|
||||||
|
})
|
||||||
|
|
||||||
|
autoUpdater.on('error', () => {
|
||||||
|
if (updateInfo) {
|
||||||
|
updateNotifier.notify(updateInfo)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
updateNotifier.onCheckUpdateRequest.subscribe(() => {
|
||||||
|
updateNotifier.notify({
|
||||||
|
version: '0.0.4',
|
||||||
|
releaseNotes: '<ul><li>some</li><li>stuff</li></ul>',
|
||||||
|
files: [{
|
||||||
|
url: 'https://github.com/thomasnordquist/MQTT-Explorer/releases/download/v0.0.2/MQTT-Explorer-0.0.2.dmg'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: 'https://github.com/thomasnordquist/MQTT-Explorer/releases/download/v0.0.2/MQTT-Explorer-0.0.2-mac.zip'
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
try {
|
||||||
|
autoUpdater.checkForUpdatesAndNotify()
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// Quit when all windows are closed.
|
// Quit when all windows are closed.
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
import { MqttOptions, DataSourceState } from '../backend/src/DataSource'
|
import { DataSourceState, MqttOptions } from '../backend/src/DataSource'
|
||||||
|
|
||||||
|
import { UpdateInfo } from 'builder-util-runtime'
|
||||||
|
|
||||||
|
export { UpdateInfo } from 'builder-util-runtime'
|
||||||
|
|
||||||
export interface Event<MessageType> {
|
export interface Event<MessageType> {
|
||||||
topic: string
|
topic: string
|
||||||
@@ -23,6 +27,14 @@ export function makeConnectionStateEvent(connectionId: string): Event<DataSource
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const checkForUpdates: Event<void> = {
|
||||||
|
topic: 'app/update/check',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const updateAvailable: Event<UpdateInfo> = {
|
||||||
|
topic: 'app/update/available',
|
||||||
|
}
|
||||||
|
|
||||||
export interface Message {
|
export interface Message {
|
||||||
topic: string,
|
topic: string,
|
||||||
payload: any
|
payload: any
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "MQTT-Explorer",
|
"name": "MQTT-Explorer",
|
||||||
"version": "0.0.2",
|
"version": "0.0.3",
|
||||||
"description": "Explore your message queues",
|
"description": "Explore your message queues",
|
||||||
"main": "electron.js",
|
"main": "electron.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
Reference in New Issue
Block a user