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

gitify-app / gitify / 12857535352

19 Jan 2025 10:02PM UTC coverage: 86.917%. Remained the same
12857535352

Pull #1734

github

web-flow
Merge dff1c6f88 into 55004bfdc
Pull Request #1734: feat: download progress precision

594 of 659 branches covered (90.14%)

Branch coverage included in aggregate %.

1585 of 1848 relevant lines covered (85.77%)

24.48 hits per line

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

85.37
/src/renderer/hooks/useNotifications.ts
1
import { useCallback, useState } from 'react';
70✔
2

3
import { logError } from '../../shared/logger';
70✔
4
import type {
5
  Account,
6
  AccountNotifications,
7
  GitifyError,
8
  GitifyState,
9
  Status,
10
} from '../types';
11
import type { Notification } from '../typesGitHub';
12
import {
70✔
13
  ignoreNotificationThreadSubscription,
14
  markNotificationThreadAsDone,
15
  markNotificationThreadAsRead,
16
} from '../utils/api/client';
17
import { isMarkAsDoneFeatureSupported } from '../utils/features';
70✔
18
import {
70✔
19
  getAllNotifications,
20
  setTrayIconColor,
21
  triggerNativeNotifications,
22
} from '../utils/notifications';
23
import { removeNotifications } from '../utils/notifications/remove';
70✔
24

25
interface NotificationsState {
26
  notifications: AccountNotifications[];
27
  removeAccountNotifications: (account: Account) => Promise<void>;
28
  fetchNotifications: (state: GitifyState) => Promise<void>;
29
  markNotificationsAsRead: (
30
    state: GitifyState,
31
    notifications: Notification[],
32
  ) => Promise<void>;
33
  markNotificationsAsDone: (
34
    state: GitifyState,
35
    notifications: Notification[],
36
  ) => Promise<void>;
37
  unsubscribeNotification: (
38
    state: GitifyState,
39
    notification: Notification,
40
  ) => Promise<void>;
41
  status: Status;
42
  globalError: GitifyError;
43
}
44

45
export const useNotifications = (): NotificationsState => {
70✔
46
  const [status, setStatus] = useState<Status>('success');
66✔
47
  const [globalError, setGlobalError] = useState<GitifyError>();
66✔
48

49
  const [notifications, setNotifications] = useState<AccountNotifications[]>(
66✔
50
    [],
51
  );
52

53
  const removeAccountNotifications = useCallback(
66✔
54
    async (account: Account) => {
55
      setStatus('loading');
×
56

57
      const updatedNotifications = notifications.filter(
×
58
        (notification) => notification.account !== account,
×
59
      );
60

61
      setNotifications(updatedNotifications);
×
62
      setTrayIconColor(updatedNotifications);
×
63
      setStatus('success');
×
64
    },
65
    [notifications],
66
  );
67

68
  const fetchNotifications = useCallback(
66✔
69
    async (state: GitifyState) => {
70
      setStatus('loading');
8✔
71
      setGlobalError(null);
8✔
72

73
      const fetchedNotifications = await getAllNotifications(state);
8✔
74

75
      // Set Global Error if all accounts have the same error
76
      if (fetchNotifications.length > 0) {
8✔
77
        const allAccountsHaveErrors = fetchedNotifications.every((account) => {
8✔
78
          return account.error !== null;
12✔
79
        });
80

81
        let accountErrorsAreAllSame = true;
8✔
82
        const accountError = fetchedNotifications[0]?.error;
8✔
83

84
        for (const fetchedNotification of fetchedNotifications) {
8✔
85
          if (accountError !== fetchedNotification.error) {
14✔
86
            accountErrorsAreAllSame = false;
2✔
87
            break;
2✔
88
          }
89
        }
90

91
        if (allAccountsHaveErrors) {
8✔
92
          setStatus('error');
4✔
93
          setGlobalError(accountErrorsAreAllSame ? accountError : null);
4✔
94
          return;
4✔
95
        }
96
      }
97

98
      setNotifications(fetchedNotifications);
4✔
99
      triggerNativeNotifications(notifications, fetchedNotifications, state);
4✔
100
      setStatus('success');
4✔
101
    },
102
    [notifications],
103
  );
104

105
  const markNotificationsAsRead = useCallback(
66✔
106
    async (state: GitifyState, readNotifications: Notification[]) => {
107
      setStatus('loading');
4✔
108

109
      try {
4✔
110
        await Promise.all(
4✔
111
          readNotifications.map((notification) =>
112
            markNotificationThreadAsRead(
4✔
113
              notification.id,
114
              notification.account.hostname,
115
              notification.account.token,
116
            ),
117
          ),
118
        );
119

120
        const updatedNotifications = removeNotifications(
2✔
121
          state.settings,
122
          readNotifications,
123
          notifications,
124
        );
125

126
        setNotifications(updatedNotifications);
2✔
127
        setTrayIconColor(updatedNotifications);
2✔
128
      } catch (err) {
129
        logError(
2✔
130
          'markNotificationsAsRead',
131
          'Error occurred while marking notifications as read',
132
          err,
133
        );
134
      }
135

136
      setStatus('success');
4✔
137
    },
138
    [notifications],
139
  );
140

141
  const markNotificationsAsDone = useCallback(
66✔
142
    async (state: GitifyState, doneNotifications: Notification[]) => {
143
      setStatus('loading');
4✔
144

145
      try {
4✔
146
        if (isMarkAsDoneFeatureSupported(doneNotifications[0].account)) {
4✔
147
          await Promise.all(
4✔
148
            doneNotifications.map((notification) =>
149
              markNotificationThreadAsDone(
4✔
150
                notification.id,
151
                notification.account.hostname,
152
                notification.account.token,
153
              ),
154
            ),
155
          );
156
        }
157

158
        const updatedNotifications = removeNotifications(
2✔
159
          state.settings,
160
          doneNotifications,
161
          notifications,
162
        );
163

164
        setNotifications(updatedNotifications);
2✔
165
        setTrayIconColor(updatedNotifications);
2✔
166
      } catch (err) {
167
        logError(
2✔
168
          'markNotificationsAsDone',
169
          'Error occurred while marking notifications as done',
170
          err,
171
        );
172
      }
173

174
      setStatus('success');
4✔
175
    },
176
    [notifications],
177
  );
178

179
  const unsubscribeNotification = useCallback(
66✔
180
    async (state: GitifyState, notification: Notification) => {
181
      setStatus('loading');
6✔
182

183
      try {
6✔
184
        await ignoreNotificationThreadSubscription(
6✔
185
          notification.id,
186
          notification.account.hostname,
187
          notification.account.token,
188
        );
189

190
        if (state.settings.markAsDoneOnUnsubscribe) {
×
191
          await markNotificationsAsDone(state, [notification]);
×
192
        } else {
193
          await markNotificationsAsRead(state, [notification]);
×
194
        }
195
      } catch (err) {
196
        logError(
6✔
197
          'unsubscribeNotification',
198
          'Error occurred while unsubscribing from notification thread',
199
          err,
200
          notification,
201
        );
202
      }
203

204
      setStatus('success');
6✔
205
    },
206
    [markNotificationsAsRead, markNotificationsAsDone],
207
  );
208

209
  return {
66✔
210
    status,
211
    globalError,
212
    notifications,
213

214
    removeAccountNotifications,
215
    fetchNotifications,
216
    markNotificationsAsRead,
217
    markNotificationsAsDone,
218
    unsubscribeNotification,
219
  };
220
};
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