cetirizine

An experimental matrix client written in reactjs utilizing tailwind and storybook
git clone git://archive.git.mtrnord.blog/MTRNord/cetirizine.git
Log | Files | Refs | README | LICENSE

commit 709dcc61e86de38ca750bd736e9795c7ad58521b
parent 5f0629533de647a9335d0a280bc0d513abf62782
Author: MTRNord <mtrnord1@gmail.com>
Date:   Tue,  9 May 2023 16:52:41 +0200

Add unknown state for presence

Diffstat:
Asrc/app/sdk/api/otherEnums.ts | 5+++++
Msrc/app/sdk/room.ts | 5+++--
Msrc/components/avatar/avatar.stories.tsx | 32++++++++++++++++++++++++++------
Msrc/components/avatar/avatar.tsx | 17++++++++++-------
Msrc/components/events/messageEvent.tsx | 11++++++-----
Msrc/components/events/unknownEvent.tsx | 7++++---
Msrc/components/roomList/roomList.stories.tsx | 13+++++++------
Msrc/components/roomList/roomList.tsx | 3++-
Msrc/components/roomList/roomListItem/roomListItem.stories.tsx | 42++++++++++++++++++++++++++++++++----------
Msrc/components/roomList/roomListItem/roomListItem.tsx | 5+++--
Msrc/pages/MainPage.tsx | 11++++++-----
11 files changed, 104 insertions(+), 47 deletions(-)

diff --git a/src/app/sdk/api/otherEnums.ts b/src/app/sdk/api/otherEnums.ts @@ -0,0 +1,5 @@ +export enum OnlineState { + Online, + Offline, + Unknown +} diff --git a/src/app/sdk/room.ts b/src/app/sdk/room.ts @@ -3,6 +3,7 @@ import { IRoomEvent, IRoomStateEvent, isRoomAvatarEvent, isRoomCreateEvent, isRo import { MatrixClient } from "./client"; import { useEffect, useState } from "react"; import { EncryptionAlgorithm, EncryptionSettings, RoomId } from "@mtrnord/matrix-sdk-crypto-js"; +import { OnlineState } from "./api/otherEnums"; export interface RoomEvents { // Used to notify about changes to the event list @@ -179,9 +180,9 @@ export class Room extends EventEmitter { return this.is_dm; } - public isOnline(): boolean { + public get presence(): OnlineState { // TODO: Implement this - return false; + return OnlineState.Unknown; } public getEvents(): IRoomEvent[] { diff --git a/src/components/avatar/avatar.stories.tsx b/src/components/avatar/avatar.stories.tsx @@ -1,5 +1,6 @@ import { Meta, StoryObj } from '@storybook/react'; import Avatar from './avatar'; +import { OnlineState } from '../../app/sdk/api/otherEnums'; const meta: Meta<typeof Avatar> = { title: 'Chat/Avatar', @@ -39,7 +40,7 @@ export const Fallback: Story = { args: { displayname: "test", dm: false, - online: false, + online: OnlineState.Unknown, avatarUrl: "" } }; @@ -49,7 +50,7 @@ export const Image: Story = { displayname: "test", avatarUrl: "https://randomuser.me/api/portraits/men/62.jpg", dm: false, - online: false, + online: OnlineState.Unknown, } }; @@ -58,7 +59,17 @@ export const DMOffline: Story = { displayname: "test", avatarUrl: "https://randomuser.me/api/portraits/men/62.jpg", dm: true, - online: false, + online: OnlineState.Offline, + } +}; + + +export const DMUnknown: Story = { + args: { + displayname: "test", + avatarUrl: "https://randomuser.me/api/portraits/men/62.jpg", + dm: true, + online: OnlineState.Unknown, } }; @@ -67,7 +78,7 @@ export const DMOnline: Story = { displayname: "test", avatarUrl: "https://randomuser.me/api/portraits/men/62.jpg", dm: true, - online: true, + online: OnlineState.Online, } }; @@ -76,7 +87,16 @@ export const DMNoAvatarOffline: Story = { displayname: "test", avatarUrl: "", dm: true, - online: false, + online: OnlineState.Offline, + } +}; + +export const DMNoAvatarUnknown: Story = { + args: { + displayname: "test", + avatarUrl: "", + dm: true, + online: OnlineState.Unknown, } }; @@ -85,6 +105,6 @@ export const DMNoAvatarOnline: Story = { displayname: "test", avatarUrl: "", dm: true, - online: true, + online: OnlineState.Online, } }; \ No newline at end of file diff --git a/src/components/avatar/avatar.tsx b/src/components/avatar/avatar.tsx @@ -1,4 +1,5 @@ import { FC, memo, useState } from "react"; +import { OnlineState } from "../../app/sdk/api/otherEnums"; type AvatarProps = { /** @@ -16,10 +17,10 @@ type AvatarProps = { /** * Wether the user is online. Only used if dm is true. */ - online: boolean + online: OnlineState }; -const Avatar: FC<AvatarProps> = memo(({ avatarUrl, displayname, dm = false, online = false }: AvatarProps) => { +const Avatar: FC<AvatarProps> = memo(({ avatarUrl, displayname, dm = false, online = OnlineState.Unknown }: AvatarProps) => { const [error, setError] = useState(false); if (avatarUrl && !error) { @@ -29,9 +30,10 @@ const Avatar: FC<AvatarProps> = memo(({ avatarUrl, displayname, dm = false, onli { dm ? ( - online ? + online === OnlineState.Online ? <div className="bg-green-500 rounded-full w-3 h-3 absolute right-0 bottom-0"></div> : - <div className="bg-red-500 rounded-full w-3 h-3 absolute right-0 bottom-0"></div> + (online === OnlineState.Offline ? <div className="bg-red-500 rounded-full w-3 h-3 absolute right-0 bottom-0"></div> : + <div className="bg-gray-500 rounded-full w-3 h-3 absolute right-0 bottom-0"></div>) ) : <></> } @@ -44,9 +46,10 @@ const Avatar: FC<AvatarProps> = memo(({ avatarUrl, displayname, dm = false, onli { dm ? ( - online ? - <div className="bg-green-500 rounded-full w-3 h-3 absolute bottom-0 right-0"></div> : - <div className="bg-red-500 rounded-full w-3 h-3 absolute bottom-0 right-0"></div> + online === OnlineState.Online ? + <div className="bg-green-500 rounded-full w-3 h-3 absolute right-0 bottom-0"></div> : + (online === OnlineState.Offline ? <div className="bg-red-500 rounded-full w-3 h-3 absolute right-0 bottom-0"></div> : + <div className="bg-gray-500 rounded-full w-3 h-3 absolute right-0 bottom-0"></div>) ) : <></> } diff --git a/src/components/events/messageEvent.tsx b/src/components/events/messageEvent.tsx @@ -11,6 +11,7 @@ import { decryptAttachment } from "matrix-encrypt-attachment"; import Waveform from './helpers/Waveform'; import hljs from 'highlight.js'; import 'highlight.js/styles/base16/solarized-dark.css'; +import { OnlineState } from "../../app/sdk/api/otherEnums"; type MessageEventProps = { /** @@ -111,7 +112,7 @@ const MessageEvent: FC<MessageEventProps> = memo(({ event, roomID, hasPreviousEv {!hasPreviousEvent && <Avatar displayname={room?.getMemberName(event.sender) || event.sender} avatarUrl={room?.getMemberAvatar(event.sender)} - online={room?.isOnline() || false} + online={room?.presence || OnlineState.Unknown} dm={room?.isDM() || false} />} <div className={!hasPreviousEvent ? "flex flex-col gap-1" : "ml-[3.7rem]"}> @@ -189,7 +190,7 @@ const MessageEvent: FC<MessageEventProps> = memo(({ event, roomID, hasPreviousEv {!hasPreviousEvent && <Avatar displayname={room?.getMemberName(event.sender) || event.sender} avatarUrl={room?.getMemberAvatar(event.sender)} - online={room?.isOnline() || false} + online={room?.presence || OnlineState.Unknown} dm={room?.isDM() || false} />} <div className={!hasPreviousEvent ? "flex flex-col gap-1" : "flex-1 ml-[3.7rem]"}> @@ -204,7 +205,7 @@ const MessageEvent: FC<MessageEventProps> = memo(({ event, roomID, hasPreviousEv {!hasPreviousEvent && <Avatar displayname={room?.getMemberName(event.sender) || event.sender} avatarUrl={room?.getMemberAvatar(event.sender)} - online={room?.isOnline() || false} + online={room?.presence || OnlineState.Unknown} dm={room?.isDM() || false} />} <div className={!hasPreviousEvent ? "flex flex-col gap-1" : "ml-[3.7rem]"}> @@ -308,7 +309,7 @@ const TextMessage: FC<TextMessage> = memo(({ event, roomID, hasPreviousEvent, me {!hasPreviousEvent && <Avatar displayname={room?.getMemberName(event.sender) || event.sender} avatarUrl={room?.getMemberAvatar(event.sender)} - online={room?.isOnline() || false} + online={room?.presence || OnlineState.Unknown} dm={room?.isDM() || false} />} <div className={!hasPreviousEvent ? "flex flex-col gap-1" : "ml-[3.7rem]"}> @@ -324,7 +325,7 @@ const TextMessage: FC<TextMessage> = memo(({ event, roomID, hasPreviousEvent, me {!hasPreviousEvent && <Avatar displayname={room?.getMemberName(event.sender) || event.sender} avatarUrl={room?.getMemberAvatar(event.sender)} - online={room?.isOnline() || false} + online={room?.presence || OnlineState.Unknown} dm={room?.isDM() || false} />} <div className={!hasPreviousEvent ? "flex flex-col gap-1" : "ml-[3.7rem]"}> diff --git a/src/components/events/unknownEvent.tsx b/src/components/events/unknownEvent.tsx @@ -4,6 +4,7 @@ import { FC } from "react"; import { useRoom } from "../../app/sdk/client"; import Linkify from "linkify-react"; import Avatar from "../avatar/avatar"; +import { OnlineState } from "../../app/sdk/api/otherEnums"; type UnknownEventProps = { /** @@ -35,7 +36,7 @@ const UnknownEvent: FC<UnknownEventProps> = memo(({ event, roomID, hasPreviousEv {!hasPreviousEvent && <Avatar displayname={room?.getMemberName(event.sender) || event.sender} avatarUrl={room?.getMemberAvatar(event.sender)} - online={room?.isOnline() || false} + online={room?.presence || OnlineState.Unknown} dm={room?.isDM() || false} />} <div className={!hasPreviousEvent ? "flex flex-col gap-1" : "ml-[3.7rem]"}> @@ -71,7 +72,7 @@ export const UndecryptableEvent: FC<UndecryptableEventProps> = memo(({ event, ro {!hasPreviousEvent && <Avatar displayname={room?.getMemberName(event.sender) || event.sender} avatarUrl={room?.getMemberAvatar(event.sender)} - online={room?.isOnline() || false} + online={room?.presence || OnlineState.Unknown} dm={room?.isDM() || false} />} <div className={!hasPreviousEvent ? "flex flex-col gap-1" : "ml-[3.7rem]"}> @@ -109,7 +110,7 @@ export const RedactedEvent: FC<RedactedEventProps> = memo(({ event, redacted_bec {!hasPreviousEvent && <Avatar displayname={room?.getMemberName(event.sender) || event.sender} avatarUrl={room?.getMemberAvatar(event.sender)} - online={room?.isOnline() || false} + online={room?.presence || OnlineState.Unknown} dm={room?.isDM() || false} />} <div className={!hasPreviousEvent ? "flex flex-col gap-1" : "ml-[3.7rem]"}> diff --git a/src/components/roomList/roomList.stories.tsx b/src/components/roomList/roomList.stories.tsx @@ -1,6 +1,7 @@ import { Meta, StoryObj } from '@storybook/react'; import RoomList from './roomList'; import { withRouter } from 'storybook-addon-react-router-v6'; +import { OnlineState } from '../../app/sdk/api/otherEnums'; const meta: Meta<typeof RoomList> = { title: 'Chat/RoomList', @@ -33,19 +34,19 @@ export const RootList: Story = { displayname: "test", avatarUrl: "https://randomuser.me/api/portraits/men/62.jpg", dm: true, - online: true, + online: OnlineState.Online, }, { roomID: "2", displayname: "test1", dm: false, - online: false, + online: OnlineState.Unknown, }, { roomID: "3", displayname: "test2", dm: false, - online: false, + online: OnlineState.Unknown, } ], sections: [ @@ -56,13 +57,13 @@ export const RootList: Story = { roomID: "2", displayname: "test1", dm: false, - online: false, + online: OnlineState.Unknown, }, { roomID: "3", displayname: "test2", dm: false, - online: false, + online: OnlineState.Unknown, } ], roomID: "12", @@ -75,7 +76,7 @@ export const RootList: Story = { displayname: "test", avatarUrl: "https://randomuser.me/api/portraits/men/62.jpg", dm: true, - online: true, + online: OnlineState.Online, } ], roomID: "14", diff --git a/src/components/roomList/roomList.tsx b/src/components/roomList/roomList.tsx @@ -5,6 +5,7 @@ import './roomList.scss'; import { useNavigate } from "react-router-dom"; import { MatrixContext } from "../../app/sdk/client"; import { useInView } from "react-intersection-observer"; +import { OnlineState } from "../../app/sdk/api/otherEnums"; type Room = { /** @@ -22,7 +23,7 @@ type Room = { /** * Wether the user is online. Only used if dm is true. */ - online: boolean + online: OnlineState /** * The roomid of the Room */ diff --git a/src/components/roomList/roomListItem/roomListItem.stories.tsx b/src/components/roomList/roomListItem/roomListItem.stories.tsx @@ -1,5 +1,6 @@ import { Meta, StoryObj } from '@storybook/react'; import RoomListItem from './roomListItem'; +import { OnlineState } from '../../../app/sdk/api/otherEnums'; const meta: Meta<typeof RoomListItem> = { title: 'Chat/RoomList/Item', @@ -46,7 +47,7 @@ export const Fallback: Story = { args: { displayname: "test", dm: false, - online: false, + online: OnlineState.Unknown, avatarUrl: "", active: false, } @@ -56,7 +57,7 @@ export const FallbackActive: Story = { args: { displayname: "test", dm: false, - online: false, + online: OnlineState.Unknown, avatarUrl: "", active: true, } @@ -68,7 +69,7 @@ export const Image: Story = { displayname: "test", avatarUrl: "https://randomuser.me/api/portraits/men/62.jpg", dm: false, - online: false, + online: OnlineState.Unknown, active: false, } }; @@ -79,7 +80,7 @@ export const ImageActive: Story = { displayname: "test", avatarUrl: "https://randomuser.me/api/portraits/men/62.jpg", dm: false, - online: false, + online: OnlineState.Unknown, active: true, } }; @@ -89,7 +90,7 @@ export const DMOffline: Story = { displayname: "test", avatarUrl: "https://randomuser.me/api/portraits/men/62.jpg", dm: true, - online: false, + online: OnlineState.Offline, active: false, } }; @@ -99,17 +100,38 @@ export const DMOfflineActive: Story = { displayname: "test", avatarUrl: "https://randomuser.me/api/portraits/men/62.jpg", dm: true, - online: false, + online: OnlineState.Online, active: true, } }; +export const DMUnknown: Story = { + args: { + displayname: "test", + avatarUrl: "https://randomuser.me/api/portraits/men/62.jpg", + dm: true, + online: OnlineState.Unknown, + active: false, + } +}; + +export const DMUnknownActive: Story = { + args: { + displayname: "test", + avatarUrl: "https://randomuser.me/api/portraits/men/62.jpg", + dm: true, + online: OnlineState.Unknown, + active: true, + } +}; + + export const DMOnline: Story = { args: { displayname: "test", avatarUrl: "https://randomuser.me/api/portraits/men/62.jpg", dm: true, - online: true, + online: OnlineState.Online, active: false, } }; @@ -119,7 +141,7 @@ export const DMOnlineActive: Story = { displayname: "test", avatarUrl: "https://randomuser.me/api/portraits/men/62.jpg", dm: true, - online: true, + online: OnlineState.Online, active: true, } }; @@ -129,7 +151,7 @@ export const DMNoAvatarOffline: Story = { displayname: "test", avatarUrl: "", dm: true, - online: false, + online: OnlineState.Offline, active: false, } }; @@ -139,7 +161,7 @@ export const DMNoAvatarOnline: Story = { displayname: "test", avatarUrl: "", dm: true, - online: true, + online: OnlineState.Online, active: false, } }; \ No newline at end of file diff --git a/src/components/roomList/roomListItem/roomListItem.tsx b/src/components/roomList/roomListItem/roomListItem.tsx @@ -2,6 +2,7 @@ import { useInView } from "react-intersection-observer"; import Avatar from "../../avatar/avatar"; import { FC, memo, useContext } from "react"; import { MatrixContext } from "../../../app/sdk/client"; +import { OnlineState } from "../../../app/sdk/api/otherEnums"; type RoomListItemProps = { /** @@ -23,7 +24,7 @@ type RoomListItemProps = { /** * Wether the user is online. Only used if dm is true. */ - online: boolean + online: OnlineState /** * Wether the current room is selected */ @@ -38,7 +39,7 @@ type RoomListItemProps = { hidden: boolean }; -const RoomListItem: FC<RoomListItemProps> = memo(({ roomId, avatarUrl, displayname, dm = false, online = false, active = false, onClick, hidden }: RoomListItemProps) => { +const RoomListItem: FC<RoomListItemProps> = memo(({ roomId, avatarUrl, displayname, dm = false, online = OnlineState.Unknown, active = false, onClick, hidden }: RoomListItemProps) => { const matrixClient = useContext(MatrixContext); const { ref, inView } = useInView({ triggerOnce: true, diff --git a/src/pages/MainPage.tsx b/src/pages/MainPage.tsx @@ -14,6 +14,7 @@ import MemberEvent from '../components/events/memberEvent'; import { IRoomEvent, IRoomMemberEvent } from '../app/sdk/api/apiTypes'; import Linkify from 'linkify-react'; import { RoomId } from '@mtrnord/matrix-sdk-crypto-js'; +import { OnlineState } from '../app/sdk/api/otherEnums'; type ChatViewProps = { /** @@ -266,7 +267,7 @@ const MainPage = memo(() => { displayname: room.getName(), avatarUrl: room.getAvatarURL(), dm: room.isDM(), - online: room.isOnline(), + online: room.presence, } }); @@ -279,7 +280,7 @@ const MainPage = memo(() => { displayname: room.getName(), avatarUrl: room.getAvatarURL(), dm: room.isDM(), - online: room.isOnline(), + online: room.presence, } }); @@ -313,7 +314,7 @@ const MainPage = memo(() => { displayname: room.getName(), avatarUrl: room.getAvatarURL(), dm: room.isDM(), - online: room.isOnline(), + online: room.presence, } }); @@ -334,7 +335,7 @@ const MainPage = memo(() => { return <div className='flex flex-row gap-2 min-h-screen h-screen'> <div className='flex flex-col bg-gradient-to-br from-slate-100 via-gray-200 to-orange-200 border-r-[1px] border-slate-300'> <div className='flex flex-row gap-2 m-2 p-1 items-center border-b-2'> - <Avatar displayname={profile.displayname || client.mxid!} avatarUrl={profile?.avatar_url} dm={false} online={false} /> + <Avatar displayname={profile.displayname || client.mxid!} avatarUrl={profile?.avatar_url} dm={false} online={OnlineState.Unknown} /> <div className='flex flex-row justify-between items-center w-full'> <span className='text-base font-semibold'>{profile?.displayname}</span> <Settings size={28} stroke='unset' className='stroke-slate-600 rounded-full hover:bg-slate-300 p-1 cursor-pointer' /> @@ -345,7 +346,7 @@ const MainPage = memo(() => { { room && <div className='flex-1 flex flex-col'> <div className='pb-2 flex flex-row items-center border-b-2 mt-4 ml-2'> - <Avatar displayname={room.getName()} avatarUrl={room.getAvatarURL()} dm={room.isDM()} online={room.isOnline()} /> + <Avatar displayname={room.getName()} avatarUrl={room.getAvatarURL()} dm={room.isDM()} online={room.presence} /> <div className='flex flex-row items-start'> <h1 className='text-black font-semibold text-lg flex-shrink-0'>{room.getName()}</h1> <Linkify options={linkifyOptions} as='p' className="ml-4 text-slate-700 font-normal text-base line-clamp-2 text-ellipsis">{room.getTopic()}</Linkify>