diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f0148021b..b5f4acf205 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### Added + - Add an unread badge if there are unread notifs from other accounts + ### Changed ### Fixed diff --git a/scss/_sidebar.scss b/scss/_sidebar.scss index 4b8d623ba1..414a3f97fb 100644 --- a/scss/_sidebar.scss +++ b/scss/_sidebar.scss @@ -165,3 +165,49 @@ -webkit-transform: translateX(-100%); } } + +.unread-badge { + border-radius: 50%; + position: relative; + background-color: var(--unreadBadgeColor1); + animation-duration: 1.5s; + animation-iteration-count: infinite; + animation-direction: alternate; +} + +@keyframes unread-badge-big-anim { + from { + background-color: var(--unreadBadgeColor1); + color: white; + } + to { + background-color: white; + color: var(--unreadBadgeColor1); + } +} +div.unread-badge-big { + @extend .unread-badge; + width: 24px; + height: 24px; + color: white; + display: flex; + justify-content: center; + align-items: center; + animation-name: unread-badge-big-anim; + animation-timing-function: ease-in; +} + +@keyframes unread-badge-small-anim { + from { + background-color: var(--unreadBadgeColor1); + } + to { + background-color: var(--unreadBadgeColor2); + } +} +div.unread-badge-small { + @extend .unread-badge; + width: 14px; + height: 14px; + animation-name: unread-badge-small-anim; +} diff --git a/src/renderer/components/OtherAccountsUnreadBadge.tsx b/src/renderer/components/OtherAccountsUnreadBadge.tsx new file mode 100644 index 0000000000..2540ac462f --- /dev/null +++ b/src/renderer/components/OtherAccountsUnreadBadge.tsx @@ -0,0 +1,71 @@ +import React, { useEffect, useState } from 'react' +import { BackendRemote, onDCEvent } from '../backend-com' +import { selectedAccountId } from '../ScreenController' +import { useSettingsStore } from '../stores/settings' + +// Tip of the Day: Keep as many ice creams as you can in your fridge +// for the ice cream outage days. FREE ICE CREAM FOR EVERY1! --Farooq + +type ComponentProps = { + style: any + big?: boolean +} + +export default function OtherAccountsUnreadBadge({ + style, + big, +}: ComponentProps) { + const [ + otherAccountsUnreadCount, + setOtherAccountsUnreadCount, + ] = useState(0) + + const settings = useSettingsStore()[0] + + useEffect(() => { + if (settings === null) return + if (settings.desktopSettings.syncAllAccounts === false) return + let updating = false + const update = () => { + if (updating) return + updating = true + BackendRemote.rpc.getAllAccountIds().then(accountIds => { + try { + selectedAccountId() + } catch { + return + } + accountIds = accountIds.filter(id => id !== selectedAccountId()) + for (const accountId of accountIds) { + BackendRemote.rpc.getFreshMsgs(accountId).then(ids => { + setOtherAccountsUnreadCount(otherAccountsUnreadCount + ids.length) + }) + } + }) + updating = false + } + + BackendRemote.rpc + .getAllAccountIds() + .then(accountIds => + accountIds.map(id => onDCEvent(id, 'IncomingMsg', update)) + ) + + update() + return update + }, [settings?.desktopSettings.syncAllAccounts]) + + if (settings?.desktopSettings.syncAllAccounts && otherAccountsUnreadCount) { + if (big) { + return ( +
+ {otherAccountsUnreadCount} +
+ ) + } else { + return
+ } + } else { + return null + } +} diff --git a/src/renderer/components/Sidebar.tsx b/src/renderer/components/Sidebar.tsx index b50aef1513..a9d702be21 100644 --- a/src/renderer/components/Sidebar.tsx +++ b/src/renderer/components/Sidebar.tsx @@ -18,6 +18,7 @@ import { EffectfulBackendActions, onDCEvent, } from '../backend-com' +import OtherAccountsUnreadBadge from './OtherAccountsUnreadBadge' export type SidebarState = 'init' | 'visible' | 'invisible' @@ -180,6 +181,10 @@ const Sidebar = React.memo(
{tx('switch_account')} +
diff --git a/src/renderer/components/screens/MainScreen.tsx b/src/renderer/components/screens/MainScreen.tsx index c1f560ae08..711debb6bc 100644 --- a/src/renderer/components/screens/MainScreen.tsx +++ b/src/renderer/components/screens/MainScreen.tsx @@ -42,6 +42,7 @@ import SettingsStoreInstance, { useSettingsStore } from '../../stores/settings' import { Type } from '../../backend-com' import { InlineVerifiedIcon } from '../VerifiedIcon' import { SettingsProfileDialog } from '../dialogs/Settings-Profile' +import OtherAccountsUnreadBadge from '../OtherAccountsUnreadBadge' const log = getLogger('renderer/main-screen') @@ -49,7 +50,8 @@ export default function MainScreen() { const [queryStr, setQueryStr] = useState('') const [queryChatId, setQueryChatId] = useState(null) const [sidebarState, setSidebarState] = useState('init') - const [showArchivedChats, setShowArchivedChats] = useState(false) + const [showArchivedChats, setShowArchivedChats] = useState(false) + // Small hack/misuse of keyBindingAction to setShowArchivedChats from other components (especially // ViewProfile when selecting a shared chat/group) useKeyBindingAction(KeybindAction.ChatList_SwitchToArchiveView, () => @@ -202,6 +204,9 @@ export default function MainScreen() { id='hamburger-menu-button' > +
{queryStr.length === 0 && showArchivedChats && ( <> diff --git a/themes/_themebase.scss b/themes/_themebase.scss index 4fb81f23b1..474c9694d0 100644 --- a/themes/_themebase.scss +++ b/themes/_themebase.scss @@ -21,6 +21,9 @@ $hover-contrast-change: 2%; --ovalButtonBgHover: #{changeContrast($ovalButtonBg, 70%)}; --ovalButtonText: #{$ovalButtonText}; --ovalButtonTextHover: #{desaturate(invert($ovalButtonText), 1)}; + /* UnreadBadge */ + --unreadBadgeColor1: #{$colorPrimary}; + --unreadBadgeColor2: mix(#{$colorPrimary}, transparent, 20%); /* NavBar */ --navBarBackground: #{$bgNavBar}; --navBarText: #{$textNavBar};