add top-of-channel message
This commit is contained in:
parent
ce13fe1c80
commit
72b0b0004d
@ -6,7 +6,7 @@ CorDis is a text and voice chat client with UI based on Discord.
|
|||||||
|
|
||||||
[Server Screenshot](data/server.png)
|
[Server Screenshot](data/server.png)
|
||||||
|
|
||||||
## Build / Run
|
## Build
|
||||||
|
|
||||||
Install Node Dependencies
|
Install Node Dependencies
|
||||||
|
|
||||||
|
2
makefile
2
makefile
@ -51,7 +51,7 @@ create-example-roles:
|
|||||||
node ./dist/server/scripts/example-roles.js
|
node ./dist/server/scripts/example-roles.js
|
||||||
|
|
||||||
create-memes-messages:
|
create-memes-messages:
|
||||||
node ./dist/server/scripts/insert-2000-memes-messages.js
|
node ./dist/server/scripts/insert-500-memes-messages.js
|
||||||
|
|
||||||
full-reset: clean build move reset-server create-invite
|
full-reset: clean build move reset-server create-invite
|
||||||
|
|
||||||
|
@ -72,6 +72,22 @@ $borderRadius: 8px;
|
|||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.top-of-feed {
|
||||||
|
margin: 8px 16px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.welcome {
|
||||||
|
color: theme.$header-primary;
|
||||||
|
font-size: 1.4em;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.start {
|
||||||
|
color: theme.$header-secondary;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import Retry from './retry';
|
|||||||
export interface InfiniteScrollRecoilProps<T, E> {
|
export interface InfiniteScrollRecoilProps<T, E> {
|
||||||
infiniteScrollRef: MutableRefObject<HTMLDivElement | null>;
|
infiniteScrollRef: MutableRefObject<HTMLDivElement | null>;
|
||||||
scrollable: LoadableValueScrolling<T, E>;
|
scrollable: LoadableValueScrolling<T, E>;
|
||||||
|
topElement: ReactNode;
|
||||||
initialErrorMessage: string; // for if there was a problem loading the initial messages
|
initialErrorMessage: string; // for if there was a problem loading the initial messages
|
||||||
aboveErrorMessage: string; // for if there was a problem loading messages above the list
|
aboveErrorMessage: string; // for if there was a problem loading messages above the list
|
||||||
belowErrorMessage: string; // for if there was a problem loading messages below the list
|
belowErrorMessage: string; // for if there was a problem loading messages below the list
|
||||||
@ -17,6 +18,7 @@ function InfiniteScrollRecoil<T>(props: InfiniteScrollRecoilProps<T[], T>) {
|
|||||||
const {
|
const {
|
||||||
infiniteScrollRef,
|
infiniteScrollRef,
|
||||||
scrollable,
|
scrollable,
|
||||||
|
topElement,
|
||||||
initialErrorMessage,
|
initialErrorMessage,
|
||||||
aboveErrorMessage,
|
aboveErrorMessage,
|
||||||
belowErrorMessage,
|
belowErrorMessage,
|
||||||
@ -56,6 +58,7 @@ function InfiniteScrollRecoil<T>(props: InfiniteScrollRecoilProps<T[], T>) {
|
|||||||
<div>
|
<div>
|
||||||
<div ref={infiniteScrollRef} className="infinite-scroll-scroll-base" onScroll={onScrollCallable}>
|
<div ref={infiniteScrollRef} className="infinite-scroll-scroll-base" onScroll={onScrollCallable}>
|
||||||
<div className="infinite-scroll-elements">
|
<div className="infinite-scroll-elements">
|
||||||
|
{scrollable.above?.hasMore === false && topElement}
|
||||||
<Retry error={scrollable.above?.error} text={aboveErrorMessage} retryFunc={fetchAboveCallable} />
|
<Retry error={scrollable.above?.error} text={aboveErrorMessage} retryFunc={fetchAboveCallable} />
|
||||||
{children}
|
{children}
|
||||||
<Retry error={scrollable.below?.error} text={belowErrorMessage} retryFunc={fetchBelowCallable} />
|
<Retry error={scrollable.below?.error} text={belowErrorMessage} retryFunc={fetchBelowCallable} />
|
||||||
|
@ -6,7 +6,12 @@ const LOG = Logger.create(__filename, electronConsole);
|
|||||||
import React, { FC, useEffect, useMemo, useRef } from 'react';
|
import React, { FC, useEffect, useMemo, useRef } from 'react';
|
||||||
import { Message } from '../../data-types';
|
import { Message } from '../../data-types';
|
||||||
import MessageElement from './components/message-element';
|
import MessageElement from './components/message-element';
|
||||||
import { currGuildActiveChannelMessagesState, currGuildSelfMemberState, currGuildState } from '../require/atoms';
|
import {
|
||||||
|
currGuildActiveChannelMessagesState,
|
||||||
|
currGuildActiveChannelState,
|
||||||
|
currGuildSelfMemberState,
|
||||||
|
currGuildState,
|
||||||
|
} from '../require/atoms';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import { isLoaded } from '../require/loadables';
|
import { isLoaded } from '../require/loadables';
|
||||||
import InfiniteScrollRecoil from '../components/infinite-scroll';
|
import InfiniteScrollRecoil from '../components/infinite-scroll';
|
||||||
@ -15,25 +20,13 @@ const MessageList: FC = () => {
|
|||||||
const infiniteScrollElementRef = useRef<HTMLDivElement>(null);
|
const infiniteScrollElementRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const guild = useRecoilValue(currGuildState);
|
const guild = useRecoilValue(currGuildState);
|
||||||
|
const channel = useRecoilValue(currGuildActiveChannelState);
|
||||||
const messages = useRecoilValue(currGuildActiveChannelMessagesState);
|
const messages = useRecoilValue(currGuildActiveChannelMessagesState);
|
||||||
const selfMember = useRecoilValue(currGuildSelfMemberState);
|
const selfMember = useRecoilValue(currGuildSelfMemberState);
|
||||||
|
|
||||||
// TODO: Show loading indicators if above/below are pending
|
// TODO: Show loading indicators if above/below are pending
|
||||||
// TODO: Show nicer retry buttons (and test the retry buttons)
|
// TODO: Show nicer retry buttons (and test the retry buttons)
|
||||||
|
|
||||||
// leaving this in for debugging purposes
|
|
||||||
// useEffect(() => {
|
|
||||||
// if (isUnload(messages)) {
|
|
||||||
// lOG.debug('recoilMessages unloaded');
|
|
||||||
// } else if (isPended(messages)) {
|
|
||||||
// lOG.debug('recoilMessages pended');
|
|
||||||
// } else if (isLoaded(messages)) {
|
|
||||||
// lOG.debug('recoilMessages loaded. length: ' + messages.value.length);
|
|
||||||
// } else if (isFailed(messages)) {
|
|
||||||
// lOG.debug('recoilMessages failed');
|
|
||||||
// }
|
|
||||||
// }, [messages]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (guild === null) return;
|
if (guild === null) return;
|
||||||
const onMessages = (messages: Message[]) => {
|
const onMessages = (messages: Message[]) => {
|
||||||
@ -71,11 +64,22 @@ const MessageList: FC = () => {
|
|||||||
return result;
|
return result;
|
||||||
}, [guild, messages]);
|
}, [guild, messages]);
|
||||||
|
|
||||||
|
const topOfFeedElement = useMemo(() => {
|
||||||
|
if (!isLoaded(channel)) return null; // TODO: placeholder/loading message instead
|
||||||
|
return (
|
||||||
|
<div className="top-of-feed">
|
||||||
|
<div className="welcome">Welcome to #{channel.value.name}</div>
|
||||||
|
<div className="start">This is the start of #{channel.value.name}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}, [channel]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="message-list">
|
<div className="message-list">
|
||||||
<InfiniteScrollRecoil
|
<InfiniteScrollRecoil
|
||||||
infiniteScrollRef={infiniteScrollElementRef}
|
infiniteScrollRef={infiniteScrollElementRef}
|
||||||
scrollable={messages}
|
scrollable={messages}
|
||||||
|
topElement={topOfFeedElement}
|
||||||
initialErrorMessage="Unable to retrieve recent messages"
|
initialErrorMessage="Unable to retrieve recent messages"
|
||||||
aboveErrorMessage="Unable to retrieve messages above"
|
aboveErrorMessage="Unable to retrieve messages above"
|
||||||
belowErrorMessage="Unable to retrieve messages below"
|
belowErrorMessage="Unable to retrieve messages below"
|
||||||
|
@ -22,7 +22,7 @@ process.on('unhandledRejection', async (reason, _promise) => {
|
|||||||
const channels = await DB.getChannels(targetGuild.id);
|
const channels = await DB.getChannels(targetGuild.id);
|
||||||
const targetChannel = channels.find(channel => channel.name === 'memes');
|
const targetChannel = channels.find(channel => channel.name === 'memes');
|
||||||
LOG.debug('inserting testing messages...');
|
LOG.debug('inserting testing messages...');
|
||||||
for (let i = 0; i < 2000; ++i) {
|
for (let i = 0; i < 500; ++i) {
|
||||||
await DB.insertMessage(targetGuild.id, targetChannel.id, targetMember.id, 'Test Message #' + i);
|
await DB.insertMessage(targetGuild.id, targetChannel.id, targetMember.id, 'Test Message #' + i);
|
||||||
}
|
}
|
||||||
LOG.info('inserted testing messages');
|
LOG.info('inserted testing messages');
|
Loading…
Reference in New Issue
Block a user