about summary refs log tree commit diff
path: root/app/javascript
diff options
context:
space:
mode:
Diffstat (limited to 'app/javascript')
-rw-r--r--app/javascript/flavours/glitch/actions/compose.js4
-rw-r--r--app/javascript/flavours/glitch/actions/streaming.js6
-rw-r--r--app/javascript/flavours/glitch/actions/timelines.js8
-rw-r--r--app/javascript/flavours/glitch/components/poll.js2
-rw-r--r--app/javascript/flavours/glitch/reducers/timelines.js9
-rw-r--r--app/javascript/flavours/glitch/util/stream.js8
-rw-r--r--app/javascript/mastodon/actions/compose.js4
-rw-r--r--app/javascript/mastodon/actions/streaming.js6
-rw-r--r--app/javascript/mastodon/actions/timelines.js8
-rw-r--r--app/javascript/mastodon/components/poll.js2
-rw-r--r--app/javascript/mastodon/reducers/timelines.js9
-rw-r--r--app/javascript/mastodon/stream.js8
12 files changed, 58 insertions, 16 deletions
diff --git a/app/javascript/flavours/glitch/actions/compose.js b/app/javascript/flavours/glitch/actions/compose.js
index 7fa35351f..ac09adceb 100644
--- a/app/javascript/flavours/glitch/actions/compose.js
+++ b/app/javascript/flavours/glitch/actions/compose.js
@@ -175,7 +175,9 @@ export function submitCompose(routerHistory) {
       // To make the app more responsive, immediately get the status into the columns
 
       const insertIfOnline = (timelineId) => {
-        if (getState().getIn(['timelines', timelineId, 'items', 0]) !== null) {
+        const timeline = getState().getIn(['timelines', timelineId]);
+
+        if (timeline && timeline.get('items').size > 0 && timeline.getIn(['items', 0]) !== null && timeline.get('online')) {
           dispatch(updateTimeline(timelineId, { ...response.data }));
         }
       };
diff --git a/app/javascript/flavours/glitch/actions/streaming.js b/app/javascript/flavours/glitch/actions/streaming.js
index 8c1bd1f08..b5dd70989 100644
--- a/app/javascript/flavours/glitch/actions/streaming.js
+++ b/app/javascript/flavours/glitch/actions/streaming.js
@@ -3,6 +3,7 @@ import {
   updateTimeline,
   deleteFromTimelines,
   expandHomeTimeline,
+  connectTimeline,
   disconnectTimeline,
 } from './timelines';
 import { updateNotifications, expandNotifications } from './notifications';
@@ -15,7 +16,12 @@ export function connectTimelineStream (timelineId, path, pollingRefresh = null,
 
   return connectStream (path, pollingRefresh, (dispatch, getState) => {
     const locale = getState().getIn(['meta', 'locale']);
+
     return {
+      onConnect() {
+        dispatch(connectTimeline(timelineId));
+      },
+
       onDisconnect() {
         dispatch(disconnectTimeline(timelineId));
       },
diff --git a/app/javascript/flavours/glitch/actions/timelines.js b/app/javascript/flavours/glitch/actions/timelines.js
index c6866f81f..f218ee06b 100644
--- a/app/javascript/flavours/glitch/actions/timelines.js
+++ b/app/javascript/flavours/glitch/actions/timelines.js
@@ -12,6 +12,7 @@ export const TIMELINE_EXPAND_FAIL    = 'TIMELINE_EXPAND_FAIL';
 
 export const TIMELINE_SCROLL_TOP = 'TIMELINE_SCROLL_TOP';
 
+export const TIMELINE_CONNECT    = 'TIMELINE_CONNECT';
 export const TIMELINE_DISCONNECT = 'TIMELINE_DISCONNECT';
 
 export function updateTimeline(timeline, status, accept) {
@@ -145,6 +146,13 @@ export function scrollTopTimeline(timeline, top) {
   };
 };
 
+export function connectTimeline(timeline) {
+  return {
+    type: TIMELINE_CONNECT,
+    timeline,
+  };
+};
+
 export function disconnectTimeline(timeline) {
   return {
     type: TIMELINE_DISCONNECT,
diff --git a/app/javascript/flavours/glitch/components/poll.js b/app/javascript/flavours/glitch/components/poll.js
index bfff7b601..a1b297ce7 100644
--- a/app/javascript/flavours/glitch/components/poll.js
+++ b/app/javascript/flavours/glitch/components/poll.js
@@ -94,7 +94,7 @@ class Poll extends ImmutablePureComponent {
 
   renderOption (option, optionIndex) {
     const { poll, disabled } = this.props;
-    const percent            = (option.get('votes_count') / poll.get('votes_count')) * 100;
+    const percent            = poll.get('votes_count') === 0 ? 0 : (option.get('votes_count') / poll.get('votes_count')) * 100;
     const leading            = poll.get('options').filterNot(other => other.get('title') === option.get('title')).every(other => option.get('votes_count') > other.get('votes_count'));
     const active             = !!this.state.selected[`${optionIndex}`];
     const showResults        = poll.get('voted') || poll.get('expired');
diff --git a/app/javascript/flavours/glitch/reducers/timelines.js b/app/javascript/flavours/glitch/reducers/timelines.js
index 4179cf477..ca71c3833 100644
--- a/app/javascript/flavours/glitch/reducers/timelines.js
+++ b/app/javascript/flavours/glitch/reducers/timelines.js
@@ -6,6 +6,7 @@ import {
   TIMELINE_EXPAND_REQUEST,
   TIMELINE_EXPAND_FAIL,
   TIMELINE_SCROLL_TOP,
+  TIMELINE_CONNECT,
   TIMELINE_DISCONNECT,
 } from 'flavours/glitch/actions/timelines';
 import {
@@ -20,6 +21,7 @@ const initialState = ImmutableMap();
 
 const initialTimeline = ImmutableMap({
   unread: 0,
+  online: false,
   top: true,
   isLoading: false,
   hasMore: true,
@@ -137,14 +139,13 @@ export default function timelines(state = initialState, action) {
     return filterTimeline('home', state, action.relationship, action.statuses);
   case TIMELINE_SCROLL_TOP:
     return updateTop(state, action.timeline, action.top);
+  case TIMELINE_CONNECT:
+    return state.update(action.timeline, initialTimeline, map => map.set('online', true));
   case TIMELINE_DISCONNECT:
     return state.update(
       action.timeline,
       initialTimeline,
-      map => map.update(
-        'items',
-        items => items.first() ? items.unshift(null) : items
-      )
+      map => map.set('online', false).update('items', items => items.first() ? items.unshift(null) : items)
     );
   default:
     return state;
diff --git a/app/javascript/flavours/glitch/util/stream.js b/app/javascript/flavours/glitch/util/stream.js
index 9928d0dd7..306a068b7 100644
--- a/app/javascript/flavours/glitch/util/stream.js
+++ b/app/javascript/flavours/glitch/util/stream.js
@@ -2,11 +2,11 @@ import WebSocketClient from 'websocket.js';
 
 const randomIntUpTo = max => Math.floor(Math.random() * Math.floor(max));
 
-export function connectStream(path, pollingRefresh = null, callbacks = () => ({ onDisconnect() {}, onReceive() {} })) {
+export function connectStream(path, pollingRefresh = null, callbacks = () => ({ onConnect() {}, onDisconnect() {}, onReceive() {} })) {
   return (dispatch, getState) => {
     const streamingAPIBaseURL = getState().getIn(['meta', 'streaming_api_base_url']);
     const accessToken = getState().getIn(['meta', 'access_token']);
-    const { onDisconnect, onReceive } = callbacks(dispatch, getState);
+    const { onConnect, onDisconnect, onReceive } = callbacks(dispatch, getState);
 
     let polling = null;
 
@@ -28,6 +28,8 @@ export function connectStream(path, pollingRefresh = null, callbacks = () => ({
         if (pollingRefresh) {
           clearPolling();
         }
+
+        onConnect();
       },
 
       disconnected () {
@@ -47,6 +49,8 @@ export function connectStream(path, pollingRefresh = null, callbacks = () => ({
           clearPolling();
           pollingRefresh(dispatch);
         }
+
+        onConnect();
       },
 
     });
diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js
index da7bd3cb0..d65d41048 100644
--- a/app/javascript/mastodon/actions/compose.js
+++ b/app/javascript/mastodon/actions/compose.js
@@ -158,7 +158,9 @@ export function submitCompose(routerHistory) {
       // into the columns
 
       const insertIfOnline = timelineId => {
-        if (getState().getIn(['timelines', timelineId, 'items', 0]) !== null) {
+        const timeline = getState().getIn(['timelines', timelineId]);
+
+        if (timeline && timeline.get('items').size > 0 && timeline.getIn(['items', 0]) !== null && timeline.get('online')) {
           dispatch(updateTimeline(timelineId, { ...response.data }));
         }
       };
diff --git a/app/javascript/mastodon/actions/streaming.js b/app/javascript/mastodon/actions/streaming.js
index cd319709d..c678e9393 100644
--- a/app/javascript/mastodon/actions/streaming.js
+++ b/app/javascript/mastodon/actions/streaming.js
@@ -3,6 +3,7 @@ import {
   updateTimeline,
   deleteFromTimelines,
   expandHomeTimeline,
+  connectTimeline,
   disconnectTimeline,
 } from './timelines';
 import { updateNotifications, expandNotifications } from './notifications';
@@ -16,7 +17,12 @@ export function connectTimelineStream (timelineId, path, pollingRefresh = null,
 
   return connectStream (path, pollingRefresh, (dispatch, getState) => {
     const locale = getState().getIn(['meta', 'locale']);
+
     return {
+      onConnect() {
+        dispatch(connectTimeline(timelineId));
+      },
+
       onDisconnect() {
         dispatch(disconnectTimeline(timelineId));
       },
diff --git a/app/javascript/mastodon/actions/timelines.js b/app/javascript/mastodon/actions/timelines.js
index 6e7bd027c..d92385e95 100644
--- a/app/javascript/mastodon/actions/timelines.js
+++ b/app/javascript/mastodon/actions/timelines.js
@@ -12,6 +12,7 @@ export const TIMELINE_EXPAND_FAIL    = 'TIMELINE_EXPAND_FAIL';
 
 export const TIMELINE_SCROLL_TOP = 'TIMELINE_SCROLL_TOP';
 
+export const TIMELINE_CONNECT    = 'TIMELINE_CONNECT';
 export const TIMELINE_DISCONNECT = 'TIMELINE_DISCONNECT';
 
 export function updateTimeline(timeline, status, accept) {
@@ -143,6 +144,13 @@ export function scrollTopTimeline(timeline, top) {
   };
 };
 
+export function connectTimeline(timeline) {
+  return {
+    type: TIMELINE_CONNECT,
+    timeline,
+  };
+};
+
 export function disconnectTimeline(timeline) {
   return {
     type: TIMELINE_DISCONNECT,
diff --git a/app/javascript/mastodon/components/poll.js b/app/javascript/mastodon/components/poll.js
index bfff7b601..a1b297ce7 100644
--- a/app/javascript/mastodon/components/poll.js
+++ b/app/javascript/mastodon/components/poll.js
@@ -94,7 +94,7 @@ class Poll extends ImmutablePureComponent {
 
   renderOption (option, optionIndex) {
     const { poll, disabled } = this.props;
-    const percent            = (option.get('votes_count') / poll.get('votes_count')) * 100;
+    const percent            = poll.get('votes_count') === 0 ? 0 : (option.get('votes_count') / poll.get('votes_count')) * 100;
     const leading            = poll.get('options').filterNot(other => other.get('title') === option.get('title')).every(other => option.get('votes_count') > other.get('votes_count'));
     const active             = !!this.state.selected[`${optionIndex}`];
     const showResults        = poll.get('voted') || poll.get('expired');
diff --git a/app/javascript/mastodon/reducers/timelines.js b/app/javascript/mastodon/reducers/timelines.js
index 38af9cd09..94b570ecd 100644
--- a/app/javascript/mastodon/reducers/timelines.js
+++ b/app/javascript/mastodon/reducers/timelines.js
@@ -6,6 +6,7 @@ import {
   TIMELINE_EXPAND_REQUEST,
   TIMELINE_EXPAND_FAIL,
   TIMELINE_SCROLL_TOP,
+  TIMELINE_CONNECT,
   TIMELINE_DISCONNECT,
 } from '../actions/timelines';
 import {
@@ -20,6 +21,7 @@ const initialState = ImmutableMap();
 
 const initialTimeline = ImmutableMap({
   unread: 0,
+  online: false,
   top: true,
   isLoading: false,
   hasMore: true,
@@ -142,14 +144,13 @@ export default function timelines(state = initialState, action) {
     return filterTimeline('home', state, action.relationship, action.statuses);
   case TIMELINE_SCROLL_TOP:
     return updateTop(state, action.timeline, action.top);
+  case TIMELINE_CONNECT:
+    return state.update(action.timeline, initialTimeline, map => map.set('online', true));
   case TIMELINE_DISCONNECT:
     return state.update(
       action.timeline,
       initialTimeline,
-      map => map.update(
-        'items',
-        items => items.first() ? items.unshift(null) : items
-      )
+      map => map.set('online', false).update('items', items => items.first() ? items.unshift(null) : items)
     );
   default:
     return state;
diff --git a/app/javascript/mastodon/stream.js b/app/javascript/mastodon/stream.js
index 9928d0dd7..306a068b7 100644
--- a/app/javascript/mastodon/stream.js
+++ b/app/javascript/mastodon/stream.js
@@ -2,11 +2,11 @@ import WebSocketClient from 'websocket.js';
 
 const randomIntUpTo = max => Math.floor(Math.random() * Math.floor(max));
 
-export function connectStream(path, pollingRefresh = null, callbacks = () => ({ onDisconnect() {}, onReceive() {} })) {
+export function connectStream(path, pollingRefresh = null, callbacks = () => ({ onConnect() {}, onDisconnect() {}, onReceive() {} })) {
   return (dispatch, getState) => {
     const streamingAPIBaseURL = getState().getIn(['meta', 'streaming_api_base_url']);
     const accessToken = getState().getIn(['meta', 'access_token']);
-    const { onDisconnect, onReceive } = callbacks(dispatch, getState);
+    const { onConnect, onDisconnect, onReceive } = callbacks(dispatch, getState);
 
     let polling = null;
 
@@ -28,6 +28,8 @@ export function connectStream(path, pollingRefresh = null, callbacks = () => ({
         if (pollingRefresh) {
           clearPolling();
         }
+
+        onConnect();
       },
 
       disconnected () {
@@ -47,6 +49,8 @@ export function connectStream(path, pollingRefresh = null, callbacks = () => ({
           clearPolling();
           pollingRefresh(dispatch);
         }
+
+        onConnect();
       },
 
     });