diff --git a/src/lib/chat/MatrixRooms.svelte b/src/lib/chat/MatrixRooms.svelte new file mode 100644 index 00000000..71306d97 --- /dev/null +++ b/src/lib/chat/MatrixRooms.svelte @@ -0,0 +1,73 @@ + + +
+ {#each $matrixClient.getRooms() as room} + {@const avatar = room.getMxcAvatarUrl()} + + {/each} + + {#await $matrixClient.publicRooms()} +
Loading...
+ {:then rooms} + {#each rooms.chunk as room} + + {/each} + {:catch error} +
{error.message}
+ {/await} +
+ + diff --git a/src/lib/chat/chat-rx.ts b/src/lib/chat/chat-rx.ts new file mode 100644 index 00000000..34ee3526 --- /dev/null +++ b/src/lib/chat/chat-rx.ts @@ -0,0 +1,109 @@ +import { derived, writable, type Writable } from "svelte/store"; +import type { + ClientEvent, + LoginResponse, + MatrixClient, + RoomMember, +} from "matrix-js-sdk"; +import { persistentWritable } from "$lib/storage"; +import { + themeFromSourceColor, + argbFromHex, + type CustomColorGroup, +} from "@material/material-color-utilities"; +import type { UserTheme } from "$lib/preferences"; +import { MatrixRx } from "./matrix-rx/client"; + +export const matrixClient: Writable = writable(); + +export const isLoggedIn: Writable = writable(false); + +export const matrix = derived( + [matrixClient, isLoggedIn], + ([matrixClient, isLoggedIn]) => + isLoggedIn ? new MatrixRx(matrixClient) : undefined, +); + +export const currentRoomId = persistentWritable( + "currentRoomId", + null, +); + +function getStoredLogin(): LoginResponse | undefined { + try { + return JSON.parse(localStorage.getItem("matrix-login")!); + } catch { + return undefined; + } +} + +export function storeLogin(response: LoginResponse) { + localStorage.setItem("matrix-login", JSON.stringify(response)); +} + +export async function initMatrixClient() { + const { createClient, IndexedDBStore, IndexedDBCryptoStore } = await import( + "matrix-js-sdk" + ); + + const storedLogin = getStoredLogin(); + + const store = new IndexedDBStore({ + dbName: "matrix", + indexedDB: window.indexedDB, + }); + const cryptoStore = new IndexedDBCryptoStore( + window.indexedDB, + "matrix-crypto", + ); + + const client = createClient({ + baseUrl: import.meta.env.VITE_MATRIX_URL, + userId: storedLogin?.user_id, + accessToken: storedLogin?.access_token, + timelineSupport: true, + store, + cryptoStore, + }); + + console.log("store"); + await store.startup(); + console.log("cryptoStore"); + await cryptoStore.startup(); + console.log("client"); + await client.startClient(); + client.once("sync" as ClientEvent.Sync, () => { + isLoggedIn.set(client.isLoggedIn()); + }); + + const loginToken = new URLSearchParams(window.location.search).get( + "loginToken", + ); + if (loginToken) { + storeLogin(await client.loginWithToken(loginToken)); + window.history.replaceState({}, document.title, window.location.pathname); + isLoggedIn.set(client.isLoggedIn()); + } + + matrixClient.set(client); + console.log("done"); +} + +export function memberColor( + member: RoomMember, + theme: UserTheme, +): CustomColorGroup { + let hash = 0; + member.userId.split("").forEach((char) => { + hash = char.charCodeAt(0) + ((hash << 5) - hash); + }); + let color = "#"; + for (let i = 0; i < 3; i++) { + const value = (hash >> (i * 8)) & 0xff; + color += value.toString(16).padStart(2, "0"); + } + + return themeFromSourceColor(argbFromHex(theme.color), [ + { value: argbFromHex(color), name: "member", blend: true }, + ]).customColors.find((c) => c.color.name === "member")!; +} diff --git a/src/lib/chat/chat.ts b/src/lib/chat/chat.ts index 34ee3526..a2b07a6d 100644 --- a/src/lib/chat/chat.ts +++ b/src/lib/chat/chat.ts @@ -1,10 +1,5 @@ -import { derived, writable, type Writable } from "svelte/store"; -import type { - ClientEvent, - LoginResponse, - MatrixClient, - RoomMember, -} from "matrix-js-sdk"; +import { writable, type Writable } from "svelte/store"; +import type { MatrixClient, RoomMember } from "matrix-js-sdk"; import { persistentWritable } from "$lib/storage"; import { themeFromSourceColor, @@ -12,83 +7,14 @@ import { type CustomColorGroup, } from "@material/material-color-utilities"; import type { UserTheme } from "$lib/preferences"; -import { MatrixRx } from "./matrix-rx/client"; export const matrixClient: Writable = writable(); -export const isLoggedIn: Writable = writable(false); - -export const matrix = derived( - [matrixClient, isLoggedIn], - ([matrixClient, isLoggedIn]) => - isLoggedIn ? new MatrixRx(matrixClient) : undefined, -); - export const currentRoomId = persistentWritable( "currentRoomId", null, ); -function getStoredLogin(): LoginResponse | undefined { - try { - return JSON.parse(localStorage.getItem("matrix-login")!); - } catch { - return undefined; - } -} - -export function storeLogin(response: LoginResponse) { - localStorage.setItem("matrix-login", JSON.stringify(response)); -} - -export async function initMatrixClient() { - const { createClient, IndexedDBStore, IndexedDBCryptoStore } = await import( - "matrix-js-sdk" - ); - - const storedLogin = getStoredLogin(); - - const store = new IndexedDBStore({ - dbName: "matrix", - indexedDB: window.indexedDB, - }); - const cryptoStore = new IndexedDBCryptoStore( - window.indexedDB, - "matrix-crypto", - ); - - const client = createClient({ - baseUrl: import.meta.env.VITE_MATRIX_URL, - userId: storedLogin?.user_id, - accessToken: storedLogin?.access_token, - timelineSupport: true, - store, - cryptoStore, - }); - - console.log("store"); - await store.startup(); - console.log("cryptoStore"); - await cryptoStore.startup(); - console.log("client"); - await client.startClient(); - client.once("sync" as ClientEvent.Sync, () => { - isLoggedIn.set(client.isLoggedIn()); - }); - - const loginToken = new URLSearchParams(window.location.search).get( - "loginToken", - ); - if (loginToken) { - storeLogin(await client.loginWithToken(loginToken)); - window.history.replaceState({}, document.title, window.location.pathname); - isLoggedIn.set(client.isLoggedIn()); - } - - matrixClient.set(client); - console.log("done"); -} - export function memberColor( member: RoomMember, theme: UserTheme, diff --git a/src/routes/(app)/Sidebar.svelte b/src/routes/(app)/Sidebar.svelte index b84e9350..40bf9f7c 100644 --- a/src/routes/(app)/Sidebar.svelte +++ b/src/routes/(app)/Sidebar.svelte @@ -27,7 +27,7 @@ external: true, }, { href: "/editor", icon: "edit_document", title: "Editor", wip: true }, - { href: "https://chat.dev.charachorder.io", icon: "chat", title: "Chat", wip: true }, + { href: "/chat", icon: "chat", title: "Chat", wip: true }, ], /*[ { href: "/plugin", icon: "code", title: "Plugin", wip: true }, diff --git a/src/routes/(app)/chat-rx/+page.svelte b/src/routes/(app)/chat-rx/+page.svelte new file mode 100644 index 00000000..36834927 --- /dev/null +++ b/src/routes/(app)/chat-rx/+page.svelte @@ -0,0 +1,92 @@ + + +{#if $isLoggedIn} +
+ +
+{:else} + +{/if} + + diff --git a/src/routes/(app)/chat/Login.svelte b/src/routes/(app)/chat-rx/Login.svelte similarity index 100% rename from src/routes/(app)/chat/Login.svelte rename to src/routes/(app)/chat-rx/Login.svelte diff --git a/src/routes/(app)/chat/Space.svelte b/src/routes/(app)/chat-rx/Space.svelte similarity index 100% rename from src/routes/(app)/chat/Space.svelte rename to src/routes/(app)/chat-rx/Space.svelte diff --git a/src/routes/(app)/chat/+page.svelte b/src/routes/(app)/chat/+page.svelte index 36834927..786602f9 100644 --- a/src/routes/(app)/chat/+page.svelte +++ b/src/routes/(app)/chat/+page.svelte @@ -1,92 +1,186 @@ -{#if $isLoggedIn} -
- -
-{:else} - + + {/if} +{:else if $matrixClient} + {#await $matrixClient.loginFlows() then flows} + {#each flows.flows as flow} + {#if flow.type === "m.login.sso"} + + {#each flow.identity_providers as idp} + {#if idp.icon} + {idp.name} + {:else} + {idp.name} + {/if} + {/each} + + {:else if flow.type === "m.login.password"} + + {/if} + {/each} + {/await} {/if}