• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

gitify-app / gitify / 9319904199

31 May 2024 02:38PM UTC coverage: 96.355% (-0.4%) from 96.787%
9319904199

Pull #1139

github

web-flow
Merge af6de505a into 72b432272
Pull Request #1139: feat(accounts): enhance auth account data structure

402 of 415 branches covered (96.87%)

Branch coverage included in aggregate %.

79 of 89 new or added lines in 12 files covered. (88.76%)

3 existing lines in 2 files now uncovered.

1052 of 1094 relevant lines covered (96.16%)

20.24 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.0
/src/hooks/useNotifications.ts
1
import { useCallback, useState } from 'react';
24✔
2
import type {
3
  AccountNotifications,
4
  AuthState,
5
  GitifyError,
6
  SettingsState,
7
  Status,
8
} from '../types';
9
import {
24✔
10
  ignoreNotificationThreadSubscription,
11
  markNotificationThreadAsDone,
12
  markNotificationThreadAsRead,
13
  markRepositoryNotificationsAsRead,
14
} from '../utils/api/client';
15
import { determineFailureType } from '../utils/api/errors';
24✔
16
import { getAccountForHost } from '../utils/helpers';
24✔
17
import {
24✔
18
  getAllNotifications,
19
  setTrayIconColor,
20
  triggerNativeNotifications,
21
} from '../utils/notifications';
22
import { removeNotification } from '../utils/remove-notification';
24✔
23
import { removeNotifications } from '../utils/remove-notifications';
24✔
24

25
interface NotificationsState {
26
  notifications: AccountNotifications[];
27
  removeNotificationFromState: (
28
    settings: SettingsState,
29
    id: string,
30
    hostname: string,
31
  ) => void;
32
  fetchNotifications: (
33
    auth: AuthState,
34
    settings: SettingsState,
35
  ) => Promise<void>;
36
  markNotificationRead: (
37
    auth: AuthState,
38
    settings: SettingsState,
39
    id: string,
40
    hostname: string,
41
  ) => Promise<void>;
42
  markNotificationDone: (
43
    auth: AuthState,
44
    settings: SettingsState,
45
    id: string,
46
    hostname: string,
47
  ) => Promise<void>;
48
  unsubscribeNotification: (
49
    auth: AuthState,
50
    settings: SettingsState,
51
    id: string,
52
    hostname: string,
53
  ) => Promise<void>;
54
  markRepoNotifications: (
55
    auth: AuthState,
56
    settings: SettingsState,
57
    repoSlug: string,
58
    hostname: string,
59
  ) => Promise<void>;
60
  markRepoNotificationsDone: (
61
    auth: AuthState,
62
    settings: SettingsState,
63
    repoSlug: string,
64
    hostname: string,
65
  ) => Promise<void>;
66
  status: Status;
67
  errorDetails: GitifyError;
68
}
69

70
export const useNotifications = (): NotificationsState => {
24✔
71
  const [status, setStatus] = useState<Status>('success');
142✔
72
  const [errorDetails, setErrorDetails] = useState<GitifyError>();
142✔
73

74
  const [notifications, setNotifications] = useState<AccountNotifications[]>(
142✔
75
    [],
76
  );
77

78
  const fetchNotifications = useCallback(
142✔
79
    async (auth: AuthState, settings: SettingsState) => {
80
      setStatus('loading');
8✔
81

82
      try {
8✔
83
        const fetchedNotifications = await getAllNotifications(auth, settings);
8✔
84

85
        setNotifications(fetchedNotifications);
6✔
86
        triggerNativeNotifications(
6✔
87
          notifications,
88
          fetchedNotifications,
89
          settings,
90
          auth,
91
        );
92
        setStatus('success');
6✔
93
      } catch (err) {
94
        setStatus('error');
2✔
95
        setErrorDetails(determineFailureType(err));
2✔
96
      }
97
    },
98
    [notifications],
99
  );
100

101
  const markNotificationRead = useCallback(
142✔
102
    async (
103
      auth: AuthState,
104
      settings: SettingsState,
105
      id: string,
106
      hostname: string,
107
    ) => {
108
      setStatus('loading');
12✔
109

110
      const account = getAccountForHost(hostname, auth);
12✔
111

112
      try {
12✔
113
        await markNotificationThreadAsRead(id, hostname, account.token);
12✔
114

115
        const updatedNotifications = removeNotification(
8✔
116
          settings,
117
          id,
118
          notifications,
119
          hostname,
120
        );
121

122
        setNotifications(updatedNotifications);
8✔
123
        setTrayIconColor(updatedNotifications);
8✔
124
        setStatus('success');
8✔
125
      } catch (err) {
126
        setStatus('success');
4✔
127
      }
128
    },
129
    [notifications],
130
  );
131

132
  const markNotificationDone = useCallback(
142✔
133
    async (
134
      auth: AuthState,
135
      settings: SettingsState,
136
      id: string,
137
      hostname: string,
138
    ) => {
139
      setStatus('loading');
8✔
140

141
      const account = getAccountForHost(hostname, auth);
8✔
142

143
      try {
8✔
144
        await markNotificationThreadAsDone(id, hostname, account.token);
8✔
145

146
        const updatedNotifications = removeNotification(
4✔
147
          settings,
148
          id,
149
          notifications,
150
          hostname,
151
        );
152

153
        setNotifications(updatedNotifications);
4✔
154
        setTrayIconColor(updatedNotifications);
4✔
155
        setStatus('success');
4✔
156
      } catch (err) {
157
        setStatus('success');
4✔
158
      }
159
    },
160
    [notifications],
161
  );
162

163
  const unsubscribeNotification = useCallback(
142✔
164
    async (
165
      auth: AuthState,
166
      settings: SettingsState,
167
      id: string,
168
      hostname: string,
169
    ) => {
170
      setStatus('loading');
8✔
171

172
      const account = getAccountForHost(hostname, auth);
8✔
173

174
      try {
8✔
175
        await ignoreNotificationThreadSubscription(id, hostname, account.token);
8✔
176
        await markNotificationRead(auth, settings, id, hostname);
4✔
177
        setStatus('success');
4✔
178
      } catch (err) {
179
        setStatus('success');
4✔
180
      }
181
    },
182
    [notifications],
183
  );
184

185
  const markRepoNotifications = useCallback(
142✔
186
    async (
187
      auth: AuthState,
188
      settings: SettingsState,
189
      repoSlug: string,
190
      hostname: string,
191
    ) => {
192
      setStatus('loading');
8✔
193

194
      const account = getAccountForHost(hostname, auth);
8✔
195

196
      try {
8✔
197
        await markRepositoryNotificationsAsRead(
8✔
198
          repoSlug,
199
          hostname,
200
          account.token,
201
        );
202
        const updatedNotifications = removeNotifications(
4✔
203
          repoSlug,
204
          notifications,
205
          hostname,
206
        );
207

208
        setNotifications(updatedNotifications);
4✔
209
        setTrayIconColor(updatedNotifications);
4✔
210
        setStatus('success');
4✔
211
      } catch (err) {
212
        setStatus('success');
4✔
213
      }
214
    },
215
    [notifications],
216
  );
217

218
  const markRepoNotificationsDone = useCallback(
142✔
219
    async (
220
      auth: AuthState,
221
      settings: SettingsState,
222
      repoSlug: string,
223
      hostname: string,
224
    ) => {
225
      setStatus('loading');
8✔
226

227
      try {
8✔
228
        const accountIndex = notifications.findIndex(
8✔
229
          (accountNotifications) =>
NEW
230
            accountNotifications.account.hostname === hostname,
×
231
        );
232

233
        if (accountIndex !== -1) {
8!
234
          const notificationsToRemove = notifications[
×
235
            accountIndex
236
          ].notifications.filter(
237
            (notification) => notification.repository.full_name === repoSlug,
×
238
          );
239

240
          await Promise.all(
×
241
            notificationsToRemove.map((notification) =>
242
              markNotificationDone(
×
243
                auth,
244
                settings,
245
                notification.id,
246
                notifications[accountIndex].account.hostname,
247
              ),
248
            ),
249
          );
250
        }
251

252
        const updatedNotifications = removeNotifications(
8✔
253
          repoSlug,
254
          notifications,
255
          hostname,
256
        );
257

258
        setNotifications(updatedNotifications);
8✔
259
        setTrayIconColor(updatedNotifications);
8✔
260
        setStatus('success');
8✔
261
      } catch (err) {
262
        setStatus('success');
×
263
      }
264
    },
265
    [notifications],
266
  );
267

268
  const removeNotificationFromState = useCallback(
142✔
269
    (settings: SettingsState, id: string, hostname: string) => {
270
      const updatedNotifications = removeNotification(
2✔
271
        settings,
272
        id,
273
        notifications,
274
        hostname,
275
      );
276

277
      setNotifications(updatedNotifications);
2✔
278
      setTrayIconColor(updatedNotifications);
2✔
279
    },
280
    [notifications],
281
  );
282

283
  return {
142✔
284
    status,
285
    errorDetails,
286
    notifications,
287

288
    removeNotificationFromState,
289
    fetchNotifications,
290
    markNotificationRead,
291
    markNotificationDone,
292
    unsubscribeNotification,
293
    markRepoNotifications,
294
    markRepoNotificationsDone,
295
  };
296
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc