commit 5734b24abf6144479b43424610fb112bcbca39bf
parent 02a035f8b25f0132d39a8c3a3e83c82d5c0100fe
Author: MTRNord <mtrnord1@gmail.com>
Date: Thu, 4 May 2023 20:06:32 +0200
replace olm with rust-sdk-crypto, fix link colors, fix timeline scroll, prepare better timeline rendering, fix unknown room in sync.
Diffstat:
8 files changed, 82 insertions(+), 50 deletions(-)
diff --git a/package-lock.json b/package-lock.json
@@ -9,6 +9,7 @@
"version": "0.1.0",
"dependencies": {
"@lexical/react": "^0.10.0",
+ "@matrix-org/matrix-sdk-crypto-js": "^0.1.0-alpha.8",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.4.3",
@@ -20,8 +21,9 @@
"idb": "^7.1.1",
"immer": "^10.0.1",
"lexical": "^0.10.0",
+ "linkify-react": "^4.1.1",
+ "linkifyjs": "^4.1.1",
"lucide-react": "^0.171.0",
- "olm": "https://packages.matrix.org/npm/olm/olm-3.2.1.tgz",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-intersection-observer": "^9.4.3",
@@ -3019,6 +3021,14 @@
"yjs": ">=13.5.22"
}
},
+ "node_modules/@matrix-org/matrix-sdk-crypto-js": {
+ "version": "0.1.0-alpha.8",
+ "resolved": "https://registry.npmjs.org/@matrix-org/matrix-sdk-crypto-js/-/matrix-sdk-crypto-js-0.1.0-alpha.8.tgz",
+ "integrity": "sha512-hdmbbGXKrN6JNo3wdBaR5Zs3lXlzllT3U43ViNTlabB3nKkOZQnEAN/Isv+4EQSgz1+8897veI9Q8sqlQX22oA==",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
"node_modules/@mdx-js/react": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-2.3.0.tgz",
@@ -10418,6 +10428,20 @@
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
"dev": true
},
+ "node_modules/linkify-react": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/linkify-react/-/linkify-react-4.1.1.tgz",
+ "integrity": "sha512-2K9Y1cUdvq40dFWqCJ//X+WP19nlzIVITFGI93RjLnA0M7KbnxQ/ffC3AZIZaEIrLangF9Hjt3i0GQ9/anEG5A==",
+ "peerDependencies": {
+ "linkifyjs": "^4.0.0",
+ "react": ">= 15.0.0"
+ }
+ },
+ "node_modules/linkifyjs": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.1.1.tgz",
+ "integrity": "sha512-zFN/CTVmbcVef+WaDXT63dNzzkfRBKT1j464NJQkV7iSgJU0sLBus9W0HBwnXK13/hf168pbrx/V/bjEHOXNHA=="
+ },
"node_modules/loader-runner": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
@@ -11098,12 +11122,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/olm": {
- "version": "3.2.1",
- "resolved": "https://packages.matrix.org/npm/olm/olm-3.2.1.tgz",
- "integrity": "sha512-B87bTpGIGieuV2FNauChjjQtVltwTGagQFoHm+3Dcse4amKAAGJB/I54dnP/JtbHZ+RYVoApM2OQ46Z4VH6eNg==",
- "license": "Apache-2.0"
- },
"node_modules/on-finished": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
diff --git a/package.json b/package.json
@@ -5,6 +5,7 @@
"type": "module",
"dependencies": {
"@lexical/react": "^0.10.0",
+ "@matrix-org/matrix-sdk-crypto-js": "^0.1.0-alpha.8",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.4.3",
@@ -16,8 +17,9 @@
"idb": "^7.1.1",
"immer": "^10.0.1",
"lexical": "^0.10.0",
+ "linkify-react": "^4.1.1",
+ "linkifyjs": "^4.1.1",
"lucide-react": "^0.171.0",
- "olm": "https://packages.matrix.org/npm/olm/olm-3.2.1.tgz",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-intersection-observer": "^9.4.3",
diff --git a/src/App.tsx b/src/App.tsx
@@ -3,44 +3,15 @@ import {
Route,
Routes,
} from "react-router-dom";
-// eslint-disable-next-line @typescript-eslint/ban-ts-comment
-// @ts-ignore
-import olmWasmPath from "olm/olm.wasm?url";
-import OlmLegacy from 'olm/olm_legacy.js?url';
-import Olm from "olm";
import LoginPage from './pages/LoginPage';
import MainPage from './pages/MainPage';
import { ProtectedRoute } from './app/protectedRoute';
import { memo } from "react";
+import { initAsync, start } from "@matrix-org/matrix-sdk-crypto-js";
-Olm
- .init({
- locateFile: () => olmWasmPath,
- })
- .then(() => {
- console.log("Using WebAssembly Olm");
- })
- .catch((wasmLoadError: any) => {
- console.log("Failed to load Olm: trying legacy version", wasmLoadError);
- return new Promise((resolve, reject) => {
- const s = document.createElement("script");
- s.src = OlmLegacy;
- s.onload = resolve;
- s.onerror = reject;
- document.body.appendChild(s);
- })
- .then(() => {
- // Init window.Olm, ie. the one just loaded by the script tag,
- // not 'Olm' which is still the failed wasm version.
- return window.Olm.init();
- })
- .then(() => {
- console.log("Using legacy Olm");
- })
- .catch((legacyLoadError) => {
- console.log("Both WebAssembly and asm.js Olm failed!", legacyLoadError);
- });
- });
+initAsync().then(() => {
+ start();
+})
function App() {
return <BrowserRouter basename={import.meta.env.BASE_URL}>
diff --git a/src/app/sdk/client.ts b/src/app/sdk/client.ts
@@ -694,11 +694,33 @@ export class MatrixClient extends EventEmitter {
const required_state = room.required_state;
const is_dm = room.is_dm;
- const roomObj = [...this.rooms].find(room => room.roomID === roomID);
+ let roomObj = [...this.rooms].find(room => room.roomID === roomID);
if (!roomObj) {
- // TODO: Warn but create missing room instead of failing on it
- console.error("Could not find roomObj for roomID", roomID);
- continue;
+ // Warn, check in the db and if that fails, create a new one.
+ console.warn("Could not find roomObj for roomID:", roomID);
+ const roomFromDB = await tx?.store.get(roomID);
+ if (roomFromDB) {
+ console.warn("Room in db but not in obj list.", roomID, "Updating obj list.");
+
+ roomObj = new Room(roomID, this.hostname!);
+ roomObj.setName(roomFromDB.name);
+ roomObj.setNotificationCount(roomFromDB.notification_count);
+ roomObj.setNotificationHighlightCount(roomFromDB.highlight_count);
+ roomObj.setJoinedCount(roomFromDB.joined_count);
+ roomObj.setInvitedCount(roomFromDB.invited_count);
+ roomObj.setDM(roomFromDB.isDM || false);
+ if (roomFromDB.events) {
+ roomObj.addEvents(roomFromDB.events);
+ }
+ if (roomFromDB.stateEvents) {
+ roomObj.addStateEvents(roomFromDB.stateEvents);
+ }
+ roomObj.windowPos = roomFromDB.windowPos;
+ } else {
+ console.warn("Could not find room in db. Creating new one.");
+ roomObj = new Room(roomID, this.hostname!);
+ this.rooms.add(roomObj);
+ }
}
if (name) {
diff --git a/src/components/events/messageEvent.tsx b/src/components/events/messageEvent.tsx
@@ -30,7 +30,7 @@ const MessageEvent: FC<MessageEventProps> = memo(({ event, roomID }) => {
if (event.content.format === "org.matrix.custom.html") {
// TODO: Sanitize HTML
return (
- <div className="flex flex-row gap-4 p-2 hover:bg-gray-300 rounded-md duration-200 ease-in-out">
+ <div className="flex flex-row gap-4 p-2 hover:bg-gray-200 rounded-md duration-200 ease-in-out">
<Avatar
displayname={room?.getMemberName(event.sender) || ""}
avatarUrl={room?.getMemberAvatar(event.sender)}
@@ -46,7 +46,7 @@ const MessageEvent: FC<MessageEventProps> = memo(({ event, roomID }) => {
)
} else {
return (
- <div className="flex flex-row gap-4 p-2 hover:bg-gray-300 rounded-md duration-200 ease-in-out">
+ <div className="flex flex-row gap-4 p-2 hover:bg-gray-200 rounded-md duration-200 ease-in-out">
<Avatar
displayname={room?.getMemberName(event.sender) || ""}
avatarUrl={room?.getMemberAvatar(event.sender)}
diff --git a/src/index.scss b/src/index.scss
@@ -7,6 +7,18 @@ a {
@apply text-blue-500;
}
+a:hover {
+ @apply text-blue-700;
+}
+
+a:active {
+ @apply text-blue-700;
+}
+
+a:visited {
+ @apply text-blue-500;
+}
+
/*
Font families defined by this CSS:
diff --git a/src/pages/MainPage.tsx b/src/pages/MainPage.tsx
@@ -32,7 +32,7 @@ const ChatView: FC<ChatViewProps> = memo(({ roomID }) => {
const events = room?.getEvents();
// Render events based on the event type and content
- const renderEvent = (event: IRoomEvent) => {
+ const renderEvent = (event: IRoomEvent, previousEventIsFromSameSender: boolean, previousEventType: string) => {
switch (event.type) {
case "m.room.message":
return <MessageEvent event={event} roomID={roomID} key={event.event_id} />
@@ -49,7 +49,13 @@ const ChatView: FC<ChatViewProps> = memo(({ roomID }) => {
return self.findIndex(e => e.event_id === event.event_id) === index;
});
- const renderedEvents = dedupedEvents?.map(event => renderEvent(event));
+ // Map events to components but also tell components if the previous event was from the same sender and which type it was
+ const renderedEvents = dedupedEvents?.map((event, index) => {
+ const previousEvent = dedupedEvents[index - 1];
+ const previousEventIsFromSameSender = previousEvent?.sender === event.sender;
+ const previousEventType = previousEvent?.type;
+ return renderEvent(event, previousEventIsFromSameSender, previousEventType);
+ });
return <div className='max-w-[130ch] flex flex-col gap-2'>{renderedEvents}</div>;
});
@@ -183,7 +189,7 @@ const MainPage = memo(() => {
<p className='ml-4 text-slate-700 font-normal text-base'>{room.getTopic()}</p>
</div>
</div>
- <div className='overflow-y-auto overflow-x-hidden scrollbarSmall mr-2 my-1 flex-1 w-full'>
+ <div className='overflow-y-auto overflow-x-hidden scrollbarSmall mr-2 my-1 flex-1 w-full flex flex-col-reverse'>
<ChatView roomID={params.roomIdOrAlias} />
</div>
<ChatInput namespace='Editor' onChange={(editorState, editor) => {
diff --git a/vite.config.ts b/vite.config.ts
@@ -4,6 +4,7 @@ import react from "@vitejs/plugin-react-swc";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react(), splitVendorChunkPlugin()],
+ appType: 'mpa',
build: {
target: 'esnext'
}