]>
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
,
13 } from '../actions/timelines';
15 ACCOUNT_BLOCK_SUCCESS
,
17 ACCOUNT_UNFOLLOW_SUCCESS
,
18 } from '../actions/accounts';
19 import { Map as ImmutableMap
, List as ImmutableList
, fromJS
} from 'immutable';
20 import compareId
from '../compare_id';
22 const initialState
= ImmutableMap();
24 const initialTimeline
= ImmutableMap({
30 pendingItems: ImmutableList(),
31 items: ImmutableList(),
35 const expandNormalizedTimeline
= (state
, timeline
, statuses
, next
, isPartial
, isLoadingRecent
, usePendingItems
) => {
36 return state
.update(timeline
, initialTimeline
, map
=> map
.withMutations(mMap
=> {
37 mMap
.set('isLoading', false);
38 mMap
.set('isPartial', isPartial
);
40 if (!next
&& !isLoadingRecent
) mMap
.set('hasMore', false);
42 if (timeline
.endsWith(':pinned')) {
43 mMap
.set('items', statuses
.map(status
=> status
.get('id')));
44 } else if (!statuses
.isEmpty()) {
45 usePendingItems
= isLoadingRecent
&& (usePendingItems
|| !mMap
.get('pendingItems').isEmpty());
47 mMap
.update(usePendingItems
? 'pendingItems' : 'items', ImmutableList(), oldIds
=> {
48 const newIds
= statuses
.map(status
=> status
.get('id'));
50 const lastIndex
= oldIds
.findLastIndex(id
=> id
!== null && compareId(id
, newIds
.last()) >= 0) + 1;
51 const firstIndex
= oldIds
.take(lastIndex
).findLastIndex(id
=> id
!== null && compareId(id
, newIds
.first()) > 0);
54 return (isPartial
? newIds
.unshift(null) : newIds
).concat(oldIds
.skip(lastIndex
));
57 return oldIds
.take(firstIndex
+ 1).concat(
58 isPartial
&& oldIds
.get(firstIndex
) !== null ? newIds
.unshift(null) : newIds
,
59 oldIds
.skip(lastIndex
)
66 const updateTimeline
= (state
, timeline
, status
, usePendingItems
) => {
67 const top
= state
.getIn([timeline
, 'top']);
69 if (usePendingItems
|| !state
.getIn([timeline
, 'pendingItems']).isEmpty()) {
70 if (state
.getIn([timeline
, 'pendingItems'], ImmutableList()).includes(status
.get('id')) || state
.getIn([timeline
, 'items'], ImmutableList()).includes(status
.get('id'))) {
74 return state
.update(timeline
, initialTimeline
, map
=> map
.update('pendingItems', list
=> list
.unshift(status
.get('id'))).update('unread', unread
=> unread
+ 1));
77 const ids
= state
.getIn([timeline
, 'items'], ImmutableList());
78 const includesId
= ids
.includes(status
.get('id'));
79 const unread
= state
.getIn([timeline
, 'unread'], 0);
87 return state
.update(timeline
, initialTimeline
, map
=> map
.withMutations(mMap
=> {
88 if (!top
) mMap
.set('unread', unread
+ 1);
89 if (top
&& ids
.size
> 40) newIds
= newIds
.take(20);
90 mMap
.set('items', newIds
.unshift(status
.get('id')));
94 const deleteStatus
= (state
, id
, accountId
, references
, exclude_account
= null) => {
95 state
.keySeq().forEach(timeline
=> {
96 if (exclude_account
=== null || (timeline
!== `account:${exclude_account}` && !timeline
.startsWith(`account:${exclude_account}:`))) {
97 const helper
= list
=> list
.filterNot(item
=> item
=== id
);
98 state
= state
.updateIn([timeline
, 'items'], helper
).updateIn([timeline
, 'pendingItems'], helper
);
102 // Remove reblogs of deleted status
103 references
.forEach(ref
=> {
104 state
= deleteStatus(state
, ref
[0], ref
[1], [], exclude_account
);
110 const clearTimeline
= (state
, timeline
) => {
111 return state
.set(timeline
, initialTimeline
);
114 const filterTimelines
= (state
, relationship
, statuses
) => {
117 statuses
.forEach(status
=> {
118 if (status
.get('account') !== relationship
.id
) {
122 references
= statuses
.filter(item
=> item
.get('reblog') === status
.get('id')).map(item
=> [item
.get('id'), item
.get('account')]);
123 state
= deleteStatus(state
, status
.get('id'), status
.get('account'), references
, relationship
.id
);
129 const filterTimeline
= (timeline
, state
, relationship
, statuses
) => {
130 const helper
= list
=> list
.filterNot(statusId
=> statuses
.getIn([statusId
, 'account']) === relationship
.id
);
131 return state
.updateIn([timeline
, 'items'], ImmutableList(), helper
).updateIn([timeline
, 'pendingItems'], ImmutableList(), helper
);
134 const updateTop
= (state
, timeline
, top
) => {
135 return state
.update(timeline
, initialTimeline
, map
=> map
.withMutations(mMap
=> {
136 if (top
) mMap
.set('unread', mMap
.get('pendingItems').size
);
137 mMap
.set('top', top
);
141 export default function timelines(state
= initialState
, action
) {
142 switch(action
.type
) {
143 case TIMELINE_LOAD_PENDING:
144 return state
.update(action
.timeline
, initialTimeline
, map
=>
145 map
.update('items', list
=> map
.get('pendingItems').concat(list
.take(40))).set('pendingItems', ImmutableList()).set('unread', 0));
146 case TIMELINE_EXPAND_REQUEST:
147 return state
.update(action
.timeline
, initialTimeline
, map
=> map
.set('isLoading', true));
148 case TIMELINE_EXPAND_FAIL:
149 return state
.update(action
.timeline
, initialTimeline
, map
=> map
.set('isLoading', false));
150 case TIMELINE_EXPAND_SUCCESS:
151 return expandNormalizedTimeline(state
, action
.timeline
, fromJS(action
.statuses
), action
.next
, action
.partial
, action
.isLoadingRecent
, action
.usePendingItems
);
152 case TIMELINE_UPDATE:
153 return updateTimeline(state
, action
.timeline
, fromJS(action
.status
), action
.usePendingItems
);
154 case TIMELINE_DELETE:
155 return deleteStatus(state
, action
.id
, action
.accountId
, action
.references
, action
.reblogOf
);
157 return clearTimeline(state
, action
.timeline
);
158 case ACCOUNT_BLOCK_SUCCESS:
159 case ACCOUNT_MUTE_SUCCESS:
160 return filterTimelines(state
, action
.relationship
, action
.statuses
);
161 case ACCOUNT_UNFOLLOW_SUCCESS:
162 return filterTimeline('home', state
, action
.relationship
, action
.statuses
);
163 case TIMELINE_SCROLL_TOP:
164 return updateTop(state
, action
.timeline
, action
.top
);
165 case TIMELINE_CONNECT:
166 return state
.update(action
.timeline
, initialTimeline
, map
=> map
.set('online', true));
167 case TIMELINE_DISCONNECT:
171 map
=> map
.set('online', false).update(action
.usePendingItems
? 'pendingItems' : 'items', items
=> items
.first() ? items
.unshift(null) : items
)
173 case CURRENTLY_VIEWING:
174 return state
.update(action
.timeline
, initialTimeline
, map
=> map
.set('currentlyViewing', action
.id
));
This page took 0.107216 seconds and 4 git commands to generate.