Compare commits

..

4 Commits

Author SHA1 Message Date
Ajay Bura c69236ff79 add mxid color toggle 2024-09-20 11:20:46 +05:30
Krishan 21164a9b61 Release v4.2.1 (#1953) 2024-09-14 23:24:34 +10:00
Krishan 4923b17ad6 Fix auth media check for dendrite (#1952) 2024-09-14 18:54:06 +05:30
Krishan c75e903619 Release v4.2.0 (#1949) 2024-09-11 19:26:08 +05:30
17 changed files with 149 additions and 102 deletions
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "cinny", "name": "cinny",
"version": "4.1.0", "version": "4.2.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "cinny", "name": "cinny",
"version": "4.1.0", "version": "4.2.1",
"license": "AGPL-3.0-only", "license": "AGPL-3.0-only",
"dependencies": { "dependencies": {
"@atlaskit/pragmatic-drag-and-drop": "1.1.6", "@atlaskit/pragmatic-drag-and-drop": "1.1.6",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "cinny", "name": "cinny",
"version": "4.1.0", "version": "4.2.1",
"description": "Yet another matrix client", "description": "Yet another matrix client",
"main": "index.js", "main": "index.js",
"type": "module", "type": "module",
+3 -2
View File
@@ -48,6 +48,7 @@ export const ThreadIndicator = as<'div'>(({ ...props }, ref) => (
type ReplyProps = { type ReplyProps = {
mx: MatrixClient; mx: MatrixClient;
room: Room; room: Room;
mxidColor?: boolean;
timelineSet?: EventTimelineSet | undefined; timelineSet?: EventTimelineSet | undefined;
replyEventId: string; replyEventId: string;
threadRootId?: string | undefined; threadRootId?: string | undefined;
@@ -55,7 +56,7 @@ type ReplyProps = {
}; };
export const Reply = as<'div', ReplyProps>((_, ref) => { export const Reply = as<'div', ReplyProps>((_, ref) => {
const { mx, room, timelineSet, replyEventId, threadRootId, onClick, ...props } = _; const { mx, room, mxidColor, timelineSet, replyEventId, threadRootId, onClick, ...props } = _;
const [replyEvent, setReplyEvent] = useState<MatrixEvent | null | undefined>( const [replyEvent, setReplyEvent] = useState<MatrixEvent | null | undefined>(
timelineSet?.findEventById(replyEventId) timelineSet?.findEventById(replyEventId)
); );
@@ -101,7 +102,7 @@ export const Reply = as<'div', ReplyProps>((_, ref) => {
)} )}
<ReplyLayout <ReplyLayout
as="button" as="button"
userColor={sender ? colorMXID(sender) : undefined} userColor={sender && mxidColor ? colorMXID(sender) : undefined}
username={ username={
sender && ( sender && (
<Text size="T300" truncate> <Text size="T300" truncate>
@@ -55,6 +55,7 @@ export function MessageSearch({
const allRooms = useRooms(mx, allRoomsAtom, mDirects); const allRooms = useRooms(mx, allRoomsAtom, mDirects);
const [mediaAutoLoad] = useSetting(settingsAtom, 'mediaAutoLoad'); const [mediaAutoLoad] = useSetting(settingsAtom, 'mediaAutoLoad');
const [urlPreview] = useSetting(settingsAtom, 'urlPreview'); const [urlPreview] = useSetting(settingsAtom, 'urlPreview');
const [mxidColor] = useSetting(settingsAtom, 'mxidColor');
const searchInputRef = useRef<HTMLInputElement>(null); const searchInputRef = useRef<HTMLInputElement>(null);
const scrollTopAnchorRef = useRef<HTMLDivElement>(null); const scrollTopAnchorRef = useRef<HTMLDivElement>(null);
const [searchParams, setSearchParams] = useSearchParams(); const [searchParams, setSearchParams] = useSearchParams();
@@ -296,6 +297,7 @@ export function MessageSearch({
items={group.items} items={group.items}
mediaAutoLoad={mediaAutoLoad} mediaAutoLoad={mediaAutoLoad}
urlPreview={urlPreview} urlPreview={urlPreview}
mxidColor={mxidColor}
onOpen={navigateRoom} onOpen={navigateRoom}
/> />
</VirtualTile> </VirtualTile>
@@ -46,6 +46,7 @@ type SearchResultGroupProps = {
items: ResultItem[]; items: ResultItem[];
mediaAutoLoad?: boolean; mediaAutoLoad?: boolean;
urlPreview?: boolean; urlPreview?: boolean;
mxidColor?: boolean;
onOpen: (roomId: string, eventId: string) => void; onOpen: (roomId: string, eventId: string) => void;
}; };
export function SearchResultGroup({ export function SearchResultGroup({
@@ -54,6 +55,7 @@ export function SearchResultGroup({
items, items,
mediaAutoLoad, mediaAutoLoad,
urlPreview, urlPreview,
mxidColor,
onOpen, onOpen,
}: SearchResultGroupProps) { }: SearchResultGroupProps) {
const mx = useMatrixClient(); const mx = useMatrixClient();
@@ -81,7 +83,15 @@ export function SearchResultGroup({
handleSpoilerClick: spoilerClickHandler, handleSpoilerClick: spoilerClickHandler,
handleMentionClick: mentionClickHandler, handleMentionClick: mentionClickHandler,
}), }),
[mx, room, linkifyOpts, highlightRegex, mentionClickHandler, spoilerClickHandler, useAuthentication] [
mx,
room,
linkifyOpts,
highlightRegex,
mentionClickHandler,
spoilerClickHandler,
useAuthentication,
]
); );
const renderMatrixEvent = useMatrixEventRenderer<[IEventWithRoomId, string, GetContentCallback]>( const renderMatrixEvent = useMatrixEventRenderer<[IEventWithRoomId, string, GetContentCallback]>(
@@ -212,7 +222,14 @@ export function SearchResultGroup({
userId={event.sender} userId={event.sender}
src={ src={
senderAvatarMxc senderAvatarMxc
? mxcUrlToHttp(mx, senderAvatarMxc, useAuthentication, 48, 48, 'crop') ?? undefined ? mxcUrlToHttp(
mx,
senderAvatarMxc,
useAuthentication,
48,
48,
'crop'
) ?? undefined
: undefined : undefined
} }
alt={displayName} alt={displayName}
@@ -224,7 +241,7 @@ export function SearchResultGroup({
> >
<Box gap="300" justifyContent="SpaceBetween" alignItems="Center" grow="Yes"> <Box gap="300" justifyContent="SpaceBetween" alignItems="Center" grow="Yes">
<Box gap="200" alignItems="Baseline"> <Box gap="200" alignItems="Baseline">
<Username style={{ color: colorMXID(event.sender) }}> <Username style={{ color: mxidColor ? colorMXID(event.sender) : undefined }}>
<Text as="span" truncate> <Text as="span" truncate>
<b>{displayName}</b> <b>{displayName}</b>
</Text> </Text>
@@ -246,6 +263,7 @@ export function SearchResultGroup({
<Reply <Reply
mx={mx} mx={mx}
room={room} room={room}
mxidColor={mxidColor}
replyEventId={replyEventId} replyEventId={replyEventId}
threadRootId={threadRootId} threadRootId={threadRootId}
onClick={handleOpenClick} onClick={handleOpenClick}
+9 -2
View File
@@ -56,7 +56,13 @@ import {
} from '../../components/editor'; } from '../../components/editor';
import { EmojiBoard, EmojiBoardTab } from '../../components/emoji-board'; import { EmojiBoard, EmojiBoardTab } from '../../components/emoji-board';
import { UseStateProvider } from '../../components/UseStateProvider'; import { UseStateProvider } from '../../components/UseStateProvider';
import { TUploadContent, encryptFile, getImageInfo, getMxIdLocalPart, mxcUrlToHttp } from '../../utils/matrix'; import {
TUploadContent,
encryptFile,
getImageInfo,
getMxIdLocalPart,
mxcUrlToHttp,
} from '../../utils/matrix';
import { useTypingStatusUpdater } from '../../hooks/useTypingStatusUpdater'; import { useTypingStatusUpdater } from '../../hooks/useTypingStatusUpdater';
import { useFilePicker } from '../../hooks/useFilePicker'; import { useFilePicker } from '../../hooks/useFilePicker';
import { useFilePasteHandler } from '../../hooks/useFilePasteHandler'; import { useFilePasteHandler } from '../../hooks/useFilePasteHandler';
@@ -120,6 +126,7 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
({ editor, fileDropContainerRef, roomId, room }, ref) => { ({ editor, fileDropContainerRef, roomId, room }, ref) => {
const mx = useMatrixClient(); const mx = useMatrixClient();
const useAuthentication = useMediaAuthentication(); const useAuthentication = useMediaAuthentication();
const [mxidColor] = useSetting(settingsAtom, 'mxidColor');
const [enterForNewline] = useSetting(settingsAtom, 'enterForNewline'); const [enterForNewline] = useSetting(settingsAtom, 'enterForNewline');
const [isMarkdown] = useSetting(settingsAtom, 'isMarkdown'); const [isMarkdown] = useSetting(settingsAtom, 'isMarkdown');
const commands = useCommands(mx, room); const commands = useCommands(mx, room);
@@ -499,7 +506,7 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
<Box direction="Column"> <Box direction="Column">
{replyDraft.relation?.rel_type === RelationType.Thread && <ThreadIndicator />} {replyDraft.relation?.rel_type === RelationType.Thread && <ThreadIndicator />}
<ReplyLayout <ReplyLayout
userColor={colorMXID(replyDraft.userId)} userColor={mxidColor ? colorMXID(replyDraft.userId) : undefined}
username={ username={
<Text size="T300" truncate> <Text size="T300" truncate>
<b> <b>
+6
View File
@@ -424,6 +424,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
const encryptedRoom = mx.isRoomEncrypted(room.roomId); const encryptedRoom = mx.isRoomEncrypted(room.roomId);
const [messageLayout] = useSetting(settingsAtom, 'messageLayout'); const [messageLayout] = useSetting(settingsAtom, 'messageLayout');
const [messageSpacing] = useSetting(settingsAtom, 'messageSpacing'); const [messageSpacing] = useSetting(settingsAtom, 'messageSpacing');
const [mxidColor] = useSetting(settingsAtom, 'mxidColor');
const [hideMembershipEvents] = useSetting(settingsAtom, 'hideMembershipEvents'); const [hideMembershipEvents] = useSetting(settingsAtom, 'hideMembershipEvents');
const [hideNickAvatarEvents] = useSetting(settingsAtom, 'hideNickAvatarEvents'); const [hideNickAvatarEvents] = useSetting(settingsAtom, 'hideNickAvatarEvents');
const [mediaAutoLoad] = useSetting(settingsAtom, 'mediaAutoLoad'); const [mediaAutoLoad] = useSetting(settingsAtom, 'mediaAutoLoad');
@@ -978,6 +979,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
mEvent={mEvent} mEvent={mEvent}
messageSpacing={messageSpacing} messageSpacing={messageSpacing}
messageLayout={messageLayout} messageLayout={messageLayout}
mxidColor={mxidColor}
collapse={collapse} collapse={collapse}
highlight={highlighted} highlight={highlighted}
edit={editId === mEventId} edit={editId === mEventId}
@@ -995,6 +997,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
<Reply <Reply
mx={mx} mx={mx}
room={room} room={room}
mxidColor={mxidColor}
timelineSet={timelineSet} timelineSet={timelineSet}
replyEventId={replyEventId} replyEventId={replyEventId}
threadRootId={threadRootId} threadRootId={threadRootId}
@@ -1050,6 +1053,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
mEvent={mEvent} mEvent={mEvent}
messageSpacing={messageSpacing} messageSpacing={messageSpacing}
messageLayout={messageLayout} messageLayout={messageLayout}
mxidColor={mxidColor}
collapse={collapse} collapse={collapse}
highlight={highlighted} highlight={highlighted}
edit={editId === mEventId} edit={editId === mEventId}
@@ -1067,6 +1071,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
<Reply <Reply
mx={mx} mx={mx}
room={room} room={room}
mxidColor={mxidColor}
timelineSet={timelineSet} timelineSet={timelineSet}
replyEventId={replyEventId} replyEventId={replyEventId}
threadRootId={threadRootId} threadRootId={threadRootId}
@@ -1159,6 +1164,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
mEvent={mEvent} mEvent={mEvent}
messageSpacing={messageSpacing} messageSpacing={messageSpacing}
messageLayout={messageLayout} messageLayout={messageLayout}
mxidColor={mxidColor}
collapse={collapse} collapse={collapse}
highlight={highlighted} highlight={highlighted}
canDelete={canRedact || mEvent.getSender() === mx.getUserId()} canDelete={canRedact || mEvent.getSender() === mx.getUserId()}
+9 -2
View File
@@ -51,7 +51,12 @@ import {
getMemberAvatarMxc, getMemberAvatarMxc,
getMemberDisplayName, getMemberDisplayName,
} from '../../../utils/room'; } from '../../../utils/room';
import { getCanonicalAliasOrRoomId, getMxIdLocalPart, isRoomAlias, mxcUrlToHttp } from '../../../utils/matrix'; import {
getCanonicalAliasOrRoomId,
getMxIdLocalPart,
isRoomAlias,
mxcUrlToHttp,
} from '../../../utils/matrix';
import { MessageLayout, MessageSpacing } from '../../../state/settings'; import { MessageLayout, MessageSpacing } from '../../../state/settings';
import { useMatrixClient } from '../../../hooks/useMatrixClient'; import { useMatrixClient } from '../../../hooks/useMatrixClient';
import { useRecentEmoji } from '../../../hooks/useRecentEmoji'; import { useRecentEmoji } from '../../../hooks/useRecentEmoji';
@@ -615,6 +620,7 @@ export type MessageProps = {
relations?: Relations; relations?: Relations;
messageLayout: MessageLayout; messageLayout: MessageLayout;
messageSpacing: MessageSpacing; messageSpacing: MessageSpacing;
mxidColor?: boolean;
onUserClick: MouseEventHandler<HTMLButtonElement>; onUserClick: MouseEventHandler<HTMLButtonElement>;
onUsernameClick: MouseEventHandler<HTMLButtonElement>; onUsernameClick: MouseEventHandler<HTMLButtonElement>;
onReplyClick: MouseEventHandler<HTMLButtonElement>; onReplyClick: MouseEventHandler<HTMLButtonElement>;
@@ -638,6 +644,7 @@ export const Message = as<'div', MessageProps>(
relations, relations,
messageLayout, messageLayout,
messageSpacing, messageSpacing,
mxidColor,
onUserClick, onUserClick,
onUsernameClick, onUsernameClick,
onReplyClick, onReplyClick,
@@ -673,7 +680,7 @@ export const Message = as<'div', MessageProps>(
> >
<Username <Username
as="button" as="button"
style={{ color: colorMXID(senderId) }} style={mxidColor ? { color: colorMXID(senderId) } : undefined}
data-user-id={senderId} data-user-id={senderId}
onContextMenu={onUserClick} onContextMenu={onUserClick}
onClick={onUsernameClick} onClick={onUsernameClick}
+3 -2
View File
@@ -1,10 +1,11 @@
import { useSpecVersions } from './useSpecVersions'; import { useSpecVersions } from './useSpecVersions';
export const useMediaAuthentication = (): boolean => { export const useMediaAuthentication = (): boolean => {
const { versions } = useSpecVersions(); const { versions, unstable_features: unstableFeatures } = useSpecVersions();
// Media authentication is introduced in spec version 1.11 // Media authentication is introduced in spec version 1.11
const authenticatedMedia = versions.includes('v1.11'); const authenticatedMedia =
unstableFeatures?.['org.matrix.msc3916.stable'] || versions.includes('v1.11');
return authenticatedMedia; return authenticatedMedia;
}; };
+6
View File
@@ -54,6 +54,7 @@ function AppearanceSection() {
const [enterForNewline, setEnterForNewline] = useSetting(settingsAtom, 'enterForNewline'); const [enterForNewline, setEnterForNewline] = useSetting(settingsAtom, 'enterForNewline');
const [messageLayout, setMessageLayout] = useSetting(settingsAtom, 'messageLayout'); const [messageLayout, setMessageLayout] = useSetting(settingsAtom, 'messageLayout');
const [messageSpacing, setMessageSpacing] = useSetting(settingsAtom, 'messageSpacing'); const [messageSpacing, setMessageSpacing] = useSetting(settingsAtom, 'messageSpacing');
const [mxidColor, setMXIDColor] = useSetting(settingsAtom, 'mxidColor');
const [twitterEmoji, setTwitterEmoji] = useSetting(settingsAtom, 'twitterEmoji'); const [twitterEmoji, setTwitterEmoji] = useSetting(settingsAtom, 'twitterEmoji');
const [pageZoom, setPageZoom] = useSetting(settingsAtom, 'pageZoom'); const [pageZoom, setPageZoom] = useSetting(settingsAtom, 'pageZoom');
const [isMarkdown, setIsMarkdown] = useSetting(settingsAtom, 'isMarkdown'); const [isMarkdown, setIsMarkdown] = useSetting(settingsAtom, 'isMarkdown');
@@ -189,6 +190,11 @@ function AppearanceSection() {
/> />
} }
/> />
<SettingTile
title="Username Color"
options={<Toggle isActive={mxidColor} onToggle={() => setMXIDColor(!mxidColor)} />}
content={<Text variant="b3">Color username with matrix userID.</Text>}
/>
<SettingTile <SettingTile
title="Use ENTER for Newline" title="Use ENTER for Newline"
options={ options={
+1 -1
View File
@@ -15,7 +15,7 @@ export function AuthFooter() {
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
> >
v4.1.0 v4.2.1
</Text> </Text>
<Text as="a" size="T300" href="https://twitter.com/cinnyapp" target="_blank" rel="noreferrer"> <Text as="a" size="T300" href="https://twitter.com/cinnyapp" target="_blank" rel="noreferrer">
Twitter Twitter
+1 -1
View File
@@ -24,7 +24,7 @@ export function WelcomePage() {
target="_blank" target="_blank"
rel="noreferrer noopener" rel="noreferrer noopener"
> >
v4.1.0 v4.2.1
</a> </a>
</span> </span>
} }
+14 -2
View File
@@ -182,6 +182,7 @@ type RoomNotificationsGroupProps = {
notifications: INotification[]; notifications: INotification[];
mediaAutoLoad?: boolean; mediaAutoLoad?: boolean;
urlPreview?: boolean; urlPreview?: boolean;
mxidColor?: boolean;
onOpen: (roomId: string, eventId: string) => void; onOpen: (roomId: string, eventId: string) => void;
}; };
function RoomNotificationsGroupComp({ function RoomNotificationsGroupComp({
@@ -189,6 +190,7 @@ function RoomNotificationsGroupComp({
notifications, notifications,
mediaAutoLoad, mediaAutoLoad,
urlPreview, urlPreview,
mxidColor,
onOpen, onOpen,
}: RoomNotificationsGroupProps) { }: RoomNotificationsGroupProps) {
const mx = useMatrixClient(); const mx = useMatrixClient();
@@ -427,7 +429,14 @@ function RoomNotificationsGroupComp({
userId={event.sender} userId={event.sender}
src={ src={
senderAvatarMxc senderAvatarMxc
? mxcUrlToHttp(mx, senderAvatarMxc, useAuthentication, 48, 48, 'crop') ?? undefined ? mxcUrlToHttp(
mx,
senderAvatarMxc,
useAuthentication,
48,
48,
'crop'
) ?? undefined
: undefined : undefined
} }
alt={displayName} alt={displayName}
@@ -439,7 +448,7 @@ function RoomNotificationsGroupComp({
> >
<Box gap="300" justifyContent="SpaceBetween" alignItems="Center" grow="Yes"> <Box gap="300" justifyContent="SpaceBetween" alignItems="Center" grow="Yes">
<Box gap="200" alignItems="Baseline"> <Box gap="200" alignItems="Baseline">
<Username style={{ color: colorMXID(event.sender) }}> <Username style={{ color: mxidColor ? colorMXID(event.sender) : undefined }}>
<Text as="span" truncate> <Text as="span" truncate>
<b>{displayName}</b> <b>{displayName}</b>
</Text> </Text>
@@ -461,6 +470,7 @@ function RoomNotificationsGroupComp({
<Reply <Reply
mx={mx} mx={mx}
room={room} room={room}
mxidColor={mxidColor}
replyEventId={replyEventId} replyEventId={replyEventId}
threadRootId={threadRootId} threadRootId={threadRootId}
onClick={handleOpenClick} onClick={handleOpenClick}
@@ -492,6 +502,7 @@ export function Notifications() {
const mx = useMatrixClient(); const mx = useMatrixClient();
const [mediaAutoLoad] = useSetting(settingsAtom, 'mediaAutoLoad'); const [mediaAutoLoad] = useSetting(settingsAtom, 'mediaAutoLoad');
const [urlPreview] = useSetting(settingsAtom, 'urlPreview'); const [urlPreview] = useSetting(settingsAtom, 'urlPreview');
const [mxidColor] = useSetting(settingsAtom, 'mxidColor');
const screenSize = useScreenSizeContext(); const screenSize = useScreenSizeContext();
const { navigateRoom } = useRoomNavigate(); const { navigateRoom } = useRoomNavigate();
@@ -648,6 +659,7 @@ export function Notifications() {
<RoomNotificationsGroupComp <RoomNotificationsGroupComp
room={groupRoom} room={groupRoom}
notifications={group.notifications} notifications={group.notifications}
mxidColor={mxidColor}
mediaAutoLoad={mediaAutoLoad} mediaAutoLoad={mediaAutoLoad}
urlPreview={urlPreview} urlPreview={urlPreview}
onOpen={navigateRoom} onOpen={navigateRoom}
+2
View File
@@ -17,6 +17,7 @@ export interface Settings {
enterForNewline: boolean; enterForNewline: boolean;
messageLayout: MessageLayout; messageLayout: MessageLayout;
messageSpacing: MessageSpacing; messageSpacing: MessageSpacing;
mxidColor: boolean;
hideMembershipEvents: boolean; hideMembershipEvents: boolean;
hideNickAvatarEvents: boolean; hideNickAvatarEvents: boolean;
mediaAutoLoad: boolean; mediaAutoLoad: boolean;
@@ -41,6 +42,7 @@ const defaultSettings: Settings = {
enterForNewline: false, enterForNewline: false,
messageLayout: 0, messageLayout: 0,
messageSpacing: '400', messageSpacing: '400',
mxidColor: true,
hideMembershipEvents: false, hideMembershipEvents: false,
hideNickAvatarEvents: true, hideNickAvatarEvents: true,
mediaAutoLoad: true, mediaAutoLoad: true,
+1 -1
View File
@@ -1,5 +1,5 @@
const cons = { const cons = {
version: '4.1.0', version: '4.2.1',
secretKey: { secretKey: {
ACCESS_TOKEN: 'cinny_access_token', ACCESS_TOKEN: 'cinny_access_token',
DEVICE_ID: 'cinny_device_id', DEVICE_ID: 'cinny_device_id',
+6 -11
View File
@@ -21,30 +21,25 @@ import './app/i18n';
document.body.classList.add(configClass, varsClass); document.body.classList.add(configClass, varsClass);
settings.applyTheme(); settings.applyTheme();
const registerServiceWorker = async () => { // Register Service Worker
if ('serviceWorker' in navigator) { if ('serviceWorker' in navigator) {
const swUrl = const swUrl =
import.meta.env.MODE === 'production' import.meta.env.MODE === 'production'
? `${trimTrailingSlash(import.meta.env.BASE_URL)}/sw.js` ? `${trimTrailingSlash(import.meta.env.BASE_URL)}/sw.js`
: `/dev-sw.js?dev-sw`; : `/dev-sw.js?dev-sw`;
await navigator.serviceWorker.register(swUrl); navigator.serviceWorker.register(swUrl);
navigator.serviceWorker.ready.then((registration) => {
navigator.serviceWorker.addEventListener('message', (event) => { navigator.serviceWorker.addEventListener('message', (event) => {
if (event.data?.type === 'token' && event.data?.messageId) { if (event.data?.type === 'token' && event.data?.responseKey) {
// Get the token for SW.
const token = localStorage.getItem('cinny_access_token') ?? undefined; const token = localStorage.getItem('cinny_access_token') ?? undefined;
registration.active?.postMessage({ event.source!.postMessage({
messageId: event.data.messageId, responseKey: event.data.responseKey,
token, token,
}); });
} }
}); });
});
} }
};
window.addEventListener('load', registerServiceWorker);
const mountApp = () => { const mountApp = () => {
const rootContainer = document.getElementById('root'); const rootContainer = document.getElementById('root');
+8 -18
View File
@@ -3,26 +3,16 @@
export type {}; export type {};
declare const self: ServiceWorkerGlobalScope; declare const self: ServiceWorkerGlobalScope;
type Message = { messageId: string };
type MessageListener = (message: Message) => void;
const messageListeners = new Map<string, MessageListener>();
self.addEventListener('message', (event) => {
const { messageId } = event.data;
if (typeof messageId === 'string') {
messageListeners.get(messageId)?.(event.data);
messageListeners.delete(messageId);
}
});
type TokenMessage = Message & {
token?: string;
};
async function askForAccessToken(client: Client): Promise<string | undefined> { async function askForAccessToken(client: Client): Promise<string | undefined> {
return new Promise((resolve) => { return new Promise((resolve) => {
const messageId = Math.random().toString(36); const responseKey = Math.random().toString(36);
messageListeners.set(messageId, (message: TokenMessage) => resolve(message.token)); const listener = (event: ExtendableMessageEvent) => {
client.postMessage({ messageId, type: 'token' }); if (event.data.responseKey !== responseKey) return;
resolve(event.data.token);
self.removeEventListener('message', listener);
};
self.addEventListener('message', listener);
client.postMessage({ responseKey, type: 'token' });
}); });
} }