this repo has no description
1import { Trans, useLingui } from '@lingui/react/macro';
2import { useMemo, useRef, useState } from 'preact/hooks';
3import { useSearchParams } from 'react-router-dom';
4
5import Link from '../components/link';
6import Timeline from '../components/timeline';
7import { api } from '../utils/api';
8import { fixNotifications } from '../utils/group-notifications';
9import { saveStatus } from '../utils/states';
10import useTitle from '../utils/useTitle';
11
12const LIMIT = 20;
13const emptySearchParams = new URLSearchParams();
14
15function Mentions({ columnMode, ...props }) {
16 const { t } = useLingui();
17 const { masto, instance } = api();
18 const [searchParams] = columnMode ? [emptySearchParams] : useSearchParams();
19 const [stateType, setStateType] = useState(null);
20 const type = props?.type || searchParams.get('type') || stateType;
21 useTitle(type === 'private' ? t`Private mentions` : t`Mentions`, '/mentions');
22
23 const mentionsIterator = useRef();
24 const latestItem = useRef();
25
26 async function fetchMentions(firstLoad) {
27 if (firstLoad || !mentionsIterator.current) {
28 mentionsIterator.current = masto.v1.notifications
29 .list({
30 limit: LIMIT,
31 types: ['mention'],
32 })
33 .values();
34 }
35 const results = await mentionsIterator.current.next();
36 let { value } = results;
37 if (value?.length) {
38 value = fixNotifications(value);
39
40 if (firstLoad) {
41 latestItem.current = value[0].id;
42 console.log('First load', latestItem.current);
43 }
44
45 value.forEach(({ status: item }) => {
46 saveStatus(item, instance);
47 });
48 }
49 return {
50 ...results,
51 value: value?.map((item) => item.status),
52 };
53 }
54
55 const conversationsIterator = useRef();
56 const latestConversationItem = useRef();
57 async function fetchConversations(firstLoad) {
58 if (firstLoad || !conversationsIterator.current) {
59 conversationsIterator.current = masto.v1.conversations
60 .list({
61 limit: LIMIT,
62 })
63 .values();
64 }
65 const results = await conversationsIterator.current.next();
66 let { value } = results;
67 value = value?.filter((item) => item.lastStatus);
68 if (value?.length) {
69 if (firstLoad) {
70 latestConversationItem.current = value[0].lastStatus.id;
71 console.log('First load', latestConversationItem.current);
72 }
73
74 value.forEach(({ lastStatus: item }) => {
75 saveStatus(item, instance);
76 });
77 }
78 console.log('results', results);
79 return {
80 ...results,
81 value: value?.map((item) => item.lastStatus),
82 };
83 }
84
85 function fetchItems(...args) {
86 if (type === 'private') {
87 return fetchConversations(...args);
88 }
89 return fetchMentions(...args);
90 }
91
92 async function checkForUpdates() {
93 if (type === 'private') {
94 try {
95 const results = await masto.v1.conversations
96 .list({
97 limit: 1,
98 since_id: latestConversationItem.current,
99 })
100 .values()
101 .next();
102 let { value } = results;
103 console.log(
104 'checkForUpdates PRIVATE',
105 latestConversationItem.current,
106 value,
107 );
108 const valueContainsLatestItem =
109 value[0]?.id === latestConversationItem.current; // since_id might not be supported
110 if (value?.length && !valueContainsLatestItem) {
111 latestConversationItem.current = value[0].lastStatus.id;
112 return true;
113 }
114 return false;
115 } catch (e) {
116 return false;
117 }
118 } else {
119 try {
120 const results = await masto.v1.notifications
121 .list({
122 limit: 1,
123 types: ['mention'],
124 since_id: latestItem.current,
125 })
126 .values()
127 .next();
128 let { value } = results;
129 console.log('checkForUpdates ALL', latestItem.current, value);
130 if (value?.length) {
131 latestItem.current = value[0].id;
132 return true;
133 }
134 return false;
135 } catch (e) {
136 return false;
137 }
138 }
139 }
140
141 const TimelineStart = useMemo(() => {
142 return (
143 <div class="filter-bar centered">
144 <Link
145 to="/mentions"
146 class={!type ? 'is-active' : ''}
147 onClick={(e) => {
148 if (columnMode) {
149 e.preventDefault();
150 setStateType(null);
151 }
152 }}
153 >
154 <Trans>All</Trans>
155 </Link>
156 <Link
157 to="/mentions?type=private"
158 class={type === 'private' ? 'is-active' : ''}
159 onClick={(e) => {
160 if (columnMode) {
161 e.preventDefault();
162 setStateType('private');
163 }
164 }}
165 >
166 <Trans>Private</Trans>
167 </Link>
168 </div>
169 );
170 }, [type]);
171
172 return (
173 <Timeline
174 title={t`Mentions`}
175 id="mentions"
176 emptyText={t`No one mentioned you :(`}
177 errorText={t`Unable to load mentions.`}
178 instance={instance}
179 fetchItems={fetchItems}
180 checkForUpdates={checkForUpdates}
181 useItemID
182 timelineStart={TimelineStart}
183 refresh={type}
184 filterContext="notifications"
185 />
186 );
187}
188
189export default Mentions;