From 29b7c47a7ece642afac28ad0cbfcd9accc60a147 Mon Sep 17 00:00:00 2001 From: Michael Peters Date: Mon, 12 Dec 2022 20:53:20 -0800 Subject: [PATCH] add infinite scroll "jump to bottom" ui components --- .../components/infinite-scroll.scss | 31 ++++++++++ .../elements/components/infinite-scroll.tsx | 56 +++++++++++++------ .../webapp/elements/require/react-helper.tsx | 2 +- src/client/webapp/guild-combined.ts | 2 +- src/client/webapp/index.scss | 1 + src/client/webapp/styles/theme.scss | 1 + .../scripts/insert-2000-memes-messages.ts | 4 ++ 7 files changed, 77 insertions(+), 20 deletions(-) create mode 100644 src/client/webapp/elements-styles/components/infinite-scroll.scss diff --git a/src/client/webapp/elements-styles/components/infinite-scroll.scss b/src/client/webapp/elements-styles/components/infinite-scroll.scss new file mode 100644 index 0000000..ea9dca3 --- /dev/null +++ b/src/client/webapp/elements-styles/components/infinite-scroll.scss @@ -0,0 +1,31 @@ +@use '../../styles/theme.scss'; + +.jump-to-bottom-wrapper { + position: relative; + + .jump-to-bottom { + box-sizing: border-box; + position: absolute; + + font-size: 0.85em; + + left: 0; + bottom: 52px; + + padding: 4px 8px 16px 8px; + margin-left: 16px; + width: calc(100% - 32px); + + display: flex; + justify-content: space-between; + + border-radius: 8px; + color: theme.$header-primary; + background-color: theme.$background-input-alt; + + .jump { + cursor: pointer; + font-weight: 600; + } + } +} diff --git a/src/client/webapp/elements/components/infinite-scroll.tsx b/src/client/webapp/elements/components/infinite-scroll.tsx index 3df96cc..2d84a94 100644 --- a/src/client/webapp/elements/components/infinite-scroll.tsx +++ b/src/client/webapp/elements/components/infinite-scroll.tsx @@ -1,4 +1,4 @@ -import React, { MutableRefObject, ReactNode } from 'react'; +import React, { useMemo, MutableRefObject, ReactNode } from 'react'; import { LoadableValueScrolling } from '../require/loadables'; import { useScrollableCallables } from '../require/react-helper'; @@ -18,24 +18,44 @@ function InfiniteScrollRecoil(props: InfiniteScrollRecoilProps) { const { fetchAboveCallable, fetchBelowCallable, onScrollCallable } = useScrollableCallables(scrollable, 600); // activate fetch above/below when 600 client px from the top/bottom + const jumpToBottom = useMemo(() => { + if (!scrollable.below?.hasMore) { + return null; + } + return ( +
+
+
You are viewing older messages
+
{ console.log('jump to bottom'); }}> + Jump to Bottom +
+
+
+ ); + }, [scrollable]); + return ( -
-
- - {children} - - { - /* do nothing if we are unloaded */ - }) - } - /> -
-
+
+
+
+ + {children} + + { + /* do nothing if we are unloaded */ + }) + } + /> +
+
+ {jumpToBottom} +
); } diff --git a/src/client/webapp/elements/require/react-helper.tsx b/src/client/webapp/elements/require/react-helper.tsx index fcd25a5..335522f 100644 --- a/src/client/webapp/elements/require/react-helper.tsx +++ b/src/client/webapp/elements/require/react-helper.tsx @@ -343,7 +343,7 @@ export function useScrollableCallables( const distToTop = -(clientHeight - scrollHeight - scrollTop); // keep in mind scrollTop is negative >:] const distToBottom = -scrollTop; - //lOG.debug(`scroll callable update. to top: ${distToTop}, to bottom: ${distToBottom}`) + // lOG.debug(`scroll callable update. to top: ${distToTop}, to bottom: ${distToBottom}`) if (distToTop < threshold && isLoaded(scrollable) && !isEndFailed(scrollable.above)) { await fetchAboveCallable(); diff --git a/src/client/webapp/guild-combined.ts b/src/client/webapp/guild-combined.ts index f90fb63..b2cb07a 100644 --- a/src/client/webapp/guild-combined.ts +++ b/src/client/webapp/guild-combined.ts @@ -392,7 +392,7 @@ export default class CombinedGuild return messages; } async fetchMessagesAfter(channelId: string, messageOrderId: string, number: number): Promise { - Util.failSometimes(0.75); // for testing + // xUtil.failSometimes(0.05); // for testing LOG.debug(`g#${this.id}: fetch messages after ch#${channelId.slice(0, 4)}, mo#${messageOrderId}, ${number}`); const members = await this.grabRAMMembersMap(); const channels = await this.grabRAMChannelsMap(); diff --git a/src/client/webapp/index.scss b/src/client/webapp/index.scss index 85e4320..6965331 100644 --- a/src/client/webapp/index.scss +++ b/src/client/webapp/index.scss @@ -9,6 +9,7 @@ @use 'elements-styles/components/buttons.scss'; @use 'elements-styles/components/file-drop-target.scss'; +@use 'elements-styles/components/infinite-scroll.scss'; @use 'elements-styles/components/input-dropdown.scss'; @use 'elements-styles/components/input-image-edit.scss'; @use 'elements-styles/components/input-text.scss'; diff --git a/src/client/webapp/styles/theme.scss b/src/client/webapp/styles/theme.scss index e3a99d4..d0a6d9d 100644 --- a/src/client/webapp/styles/theme.scss +++ b/src/client/webapp/styles/theme.scss @@ -29,6 +29,7 @@ $background-popup-message: rgba(30, 31, 34, 0.75); $background-primary-divider: #3f4149; $background-input: #2f3136; +$background-input-alt: #646872; $border-input: #1d1e22; $border-input-hover: #0b0c0e; $border-input-focus: #0099ff; diff --git a/src/server/scripts/insert-2000-memes-messages.ts b/src/server/scripts/insert-2000-memes-messages.ts index cb3a347..185d76e 100644 --- a/src/server/scripts/insert-2000-memes-messages.ts +++ b/src/server/scripts/insert-2000-memes-messages.ts @@ -16,8 +16,12 @@ process.on('unhandledRejection', async (reason, _promise) => { const targetGuild = guilds.find(guild => guild.name === 'no chicoms'); const members = await DB.getMembers(targetGuild.id); const targetMember = members.find(member => member.display_name === 'Elipzer'); + if (targetMember === undefined) { + LOG.error('unable to find target member'); + } const channels = await DB.getChannels(targetGuild.id); const targetChannel = channels.find(channel => channel.name === 'memes'); + LOG.debug('inserting testing messages...'); for (let i = 0; i < 2000; ++i) { await DB.insertMessage(targetGuild.id, targetChannel.id, targetMember.id, 'Test Message #' + i); }