Add configurable default homeserver

This commit is contained in:
Robert Long 2021-12-17 16:30:10 -08:00
parent 34d0483c99
commit 39d28a0488
8 changed files with 71 additions and 88 deletions

3
.env
View file

@ -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

View file

@ -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 (
<Router>
<ClientProvider homeserverUrl={homeserverUrl}>
<Router history={history}>
<ClientProvider>
<OverlayProvider>
<Switch>
<SentryRoute exact path="/">
@ -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 <ErrorView error={error} />;
}
history.replace(`/room/${roomId}`);
}, [pathname, history]);
return <LoadingView />;
}

View file

@ -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}`;

View file

@ -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(

View file

@ -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 (
<>
<div className={styles.container}>
@ -76,7 +86,7 @@ export function LoginPage() {
autoCorrect="off"
autoCapitalize="none"
prefix="@"
suffix={`:${window.location.host}`}
suffix={`:${homeserverHost}`}
/>
</FieldRow>
<FieldRow>

View file

@ -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()

View file

@ -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({
</div>
<p>Or</p>
<CopyButton
value={window.location.href}
value={getRoomUrl(roomId)}
className={styles.copyButton}
copiedMessage="Call link copied"
>

View file

@ -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"],
},
};
});