Newer
Older
import { AppContext, useAppContext } from "../contexts/AppContext";
import { TemplateContext } from "../contexts/TemplateContext";
import { SettingsSidebar } from "./Settings/SettingsSidebar";
import { ToolbarWrapper } from "./Toolbar/ToolbarWrapper";
import React, { lazy, useEffect } from "react";
import { ChatContext } from "../contexts/ChatContext";
import "react-toastify/dist/ReactToastify.css";
import { ToastContainer } from "react-toastify";
import { AuthErrors } from "./AuthErrors";
import "../lib/keybinds";
import { PixelWhoisSidebar } from "./PixelWhoisSidebar";
import { KeybindModal } from "./KeybindModal";
console.log("Client init with version " + __COMMIT_HASH__);
const DynamicallyLoadChat = () => {
const { loadChat } = useAppContext();
return <React.Suspense>{loadChat && <Chat />}</React.Suspense>;
};
// get access to context data
const AppInner = () => {
const { config } = useAppContext();
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
const shouldCloseWindow =
window.location.pathname.startsWith("/chat_callback");
// token provided by matrix's /sso/redirect
const token = params.get("loginToken")!;
// immediately remove from url to prevent reloading
window.history.replaceState({}, "", "/");
const loginReq = await fetch(
`https://${config.chat.matrix_homeserver}/_matrix/client/v3/login`,
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
type: "m.login.token",
token,
}),
}
);
const loginRes = await loginReq.json();
console.log("[Chat] Matrix login", loginReq.status);
switch (loginReq.status) {
case 200: {
// success
console.log("[Chat] Logged in successfully", loginRes);
localStorage.setItem(
"matrix.access_token",
loginRes.access_token + ""
);
localStorage.setItem("matrix.device_id", loginRes.device_id + "");
localStorage.setItem("matrix.user_id", loginRes.user_id + "");
if (shouldCloseWindow) {
console.log(
"[Chat] Path matches autoclose, attempting to close window..."
);
window.close();
alert("You can close this window and return to the other tab :)");
} else {
console.log(
"[Chat] Path doesn't match autoclose, not doing anything"
);
}
break;
}
case 400:
case 403:
console.log("[Chat] Matrix login", loginRes);
alert(
"[Chat] Failed to login\n" +
loginRes.errcode +
" " +
loginRes.error
);
break;
case 429:
alert(
"[Chat] Failed to login, ratelimited.\nTry again in " +
Math.floor(loginRes.retry_after_ms / 1000) +
"s\n" +
loginRes.errcode +
" " +
loginRes.error
);
break;
default:
alert(
"Error " +
loginReq.status +
" returned when trying to login to chat"
);
}
}
})();
}, [config]);
return (
<>
<Header />
<CanvasWrapper />
<ToolbarWrapper />
{/* <DynamicallyLoadChat /> */}
<DebugModal />
<SettingsSidebar />
<PixelWhoisSidebar />
<KeybindModal />
<AuthErrors />
<ToastContainer position="top-left" />
</>
);
};
const App = () => {
<AppInner />