Loading packages/client/src/components/App.tsx +30 −21 Original line number Diff line number Diff line Loading @@ -27,32 +27,21 @@ const DynamicallyLoadChat = () => { // get access to context data const AppInner = () => { return ( <> <Header /> <CanvasWrapper /> <ToolbarWrapper /> const { config } = useAppContext(); {/* <DynamicallyLoadChat /> */} <DebugModal /> <SettingsSidebar /> <PixelWhoisSidebar /> <KeybindModal /> <AuthErrors /> <ToastContainer position="top-left" /> </> ); }; const App = () => { useEffect(() => { // detect auth callback for chat, regardless of it being loaded // callback token expires quickly, so we should exchange it as quick as possible (async () => { const params = new URLSearchParams(window.location.search); if (params.has("loginToken")) { if (!config) { console.warn( "[App] loginToken parsing is delayed because config is not available" ); return; } // login button opens a new tab that redirects here // if we're that tab, we should try to close this tab when we're done // should work because this tab is opened by JS Loading @@ -66,7 +55,7 @@ const App = () => { window.history.replaceState({}, "", "/"); const loginReq = await fetch( `https://${import.meta.env.VITE_MATRIX_HOST}/_matrix/client/v3/login`, `https://${config.chat.matrix_homeserver}/_matrix/client/v3/login`, { method: "POST", headers: { Loading Loading @@ -137,8 +126,28 @@ const App = () => { } } })(); }, []); }, [config]); return ( <> <Header /> <CanvasWrapper /> <ToolbarWrapper /> {/* <DynamicallyLoadChat /> */} <DebugModal /> <SettingsSidebar /> <PixelWhoisSidebar /> <KeybindModal /> <AuthErrors /> <ToastContainer position="top-left" /> </> ); }; const App = () => { return ( <AppContext> <ChatContext> Loading packages/client/src/components/Chat/OpenChatButton.tsx +3 −5 Original line number Diff line number Diff line import { Badge, Button, Link } from "@nextui-org/react"; import { useChatContext } from "../../contexts/ChatContext"; import { useAppContext } from "../../contexts/AppContext"; const OpenChatButton = () => { const { config } = useAppContext(); const { notificationCount } = useChatContext(); return ( Loading @@ -11,11 +13,7 @@ const OpenChatButton = () => { color="danger" size="sm" > <Button as={Link} href={import.meta.env.VITE_ELEMENT_HOST!} target="_blank" > <Button as={Link} href={config.chat.element_host} target="_blank"> Chat </Button> </Badge> Loading packages/client/src/components/Profile/UserCard.tsx +13 −8 Original line number Diff line number Diff line import { faMessage, faWarning, faX } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Button, Link, Spinner } from "@nextui-org/react"; import { ClientConfig } from "@sc07-canvas/lib/src/net"; import { MouseEvent, useEffect, useState } from "react"; import { toast } from "react-toastify"; import { useAppContext } from "../../contexts/AppContext"; interface IUser { sub: string; Loading @@ -13,11 +15,8 @@ interface IUser { isModerator: boolean; } const MATRIX_HOST = import.meta.env.VITE_MATRIX_HOST!; // eg aftermath.gg const ELEMENT_HOST = import.meta.env.VITE_ELEMENT_HOST!; // eg https://chat.fediverse.events const getMatrixLink = (user: IUser) => { return `${ELEMENT_HOST}/#/user/@${user.sub.replace("@", "=40")}:${MATRIX_HOST}`; const getMatrixLink = (user: IUser, config: ClientConfig) => { return `${config.chat.element_host}/#/user/@${user.sub.replace("@", "=40")}:${config.chat.matrix_homeserver}`; }; /** Loading @@ -26,15 +25,21 @@ const getMatrixLink = (user: IUser) => { * @returns */ export const UserCard = ({ user }: { user: IUser }) => { const { config } = useAppContext(); const [messageStatus, setMessageStatus] = useState< "loading" | "no_account" | "has_account" | "error" >("loading"); useEffect(() => { if (!config) { console.warn("[UserCard] config is not available yet"); return; } setMessageStatus("loading"); fetch( `https://${MATRIX_HOST}/_matrix/client/v3/profile/${encodeURIComponent(`@${user.sub.replace("@", "=40")}:${MATRIX_HOST}`)}` `https://${config.chat.matrix_homeserver}/_matrix/client/v3/profile/${encodeURIComponent(`@${user.sub.replace("@", "=40")}:${config.chat.matrix_homeserver}`)}` ) .then((req) => { if (req.status === 200) { Loading @@ -53,7 +58,7 @@ export const UserCard = ({ user }: { user: IUser }) => { "Error while getting Matrix account details for " + user.sub ); }); }, [user]); }, [user, config]); const handleMatrixClick = (e: MouseEvent) => { if (messageStatus === "no_account") { Loading @@ -79,7 +84,7 @@ export const UserCard = ({ user }: { user: IUser }) => { <Button isIconOnly as={Link} href={getMatrixLink(user)} href={getMatrixLink(user, config)} target="_blank" onClick={handleMatrixClick} > Loading packages/client/src/contexts/ChatContext.tsx +5 −3 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ import { useRef, useState, } from "react"; import { useAppContext } from "./AppContext"; interface IMatrixUser { userId: string; Loading @@ -24,6 +25,7 @@ const chatContext = createContext<IChatContext>({} as any); export const useChatContext = () => useContext(chatContext); export const ChatContext = ({ children }: PropsWithChildren) => { const { config } = useAppContext(); const checkInterval = useRef<ReturnType<typeof setInterval>>(); const checkNotifs = useRef<ReturnType<typeof setInterval>>(); Loading @@ -38,14 +40,14 @@ export const ChatContext = ({ children }: PropsWithChildren) => { checkInterval.current = setInterval(checkForAccessToken, 500); window.open( `https://${import.meta.env.VITE_MATRIX_HOST}/_matrix/client/v3/login/sso/redirect?redirectUrl=${encodeURIComponent(redirectUrl)}`, `https://${config.chat.matrix_homeserver}/_matrix/client/v3/login/sso/redirect?redirectUrl=${encodeURIComponent(redirectUrl)}`, "_blank" ); }; const doLogout = async () => { await fetch( `https://${import.meta.env.VITE_MATRIX_HOST}/_matrix/client/v3/logout`, `https://${config.chat.matrix_homeserver}/_matrix/client/v3/logout`, { method: "POST", headers: { Loading Loading @@ -99,7 +101,7 @@ export const ChatContext = ({ children }: PropsWithChildren) => { if (!accessToken) return; const notifReq = await fetch( `https://${import.meta.env.VITE_MATRIX_HOST}/_matrix/client/v3/notifications?limit=10`, `https://${config.chat.matrix_homeserver}/_matrix/client/v3/notifications?limit=10`, { headers: { Authorization: "Bearer " + accessToken, Loading packages/lib/src/net.ts +11 −0 Original line number Diff line number Diff line Loading @@ -110,6 +110,17 @@ export type ClientConfig = { pixel_cooldown: number; }; canvas: CanvasConfig; chat: { enabled: boolean; /** * @example aftermath.gg */ matrix_homeserver: string; /** * @example https://chat.fediverse.events */ element_host: string; }; }; /** Loading Loading
packages/client/src/components/App.tsx +30 −21 Original line number Diff line number Diff line Loading @@ -27,32 +27,21 @@ const DynamicallyLoadChat = () => { // get access to context data const AppInner = () => { return ( <> <Header /> <CanvasWrapper /> <ToolbarWrapper /> const { config } = useAppContext(); {/* <DynamicallyLoadChat /> */} <DebugModal /> <SettingsSidebar /> <PixelWhoisSidebar /> <KeybindModal /> <AuthErrors /> <ToastContainer position="top-left" /> </> ); }; const App = () => { useEffect(() => { // detect auth callback for chat, regardless of it being loaded // callback token expires quickly, so we should exchange it as quick as possible (async () => { const params = new URLSearchParams(window.location.search); if (params.has("loginToken")) { if (!config) { console.warn( "[App] loginToken parsing is delayed because config is not available" ); return; } // login button opens a new tab that redirects here // if we're that tab, we should try to close this tab when we're done // should work because this tab is opened by JS Loading @@ -66,7 +55,7 @@ const App = () => { window.history.replaceState({}, "", "/"); const loginReq = await fetch( `https://${import.meta.env.VITE_MATRIX_HOST}/_matrix/client/v3/login`, `https://${config.chat.matrix_homeserver}/_matrix/client/v3/login`, { method: "POST", headers: { Loading Loading @@ -137,8 +126,28 @@ const App = () => { } } })(); }, []); }, [config]); return ( <> <Header /> <CanvasWrapper /> <ToolbarWrapper /> {/* <DynamicallyLoadChat /> */} <DebugModal /> <SettingsSidebar /> <PixelWhoisSidebar /> <KeybindModal /> <AuthErrors /> <ToastContainer position="top-left" /> </> ); }; const App = () => { return ( <AppContext> <ChatContext> Loading
packages/client/src/components/Chat/OpenChatButton.tsx +3 −5 Original line number Diff line number Diff line import { Badge, Button, Link } from "@nextui-org/react"; import { useChatContext } from "../../contexts/ChatContext"; import { useAppContext } from "../../contexts/AppContext"; const OpenChatButton = () => { const { config } = useAppContext(); const { notificationCount } = useChatContext(); return ( Loading @@ -11,11 +13,7 @@ const OpenChatButton = () => { color="danger" size="sm" > <Button as={Link} href={import.meta.env.VITE_ELEMENT_HOST!} target="_blank" > <Button as={Link} href={config.chat.element_host} target="_blank"> Chat </Button> </Badge> Loading
packages/client/src/components/Profile/UserCard.tsx +13 −8 Original line number Diff line number Diff line import { faMessage, faWarning, faX } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Button, Link, Spinner } from "@nextui-org/react"; import { ClientConfig } from "@sc07-canvas/lib/src/net"; import { MouseEvent, useEffect, useState } from "react"; import { toast } from "react-toastify"; import { useAppContext } from "../../contexts/AppContext"; interface IUser { sub: string; Loading @@ -13,11 +15,8 @@ interface IUser { isModerator: boolean; } const MATRIX_HOST = import.meta.env.VITE_MATRIX_HOST!; // eg aftermath.gg const ELEMENT_HOST = import.meta.env.VITE_ELEMENT_HOST!; // eg https://chat.fediverse.events const getMatrixLink = (user: IUser) => { return `${ELEMENT_HOST}/#/user/@${user.sub.replace("@", "=40")}:${MATRIX_HOST}`; const getMatrixLink = (user: IUser, config: ClientConfig) => { return `${config.chat.element_host}/#/user/@${user.sub.replace("@", "=40")}:${config.chat.matrix_homeserver}`; }; /** Loading @@ -26,15 +25,21 @@ const getMatrixLink = (user: IUser) => { * @returns */ export const UserCard = ({ user }: { user: IUser }) => { const { config } = useAppContext(); const [messageStatus, setMessageStatus] = useState< "loading" | "no_account" | "has_account" | "error" >("loading"); useEffect(() => { if (!config) { console.warn("[UserCard] config is not available yet"); return; } setMessageStatus("loading"); fetch( `https://${MATRIX_HOST}/_matrix/client/v3/profile/${encodeURIComponent(`@${user.sub.replace("@", "=40")}:${MATRIX_HOST}`)}` `https://${config.chat.matrix_homeserver}/_matrix/client/v3/profile/${encodeURIComponent(`@${user.sub.replace("@", "=40")}:${config.chat.matrix_homeserver}`)}` ) .then((req) => { if (req.status === 200) { Loading @@ -53,7 +58,7 @@ export const UserCard = ({ user }: { user: IUser }) => { "Error while getting Matrix account details for " + user.sub ); }); }, [user]); }, [user, config]); const handleMatrixClick = (e: MouseEvent) => { if (messageStatus === "no_account") { Loading @@ -79,7 +84,7 @@ export const UserCard = ({ user }: { user: IUser }) => { <Button isIconOnly as={Link} href={getMatrixLink(user)} href={getMatrixLink(user, config)} target="_blank" onClick={handleMatrixClick} > Loading
packages/client/src/contexts/ChatContext.tsx +5 −3 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ import { useRef, useState, } from "react"; import { useAppContext } from "./AppContext"; interface IMatrixUser { userId: string; Loading @@ -24,6 +25,7 @@ const chatContext = createContext<IChatContext>({} as any); export const useChatContext = () => useContext(chatContext); export const ChatContext = ({ children }: PropsWithChildren) => { const { config } = useAppContext(); const checkInterval = useRef<ReturnType<typeof setInterval>>(); const checkNotifs = useRef<ReturnType<typeof setInterval>>(); Loading @@ -38,14 +40,14 @@ export const ChatContext = ({ children }: PropsWithChildren) => { checkInterval.current = setInterval(checkForAccessToken, 500); window.open( `https://${import.meta.env.VITE_MATRIX_HOST}/_matrix/client/v3/login/sso/redirect?redirectUrl=${encodeURIComponent(redirectUrl)}`, `https://${config.chat.matrix_homeserver}/_matrix/client/v3/login/sso/redirect?redirectUrl=${encodeURIComponent(redirectUrl)}`, "_blank" ); }; const doLogout = async () => { await fetch( `https://${import.meta.env.VITE_MATRIX_HOST}/_matrix/client/v3/logout`, `https://${config.chat.matrix_homeserver}/_matrix/client/v3/logout`, { method: "POST", headers: { Loading Loading @@ -99,7 +101,7 @@ export const ChatContext = ({ children }: PropsWithChildren) => { if (!accessToken) return; const notifReq = await fetch( `https://${import.meta.env.VITE_MATRIX_HOST}/_matrix/client/v3/notifications?limit=10`, `https://${config.chat.matrix_homeserver}/_matrix/client/v3/notifications?limit=10`, { headers: { Authorization: "Bearer " + accessToken, Loading
packages/lib/src/net.ts +11 −0 Original line number Diff line number Diff line Loading @@ -110,6 +110,17 @@ export type ClientConfig = { pixel_cooldown: number; }; canvas: CanvasConfig; chat: { enabled: boolean; /** * @example aftermath.gg */ matrix_homeserver: string; /** * @example https://chat.fediverse.events */ element_host: string; }; }; /** Loading