diff --git a/src/packages/database/postgres/messages.ts b/src/packages/database/postgres/messages.ts index 3dfde1420d..9721bf6972 100644 --- a/src/packages/database/postgres/messages.ts +++ b/src/packages/database/postgres/messages.ts @@ -31,7 +31,6 @@ FROM ( LIMIT ${NUM_MESSAGES} ) AS subquery WHERE read=false AND saved=false AND deleted=false`; - console.log(query); const { rows: counts } = await pool.query(query, [account_id]); const { unread_count } = counts[0]; diff --git a/src/packages/frontend/app/notifications.tsx b/src/packages/frontend/app/notifications.tsx index 6e7a4da22f..6505612b94 100644 --- a/src/packages/frontend/app/notifications.tsx +++ b/src/packages/frontend/app/notifications.tsx @@ -5,13 +5,11 @@ import { blue as ANTD_BLUE } from "@ant-design/colors"; import { Badge } from "antd"; - import { CSS, React, redux, useActions, - useMemo, useTypedRedux, } from "@cocalc/frontend/app-framework"; import { Icon } from "@cocalc/frontend/components"; @@ -20,6 +18,8 @@ import { COLORS } from "@cocalc/util/theme"; import track from "@cocalc/frontend/user-tracking"; import { PageStyle, TOP_BAR_ELEMENT_CLASS } from "./top-nav-consts"; import { blur_active_element } from "./util"; +import { useEffect, useMemo } from "react"; +import { set_window_title } from "@cocalc/frontend/browser"; interface Props { type: "bell" | "notifications"; @@ -45,13 +45,17 @@ export const Notification: React.FC = React.memo((props: Props) => { case "bell": return notify_count ?? 0; case "notifications": - return mentions_store.get_unseen_size(mentions) ?? 0; + return mentions_store.getUnreadSize() ?? 0; default: unreachable(type); return 0; } }, [type, notify_count, mentions]); + useEffect(() => { + set_window_title(); + }, [count, news_unread]); + const outer_style: CSS = { padding: `${topPaddingIcons} ${sidePaddingIcons}`, height: `${pageStyle.height}px`, @@ -107,7 +111,7 @@ export const Notification: React.FC = React.memo((props: Props) => { return ( 0 ? "smc-bell-notification" : ""} /> @@ -116,7 +120,7 @@ export const Notification: React.FC = React.memo((props: Props) => { case "notifications": // only wiggle, if there are unread news – because they clear out automatically. // mentions can be more long term, i.e. keep them unread until you mark them done. - const wiggle = news_unread > 0; + const wiggle = news_unread > 0 || unread_message_count > 0; return ( number; -let notify_count: NotifyFunction | undefined = undefined; - -export function set_notify_count_function() { - const store = redux.getStore("file_use"); - if (store == null) throw Error("file_use must be defined"); - notify_count = store?.get_notify_count; +export function notifyCount() { + const mentions = redux.getStore("mentions"); + const account = redux.getStore("account"); + const news = redux.getStore("news"); + return ( + (mentions?.getUnreadSize() ?? 0) + + (account?.get("unread_message_count") ?? 0) + + (news?.get("unread") ?? 0) + ); } let last_title: string = ""; @@ -24,7 +26,7 @@ export function set_window_title(title?: string): void { title = last_title; } last_title = title; - const u = notify_count?.(); + const u = notifyCount(); if (u) { title = `(${u}) ${title}`; } diff --git a/src/packages/frontend/file-use/init.ts b/src/packages/frontend/file-use/init.ts index 0242f844c5..e2bdd475e3 100644 --- a/src/packages/frontend/file-use/init.ts +++ b/src/packages/frontend/file-use/init.ts @@ -8,8 +8,6 @@ import { redux } from "../app-framework"; import { FileUseStore } from "./store"; import { FileUseActions } from "./actions"; import { FileUseTable } from "./table"; -// Initialize function to updates the browser's awareness of a notification -import { set_notify_count_function } from "../browser"; export function init() { redux.createStore("file_use", FileUseStore, { notify_count: 0 }); @@ -23,6 +21,4 @@ export function init() { redux.createTable("file_use", FileUseTable); } actions._init(); // must be after making store - - set_notify_count_function(); } diff --git a/src/packages/frontend/messages/counter.tsx b/src/packages/frontend/messages/counter.tsx index ff6401830a..019da0c613 100644 --- a/src/packages/frontend/messages/counter.tsx +++ b/src/packages/frontend/messages/counter.tsx @@ -1,6 +1,8 @@ +import { useEffect } from "react"; import { Badge, Tooltip } from "antd"; import { useTypedRedux } from "@cocalc/frontend/app-framework"; import { COLORS } from "@cocalc/util/theme"; +import { set_window_title } from "@cocalc/frontend/browser"; export default function Counter({ minimal, @@ -11,6 +13,9 @@ export default function Counter({ }) { const unread_message_count = useTypedRedux("account", "unread_message_count") ?? 0; + useEffect(() => { + set_window_title(); + }, [unread_message_count]); if (minimal) { return {unread_message_count}; } diff --git a/src/packages/frontend/messages/thread.tsx b/src/packages/frontend/messages/thread.tsx index 9e8e9e027b..110c5c0f30 100644 --- a/src/packages/frontend/messages/thread.tsx +++ b/src/packages/frontend/messages/thread.tsx @@ -4,7 +4,7 @@ import { MessageInThread } from "./message"; import type { Message as MessageType } from "@cocalc/util/db-schema/messages"; import { useState } from "react"; import { plural } from "@cocalc/util/misc"; -import { isFromMe, isToMe, isRead } from "./util"; +import { isFromMe, isRead } from "./util"; import User from "./user"; import { redux } from "@cocalc/frontend/app-framework"; @@ -39,10 +39,10 @@ export default function Thread({ if (thread_id != null) { const thread = threads.get(thread_id)?.toJS() as unknown as MessageType[]; if (thread != null) { - // expand each message *to me* that is not read: + // expand each message that is not read: const ids = new Set(); for (const id of thread - .filter((message) => isToMe(message) && !isRead(message)) + .filter((message) => !isRead(message)) .map(({ id }) => id)) { ids.add(id); expanded.add(id); diff --git a/src/packages/frontend/notifications/mentions/mention-row.tsx b/src/packages/frontend/notifications/mentions/mention-row.tsx index b5348a84ef..1815079b89 100644 --- a/src/packages/frontend/notifications/mentions/mention-row.tsx +++ b/src/packages/frontend/notifications/mentions/mention-row.tsx @@ -49,9 +49,7 @@ export function MentionRow(props: Props) { const is_saved = mention.getIn(["users", target, "saved"]); const read_icon: IconName = - (is_read && !clicked) || (!is_read && clicked) - ? "check-square-o" - : "square-o"; + (is_read && !clicked) || (!is_read && clicked) ? "eye" : "eye-slash"; // think of "in transition" between read and unread const clickedStyle: CSS = diff --git a/src/packages/frontend/notifications/mentions/store.ts b/src/packages/frontend/notifications/mentions/store.ts index 8010ff5951..7115a39944 100644 --- a/src/packages/frontend/notifications/mentions/store.ts +++ b/src/packages/frontend/notifications/mentions/store.ts @@ -19,27 +19,28 @@ export class MentionsStore extends Store { super(name, redux); } - get_unseen_size = (mentions?: MentionsMap): number => { + getUnreadSize = (): number => { + const mentions = this.get("mentions"); if (mentions == null) { // e.g., happens with a brand new account. return 0; } const account_store = this.redux.getStore("account"); - if (account_store == undefined) { + if (account_store == null) { return 0; } const account_id = account_store.get("account_id"); - let unseen_count = 0; + let unread_count = 0; mentions.map((mention) => { if ( - mention.get("target") === account_id && + mention.get("target") == account_id && !mention.getIn(["users", account_id, "read"]) ) { - unseen_count += 1; + unread_count += 1; } }); - return unseen_count; + return unread_count; }; } diff --git a/src/packages/frontend/notifications/notification-nav.tsx b/src/packages/frontend/notifications/notification-nav.tsx index 5ccceca5cf..aa080e1794 100644 --- a/src/packages/frontend/notifications/notification-nav.tsx +++ b/src/packages/frontend/notifications/notification-nav.tsx @@ -32,7 +32,7 @@ const MentionsCounter = () => { const mentions = useTypedRedux("mentions", "mentions"); const mentions_store = redux.getStore("mentions"); const count = useMemo(() => { - return mentions_store.get_unseen_size(mentions); + return mentions_store.getUnreadSize(); }, [mentions]); return (