diff --git a/.env b/.env index c8b232c2..c13d0719 100644 --- a/.env +++ b/.env @@ -1,5 +1,5 @@ # VITE_API_URL=https://api.revolt.chat -VITE_API_URL=https://app.revolt.chat/api +# VITE_API_URL=https://app.revolt.chat/api # VITE_API_URL=http://local.revolt.chat:8000 -# VITE_API_URL=https://revolt.chat/api +VITE_API_URL=https://revolt.chat/api VITE_THEMES_URL=https://themes.revolt.chat diff --git a/external/revolt.js b/external/revolt.js index 783c8d1a..3fbd5428 160000 --- a/external/revolt.js +++ b/external/revolt.js @@ -1 +1 @@ -Subproject commit 783c8d1a3e3ad6071d268b18077569262ea61602 +Subproject commit 3fbd54281924e4778ed141de23305a8faaa31516 diff --git a/src/pages/channels/Channel.tsx b/src/pages/channels/Channel.tsx index 3545fd55..c60de584 100644 --- a/src/pages/channels/Channel.tsx +++ b/src/pages/channels/Channel.tsx @@ -163,6 +163,7 @@ const TextChannel = observer(({ channel }: { channel: ChannelI }) => { const checkUnread = () => channel.unread && + document.hasFocus() && channel.client.unreads!.markRead( channel._id, channel.last_message_id!, @@ -176,6 +177,45 @@ const TextChannel = observer(({ channel }: { channel: ChannelI }) => { ); }, [channel]); + useEffect(() => { + let lastSubscribed: number | undefined; + function subscribe() { + if (document.hasFocus()) { + const tenMinutesAgo = new Date(); + tenMinutesAgo.setMinutes(tenMinutesAgo.getMinutes() - 10); + + if (!lastSubscribed || +tenMinutesAgo > lastSubscribed) { + channel.server?.subscribe(); + lastSubscribed = +tenMinutesAgo; + } + } + } + + // Trigger logic every minute + const subTimer = setInterval(subscribe, 60e3); + + function onFocus() { + // Mark channel as read if it's unread + if (channel.unread) { + channel.client.unreads!.markRead( + channel._id, + channel.last_message_id!, + true, + ); + } + + // Subscribe to channel if expired + subscribe(); + } + + addEventListener("focus", onFocus); + + return () => { + removeEventListener("focus", onFocus); + clearInterval(subTimer); + }; + }, [channel]); + return ( { const [query, setQuery] = useState(""); useEffect(() => { - server - .fetchMembers() - .then((data) => data.members) - .then(setData); + function fetch() { + server + .fetchMembers() + .then((data) => data.members) + .then(setData); + } + + fetch(); + + // Members may be invalidated if we stop receiving events + // This is not very accurate, this should be tracked within + // revolt.js so we know the true validity. + let valid = true, + invalidationTimer: number; + + function waitToInvalidate() { + invalidationTimer = setTimeout(() => { + valid = false; + }, 15 * 60e3) as never; // 15 minutes + } + + function cancelInvalidation() { + if (!valid) { + fetch(); + valid = true; + } + + clearTimeout(invalidationTimer); + } + + addEventListener("blur", waitToInvalidate); + addEventListener("focus", cancelInvalidation); + + return () => { + removeEventListener("blur", waitToInvalidate); + removeEventListener("focus", cancelInvalidation); + }; }, [server, setData]); const members = useMemo(