From 39d28a048809ac8cb0063e51f480580e0e5657d1 Mon Sep 17 00:00:00 2001 From: Robert Long Date: Fri, 17 Dec 2021 16:30:10 -0800 Subject: [PATCH] Add configurable default homeserver --- .env | 3 ++ src/App.jsx | 63 ++++++++---------------------- src/ConferenceCallManagerHooks.jsx | 31 +++++++-------- src/Home.jsx | 4 +- src/LoginPage.jsx | 22 ++++++++--- src/RegisterPage.jsx | 4 +- src/Room.jsx | 4 +- vite.config.js | 28 +++++++------ 8 files changed, 71 insertions(+), 88 deletions(-) diff --git a/.env b/.env index f94203a4..1ea63ac1 100644 --- a/.env +++ b/.env @@ -4,6 +4,9 @@ # https://vitejs.dev/guide/env-and-mode.html#env-files #### +# Used for determining the homeserver to use for short urls etc. +# VITE_DEFAULT_HOMESERVER=http://localhost:8008 + # The room id for the space to use for listing public group call rooms # VITE_PUBLIC_SPACE_ROOM_ID=!hjdfshkdskjdsk:myhomeserver.com diff --git a/src/App.jsx b/src/App.jsx index 6f7b527c..d9fb5eea 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -28,18 +28,17 @@ import { Home } from "./Home"; import { LoginPage } from "./LoginPage"; import { RegisterPage } from "./RegisterPage"; import { Room } from "./Room"; -import { ClientProvider } from "./ConferenceCallManagerHooks"; +import { + ClientProvider, + defaultHomeserverHost, +} from "./ConferenceCallManagerHooks"; import { useFocusVisible } from "@react-aria/interactions"; import styles from "./App.module.css"; -import { ErrorView, LoadingView } from "./FullScreenView"; +import { LoadingView } from "./FullScreenView"; const SentryRoute = Sentry.withSentryRouting(Route); -const { protocol, host } = window.location; -// Assume homeserver is hosted on same domain (proxied in development by vite) -const homeserverUrl = `${protocol}//${host}`; - -export default function App() { +export default function App({ history }) { const { isFocusVisible } = useFocusVisible(); useEffect(() => { @@ -58,8 +57,8 @@ export default function App() { }, [isFocusVisible]); return ( - - + + @@ -87,50 +86,20 @@ export default function App() { function RoomRedirect() { const { pathname } = useLocation(); const history = useHistory(); - const [error, setError] = useState(); useEffect(() => { - async function redirect() { - let roomId = pathname; + let roomId = pathname; - if (pathname.startsWith("/")) { - roomId = roomId.substr(1, roomId.length); - } - - if (!roomId.startsWith("#") && !roomId.startsWith("!")) { - let loginHomeserverUrl = homeserverUrl.trim(); - - if (!loginHomeserverUrl.includes("://")) { - loginHomeserverUrl = "https://" + loginHomeserverUrl; - } - - try { - const wellKnownUrl = new URL( - "/.well-known/matrix/client", - window.location - ); - const response = await fetch(wellKnownUrl); - const config = await response.json(); - - if (config["m.homeserver"]) { - loginHomeserverUrl = config["m.homeserver"]; - } - } catch (error) {} - - const { host } = new URL(loginHomeserverUrl); - - roomId = `#${roomId}:${host}`; - } - - history.replace(`/room/${roomId}`); + if (pathname.startsWith("/")) { + roomId = roomId.substr(1, roomId.length); } - redirect().catch(setError); - }, [history, pathname]); + if (!roomId.startsWith("#") && !roomId.startsWith("!")) { + roomId = `#${roomId}:${defaultHomeserverHost}`; + } - if (error) { - return ; - } + history.replace(`/room/${roomId}`); + }, [pathname, history]); return ; } diff --git a/src/ConferenceCallManagerHooks.jsx b/src/ConferenceCallManagerHooks.jsx index 13e2251e..cd7b1d91 100644 --- a/src/ConferenceCallManagerHooks.jsx +++ b/src/ConferenceCallManagerHooks.jsx @@ -29,6 +29,12 @@ import { } from "matrix-js-sdk/src/browser-index"; import { useHistory } from "react-router-dom"; +export const defaultHomeserver = + import.meta.env.VITE_DEFAULT_HOMESERVER || + `${window.location.protocol}//${window.location.host}`; + +export const defaultHomeserverHost = new URL(defaultHomeserver).host; + const ClientContext = createContext(); function waitForSync(client) { @@ -100,18 +106,10 @@ export async function fetchGroupCall( }); } -export function ClientProvider({ homeserverUrl, children }) { +export function ClientProvider({ children }) { const history = useHistory(); const [ - { - loading, - isAuthenticated, - isPasswordlessUser, - isGuest, - client, - userName, - displayName, - }, + { loading, isAuthenticated, isPasswordlessUser, isGuest, client, userName }, setState, ] = useState({ loading: true, @@ -120,7 +118,6 @@ export function ClientProvider({ homeserverUrl, children }) { isGuest: false, client: undefined, userName: null, - displayName: null, }); useEffect(() => { @@ -140,7 +137,7 @@ export function ClientProvider({ homeserverUrl, children }) { const client = await initClient( { - baseUrl: homeserverUrl, + baseUrl: defaultHomeserver, accessToken: access_token, userId: user_id, deviceId: device_id, @@ -255,14 +252,14 @@ export function ClientProvider({ homeserverUrl, children }) { const registerGuest = useCallback(async () => { try { - const registrationClient = matrix.createClient(homeserverUrl); + const registrationClient = matrix.createClient(defaultHomeserver); const { user_id, device_id, access_token } = await registrationClient.registerGuest({}); const client = await initClient( { - baseUrl: homeserverUrl, + baseUrl: defaultHomeserver, accessToken: access_token, userId: user_id, deviceId: device_id, @@ -303,7 +300,7 @@ export function ClientProvider({ homeserverUrl, children }) { const register = useCallback(async (username, password, passwordlessUser) => { try { - const registrationClient = matrix.createClient(homeserverUrl); + const registrationClient = matrix.createClient(defaultHomeserver); const { user_id, device_id, access_token } = await registrationClient.register(username, password, null, { @@ -311,7 +308,7 @@ export function ClientProvider({ homeserverUrl, children }) { }); const client = await initClient({ - baseUrl: homeserverUrl, + baseUrl: defaultHomeserver, accessToken: access_token, userId: user_id, deviceId: device_id, @@ -617,7 +614,7 @@ export function getRoomUrl(roomId) { if (roomId.startsWith("#")) { const [localPart, host] = roomId.replace("#", "").split(":"); - if (host !== window.location.host) { + if (host !== defaultHomeserverHost) { return `${window.location.host}/room/${roomId}`; } else { return `${window.location.host}/${localPart}`; diff --git a/src/Home.jsx b/src/Home.jsx index 9af93c75..f51e11e5 100644 --- a/src/Home.jsx +++ b/src/Home.jsx @@ -62,7 +62,7 @@ export function Home() { async function onCreateRoom() { let _client = client; - if (!_client) { + if (!_client || isGuest) { _client = await register(userName, randomString(16), true); } @@ -88,7 +88,7 @@ export function Home() { setCreatingRoom(false); }); }, - [client, history, register] + [client, history, register, isGuest] ); const onJoinRoom = useCallback( diff --git a/src/LoginPage.jsx b/src/LoginPage.jsx index c20e7da5..48654023 100644 --- a/src/LoginPage.jsx +++ b/src/LoginPage.jsx @@ -14,19 +14,21 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { useCallback, useRef, useState } from "react"; +import React, { useCallback, useRef, useState, useMemo } from "react"; import { useHistory, useLocation, Link } from "react-router-dom"; import { ReactComponent as Logo } from "./icons/LogoLarge.svg"; import { FieldRow, InputField, ErrorMessage } from "./Input"; import { Button } from "./button"; -import { useClient } from "./ConferenceCallManagerHooks"; +import { + useClient, + defaultHomeserver, + defaultHomeserverHost, +} from "./ConferenceCallManagerHooks"; import styles from "./LoginPage.module.css"; export function LoginPage() { const { login } = useClient(); - const [homeserver, setHomeServer] = useState( - `${window.location.protocol}//${window.location.host}` - ); + const [homeserver, setHomeServer] = useState(defaultHomeserver); const usernameRef = useRef(); const passwordRef = useRef(); const history = useHistory(); @@ -57,6 +59,14 @@ export function LoginPage() { [login, location, history, homeserver] ); + const homeserverHost = useMemo(() => { + try { + return new URL(homeserver).host; + } catch (_error) { + return defaultHomeserverHost; + } + }, [homeserver]); + return ( <>
@@ -76,7 +86,7 @@ export function LoginPage() { autoCorrect="off" autoCapitalize="none" prefix="@" - suffix={`:${window.location.host}`} + suffix={`:${homeserverHost}`} /> diff --git a/src/RegisterPage.jsx b/src/RegisterPage.jsx index 1c4c9f3f..ddddbee7 100644 --- a/src/RegisterPage.jsx +++ b/src/RegisterPage.jsx @@ -18,7 +18,7 @@ import React, { useCallback, useEffect, useRef, useState } from "react"; import { useHistory, useLocation, Link } from "react-router-dom"; import { FieldRow, InputField, ErrorMessage } from "./Input"; import { Button } from "./button"; -import { useClient } from "./ConferenceCallManagerHooks"; +import { useClient, defaultHomeserverHost } from "./ConferenceCallManagerHooks"; import styles from "./LoginPage.module.css"; import { ReactComponent as Logo } from "./icons/LogoLarge.svg"; import { LoadingView } from "./FullScreenView"; @@ -126,7 +126,7 @@ export function RegisterPage() { autoCorrect="off" autoCapitalize="none" prefix="@" - suffix={`:${window.location.host}`} + suffix={`:${defaultHomeserverHost}`} value={ isAuthenticated && isPasswordlessUser ? client.getUserIdLocalpart() diff --git a/src/Room.jsx b/src/Room.jsx index 654eaec7..90b8373e 100644 --- a/src/Room.jsx +++ b/src/Room.jsx @@ -37,6 +37,7 @@ import { useGroupCall } from "matrix-react-sdk/src/hooks/useGroupCall"; import { useCallFeed } from "matrix-react-sdk/src/hooks/useCallFeed"; import { useMediaStream } from "matrix-react-sdk/src/hooks/useMediaStream"; import { + getRoomUrl, useClient, useLoadGroupCall, useProfile, @@ -294,7 +295,6 @@ function RoomSetupView({ }) { const { stream } = useCallFeed(localCallFeed); const videoRef = useMediaStream(stream, true); - const location = useLocation(); useEffect(() => { onInitLocalCallFeed(); @@ -354,7 +354,7 @@ function RoomSetupView({

Or

diff --git a/vite.config.js b/vite.config.js index ef94da11..953c0e0b 100644 --- a/vite.config.js +++ b/vite.config.js @@ -14,22 +14,26 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { defineConfig } from "vite"; +import { defineConfig, loadEnv } from "vite"; import svgrPlugin from "vite-plugin-svgr"; import path from "path"; // https://vitejs.dev/config/ -export default defineConfig({ - plugins: [svgrPlugin()], - server: { - proxy: { - "/_matrix": "http://localhost:8008", +export default defineConfig(({ mode }) => { + const env = loadEnv(mode, process.cwd()); + + return { + plugins: [svgrPlugin()], + server: { + proxy: { + "/_matrix": env.VITE_DEFAULT_HOMESERVER || "http://localhost:8008", + }, }, - }, - resolve: { - alias: { - "$(res)": path.resolve(__dirname, "node_modules/matrix-react-sdk/res"), + resolve: { + alias: { + "$(res)": path.resolve(__dirname, "node_modules/matrix-react-sdk/res"), + }, + dedupe: ["react", "react-dom", "matrix-js-sdk"], }, - dedupe: ["react", "react-dom", "matrix-js-sdk"], - }, + }; });