1import * as Container from '../util/container'
2import * as NotificationsGen from '../actions/notifications-gen'
3import * as Tabs from '../constants/tabs'
4import * as Types from '../constants/types/notifications'
5import isEqual from 'lodash/isEqual'
6
7const initialState: Types.State = {
8  badgeVersion: -1,
9  desktopAppBadgeCount: 0,
10  keyState: new Map(),
11  mobileAppBadgeCount: 0,
12  navBadges: new Map(),
13  widgetBadge: 'regular',
14}
15
16const updateWidgetBadge = (draftState: Container.Draft<Types.State>) => {
17  let widgetBadge: Types.BadgeType = 'regular'
18  const {keyState} = draftState
19  if (keyState.get('outOfSpace')) {
20    widgetBadge = 'error'
21  } else if (keyState.get('kbfsUploading')) {
22    widgetBadge = 'uploading'
23  }
24  if (widgetBadge !== draftState.widgetBadge) {
25    draftState.widgetBadge = widgetBadge
26  }
27}
28
29export default Container.makeReducer<NotificationsGen.Actions, Types.State>(initialState, {
30  [NotificationsGen.resetStore]: () => initialState,
31  [NotificationsGen.setBadgeCounts]: (draftState, action) => {
32    const {counts} = action.payload
33    const chatCount = counts.get(Tabs.chatTab)
34    if (chatCount) {
35      draftState.mobileAppBadgeCount = chatCount
36    }
37
38    // desktopAppBadgeCount is the sum of badge counts on all tabs. What
39    // happens here is for each tab we deduct the old count from the
40    // current desktopAppBadgeCount, then add the new count into it.
41    //
42    // For example, assume following existing state:
43    // 1) the overall app badge has 12, i.e. state.desktopAppBadgeCount === 12;
44    // 2) and the FS tab count is 4, i.e. state.navBadges.get(Tabs.fsTab) === 4;
45    // Now we receive `{count: {[Tabs.fsTab]: 7}}` indicating that the
46    // new FS tab badge count should become 7. So we deduct 4 from 12 and
47    // add 7, and we'd get 15.
48    //
49    // This way the app badge count is always consistent with the badged
50    // tabs.
51    draftState.desktopAppBadgeCount = [...counts.entries()].reduce<number>(
52      (count, [k, v]) => count - (draftState.navBadges.get(k) || 0) + v,
53      draftState.desktopAppBadgeCount
54    )
55
56    const navBadges = new Map([...draftState.navBadges, ...counts])
57    if (!isEqual(navBadges, draftState.navBadges)) {
58      draftState.navBadges = navBadges
59    }
60    updateWidgetBadge(draftState)
61  },
62  [NotificationsGen.badgeApp]: (draftState, action) => {
63    const {key, on} = action.payload
64    const {keyState} = draftState
65    keyState.set(key, on)
66    updateWidgetBadge(draftState)
67  },
68})
69