refactoring (#178)

* unify components import

* refactor config and app context

* refactor icons

* refactor date, error, mxid and storage

* refactor synapse utils
This commit is contained in:
Aine
2024-11-25 12:51:05 +02:00
committed by GitHub
parent ea0c7a73fd
commit 392fec3186
35 changed files with 200 additions and 206 deletions

82
src/utils/config.ts Normal file
View File

@@ -0,0 +1,82 @@
export interface Config {
restrictBaseUrl: string | string[];
asManagedUsers: RegExp[];
menu: MenuItem[];
}
export interface MenuItem {
label: string;
icon: string;
url: string;
}
export const WellKnownKey = "cc.etke.synapse-admin";
// current configuration
let config: Config = {
restrictBaseUrl: "",
asManagedUsers: [],
menu: [],
};
export const FetchConfig = async () => {
try {
const resp = await fetch("config.json");
const configJSON = await resp.json();
console.log("Loaded config.json", configJSON);
LoadConfig(configJSON);
} catch (e) {
console.error(e);
}
// if home_server is set, try to load https://home_server/.well-known/matrix/client
const homeserver = localStorage.getItem("home_server");
if (homeserver) {
try {
const resp = await fetch(`https://${homeserver}/.well-known/matrix/client`);
const configWK = await resp.json();
if (!configWK[WellKnownKey]) {
console.log(`Loaded https://${homeserver}.well-known/matrix/client, but it doesn't contain ${WellKnownKey} key, skipping`, configWK);
} else {
console.log(`Loaded https://${homeserver}.well-known/matrix/client`, configWK);
LoadConfig(configWK[WellKnownKey]);
}
} catch (e) {
console.log(`https://${homeserver}/.well-known/matrix/client not found, skipping`, e);
}
}
}
// load config from context
export const LoadConfig = (context: any) => {
if (context?.restrictBaseUrl) {
config.restrictBaseUrl = context.restrictBaseUrl as string | string[];
}
if (context?.asManagedUsers) {
config.asManagedUsers = context.asManagedUsers.map((regex: string) => new RegExp(regex));
}
let menu: MenuItem[] = [];
if (context?.menu) {
menu = context.menu as MenuItem[];
}
if (menu.length > 0) {
config.menu = menu;
}
}
// get config
export const GetConfig = (): Config => {
return config;
}
// clear config
export const ClearConfig = () => {
// config.json
config = {} as Config;
// session
localStorage.clear();
}

28
src/utils/date.ts Normal file
View File

@@ -0,0 +1,28 @@
export const DATE_FORMAT: Intl.DateTimeFormatOptions = {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
};
export const dateParser = (v: string | number | Date): number => {
const d = new Date(v);
return d.getTime();
};
export const dateFormatter = (v: string | number | Date | undefined | null): string => {
if (v === undefined || v === null) return "";
const d = new Date(v);
const pad = "00";
const year = d.getFullYear().toString();
const month = (pad + (d.getMonth() + 1).toString()).slice(-2);
const day = (pad + d.getDate().toString()).slice(-2);
const hour = (pad + d.getHours().toString()).slice(-2);
const minute = (pad + d.getMinutes().toString()).slice(-2);
// target format yyyy-MM-ddThh:mm
return `${year}-${month}-${day}T${hour}:${minute}`;
};

6
src/utils/error.ts Normal file
View File

@@ -0,0 +1,6 @@
export type MatrixError = {
errcode: string;
error: string;
}
export const displayError = (errcode: string, status: number, message: string) => `${errcode} (${status}): ${message}`;

View File

@@ -1,9 +1,6 @@
import storage from "../storage";
export const getServerAndMediaIdFromMxcUrl = (mxcUrl: string): { serverName: string, mediaId: string } => {
const re = /^mxc:\/\/([^/]+)\/(\w+)/;
const ret = re.exec(mxcUrl);
console.log("mxcClient " + ret);
if (ret == null) {
throw new Error("Invalid mxcUrl");
}
@@ -15,8 +12,8 @@ export const getServerAndMediaIdFromMxcUrl = (mxcUrl: string): { serverName: str
export type MediaType = "thumbnail" | "original";
export const fetchAuthenticatedMedia = async (mxcUrl: string, type: MediaType): Promise<Response> => {
const homeserver = storage.getItem("base_url");
const accessToken = storage.getItem("access_token");
const homeserver = localStorage.getItem("base_url");
const accessToken = localStorage.getItem("access_token");
const { serverName, mediaId } = getServerAndMediaIdFromMxcUrl(mxcUrl);
if (!serverName || !mediaId) {
@@ -40,4 +37,4 @@ export const fetchAuthenticatedMedia = async (mxcUrl: string, type: MediaType):
});
return response;
};
};

16
src/utils/icons.ts Normal file
View File

@@ -0,0 +1,16 @@
import AnnouncementIcon from '@mui/icons-material/Announcement';
import EngineeringIcon from '@mui/icons-material/Engineering';
import HelpCenterIcon from '@mui/icons-material/HelpCenter';
import SupportAgentIcon from '@mui/icons-material/SupportAgent';
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
export const Icons = {
Announcement: AnnouncementIcon,
Engineering: EngineeringIcon,
HelpCenter: HelpCenterIcon,
SupportAgent: SupportAgentIcon,
Default: OpenInNewIcon,
// Add more icons as needed
};
export const DefaultIcon = Icons.Default;

52
src/utils/mxid.ts Normal file
View File

@@ -0,0 +1,52 @@
import { Identifier } from "ra-core";
import { GetConfig } from "../utils/config";
const mxidPattern = /^@[^@:]+:[^@:]+$/;
/*
* Check if id is a valid Matrix ID (user)
* @param id The ID to check
* @returns Whether the ID is a valid Matrix ID
*/
export const isMXID = (id: string | Identifier): boolean => mxidPattern.test(id as string);
/**
* Check if a user is managed by an application service
* @param id The user ID to check
* @returns Whether the user is managed by an application service
*/
export const isASManaged = (id: string | Identifier): boolean => {
return GetConfig().asManagedUsers.some(regex => regex.test(id as string));
};
/**
* Generate a random MXID for current homeserver
* @returns full MXID as string
*/
export function generateRandomMXID(): string {
const homeserver = localStorage.getItem("home_server");
const characters = "0123456789abcdefghijklmnopqrstuvwxyz";
const localpart = Array.from(crypto.getRandomValues(new Uint32Array(8)))
.map(x => characters[x % characters.length])
.join("");
return `@${localpart}:${homeserver}`;
}
/**
* Return the full MXID from an arbitrary input
* @param input the input string
* @returns full MXID as string
*/
export function returnMXID(input: string | Identifier): string {
const homeserver = localStorage.getItem("home_server");
// Check if the input already looks like a valid MXID (i.e., starts with "@" and contains ":")
const mxidPattern = /^@[^@:]+:[^@:]+$/;
if (isMXID(input)) {
return input as string; // Already a valid MXID
}
// If input is not a valid MXID, assume it's a localpart and construct the MXID
const localpart = typeof input === 'string' && input.startsWith('@') ? input.slice(1) : input;
return `@${localpart}:${homeserver}`;
}

10
src/utils/password.ts Normal file
View File

@@ -0,0 +1,10 @@
/**
* Generate a random user password
* @returns a new random password as string
*/
export function generateRandomPassword(length = 64): string {
const characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~`!@#$%^&*()_-+={[}]|:;'.?/<>,";
return Array.from(crypto.getRandomValues(new Uint32Array(length)))
.map(x => characters[x % characters.length])
.join("");
}