cetirizine.meta

Issues/PRs archive for MTRNord/cetirizine
git clone git://archive.git.mtrnord.blog/MTRNord/cetirizine.meta.git
Log | Files | Refs

8.diff (21033B)


      1 diff --git a/changelog.d/8.feature b/changelog.d/8.feature
      2 new file mode 100644
      3 index 0000000..ccf3dd6
      4 --- /dev/null
      5 +++ b/changelog.d/8.feature
      6 @@ -0,0 +1 @@
      7 +Add support for MSC4015
      8 \ No newline at end of file
      9 diff --git a/src/app/sdk/room.ts b/src/app/sdk/room.ts
     10 index edbba95..ba7a436 100644
     11 --- a/src/app/sdk/room.ts
     12 +++ b/src/app/sdk/room.ts
     13 @@ -223,18 +223,26 @@ export class Room extends EventEmitter {
     14      public getMemberAvatar(userID: string, size: number = 32): string | undefined {
     15          let avatarURL: string | undefined = undefined;
     16          this.stateEvents.forEach((event) => {
     17 -            if (event.type === "m.room.member") {
     18 -                if (event.state_key === userID && event.content.membership == "join") {
     19 -                    const rawAvatarURL = event.content.avatar_url;
     20 -                    if (rawAvatarURL?.startsWith("mxc://")) {
     21 -                        avatarURL = this.client.convertMXC(rawAvatarURL, size);
     22 -                    }
     23 +            if (event.type === "m.room.member" && event.state_key === userID && event.content.membership == "join") {
     24 +                const rawAvatarURL = event.content.avatar_url;
     25 +                if (rawAvatarURL?.startsWith("mxc://")) {
     26 +                    avatarURL = this.client.convertMXC(rawAvatarURL, size);
     27                  }
     28              }
     29          });
     30          return avatarURL;
     31      }
     32  
     33 +    public isBot(userID: string): boolean {
     34 +        let isBot: boolean = false;
     35 +        this.stateEvents.forEach((event) => {
     36 +            if (event.type === "m.room.member" && event.state_key === userID && event.content.membership == "join") {
     37 +                isBot = event.content.bot;
     38 +            }
     39 +        });
     40 +        return isBot;
     41 +    }
     42 +
     43      public isEncrypted(): boolean {
     44          let isEncrypted: boolean = false;
     45          this.stateEvents.forEach((event) => {
     46 diff --git a/src/components/avatar/avatar.tsx b/src/components/avatar/avatar.tsx
     47 index e32d0cf..f154e99 100644
     48 --- a/src/components/avatar/avatar.tsx
     49 +++ b/src/components/avatar/avatar.tsx
     50 @@ -18,6 +18,11 @@ type AvatarProps = {
     51       * Wether the user is online. Only used if dm is true.
     52       */
     53      online: OnlineState
     54 +    /**
     55 +     * Wether the user is a bot
     56 +     * @default false
     57 +     */
     58 +    isBot: boolean
     59  };
     60  
     61  const Avatar: FC<AvatarProps> = memo(({ avatarUrl, displayname, dm = false, online = OnlineState.Unknown }: AvatarProps) => {
     62 diff --git a/src/components/events/messageEvent.tsx b/src/components/events/messageEvent.tsx
     63 index 700eba7..fa9e9f7 100644
     64 --- a/src/components/events/messageEvent.tsx
     65 +++ b/src/components/events/messageEvent.tsx
     66 @@ -1,7 +1,6 @@
     67  import { memo, useContext, useEffect, useState } from "react";
     68  import { IRoomEvent, isRoomMessageAudioEvent, isRoomMessageImageEvent, isRoomMessageNoticeEvent, isRoomMessageTextEvent } from "../../app/sdk/api/events";
     69  import { FC } from "react";
     70 -import Avatar from "../avatar/avatar";
     71  import { MatrixClient, MatrixContext } from "../../app/sdk/client";
     72  import Linkify from "linkify-react";
     73  import linkifyHtml from 'linkify-html';
     74 @@ -13,6 +12,7 @@ import hljs from 'highlight.js';
     75  import 'highlight.js/styles/base16/solarized-dark.css';
     76  import { OnlineState } from "../../app/sdk/api/otherEnums";
     77  import { Room } from "../../app/sdk/room";
     78 +import { MessageWrapper } from "./wrapper";
     79  
     80  type MessageEventProps = {
     81      /**
     82 @@ -117,24 +117,22 @@ const MessageEvent: FC<MessageEventProps> = memo(({ event, room, hasPreviousEven
     83              }
     84  
     85              return (
     86 -                <div className={!hasPreviousEvent ? "flex flex-row gap-4 p-2 pb-1 hover:bg-gray-200 rounded-md duration-200 ease-in-out items-start" : "flex flex-row p-2 pb-1 pt-1 hover:bg-gray-200 rounded-md duration-200 ease-in-out"}>
     87 -                    {!hasPreviousEvent && <Avatar
     88 -                        displayname={room?.getMemberName(event.sender) || event.sender}
     89 -                        avatarUrl={room?.getMemberAvatar(event.sender)}
     90 -                        online={room?.presence || OnlineState.Unknown}
     91 -                        dm={room?.isDM() || false}
     92 -                    />}
     93 -                    <div className={!hasPreviousEvent ? "flex flex-col gap-1" : "ml-[3.7rem]"}>
     94 -                        {!hasPreviousEvent && <h2 className="text-xl font-medium text-red-500 whitespace-pre-wrap">{room?.getMemberName(event.sender) || event.sender}</h2>}
     95 -                        {/* TODO: Loading circle while image is loading */}
     96 -                        <img
     97 -                            src={url}
     98 -                            alt={event.content.body}
     99 -                            title={event.content.body}
    100 -                            className="rounded-md object-cover border-slate-400 border-2 max-h-[50rem] max-w-[50rem] h-[unset]"
    101 -                        />
    102 -                    </div>
    103 -                </div>
    104 +                <MessageWrapper
    105 +                    displayname={room?.getMemberName(event.sender) || event.sender}
    106 +                    avatar_url={room?.getMemberAvatar(event.sender) || ""}
    107 +                    onlineState={room?.presence || OnlineState.Unknown}
    108 +                    isBot={room?.isBot(event.sender) || false}
    109 +                    dm={room?.isDM() || false}
    110 +                    hasPreviousEvent={hasPreviousEvent}
    111 +                >
    112 +                    {/* TODO: Loading circle while image is loading */}
    113 +                    <img
    114 +                        src={url}
    115 +                        alt={event.content.body}
    116 +                        title={event.content.body}
    117 +                        className="rounded-md object-cover border-slate-400 border-2 max-h-[50rem] max-w-[50rem] h-[unset]"
    118 +                    />
    119 +                </MessageWrapper>
    120              )
    121          } else if (isRoomMessageAudioEvent(event)) {
    122              const [url, setUrl] = useState<string | undefined>(undefined);
    123 @@ -169,33 +167,29 @@ const MessageEvent: FC<MessageEventProps> = memo(({ event, room, hasPreviousEven
    124              }
    125  
    126              return (
    127 -                <div className={!hasPreviousEvent ? "flex flex-row gap-4 p-2 pb-1 hover:bg-gray-200 rounded-md duration-200 ease-in-out items-start" : "flex flex-row p-2 pb-1 pt-1 hover:bg-gray-200 rounded-md duration-200 ease-in-out"}>
    128 -                    {!hasPreviousEvent && <Avatar
    129 -                        displayname={room?.getMemberName(event.sender) || event.sender}
    130 -                        avatarUrl={room?.getMemberAvatar(event.sender)}
    131 -                        online={room?.presence || OnlineState.Unknown}
    132 -                        dm={room?.isDM() || false}
    133 -                    />}
    134 -                    <div className={!hasPreviousEvent ? "flex flex-col gap-1" : "flex-1 ml-[3.7rem]"}>
    135 -                        {!hasPreviousEvent && <h2 className="text-xl font-medium text-red-500 whitespace-pre-wrap">{room?.getMemberName(event.sender) || event.sender}</h2>}
    136 -                        {url && <Waveform src_url={url} />}
    137 -                    </div>
    138 -                </div>
    139 +                <MessageWrapper
    140 +                    displayname={room?.getMemberName(event.sender) || event.sender}
    141 +                    avatar_url={room?.getMemberAvatar(event.sender) || ""}
    142 +                    onlineState={room?.presence || OnlineState.Unknown}
    143 +                    isBot={room?.isBot(event.sender) || false}
    144 +                    dm={room?.isDM() || false}
    145 +                    hasPreviousEvent={hasPreviousEvent}
    146 +                >
    147 +                    {url && <Waveform src_url={url} />}
    148 +                </MessageWrapper>
    149              )
    150          } else {
    151              return (
    152 -                <div className={!hasPreviousEvent ? "flex flex-row gap-4 p-2 pb-1 hover:bg-gray-200 rounded-md duration-200 ease-in-out items-start" : "flex flex-row p-2 pb-1 pt-0 hover:bg-gray-200 rounded-md duration-200 ease-in-out"}>
    153 -                    {!hasPreviousEvent && <Avatar
    154 -                        displayname={room?.getMemberName(event.sender) || event.sender}
    155 -                        avatarUrl={room?.getMemberAvatar(event.sender)}
    156 -                        online={room?.presence || OnlineState.Unknown}
    157 -                        dm={room?.isDM() || false}
    158 -                    />}
    159 -                    <div className={!hasPreviousEvent ? "flex flex-col gap-1" : "ml-[3.7rem]"}>
    160 -                        {!hasPreviousEvent && <h2 className="text-xl font-medium text-red-500 whitespace-pre-wrap">{room?.getMemberName(event.sender) || event.sender}</h2>}
    161 -                        <Linkify options={linkifyOptions} as='p' className="text-black text-base font-normal">{event.content.body}</Linkify>
    162 -                    </div>
    163 -                </div>
    164 +                <MessageWrapper
    165 +                    displayname={room?.getMemberName(event.sender) || event.sender}
    166 +                    avatar_url={room?.getMemberAvatar(event.sender) || ""}
    167 +                    onlineState={room?.presence || OnlineState.Unknown}
    168 +                    isBot={room?.isBot(event.sender) || false}
    169 +                    dm={room?.isDM() || false}
    170 +                    hasPreviousEvent={hasPreviousEvent}
    171 +                >
    172 +                    <Linkify options={linkifyOptions} as='p' className="text-black text-base font-normal">{event.content.body}</Linkify>
    173 +                </MessageWrapper >
    174              )
    175          }
    176      }
    177 @@ -286,34 +280,30 @@ const TextMessage: FC<TextMessage> = memo(({ event, room, hasPreviousEvent, mess
    178          // TODO: sanitize the attributes allowed by matrix spec
    179  
    180          return (
    181 -            <div className={!hasPreviousEvent ? "flex flex-row gap-4 p-2 pb-1 hover:bg-gray-200 rounded-md duration-200 ease-in-out items-start" : "flex flex-row p-2 pb-1 pt-0 hover:bg-gray-200 rounded-md duration-200 ease-in-out"}>
    182 -                {!hasPreviousEvent && <Avatar
    183 -                    displayname={room?.getMemberName(event.sender) || event.sender}
    184 -                    avatarUrl={room?.getMemberAvatar(event.sender)}
    185 -                    online={room?.presence || OnlineState.Unknown}
    186 -                    dm={room?.isDM() || false}
    187 -                />}
    188 -                <div className={!hasPreviousEvent ? "flex flex-col gap-1" : "ml-[3.7rem]"}>
    189 -                    {!hasPreviousEvent && <h2 className="text-xl font-medium text-red-500 whitespace-pre-wrap">{room?.getMemberName(event.sender) || event.sender}</h2>}
    190 -                    {/* TODO: Fixme */}
    191 -                    <p className={`${text_color} text-base font-normal`} dangerouslySetInnerHTML={{ __html: linkified }}></p>
    192 -                </div>
    193 -            </div>
    194 +            <MessageWrapper
    195 +                displayname={room?.getMemberName(event.sender) || event.sender}
    196 +                avatar_url={room?.getMemberAvatar(event.sender) || ""}
    197 +                onlineState={room?.presence || OnlineState.Unknown}
    198 +                isBot={room?.isBot(event.sender) || false}
    199 +                dm={room?.isDM() || false}
    200 +                hasPreviousEvent={hasPreviousEvent}
    201 +            >
    202 +                {/* TODO: Fixme */}
    203 +                <p className={`${text_color} text-base font-normal`} dangerouslySetInnerHTML={{ __html: linkified }}></p>
    204 +            </MessageWrapper>
    205          )
    206      } else {
    207          return (
    208 -            <div className={!hasPreviousEvent ? "flex flex-row gap-4 p-2 pb-1 hover:bg-gray-200 rounded-md duration-200 ease-in-out items-start" : "flex flex-row p-2 pb-1 pt-0 hover:bg-gray-200 rounded-md duration-200 ease-in-out"}>
    209 -                {!hasPreviousEvent && <Avatar
    210 -                    displayname={room?.getMemberName(event.sender) || event.sender}
    211 -                    avatarUrl={room?.getMemberAvatar(event.sender)}
    212 -                    online={room?.presence || OnlineState.Unknown}
    213 -                    dm={room?.isDM() || false}
    214 -                />}
    215 -                <div className={!hasPreviousEvent ? "flex flex-col gap-1" : "ml-[3.7rem]"}>
    216 -                    {!hasPreviousEvent && <h2 className="text-xl font-medium text-red-500 whitespace-pre-wrap">{room?.getMemberName(event.sender) || event.sender}</h2>}
    217 -                    <Linkify options={linkifyOptions} as='p' className={`${text_color} text-base font-normal`}>{event.content.body}</Linkify>
    218 -                </div>
    219 -            </div>
    220 +            <MessageWrapper
    221 +                displayname={room?.getMemberName(event.sender) || event.sender}
    222 +                avatar_url={room?.getMemberAvatar(event.sender) || ""}
    223 +                onlineState={room?.presence || OnlineState.Unknown}
    224 +                isBot={room?.isBot(event.sender) || false}
    225 +                dm={room?.isDM() || false}
    226 +                hasPreviousEvent={hasPreviousEvent}
    227 +            >
    228 +                <Linkify options={linkifyOptions} as='p' className={`${text_color} text-base font-normal`}>{event.content.body}</Linkify>
    229 +            </MessageWrapper>
    230          )
    231      }
    232  })
    233 diff --git a/src/components/events/unknownEvent.tsx b/src/components/events/unknownEvent.tsx
    234 index d67f8f6..98886a8 100644
    235 --- a/src/components/events/unknownEvent.tsx
    236 +++ b/src/components/events/unknownEvent.tsx
    237 @@ -2,9 +2,9 @@ import { memo } from "react";
    238  import { IRoomEvent } from "../../app/sdk/api/events";
    239  import { FC } from "react";
    240  import Linkify from "linkify-react";
    241 -import Avatar from "../avatar/avatar";
    242  import { OnlineState } from "../../app/sdk/api/otherEnums";
    243  import { Room } from "../../app/sdk/room";
    244 +import { MessageWrapper } from "./wrapper";
    245  
    246  type UnknownEventProps = {
    247      /**
    248 @@ -30,18 +30,16 @@ const linkifyOptions = {
    249  
    250  const UnknownEvent: FC<UnknownEventProps> = memo(({ event, room, hasPreviousEvent }) => {
    251      return (
    252 -        <div className={!hasPreviousEvent ? "flex flex-row gap-4 p-2 pb-1 hover:bg-gray-200 rounded-md duration-200 ease-in-out items-start" : "flex flex-row p-2 pb-1 pt-0 hover:bg-gray-200 rounded-md duration-200 ease-in-out"}>
    253 -            {!hasPreviousEvent && <Avatar
    254 -                displayname={room?.getMemberName(event.sender) || event.sender}
    255 -                avatarUrl={room?.getMemberAvatar(event.sender)}
    256 -                online={room?.presence || OnlineState.Unknown}
    257 -                dm={room?.isDM() || false}
    258 -            />}
    259 -            <div className={!hasPreviousEvent ? "flex flex-col gap-1" : "ml-[3.7rem]"}>
    260 -                {!hasPreviousEvent && <h2 className="text-xl font-medium text-red-500 whitespace-pre-wrap">{room?.getMemberName(event.sender) || event.sender}</h2>}
    261 -                <Linkify options={linkifyOptions} as='p' className="whitespace-break-spaces text-black text-base font-normal">{JSON.stringify(event, null, 4)}</Linkify>
    262 -            </div>
    263 -        </div>
    264 +        <MessageWrapper
    265 +            displayname={room?.getMemberName(event.sender) || event.sender}
    266 +            avatar_url={room?.getMemberAvatar(event.sender) || ""}
    267 +            onlineState={room?.presence || OnlineState.Unknown}
    268 +            isBot={room?.isBot(event.sender) || false}
    269 +            dm={room?.isDM() || false}
    270 +            hasPreviousEvent={hasPreviousEvent}
    271 +        >
    272 +            <Linkify options={linkifyOptions} as='p' className="whitespace-break-spaces text-black text-base font-normal">{JSON.stringify(event, null, 4)}</Linkify>
    273 +        </MessageWrapper>
    274      )
    275  });
    276  
    277 @@ -64,18 +62,16 @@ type UndecryptableEventProps = {
    278  
    279  export const UndecryptableEvent: FC<UndecryptableEventProps> = memo(({ event, room, hasPreviousEvent }) => {
    280      return (
    281 -        <div className={!hasPreviousEvent ? "flex flex-row gap-4 p-2 pb-1 hover:bg-gray-200 rounded-md duration-200 ease-in-out items-start" : "flex flex-row p-2 pb-1 pt-0 hover:bg-gray-200 rounded-md duration-200 ease-in-out"}>
    282 -            {!hasPreviousEvent && <Avatar
    283 -                displayname={room?.getMemberName(event.sender) || event.sender}
    284 -                avatarUrl={room?.getMemberAvatar(event.sender)}
    285 -                online={room?.presence || OnlineState.Unknown}
    286 -                dm={room?.isDM() || false}
    287 -            />}
    288 -            <div className={!hasPreviousEvent ? "flex flex-col gap-1" : "ml-[3.7rem]"}>
    289 -                {!hasPreviousEvent && <h2 className="text-xl font-medium text-red-500 whitespace-pre-wrap">{room?.getMemberName(event.sender) || event.sender}</h2>}
    290 -                <Linkify options={linkifyOptions} as='p' className="whitespace-pre-wrap text-base font-normal text-orange-600">Unable to decrypt event</Linkify>
    291 -            </div>
    292 -        </div>
    293 +        <MessageWrapper
    294 +            displayname={room?.getMemberName(event.sender) || event.sender}
    295 +            avatar_url={room?.getMemberAvatar(event.sender) || ""}
    296 +            onlineState={room?.presence || OnlineState.Unknown}
    297 +            isBot={room?.isBot(event.sender) || false}
    298 +            dm={room?.isDM() || false}
    299 +            hasPreviousEvent={hasPreviousEvent}
    300 +        >
    301 +            <Linkify options={linkifyOptions} as='p' className="whitespace-pre-wrap text-base font-normal text-orange-600">Unable to decrypt event</Linkify>
    302 +        </MessageWrapper>
    303      )
    304  });
    305  
    306 @@ -100,19 +96,17 @@ type RedactedEventProps = {
    307  
    308  export const RedactedEvent: FC<RedactedEventProps> = memo(({ event, redacted_because, room, hasPreviousEvent }) => {
    309      return (
    310 -        <div className={!hasPreviousEvent ? "flex flex-row gap-4 p-2 pb-1 hover:bg-gray-200 rounded-md duration-200 ease-in-out items-start" : "flex flex-row p-2 pb-1 pt-0 hover:bg-gray-200 rounded-md duration-200 ease-in-out"}>
    311 -            {!hasPreviousEvent && <Avatar
    312 -                displayname={room?.getMemberName(event.sender) || event.sender}
    313 -                avatarUrl={room?.getMemberAvatar(event.sender)}
    314 -                online={room?.presence || OnlineState.Unknown}
    315 -                dm={room?.isDM() || false}
    316 -            />}
    317 -            <div className={!hasPreviousEvent ? "flex flex-col gap-1" : "ml-[3.7rem]"}>
    318 -                {!hasPreviousEvent && <h2 className="text-xl font-medium text-red-500 whitespace-pre-wrap">{room?.getMemberName(event.sender) || event.sender}</h2>}
    319 -                {redacted_because && <p className="whitespace-pre-wrap text-base font-normal text-blue-600 italic">Message was redacted: {redacted_because}</p>}
    320 -                {!redacted_because && <p className="whitespace-pre-wrap text-base font-normal text-blue-600 italic">Message was redacted</p>}
    321 -            </div>
    322 -        </div>
    323 +        <MessageWrapper
    324 +            displayname={room?.getMemberName(event.sender) || event.sender}
    325 +            avatar_url={room?.getMemberAvatar(event.sender) || ""}
    326 +            onlineState={room?.presence || OnlineState.Unknown}
    327 +            isBot={room?.isBot(event.sender) || false}
    328 +            dm={room?.isDM() || false}
    329 +            hasPreviousEvent={hasPreviousEvent}
    330 +        >
    331 +            {redacted_because && <p className="whitespace-pre-wrap text-base font-normal text-blue-600 italic">Message was redacted: {redacted_because}</p>}
    332 +            {!redacted_because && <p className="whitespace-pre-wrap text-base font-normal text-blue-600 italic">Message was redacted</p>}
    333 +        </MessageWrapper>
    334      )
    335  });
    336  
    337 diff --git a/src/components/events/wrapper.tsx b/src/components/events/wrapper.tsx
    338 new file mode 100644
    339 index 0000000..23be1ee
    340 --- /dev/null
    341 +++ b/src/components/events/wrapper.tsx
    342 @@ -0,0 +1,54 @@
    343 +import { FC, memo } from "react";
    344 +import { OnlineState } from "../../app/sdk/api/otherEnums";
    345 +import Avatar from "../avatar/avatar";
    346 +import { Bot } from "lucide-react";
    347 +
    348 +export type MessageWrapperProps = {
    349 +    /**
    350 +     * The displayname to render
    351 +     */
    352 +    displayname: string;
    353 +    /**
    354 +     * The avatar_url to render
    355 +     */
    356 +    avatar_url: string;
    357 +    /**
    358 +     * If the sender is a bot
    359 +     */
    360 +    isBot: boolean;
    361 +    /**
    362 +     * If the sender is online
    363 +     */
    364 +    onlineState: OnlineState;
    365 +    /**
    366 +     * If the room is a DM
    367 +     */
    368 +    dm: boolean;
    369 +    /**
    370 +     * If the previous event was sent by the same user
    371 +     */
    372 +    hasPreviousEvent?: boolean;
    373 +    /**
    374 +     * Children to render
    375 +     */
    376 +    children: React.ReactNode;
    377 +};
    378 +
    379 +
    380 +export const MessageWrapper: FC<MessageWrapperProps> = memo(({ hasPreviousEvent, displayname, avatar_url, onlineState, isBot, dm, children }) => {
    381 +    return (
    382 +        <div className={!hasPreviousEvent ? "flex flex-row gap-4 p-2 pb-1 hover:bg-gray-200 rounded-md duration-200 ease-in-out items-start" : "flex flex-row p-2 pb-1 pt-1 hover:bg-gray-200 rounded-md duration-200 ease-in-out"}>
    383 +            {!hasPreviousEvent && <Avatar
    384 +                displayname={displayname}
    385 +                avatarUrl={avatar_url}
    386 +                online={onlineState}
    387 +                dm={dm}
    388 +                isBot={isBot}
    389 +            />}
    390 +            <div className={!hasPreviousEvent ? "flex flex-col gap-1" : "ml-[3.7rem]"}>
    391 +                {!hasPreviousEvent && <h2 className="flex flex-row items-center gap-2 text-base font-medium text-red-500 whitespace-pre-wrap">{isBot ? <Bot size={16} /> : <></>}{displayname}</h2>}
    392 +                {children}
    393 +            </div>
    394 +        </div>
    395 +    )
    396 +});
    397 \ No newline at end of file