diff --git a/lib/actions/index.js b/lib/actions/index.js
index 8a0fa3b7..432a4b01 100644
--- a/lib/actions/index.js
+++ b/lib/actions/index.js
@@ -1,5 +1,9 @@
+import {INIT} from '../constants/index';
import rpc from '../rpc';
export function init() {
rpc.emit('init');
+ return {
+ type: INIT
+ }
}
diff --git a/lib/actions/notifications.js b/lib/actions/notifications.js
index 10cddfd7..b33e1f8d 100644
--- a/lib/actions/notifications.js
+++ b/lib/actions/notifications.js
@@ -1,4 +1,11 @@
-import {NOTIFICATION_DISMISS} from '../constants/notifications';
+import ms from 'ms';
+import {version} from '../../package';
+import {satisfies} from 'semver';
+import {remote} from 'electron';
+import {
+ NOTIFICATION_MESSAGE,
+ NOTIFICATION_DISMISS
+} from '../constants/notifications';
export function dismissNotification(id) {
return {
@@ -6,3 +13,59 @@ export function dismissNotification(id) {
id
};
}
+
+export function addNotificationMessage(text, url = null, dismissable = true) {
+ return {
+ type: NOTIFICATION_MESSAGE,
+ text,
+ url,
+ dismissable
+ };
+}
+
+export function fetchNotifications() {
+ return dispatch => {
+ const retry = err => {
+ setTimeout(() => dispatch(fetchNotifications()), ms(err ? '10s' : '5m'));
+ if (err) {
+ console.error('Notification messages fetch error', err.stack);
+ }
+ };
+
+ console.log('Checking for notification messages');
+ fetch('https://hyper-news.now.sh')
+ .then(res => {
+ res.json()
+ .then(data => {
+ const {messages} = data || {};
+ if (!messages) {
+ throw new Error('Bad response');
+ }
+ const message = messages.filter(msg => {
+ return matchVersion(msg.versions);
+ })[0];
+ if (message) {
+ dispatch(addNotificationMessage(
+ message.text,
+ message.url,
+ message.dismissable
+ ));
+ } else {
+ console.log('No matching notification messages');
+ }
+ retry();
+ })
+ .catch(retry);
+ })
+ .catch(retry);
+ };
+}
+
+function matchVersion(versions) {
+ return versions.some(v => {
+ if (v === '*') {
+ return true;
+ }
+ return satisfies(version, v);
+ });
+}
diff --git a/lib/components/notification.js b/lib/components/notification.js
index e57f127e..ada20b62 100644
--- a/lib/components/notification.js
+++ b/lib/components/notification.js
@@ -83,6 +83,7 @@ export default class Notification extends Component {
[x] :
null
}
diff --git a/lib/components/notifications.js b/lib/components/notifications.js
index 5569e3b3..c61697f5 100644
--- a/lib/components/notifications.js
+++ b/lib/components/notifications.js
@@ -36,6 +36,34 @@ export default class Notifications extends Component {
/>
}
+ {
+ this.props.messageShowing &&
+ {
+ this.props.messageURL ? [
+ this.props.messageText,
+ ' (',
+ {
+ window.require('electron').shell.openExternal(ev.target.href);
+ ev.preventDefault();
+ }}
+ href={this.props.messageURL}
+ >more,
+ ')'
+ ] : null
+ }
+
+ }
+
{
this.props.updateShowing &&
{
dispatch(dismissNotification('updates'));
},
+ onDismissMessage: () => {
+ dispatch(dismissNotification('message'));
+ },
onUpdateInstall: () => {
dispatch(installUpdate());
}
diff --git a/lib/index.js b/lib/index.js
index aec419ca..818bf2df 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -12,6 +12,7 @@ import * as uiActions from './actions/ui';
import * as updaterActions from './actions/updater';
import * as sessionActions from './actions/sessions';
import * as termGroupActions from './actions/term-groups';
+import {fetchNotifications} from './actions/notifications';
import HyperTermContainer from './containers/hyperterm';
import {loadConfig, reloadConfig} from './actions/config';
import configureStore from './store/configure-store';
@@ -36,6 +37,7 @@ config.subscribe(() => {
// and subscribe to all user intents for example from menus
rpc.on('ready', () => {
store_.dispatch(init());
+ store_.dispatch(fetchNotifications());
store_.dispatch(uiActions.setFontSmoothing());
});
diff --git a/lib/reducers/ui.js b/lib/reducers/ui.js
index cd74901e..4a108c85 100644
--- a/lib/reducers/ui.js
+++ b/lib/reducers/ui.js
@@ -8,7 +8,7 @@ import {
UI_WINDOW_MAXIMIZE,
UI_WINDOW_UNMAXIMIZE
} from '../constants/ui';
-import {NOTIFICATION_DISMISS} from '../constants/notifications';
+import {NOTIFICATION_MESSAGE, NOTIFICATION_DISMISS} from '../constants/notifications';
import {
SESSION_ADD,
SESSION_RESIZE,
@@ -62,13 +62,17 @@ const initial = Immutable({
notifications: {
font: false,
resize: false,
- updates: false
+ updates: false,
+ message: false
},
foregroundColor: '#fff',
backgroundColor: '#000',
maximized: false,
updateVersion: null,
updateNotes: null,
+ messageText: null,
+ messageURL: null,
+ messageDismissable: null,
bell: 'SOUND',
bellSoundURL: 'lib-resource:hterm/audio/bell',
copyOnSelect: false,
@@ -273,6 +277,14 @@ const reducer = (state = initial, action) => {
}, {deep: true});
break;
+ case NOTIFICATION_MESSAGE:
+ state_ = state.merge({
+ messageText: action.text,
+ messageURL: action.url || null,
+ messageDismissable: action.dismissable === true
+ });
+ break;
+
case UPDATE_AVAILABLE:
state_ = state.merge({
updateVersion: action.version,
@@ -296,6 +308,10 @@ const reducer = (state = initial, action) => {
state_ = state_.merge({notifications: {resize: true}}, {deep: true});
}
+ if (state.messageText !== state_.messageText || state.messageURL !== state_.messageURL) {
+ state_ = state_.merge({notifications: {message: true}}, {deep: true});
+ }
+
if (state.updateVersion !== state_.updateVersion) {
state_ = state_.merge({notifications: {updates: true}}, {deep: true});
}
diff --git a/package.json b/package.json
index 55ddf17e..c2e03edb 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "hyperterm",
- "version": "1.0.0",
+ "version": "0.8.0",
"description": "Web app that runs in the renderer process",
"repository": "zeit/hyperterm",
"license": "MIT",
@@ -28,8 +28,9 @@
"redux": "3.6.0",
"redux-thunk": "2.1.0",
"reselect": "2.5.4",
- "uuid": "2.0.2",
- "seamless-immutable": "6.1.3"
+ "seamless-immutable": "6.1.3",
+ "semver": "5.3.0",
+ "uuid": "2.0.2"
},
"devDependencies": {
"ava": "^0.16.0",