Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change color of tray icon when there are unread notifications #156

Merged
merged 4 commits into from
Jul 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions packages/components/src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { ColumnWidthProvider } from './context/ColumnWidthContext'
import { DeepLinkProvider } from './context/DeepLinkContext'
import { AppLayoutProvider } from './context/LayoutContext'
import { SpringAnimatedThemeProvider } from './context/SpringAnimatedThemeContext'
import { UnreadCountProvider } from './context/UnreadCountContext'

enableNetworkInterceptors()

Expand All @@ -34,10 +35,12 @@ export function App() {
<ColumnFiltersProvider>
<ColumnWidthProvider>
<SpringAnimatedThemeProvider>
<>
<AppGlobalStyles key="app-global-styles" />
<AppNavigator key="app-navigator" />
</>
<UnreadCountProvider>
<>
<AppGlobalStyles key="app-global-styles" />
<AppNavigator key="app-navigator" />
</>
</UnreadCountProvider>
</SpringAnimatedThemeProvider>
</ColumnWidthProvider>
</ColumnFiltersProvider>
Expand Down
14 changes: 14 additions & 0 deletions packages/components/src/components/common/AppIconBadge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react'

import { Platform } from '../../libs/platform'
import { useUnreadCount } from '../context/UnreadCountContext'

interface IProps {}

export const AppIconBadge = React.memo((_props: IProps) => {
if (Platform.isElectron) {
const unreadCount = useUnreadCount()
window.ipc.send('unread-counter', unreadCount)
}
return null
})
72 changes: 72 additions & 0 deletions packages/components/src/components/context/UnreadCountContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React, { useContext } from 'react'

import {
EnhancedItem,
getFilteredItems,
getItemsFilterMetadata,
} from '@devhub/core'
import { useColumnData } from '../../hooks/use-column-data'
import { useReduxState } from '../../hooks/use-redux-state'
import * as selectors from '../../redux/selectors'

export interface UnreadCountProviderProps {
children?: React.ReactNode
}

export type UnreadCountProviderState = number

export const UnreadCountContext = React.createContext<UnreadCountProviderState>(
0,
)
UnreadCountContext.displayName = 'UnreadCountContext'

export function UnreadCountProvider(props: UnreadCountProviderProps) {
const columns = useReduxState(selectors.columnsArrSelector)

// TODO: Fix memoization
const subscriptionsDataSelector = selectors.createSubscriptionsDataSelector()

const totalUnreadCount = columns.reduce((acc, column) => {
const getFilteredItemsOptions: Parameters<typeof getFilteredItems>[3] = {
mergeSimilar: false,
}

const allItems: EnhancedItem[] = useReduxState(state =>
subscriptionsDataSelector(state, column.subscriptionIds),
)

const filteredItemsMetadata = getItemsFilterMetadata(
column.type,
getFilteredItems(
column.type,
allItems,
column.filters,
getFilteredItemsOptions,
),
)

const inbox =
column.type === 'notifications' &&
column.filters &&
column.filters.notifications &&
column.filters.notifications.participating
? 'participating'
: 'all'

const columnUnreadCount = filteredItemsMetadata.inbox[inbox].unread
return acc + columnUnreadCount
}, 0)

return (
<UnreadCountContext.Provider value={totalUnreadCount}>
{props.children}
</UnreadCountContext.Provider>
)
}

export const UnreadCountConsumer = UnreadCountContext.Consumer
;(UnreadCountConsumer as any).displayName = 'UnreadCountConsumer'

export function useUnreadCount() {
return useContext(UnreadCountContext)
}
5 changes: 2 additions & 3 deletions packages/components/src/components/layout/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ const SidebarColumnItem = React.memo(
getFilteredItems(
column.type,
allItems,
{ ...column.filters, unread: undefined },
column.filters,
getFilteredItemsOptions,
),
)
Expand All @@ -631,8 +631,7 @@ const SidebarColumnItem = React.memo(
? 'participating'
: 'all'

const isUnread =
filteredItemsMetadata.inbox[inbox].unread > 0 ? true : false
const isUnread = filteredItemsMetadata.inbox[inbox].unread > 0

const label = `${headerDetails.title ||
headerDetails.subtitle ||
Expand Down
2 changes: 2 additions & 0 deletions packages/components/src/screens/MainScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import url from 'url'
import { AppBannerMessage } from '../components/banners/AppBannerMessage'
import { ColumnSeparator } from '../components/columns/ColumnSeparator'
import { ColumnsRenderer } from '../components/columns/ColumnsRenderer'
import { AppIconBadge } from '../components/common/AppIconBadge'
import { ConditionalWrap } from '../components/common/ConditionalWrap'
import { Screen } from '../components/common/Screen'
import { Separator } from '../components/common/Separator'
Expand Down Expand Up @@ -362,6 +363,7 @@ export const MainScreen = React.memo(() => {
return (
<Screen statusBarBackgroundThemeColor="header" useSafeArea={false}>
<AppBannerMessage />
<AppIconBadge />

<View
style={[
Expand Down
Binary file added packages/desktop/assets/icons/trayIconActive.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/desktop/assets/icons/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/desktop/assets/icons/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions packages/desktop/src/ipc.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { app, ipcMain } from 'electron'

import * as constants from './constants'
import * as tray from './tray'
import * as window from './window'

export function register() {
Expand Down Expand Up @@ -46,4 +47,8 @@ export function register() {
if (!mainWindow) return
mainWindow.setFullScreen(false)
})

ipcMain.on('unread-counter', (_e: any, unreadCount: any) => {
tray.updateIconState(unreadCount)
})
}
31 changes: 23 additions & 8 deletions packages/desktop/src/tray.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,28 @@ import * as helpers from './helpers'
import * as menu from './menu'
import * as window from './window'

const inactiveIcon = path.join(
__dirname,
`../assets/icons/${
process.platform === 'darwin' ? 'trayIconTemplate' : 'trayIconWhite'
}.png`,
)

const activeIcon = path.join(
__dirname,
`../assets/icons/${
process.platform === 'darwin' ? 'trayIconActive' : 'trayIconWhite'
}.png`,
)

let tray: Tray | null = null

export function getTray() {
return tray
}

export function createTray() {
const trayIcon = nativeImage.createFromPath(
path.join(
__dirname,
`../assets/icons/${
process.platform === 'darwin' ? 'trayIconTemplate' : 'trayIconWhite'
}.png`,
),
)
const trayIcon = nativeImage.createFromPath(activeIcon)

if (tray && !tray.isDestroyed()) tray.destroy()

Expand Down Expand Up @@ -121,3 +128,11 @@ export function alignWindowWithTray(win: BrowserWindow) {

win.setPosition(fixedX, fixedY)
}

export function updateIconState(unreadCount: number) {
if (unreadCount > 0) {
tray!.setImage(activeIcon)
} else {
tray!.setImage(inactiveIcon)
}
}