From bac1130e4d27d18ba2f455b409dfe906364f0c9a Mon Sep 17 00:00:00 2001 From: Farooq Karimi Zadeh Date: Wed, 13 Sep 2023 08:11:06 +0330 Subject: [PATCH] show an unread badge when there are notifs from other account(s) --- CHANGELOG.md | 1 + scss/_sidebar.scss | 25 +++++++++++ src/renderer/components/Sidebar.tsx | 6 +++ src/renderer/components/UnreadBadge.tsx | 10 +++++ .../components/screens/MainScreen.tsx | 45 ++++++++++++++++++- 5 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 src/renderer/components/UnreadBadge.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d56040441..cdb8ad4fbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Added - Show video chat instance URLs as subtitles #3369 + - Add an unread badge if there are unread notifs from other accounts ### Changed - remove jitsi as a default Video Chat instance, because they added a sign-in requirement #3366 diff --git a/scss/_sidebar.scss b/scss/_sidebar.scss index 4b8d623ba1..4e1d1dfd3e 100644 --- a/scss/_sidebar.scss +++ b/scss/_sidebar.scss @@ -165,3 +165,28 @@ -webkit-transform: translateX(-100%); } } +/* + @keyframes unread-badge-bg-anim { + from { + background-color: color-mix(in srgb, var(--colorPrimary), transparent 100%); + } + to { + background-color: color-mix(in srgb, var(--colorPrimary), transparent 20%); + } + } + */ +// TODO: When Electron was upgraded, uncomment these to add animation. +// color-mix has been added in Chrome and other browsers in early 2023 +div.unread-badge { + width: 14px; + height: 14px; + border-radius: 50%; + position: relative; + background-color: var(--colorPrimary); + /* + animation-duration: 1.5s; + animation-name: unread-badge-bg-anim; + animation-iteration-count: infinite; + animation-direction: alternate; + */ +} diff --git a/src/renderer/components/Sidebar.tsx b/src/renderer/components/Sidebar.tsx index b50aef1513..c1e3268d22 100644 --- a/src/renderer/components/Sidebar.tsx +++ b/src/renderer/components/Sidebar.tsx @@ -13,6 +13,7 @@ import { VERSION } from '../../shared/build-info' import { ActionEmitter, KeybindAction } from '../keybindings' import SettingsConnectivityDialog from './dialogs/Settings-Connectivity' import { debounceWithInit } from './chat/ChatListHelpers' +import UnreadBadge from './UnreadBadge' import { BackendRemote, EffectfulBackendActions, @@ -25,9 +26,11 @@ const Sidebar = React.memo( ({ sidebarState, setSidebarState, + haveOtherAccountsUnread, }: { sidebarState: SidebarState setSidebarState: React.Dispatch> + haveOtherAccountsUnread: boolean }) => { const screenContext = useContext(ScreenContext) const settings = useSettingsStore()[0] @@ -180,6 +183,9 @@ const Sidebar = React.memo(
{tx('switch_account')} + {haveOtherAccountsUnread && ( + + )}
diff --git a/src/renderer/components/UnreadBadge.tsx b/src/renderer/components/UnreadBadge.tsx new file mode 100644 index 0000000000..6d86ea31b0 --- /dev/null +++ b/src/renderer/components/UnreadBadge.tsx @@ -0,0 +1,10 @@ +import React from 'react' + +type UnreadBadgeProps = { + top: string + left: string +} + +export default function UnreadBadge(props: UnreadBadgeProps) { + return
+} diff --git a/src/renderer/components/screens/MainScreen.tsx b/src/renderer/components/screens/MainScreen.tsx index c1f560ae08..71027a1543 100644 --- a/src/renderer/components/screens/MainScreen.tsx +++ b/src/renderer/components/screens/MainScreen.tsx @@ -19,6 +19,8 @@ import { selectChat, setChatView, } from '../helpers/ChatMethods' +import { BackendRemote, onDCEvent } from '../../backend-com' +import { selectedAccountId } from '../../ScreenController' import { Alignment, @@ -42,6 +44,7 @@ import SettingsStoreInstance, { useSettingsStore } from '../../stores/settings' import { Type } from '../../backend-com' import { InlineVerifiedIcon } from '../VerifiedIcon' import { SettingsProfileDialog } from '../dialogs/Settings-Profile' +import UnreadBadge from '../UnreadBadge' const log = getLogger('renderer/main-screen') @@ -49,7 +52,38 @@ 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) + const [ + haveOtherAccountsUnread, + setHaveOtherAccountsUnread, + ] = useState(false) + + useEffect(() => { + let updating = false + const update = () => { + if (updating) return + updating = true + BackendRemote.rpc.getAllAccountIds().then(accountIds => { + accountIds = accountIds.filter(id => id !== selectedAccountId()) + for (const accountId of accountIds) { + BackendRemote.rpc.getFreshMsgs(accountId).then(ids => { + if (ids.length > 0) setHaveOtherAccountsUnread(true) + }) + } + }) + updating = false + } + update() + + BackendRemote.rpc + .getAllAccountIds() + .then(accountIds => + accountIds.map(id => onDCEvent(id, 'IncomingMsg', update)) + ) + + return update + }) + // Small hack/misuse of keyBindingAction to setShowArchivedChats from other components (especially // ViewProfile when selecting a shared chat/group) useKeyBindingAction(KeybindAction.ChatList_SwitchToArchiveView, () => @@ -202,6 +236,9 @@ export default function MainScreen() { id='hamburger-menu-button' > + {haveOtherAccountsUnread && ( + + )}
{queryStr.length === 0 && showArchivedChats && ( <> @@ -336,7 +373,11 @@ export default function MainScreen() { /> {MessageListView}
- + )