diff --git a/.github/workflows/build-pull-request.yml b/.github/workflows/build-pull-request.yml index 441da0de..450e4e29 100644 --- a/.github/workflows/build-pull-request.yml +++ b/.github/workflows/build-pull-request.yml @@ -14,7 +14,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4.2.0 - name: Setup node - uses: actions/setup-node@v4.3.0 + uses: actions/setup-node@v4.4.0 with: node-version: 20.12.2 cache: 'npm' diff --git a/.github/workflows/docker-pr.yml b/.github/workflows/docker-pr.yml index 4e88c78d..398785ab 100644 --- a/.github/workflows/docker-pr.yml +++ b/.github/workflows/docker-pr.yml @@ -13,7 +13,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4.2.0 - name: Build Docker image - uses: docker/build-push-action@v6.15.0 + uses: docker/build-push-action@v6.18.0 with: context: . push: false diff --git a/.github/workflows/netlify-dev.yml b/.github/workflows/netlify-dev.yml index 34308c21..66cd5ad5 100644 --- a/.github/workflows/netlify-dev.yml +++ b/.github/workflows/netlify-dev.yml @@ -13,7 +13,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4.2.0 - name: Setup node - uses: actions/setup-node@v4.3.0 + uses: actions/setup-node@v4.4.0 with: node-version: 20.12.2 cache: 'npm' diff --git a/.github/workflows/prod-deploy.yml b/.github/workflows/prod-deploy.yml index 44205ff2..0a758c51 100644 --- a/.github/workflows/prod-deploy.yml +++ b/.github/workflows/prod-deploy.yml @@ -12,7 +12,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4.2.0 - name: Setup node - uses: actions/setup-node@v4.3.0 + uses: actions/setup-node@v4.4.0 with: node-version: 20.12.2 cache: 'npm' @@ -90,7 +90,7 @@ jobs: ${{ secrets.DOCKER_USERNAME }}/cinny ghcr.io/${{ github.repository }} - name: Build and push Docker image - uses: docker/build-push-action@v6.15.0 + uses: docker/build-push-action@v6.18.0 with: context: . platforms: linux/amd64,linux/arm64 diff --git a/package-lock.json b/package-lock.json index 6d82c219..7dd2bf0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cinny", - "version": "4.8.0", + "version": "4.8.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cinny", - "version": "4.8.0", + "version": "4.8.1", "license": "AGPL-3.0-only", "dependencies": { "@atlaskit/pragmatic-drag-and-drop": "1.1.6", diff --git a/package.json b/package.json index b1b14e55..3c1cef8c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cinny", - "version": "4.8.0", + "version": "4.8.1", "description": "Yet another matrix client", "main": "index.js", "type": "module", diff --git a/src/app/features/common-settings/general/RoomJoinRules.tsx b/src/app/features/common-settings/general/RoomJoinRules.tsx index ebd4cad5..c0d62a6a 100644 --- a/src/app/features/common-settings/general/RoomJoinRules.tsx +++ b/src/app/features/common-settings/general/RoomJoinRules.tsx @@ -2,6 +2,7 @@ import React, { useCallback, useMemo } from 'react'; import { color, Text } from 'folds'; import { JoinRule, MatrixError, RestrictedAllowType } from 'matrix-js-sdk'; import { RoomJoinRulesEventContent } from 'matrix-js-sdk/lib/types'; +import { useAtomValue } from 'jotai'; import { IPowerLevels, powerLevelAPI } from '../../../hooks/usePowerLevels'; import { ExtendedJoinRules, @@ -20,6 +21,12 @@ import { useStateEvent } from '../../../hooks/useStateEvent'; import { useSpaceOptionally } from '../../../hooks/useSpace'; import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback'; import { getStateEvents } from '../../../utils/room'; +import { + useRecursiveChildSpaceScopeFactory, + useSpaceChildren, +} from '../../../state/hooks/roomList'; +import { allRoomsAtom } from '../../../state/room-list/roomList'; +import { roomToParentsAtom } from '../../../state/room/roomToParents'; type RestrictedRoomAllowContent = { room_id: string; @@ -36,7 +43,11 @@ export function RoomJoinRules({ powerLevels }: RoomJoinRulesProps) { const allowKnockRestricted = roomVersion >= 10; const allowRestricted = roomVersion >= 8; const allowKnock = roomVersion >= 7; + + const roomIdToParents = useAtomValue(roomToParentsAtom); const space = useSpaceOptionally(); + const subspacesScope = useRecursiveChildSpaceScopeFactory(mx, roomIdToParents); + const subspaces = useSpaceChildren(allRoomsAtom, space?.roomId ?? '', subspacesScope); const userPowerLevel = powerLevelAPI.getPowerLevel(powerLevels, mx.getSafeUserId()); const canEdit = powerLevelAPI.canSendStateEvent( @@ -74,9 +85,22 @@ export function RoomJoinRules({ powerLevels }: RoomJoinRulesProps) { async (joinRule: ExtendedJoinRules) => { const allow: RestrictedRoomAllowContent[] = []; if (joinRule === JoinRule.Restricted || joinRule === 'knock_restricted') { - const parents = getStateEvents(room, StateEvent.SpaceParent).map((event) => - event.getStateKey() - ); + const roomParents = roomIdToParents.get(room.roomId); + + const parents = getStateEvents(room, StateEvent.SpaceParent) + .map((event) => event.getStateKey()) + .filter((parentId) => typeof parentId === 'string') + .filter((parentId) => roomParents?.has(parentId)); + + if (parents.length === 0 && space && roomParents) { + // if no m.space.parent found + // find parent in current space + const selectedParents = subspaces.filter((rId) => roomParents.has(rId)); + if (roomParents.has(space.roomId)) { + selectedParents.push(space.roomId); + } + selectedParents.forEach((pId) => parents.push(pId)); + } parents.forEach((parentRoomId) => { if (!parentRoomId) return; allow.push({ @@ -92,7 +116,7 @@ export function RoomJoinRules({ powerLevels }: RoomJoinRulesProps) { if (allow.length > 0) c.allow = allow; await mx.sendStateEvent(room.roomId, StateEvent.RoomJoinRules as any, c); }, - [mx, room] + [mx, room, space, subspaces, roomIdToParents] ) ); diff --git a/src/app/features/message-search/SearchInput.tsx b/src/app/features/message-search/SearchInput.tsx index db646c26..533eb5fd 100644 --- a/src/app/features/message-search/SearchInput.tsx +++ b/src/app/features/message-search/SearchInput.tsx @@ -29,6 +29,7 @@ export function SearchInput({ active, loading, searchInputRef, onSearch, onReset ref={searchInputRef} style={{ paddingRight: config.space.S300 }} name="searchInput" + autoFocus size="500" variant="Background" placeholder="Search for keyword" diff --git a/src/app/features/room/RoomTimeline.tsx b/src/app/features/room/RoomTimeline.tsx index 340c0943..f2218b04 100644 --- a/src/app/features/room/RoomTimeline.tsx +++ b/src/app/features/room/RoomTimeline.tsx @@ -448,6 +448,7 @@ export function RoomTimeline({ const [encUrlPreview] = useSetting(settingsAtom, 'encUrlPreview'); const showUrlPreview = room.hasEncryptionStateEvent() ? encUrlPreview : urlPreview; const [showHiddenEvents] = useSetting(settingsAtom, 'showHiddenEvents'); + const [showDeveloperTools] = useSetting(settingsAtom, 'developerTools'); const ignoredUsersList = useIgnoredUsers(); const ignoredUsersSet = useMemo(() => new Set(ignoredUsersList), [ignoredUsersList]); @@ -1067,6 +1068,7 @@ export function RoomTimeline({ ) } hideReadReceipts={hideActivity} + showDeveloperTools={showDeveloperTools} powerLevelTag={getPowerLevelTag(senderPowerLevel)} accessibleTagColors={accessibleTagColors} legacyUsernameColor={legacyUsernameColor || direct} @@ -1148,6 +1150,7 @@ export function RoomTimeline({ ) } hideReadReceipts={hideActivity} + showDeveloperTools={showDeveloperTools} powerLevelTag={getPowerLevelTag(senderPowerLevel)} accessibleTagColors={accessibleTagColors} legacyUsernameColor={legacyUsernameColor || direct} @@ -1249,6 +1252,7 @@ export function RoomTimeline({ ) } hideReadReceipts={hideActivity} + showDeveloperTools={showDeveloperTools} powerLevelTag={getPowerLevelTag(senderPowerLevel)} accessibleTagColors={accessibleTagColors} legacyUsernameColor={legacyUsernameColor || direct} @@ -1294,6 +1298,7 @@ export function RoomTimeline({ messageSpacing={messageSpacing} canDelete={canRedact || mEvent.getSender() === mx.getUserId()} hideReadReceipts={hideActivity} + showDeveloperTools={showDeveloperTools} > ; legacyUsernameColor?: boolean; @@ -706,6 +707,7 @@ export const Message = as<'div', MessageProps>( reply, reactions, hideReadReceipts, + showDeveloperTools, powerLevelTag, accessibleTagColors, legacyUsernameColor, @@ -1042,7 +1044,13 @@ export const Message = as<'div', MessageProps>( onClose={closeMenu} /> )} - + {showDeveloperTools && ( + + )} {canPinEvent && ( @@ -1117,6 +1125,7 @@ export type EventProps = { canDelete?: boolean; messageSpacing: MessageSpacing; hideReadReceipts?: boolean; + showDeveloperTools?: boolean; }; export const Event = as<'div', EventProps>( ( @@ -1128,6 +1137,7 @@ export const Event = as<'div', EventProps>( canDelete, messageSpacing, hideReadReceipts, + showDeveloperTools, children, ...props }, @@ -1204,7 +1214,13 @@ export const Event = as<'div', EventProps>( onClose={closeMenu} /> )} - + {showDeveloperTools && ( + + )} {((!mEvent.isRedacted() && canDelete && !stateEvent) || diff --git a/src/app/hooks/useRoomNavigate.ts b/src/app/hooks/useRoomNavigate.ts index 0f9f365c..e626c06b 100644 --- a/src/app/hooks/useRoomNavigate.ts +++ b/src/app/hooks/useRoomNavigate.ts @@ -13,6 +13,8 @@ import { getOrphanParents } from '../utils/room'; import { roomToParentsAtom } from '../state/room/roomToParents'; import { mDirectAtom } from '../state/mDirectList'; import { useSelectedSpace } from './router/useSelectedSpace'; +import { settingsAtom } from '../state/settings'; +import { useSetting } from '../state/hooks/settings'; export const useRoomNavigate = () => { const navigate = useNavigate(); @@ -20,6 +22,7 @@ export const useRoomNavigate = () => { const roomToParents = useAtomValue(roomToParentsAtom); const mDirects = useAtomValue(mDirectAtom); const spaceSelectedId = useSelectedSpace(); + const [developerTools] = useSetting(settingsAtom, 'developerTools'); const navigateSpace = useCallback( (roomId: string) => { @@ -32,15 +35,22 @@ export const useRoomNavigate = () => { const navigateRoom = useCallback( (roomId: string, eventId?: string, opts?: NavigateOptions) => { const roomIdOrAlias = getCanonicalAliasOrRoomId(mx, roomId); + const openSpaceTimeline = developerTools && spaceSelectedId === roomId; - const orphanParents = getOrphanParents(roomToParents, roomId); + const orphanParents = openSpaceTimeline ? [roomId] : getOrphanParents(roomToParents, roomId); if (orphanParents.length > 0) { const pSpaceIdOrAlias = getCanonicalAliasOrRoomId( mx, spaceSelectedId && orphanParents.includes(spaceSelectedId) ? spaceSelectedId - : orphanParents[0] + : orphanParents[0] // TODO: better orphan parent selection. ); + + if (openSpaceTimeline) { + navigate(getSpaceRoomPath(pSpaceIdOrAlias, roomId, eventId), opts); + return; + } + navigate(getSpaceRoomPath(pSpaceIdOrAlias, roomIdOrAlias, eventId), opts); return; } @@ -52,7 +62,7 @@ export const useRoomNavigate = () => { navigate(getHomeRoomPath(roomIdOrAlias, eventId), opts); }, - [mx, navigate, spaceSelectedId, roomToParents, mDirects] + [mx, navigate, spaceSelectedId, roomToParents, mDirects, developerTools] ); return { diff --git a/src/app/organisms/invite-user/InviteUser.jsx b/src/app/organisms/invite-user/InviteUser.jsx index c5bade69..271c22a9 100644 --- a/src/app/organisms/invite-user/InviteUser.jsx +++ b/src/app/organisms/invite-user/InviteUser.jsx @@ -273,7 +273,7 @@ function InviteUser({ isOpen, roomId, searchTerm, onRequestClose }) { searchUser(usernameRef.current.value); }} > - + diff --git a/src/app/organisms/join-alias/JoinAlias.jsx b/src/app/organisms/join-alias/JoinAlias.jsx index 99cf6e6e..d4e313af 100644 --- a/src/app/organisms/join-alias/JoinAlias.jsx +++ b/src/app/organisms/join-alias/JoinAlias.jsx @@ -75,7 +75,7 @@ function JoinAliasContent({ term, requestClose }) { return (
- + {error && ( {error} diff --git a/src/app/pages/auth/AuthFooter.tsx b/src/app/pages/auth/AuthFooter.tsx index 30f4b3ca..ff2fdb9b 100644 --- a/src/app/pages/auth/AuthFooter.tsx +++ b/src/app/pages/auth/AuthFooter.tsx @@ -15,7 +15,7 @@ export function AuthFooter() { target="_blank" rel="noreferrer" > - v4.8.0 + v4.8.1 Twitter diff --git a/src/app/pages/client/WelcomePage.tsx b/src/app/pages/client/WelcomePage.tsx index 88d38981..645753ff 100644 --- a/src/app/pages/client/WelcomePage.tsx +++ b/src/app/pages/client/WelcomePage.tsx @@ -24,7 +24,7 @@ export function WelcomePage() { target="_blank" rel="noreferrer noopener" > - v4.8.0 + v4.8.1 } diff --git a/src/app/pages/client/sidebar/SpaceTabs.tsx b/src/app/pages/client/sidebar/SpaceTabs.tsx index 5b47cb52..011741ee 100644 --- a/src/app/pages/client/sidebar/SpaceTabs.tsx +++ b/src/app/pages/client/sidebar/SpaceTabs.tsx @@ -744,13 +744,14 @@ export function SpaceTabs({ scrollRef }: SpaceTabsProps) { const targetSpaceId = target.getAttribute('data-id'); if (!targetSpaceId) return; + const spacePath = getSpacePath(getCanonicalAliasOrRoomId(mx, targetSpaceId)); if (screenSize === ScreenSize.Mobile) { - navigate(getSpacePath(getCanonicalAliasOrRoomId(mx, targetSpaceId))); + navigate(spacePath); return; } const activePath = navToActivePath.get(targetSpaceId); - if (activePath) { + if (activePath && activePath.pathname.startsWith(spacePath)) { navigate(joinPathComponent(activePath)); return; } diff --git a/src/app/pages/client/space/RoomProvider.tsx b/src/app/pages/client/space/RoomProvider.tsx index a9632137..0fd52ab6 100644 --- a/src/app/pages/client/space/RoomProvider.tsx +++ b/src/app/pages/client/space/RoomProvider.tsx @@ -1,21 +1,24 @@ import React, { ReactNode } from 'react'; import { useParams } from 'react-router-dom'; -import { useAtomValue } from 'jotai'; +import { useAtom, useAtomValue } from 'jotai'; import { useSelectedRoom } from '../../../hooks/router/useSelectedRoom'; import { IsDirectRoomProvider, RoomProvider } from '../../../hooks/useRoom'; import { useMatrixClient } from '../../../hooks/useMatrixClient'; import { JoinBeforeNavigate } from '../../../features/join-before-navigate'; import { useSpace } from '../../../hooks/useSpace'; -import { getAllParents } from '../../../utils/room'; +import { getAllParents, getSpaceChildren } from '../../../utils/room'; import { roomToParentsAtom } from '../../../state/room/roomToParents'; import { allRoomsAtom } from '../../../state/room-list/roomList'; import { useSearchParamsViaServers } from '../../../hooks/router/useSearchParamsViaServers'; import { mDirectAtom } from '../../../state/mDirectList'; +import { settingsAtom } from '../../../state/settings'; +import { useSetting } from '../../../state/hooks/settings'; export function SpaceRouteRoomProvider({ children }: { children: ReactNode }) { const mx = useMatrixClient(); const space = useSpace(); - const roomToParents = useAtomValue(roomToParentsAtom); + const [developerTools] = useSetting(settingsAtom, 'developerTools'); + const [roomToParents, setRoomToParents] = useAtom(roomToParentsAtom); const mDirects = useAtomValue(mDirectAtom); const allRooms = useAtomValue(allRoomsAtom); @@ -24,12 +27,36 @@ export function SpaceRouteRoomProvider({ children }: { children: ReactNode }) { const roomId = useSelectedRoom(); const room = mx.getRoom(roomId); - if ( - !room || - room.isSpaceRoom() || - !allRooms.includes(room.roomId) || - !getAllParents(roomToParents, room.roomId).has(space.roomId) - ) { + if (!room || !allRooms.includes(room.roomId)) { + // room is not joined + return ( + + ); + } + + if (developerTools && room.isSpaceRoom() && room.roomId === space.roomId) { + // allow to view space timeline + return ( + + {children} + + ); + } + + if (!getAllParents(roomToParents, room.roomId).has(space.roomId)) { + if (getSpaceChildren(space).includes(room.roomId)) { + // fill missing roomToParent mapping + setRoomToParents({ + type: 'PUT', + parent: space.roomId, + children: [room.roomId], + }); + } + return ( (({ room, requestClose }, ref) => { const mx = useMatrixClient(); const [hideActivity] = useSetting(settingsAtom, 'hideActivity'); + const [developerTools] = useSetting(settingsAtom, 'developerTools'); const roomToParents = useAtomValue(roomToParentsAtom); const powerLevels = usePowerLevels(room); const { getPowerLevel, canDoAction } = usePowerLevelsAPI(powerLevels); const canInvite = canDoAction('invite', getPowerLevel(mx.getUserId() ?? '')); const openSpaceSettings = useOpenSpaceSettings(); + const { navigateRoom } = useRoomNavigate(); const allChild = useSpaceChildren( allRoomsAtom, @@ -118,6 +121,11 @@ const SpaceMenu = forwardRef(({ room, requestClo requestClose(); }; + const handleOpenTimeline = () => { + navigateRoom(room.roomId); + requestClose(); + }; + return ( @@ -168,6 +176,18 @@ const SpaceMenu = forwardRef(({ room, requestClo Space Settings + {developerTools && ( + } + radii="300" + > + + Event Timeline + + + )} diff --git a/src/app/plugins/react-prism/ReactPrism.tsx b/src/app/plugins/react-prism/ReactPrism.tsx index f93c6ef1..ab2e9320 100644 --- a/src/app/plugins/react-prism/ReactPrism.tsx +++ b/src/app/plugins/react-prism/ReactPrism.tsx @@ -2,18 +2,307 @@ import React, { MutableRefObject, ReactNode, useEffect, useRef } from 'react'; import Prism from 'prismjs'; -import 'prismjs/components/prism-json'; -import 'prismjs/components/prism-javascript'; -import 'prismjs/components/prism-typescript'; -import 'prismjs/components/prism-css'; -import 'prismjs/components/prism-sass'; -import 'prismjs/components/prism-swift'; -import 'prismjs/components/prism-rust'; -import 'prismjs/components/prism-go'; -import 'prismjs/components/prism-c'; -import 'prismjs/components/prism-cpp'; -import 'prismjs/components/prism-java'; -import 'prismjs/components/prism-python'; +import 'prismjs/components/prism-abap.js'; +import 'prismjs/components/prism-abnf.js'; +import 'prismjs/components/prism-actionscript.js'; +import 'prismjs/components/prism-ada.js'; +import 'prismjs/components/prism-agda.js'; +import 'prismjs/components/prism-al.js'; +import 'prismjs/components/prism-antlr4.js'; +import 'prismjs/components/prism-apacheconf.js'; +import 'prismjs/components/prism-apex.js'; +import 'prismjs/components/prism-apl.js'; +import 'prismjs/components/prism-applescript.js'; +import 'prismjs/components/prism-aql.js'; +import 'prismjs/components/prism-arff.js'; +import 'prismjs/components/prism-armasm.js'; +import 'prismjs/components/prism-arturo.js'; +import 'prismjs/components/prism-asciidoc.js'; +import 'prismjs/components/prism-asm6502.js'; +import 'prismjs/components/prism-asmatmel.js'; +import 'prismjs/components/prism-aspnet.js'; +import 'prismjs/components/prism-autohotkey.js'; +import 'prismjs/components/prism-autoit.js'; +import 'prismjs/components/prism-avisynth.js'; +import 'prismjs/components/prism-avro-idl.js'; +import 'prismjs/components/prism-awk.js'; +import 'prismjs/components/prism-bash.js'; +import 'prismjs/components/prism-basic.js'; +import 'prismjs/components/prism-batch.js'; +import 'prismjs/components/prism-bbcode.js'; +import 'prismjs/components/prism-bbj.js'; +import 'prismjs/components/prism-bicep.js'; +import 'prismjs/components/prism-birb.js'; +import 'prismjs/components/prism-bnf.js'; +import 'prismjs/components/prism-bqn.js'; +import 'prismjs/components/prism-brainfuck.js'; +import 'prismjs/components/prism-brightscript.js'; +import 'prismjs/components/prism-bro.js'; +import 'prismjs/components/prism-bsl.js'; +import 'prismjs/components/prism-c.js'; +import 'prismjs/components/prism-cfscript.js'; +import 'prismjs/components/prism-cil.js'; +import 'prismjs/components/prism-cilkc.js'; +import 'prismjs/components/prism-cilkcpp.js'; +import 'prismjs/components/prism-clike.js'; +import 'prismjs/components/prism-clojure.js'; +import 'prismjs/components/prism-cmake.js'; +import 'prismjs/components/prism-cobol.js'; +import 'prismjs/components/prism-coffeescript.js'; +import 'prismjs/components/prism-concurnas.js'; +import 'prismjs/components/prism-cooklang.js'; +import 'prismjs/components/prism-coq.js'; +import 'prismjs/components/prism-cpp.js'; +import 'prismjs/components/prism-csharp.js'; +import 'prismjs/components/prism-cshtml.js'; +import 'prismjs/components/prism-csp.js'; +import 'prismjs/components/prism-css-extras.js'; +import 'prismjs/components/prism-css.js'; +import 'prismjs/components/prism-csv.js'; +import 'prismjs/components/prism-cue.js'; +import 'prismjs/components/prism-cypher.js'; +import 'prismjs/components/prism-d.js'; +import 'prismjs/components/prism-dart.js'; +import 'prismjs/components/prism-dataweave.js'; +import 'prismjs/components/prism-dax.js'; +import 'prismjs/components/prism-dhall.js'; +import 'prismjs/components/prism-diff.js'; +import 'prismjs/components/prism-dns-zone-file.js'; +import 'prismjs/components/prism-docker.js'; +import 'prismjs/components/prism-dot.js'; +import 'prismjs/components/prism-ebnf.js'; +import 'prismjs/components/prism-editorconfig.js'; +import 'prismjs/components/prism-eiffel.js'; +import 'prismjs/components/prism-ejs.js'; +import 'prismjs/components/prism-elixir.js'; +import 'prismjs/components/prism-elm.js'; +import 'prismjs/components/prism-erb.js'; +import 'prismjs/components/prism-erlang.js'; +import 'prismjs/components/prism-etlua.js'; +import 'prismjs/components/prism-excel-formula.js'; +import 'prismjs/components/prism-factor.js'; +import 'prismjs/components/prism-false.js'; +import 'prismjs/components/prism-firestore-security-rules.js'; +import 'prismjs/components/prism-flow.js'; +import 'prismjs/components/prism-fortran.js'; +import 'prismjs/components/prism-fsharp.js'; +import 'prismjs/components/prism-ftl.js'; +import 'prismjs/components/prism-gap.js'; +import 'prismjs/components/prism-gcode.js'; +import 'prismjs/components/prism-gdscript.js'; +import 'prismjs/components/prism-gedcom.js'; +import 'prismjs/components/prism-gettext.js'; +import 'prismjs/components/prism-gherkin.js'; +import 'prismjs/components/prism-git.js'; +import 'prismjs/components/prism-glsl.js'; +import 'prismjs/components/prism-gml.js'; +import 'prismjs/components/prism-gn.js'; +import 'prismjs/components/prism-go-module.js'; +import 'prismjs/components/prism-go.js'; +import 'prismjs/components/prism-gradle.js'; +import 'prismjs/components/prism-graphql.js'; +import 'prismjs/components/prism-groovy.js'; +import 'prismjs/components/prism-haml.js'; +import 'prismjs/components/prism-handlebars.js'; +import 'prismjs/components/prism-haskell.js'; +import 'prismjs/components/prism-haxe.js'; +import 'prismjs/components/prism-hcl.js'; +import 'prismjs/components/prism-hlsl.js'; +import 'prismjs/components/prism-hoon.js'; +import 'prismjs/components/prism-hpkp.js'; +import 'prismjs/components/prism-hsts.js'; +import 'prismjs/components/prism-http.js'; +import 'prismjs/components/prism-ichigojam.js'; +import 'prismjs/components/prism-icon.js'; +import 'prismjs/components/prism-icu-message-format.js'; +import 'prismjs/components/prism-idris.js'; +import 'prismjs/components/prism-iecst.js'; +import 'prismjs/components/prism-ignore.js'; +import 'prismjs/components/prism-inform7.js'; +import 'prismjs/components/prism-ini.js'; +import 'prismjs/components/prism-io.js'; +import 'prismjs/components/prism-j.js'; +import 'prismjs/components/prism-java.js'; +import 'prismjs/components/prism-javadoclike.js'; +import 'prismjs/components/prism-javascript.js'; +import 'prismjs/components/prism-javastacktrace.js'; +import 'prismjs/components/prism-jexl.js'; +import 'prismjs/components/prism-jolie.js'; +import 'prismjs/components/prism-jq.js'; +import 'prismjs/components/prism-js-extras.js'; +import 'prismjs/components/prism-js-templates.js'; +import 'prismjs/components/prism-json.js'; +import 'prismjs/components/prism-json5.js'; +import 'prismjs/components/prism-jsonp.js'; +import 'prismjs/components/prism-jsstacktrace.js'; +import 'prismjs/components/prism-jsx.js'; +import 'prismjs/components/prism-julia.js'; +import 'prismjs/components/prism-keepalived.js'; +import 'prismjs/components/prism-keyman.js'; +import 'prismjs/components/prism-kotlin.js'; +import 'prismjs/components/prism-kumir.js'; +import 'prismjs/components/prism-kusto.js'; +import 'prismjs/components/prism-latex.js'; +import 'prismjs/components/prism-latte.js'; +import 'prismjs/components/prism-less.js'; +import 'prismjs/components/prism-lilypond.js'; +import 'prismjs/components/prism-linker-script.js'; +import 'prismjs/components/prism-liquid.js'; +import 'prismjs/components/prism-lisp.js'; +import 'prismjs/components/prism-livescript.js'; +import 'prismjs/components/prism-llvm.js'; +import 'prismjs/components/prism-log.js'; +import 'prismjs/components/prism-lolcode.js'; +import 'prismjs/components/prism-lua.js'; +import 'prismjs/components/prism-magma.js'; +import 'prismjs/components/prism-makefile.js'; +import 'prismjs/components/prism-markdown.js'; +import 'prismjs/components/prism-markup-templating.js'; +import 'prismjs/components/prism-markup.js'; +import 'prismjs/components/prism-mata.js'; +import 'prismjs/components/prism-matlab.js'; +import 'prismjs/components/prism-maxscript.js'; +import 'prismjs/components/prism-mel.js'; +import 'prismjs/components/prism-mermaid.js'; +import 'prismjs/components/prism-metafont.js'; +import 'prismjs/components/prism-mizar.js'; +import 'prismjs/components/prism-mongodb.js'; +import 'prismjs/components/prism-monkey.js'; +import 'prismjs/components/prism-moonscript.js'; +import 'prismjs/components/prism-n1ql.js'; +import 'prismjs/components/prism-n4js.js'; +import 'prismjs/components/prism-nand2tetris-hdl.js'; +import 'prismjs/components/prism-naniscript.js'; +import 'prismjs/components/prism-nasm.js'; +import 'prismjs/components/prism-neon.js'; +import 'prismjs/components/prism-nevod.js'; +import 'prismjs/components/prism-nginx.js'; +import 'prismjs/components/prism-nim.js'; +import 'prismjs/components/prism-nix.js'; +import 'prismjs/components/prism-nsis.js'; +import 'prismjs/components/prism-objectivec.js'; +import 'prismjs/components/prism-ocaml.js'; +import 'prismjs/components/prism-odin.js'; +import 'prismjs/components/prism-opencl.js'; +import 'prismjs/components/prism-openqasm.js'; +import 'prismjs/components/prism-oz.js'; +import 'prismjs/components/prism-parigp.js'; +import 'prismjs/components/prism-parser.js'; +import 'prismjs/components/prism-pascal.js'; +import 'prismjs/components/prism-pascaligo.js'; +import 'prismjs/components/prism-pcaxis.js'; +import 'prismjs/components/prism-peoplecode.js'; +import 'prismjs/components/prism-perl.js'; +import 'prismjs/components/prism-php-extras.js'; +import 'prismjs/components/prism-php.js'; +import 'prismjs/components/prism-phpdoc.js'; +import 'prismjs/components/prism-plant-uml.js'; +import 'prismjs/components/prism-powerquery.js'; +import 'prismjs/components/prism-powershell.js'; +import 'prismjs/components/prism-processing.js'; +import 'prismjs/components/prism-prolog.js'; +import 'prismjs/components/prism-promql.js'; +import 'prismjs/components/prism-properties.js'; +import 'prismjs/components/prism-protobuf.js'; +import 'prismjs/components/prism-psl.js'; +import 'prismjs/components/prism-pug.js'; +import 'prismjs/components/prism-puppet.js'; +import 'prismjs/components/prism-pure.js'; +import 'prismjs/components/prism-purebasic.js'; +import 'prismjs/components/prism-purescript.js'; +import 'prismjs/components/prism-python.js'; +import 'prismjs/components/prism-q.js'; +import 'prismjs/components/prism-qml.js'; +import 'prismjs/components/prism-qore.js'; +import 'prismjs/components/prism-qsharp.js'; +import 'prismjs/components/prism-r.js'; +import 'prismjs/components/prism-reason.js'; +import 'prismjs/components/prism-regex.js'; +import 'prismjs/components/prism-rego.js'; +import 'prismjs/components/prism-renpy.js'; +import 'prismjs/components/prism-rescript.js'; +import 'prismjs/components/prism-rest.js'; +import 'prismjs/components/prism-rip.js'; +import 'prismjs/components/prism-roboconf.js'; +import 'prismjs/components/prism-robotframework.js'; +import 'prismjs/components/prism-ruby.js'; +import 'prismjs/components/prism-rust.js'; +import 'prismjs/components/prism-sas.js'; +import 'prismjs/components/prism-sass.js'; +import 'prismjs/components/prism-scala.js'; +import 'prismjs/components/prism-scheme.js'; +import 'prismjs/components/prism-scss.js'; +import 'prismjs/components/prism-shell-session.js'; +import 'prismjs/components/prism-smali.js'; +import 'prismjs/components/prism-smalltalk.js'; +import 'prismjs/components/prism-smarty.js'; +import 'prismjs/components/prism-sml.js'; +import 'prismjs/components/prism-solidity.js'; +import 'prismjs/components/prism-solution-file.js'; +import 'prismjs/components/prism-soy.js'; +import 'prismjs/components/prism-splunk-spl.js'; +import 'prismjs/components/prism-sqf.js'; +import 'prismjs/components/prism-sql.js'; +import 'prismjs/components/prism-squirrel.js'; +import 'prismjs/components/prism-stan.js'; +import 'prismjs/components/prism-stata.js'; +import 'prismjs/components/prism-stylus.js'; +import 'prismjs/components/prism-supercollider.js'; +import 'prismjs/components/prism-swift.js'; +import 'prismjs/components/prism-systemd.js'; +import 'prismjs/components/prism-t4-templating.js'; +import 'prismjs/components/prism-t4-vb.js'; +import 'prismjs/components/prism-tap.js'; +import 'prismjs/components/prism-tcl.js'; +import 'prismjs/components/prism-textile.js'; +import 'prismjs/components/prism-toml.js'; +import 'prismjs/components/prism-tremor.js'; +import 'prismjs/components/prism-tsx.js'; +import 'prismjs/components/prism-tt2.js'; +import 'prismjs/components/prism-turtle.js'; +import 'prismjs/components/prism-twig.js'; +import 'prismjs/components/prism-typescript.js'; +import 'prismjs/components/prism-typoscript.js'; +import 'prismjs/components/prism-unrealscript.js'; +import 'prismjs/components/prism-uorazor.js'; +import 'prismjs/components/prism-uri.js'; +import 'prismjs/components/prism-v.js'; +import 'prismjs/components/prism-vala.js'; +import 'prismjs/components/prism-vbnet.js'; +import 'prismjs/components/prism-velocity.js'; +import 'prismjs/components/prism-verilog.js'; +import 'prismjs/components/prism-vhdl.js'; +import 'prismjs/components/prism-vim.js'; +import 'prismjs/components/prism-visual-basic.js'; +import 'prismjs/components/prism-warpscript.js'; +import 'prismjs/components/prism-wasm.js'; +import 'prismjs/components/prism-web-idl.js'; +import 'prismjs/components/prism-wgsl.js'; +import 'prismjs/components/prism-wiki.js'; +import 'prismjs/components/prism-wolfram.js'; +import 'prismjs/components/prism-wren.js'; +import 'prismjs/components/prism-xeora.js'; +import 'prismjs/components/prism-xml-doc.js'; +import 'prismjs/components/prism-xojo.js'; +import 'prismjs/components/prism-xquery.js'; +import 'prismjs/components/prism-yaml.js'; +import 'prismjs/components/prism-yang.js'; +import 'prismjs/components/prism-zig.js'; +import 'prismjs/components/prism-arduino.js'; + +// Broken: +// +// import 'prismjs/components/prism-bison.js'; +// import 'prismjs/components/prism-chaiscript.js'; +// import 'prismjs/components/prism-core.js'; +// import 'prismjs/components/prism-crystal.js'; +// import 'prismjs/components/prism-django.js'; +// import 'prismjs/components/prism-javadoc.js'; +// import 'prismjs/components/prism-jsdoc.js'; +// import 'prismjs/components/prism-plsql.js'; +// import 'prismjs/components/prism-racket.js'; +// import 'prismjs/components/prism-sparql.js'; +// import 'prismjs/components/prism-t4-cs.js'; import './ReactPrism.css'; // using classNames .prism-dark .prism-light from ReactPrism.css diff --git a/src/app/state/navToActivePath.ts b/src/app/state/navToActivePath.ts index 80869146..af90c914 100644 --- a/src/app/state/navToActivePath.ts +++ b/src/app/state/navToActivePath.ts @@ -9,6 +9,8 @@ import { const NAV_TO_ACTIVE_PATH = 'navToActivePath'; +const getStoreKey = (userId: string): string => `${NAV_TO_ACTIVE_PATH}${userId}`; + type NavToActivePath = Map; type NavToActivePathAction = @@ -25,7 +27,7 @@ type NavToActivePathAction = export type NavToActivePathAtom = WritableAtom; export const makeNavToActivePathAtom = (userId: string): NavToActivePathAtom => { - const storeKey = `${NAV_TO_ACTIVE_PATH}${userId}`; + const storeKey = getStoreKey(userId); const baseNavToActivePathAtom = atomWithLocalStorage( storeKey, @@ -64,3 +66,7 @@ export const makeNavToActivePathAtom = (userId: string): NavToActivePathAtom => return navToActivePathAtom; }; + +export const clearNavToActivePathStore = (userId: string) => { + localStorage.removeItem(getStoreKey(userId)); +}; diff --git a/src/client/initMatrix.ts b/src/client/initMatrix.ts index b513e27c..b80a080f 100644 --- a/src/client/initMatrix.ts +++ b/src/client/initMatrix.ts @@ -1,6 +1,7 @@ import { createClient, MatrixClient, IndexedDBStore, IndexedDBCryptoStore } from 'matrix-js-sdk'; import { cryptoCallbacks } from './state/secretStorageKeys'; +import { clearNavToActivePathStore } from '../app/state/navToActivePath'; type Session = { baseUrl: string; @@ -46,6 +47,7 @@ export const startClient = async (mx: MatrixClient) => { export const clearCacheAndReload = async (mx: MatrixClient) => { mx.stopClient(); + clearNavToActivePathStore(mx.getSafeUserId()); await mx.store.deleteAllData(); window.location.reload(); }; diff --git a/src/client/state/cons.js b/src/client/state/cons.js index 3e9306b2..1cb8b102 100644 --- a/src/client/state/cons.js +++ b/src/client/state/cons.js @@ -1,5 +1,5 @@ const cons = { - version: '4.8.0', + version: '4.8.1', secretKey: { ACCESS_TOKEN: 'cinny_access_token', DEVICE_ID: 'cinny_device_id',