]>
cat aescling's git repositories - mastodon.git/blob - app/javascript/mastodon/reducers/timelines.js
5 TIMELINE_EXPAND_SUCCESS
,
6 TIMELINE_EXPAND_REQUEST
,
11 TIMELINE_LOAD_PENDING
,
12 } from '../actions/timelines';
14 ACCOUNT_BLOCK_SUCCESS
,
16 ACCOUNT_UNFOLLOW_SUCCESS
,
17 } from '../actions/accounts';
18 import { Map as ImmutableMap
, List as ImmutableList
, fromJS
} from 'immutable';
19 import compareId
from '../compare_id';
21 const initialState
= ImmutableMap();
23 const initialTimeline
= ImmutableMap({
29 pendingItems: ImmutableList(),
30 items: ImmutableList(),
33 const expandNormalizedTimeline
= (state
, timeline
, statuses
, next
, isPartial
, isLoadingRecent
, usePendingItems
) => {
34 return state
.update(timeline
, initialTimeline
, map
=> map
.withMutations(mMap
=> {
35 mMap
.set('isLoading', false);
36 mMap
.set('isPartial', isPartial
);
38 if (!next
&& !isLoadingRecent
) mMap
.set('hasMore', false);
40 if (timeline
.endsWith(':pinned')) {
41 mMap
.set('items', statuses
.map(status
=> status
.get('id')));
42 } else if (!statuses
.isEmpty()) {
43 usePendingItems
= isLoadingRecent
&& (usePendingItems
|| !mMap
.get('top') || !mMap
.get('pendingItems').isEmpty());
44 mMap
.update(usePendingItems
? 'pendingItems' : 'items', ImmutableList(), oldIds
=> {
45 const newIds
= statuses
.map(status
=> status
.get('id'));
47 const lastIndex
= oldIds
.findLastIndex(id
=> id
!== null && compareId(id
, newIds
.last()) >= 0) + 1;
48 const firstIndex
= oldIds
.take(lastIndex
).findLastIndex(id
=> id
!== null && compareId(id
, newIds
.first()) > 0);
51 return (isPartial
? newIds
.unshift(null) : newIds
).concat(oldIds
.skip(lastIndex
));
54 return oldIds
.take(firstIndex
+ 1).concat(
55 isPartial
&& oldIds
.get(firstIndex
) !== null ? newIds
.unshift(null) : newIds
,
56 oldIds
.skip(lastIndex
)
63 const updateTimeline
= (state
, timeline
, status
, usePendingItems
) => {
64 const top
= state
.getIn([timeline
, 'top']);
66 if (usePendingItems
|| !top
|| !state
.getIn([timeline
, 'pendingItems']).isEmpty()) {
67 if (state
.getIn([timeline
, 'pendingItems'], ImmutableList()).includes(status
.get('id')) || state
.getIn([timeline
, 'items'], ImmutableList()).includes(status
.get('id'))) {
71 return state
.update(timeline
, initialTimeline
, map
=> map
.update('pendingItems', list
=> list
.unshift(status
.get('id'))).update('unread', unread
=> unread
+ 1));
74 const ids
= state
.getIn([timeline
, 'items'], ImmutableList());
75 const includesId
= ids
.includes(status
.get('id'));
76 const unread
= state
.getIn([timeline
, 'unread'], 0);
84 return state
.update(timeline
, initialTimeline
, map
=> map
.withMutations(mMap
=> {
85 if (!top
) mMap
.set('unread', unread
+ 1);
86 if (top
&& ids
.size
> 40) newIds
= newIds
.take(20);
87 mMap
.set('items', newIds
.unshift(status
.get('id')));
91 const deleteStatus
= (state
, id
, accountId
, references
, exclude_account
= null) => {
92 state
.keySeq().forEach(timeline
=> {
93 if (exclude_account
=== null || (timeline
!== `account:${exclude_account}` && !timeline
.startsWith(`account:${exclude_account}:`))) {
94 const helper
= list
=> list
.filterNot(item
=> item
=== id
);
95 state
= state
.updateIn([timeline
, 'items'], helper
).updateIn([timeline
, 'pendingItems'], helper
);
99 // Remove reblogs of deleted status
100 references
.forEach(ref
=> {
101 state
= deleteStatus(state
, ref
[0], ref
[1], [], exclude_account
);
107 const clearTimeline
= (state
, timeline
) => {
108 return state
.set(timeline
, initialTimeline
);
111 const filterTimelines
= (state
, relationship
, statuses
) => {
114 statuses
.forEach(status
=> {
115 if (status
.get('account') !== relationship
.id
) {
119 references
= statuses
.filter(item
=> item
.get('reblog') === status
.get('id')).map(item
=> [item
.get('id'), item
.get('account')]);
120 state
= deleteStatus(state
, status
.get('id'), status
.get('account'), references
, relationship
.id
);
126 const filterTimeline
= (timeline
, state
, relationship
, statuses
) => {
127 const helper
= list
=> list
.filterNot(statusId
=> statuses
.getIn([statusId
, 'account']) === relationship
.id
);
128 return state
.updateIn([timeline
, 'items'], ImmutableList(), helper
).updateIn([timeline
, 'pendingItems'], ImmutableList(), helper
);
131 const updateTop
= (state
, timeline
, top
) => {
132 return state
.update(timeline
, initialTimeline
, map
=> map
.withMutations(mMap
=> {
133 if (top
) mMap
.set('unread', mMap
.get('pendingItems').size
);
134 mMap
.set('top', top
);
138 export default function timelines(state
= initialState
, action
) {
139 switch(action
.type
) {
140 case TIMELINE_LOAD_PENDING:
141 return state
.update(action
.timeline
, initialTimeline
, map
=>
142 map
.update('items', list
=> map
.get('pendingItems').concat(list
.take(40))).set('pendingItems', ImmutableList()).set('unread', 0));
143 case TIMELINE_EXPAND_REQUEST:
144 return state
.update(action
.timeline
, initialTimeline
, map
=> map
.set('isLoading', true));
145 case TIMELINE_EXPAND_FAIL:
146 return state
.update(action
.timeline
, initialTimeline
, map
=> map
.set('isLoading', false));
147 case TIMELINE_EXPAND_SUCCESS:
148 return expandNormalizedTimeline(state
, action
.timeline
, fromJS(action
.statuses
), action
.next
, action
.partial
, action
.isLoadingRecent
, action
.usePendingItems
);
149 case TIMELINE_UPDATE:
150 return updateTimeline(state
, action
.timeline
, fromJS(action
.status
), action
.usePendingItems
);
151 case TIMELINE_DELETE:
152 return deleteStatus(state
, action
.id
, action
.accountId
, action
.references
, action
.reblogOf
);
154 return clearTimeline(state
, action
.timeline
);
155 case ACCOUNT_BLOCK_SUCCESS:
156 case ACCOUNT_MUTE_SUCCESS:
157 return filterTimelines(state
, action
.relationship
, action
.statuses
);
158 case ACCOUNT_UNFOLLOW_SUCCESS:
159 return filterTimeline('home', state
, action
.relationship
, action
.statuses
);
160 case TIMELINE_SCROLL_TOP:
161 return updateTop(state
, action
.timeline
, action
.top
);
162 case TIMELINE_CONNECT:
163 return state
.update(action
.timeline
, initialTimeline
, map
=> map
.set('online', true));
164 case TIMELINE_DISCONNECT:
168 map
=> map
.set('online', false).update(action
.usePendingItems
? 'pendingItems' : 'items', items
=> items
.first() ? items
.unshift(null) : items
)
This page took 0.11116 seconds and 4 git commands to generate.