Port modal / popover context.

This commit is contained in:
Paul
2021-06-19 18:46:05 +01:00
parent 5b77ed439f
commit 9706dd75f3
57 changed files with 2562 additions and 140 deletions

View File

@@ -2,7 +2,7 @@ import { ReactNode } from "react";
import { useContext } from "preact/hooks";
import { Redirect } from "react-router-dom";
import { AppContext } from "./RevoltClient";
import { OperationsContext } from "./RevoltClient";
interface Props {
auth?: boolean;
@@ -10,7 +10,7 @@ interface Props {
}
export const CheckAuth = (props: Props) => {
const { operations } = useContext(AppContext);
const operations = useContext(OperationsContext);
if (props.auth && !operations.ready()) {
return <Redirect to="/login" />;

View File

@@ -1,10 +1,10 @@
import { openDB } from 'idb';
import { Client } from "revolt.js";
import { takeError } from "./error";
import { takeError } from "./util";
import { createContext } from "preact";
import { Children } from "../../types/Preact";
import { Route } from "revolt.js/dist/api/routes";
import { useEffect, useState } from "preact/hooks";
import { useEffect, useMemo, useState } from "preact/hooks";
import { connectState } from "../../redux/connector";
import Preloader from "../../components/ui/Preloader";
import { WithDispatcher } from "../../redux/reducers";
@@ -30,13 +30,9 @@ export interface ClientOperations {
ready: () => boolean;
}
export interface AppState {
client: Client;
status: ClientStatus;
operations: ClientOperations;
}
export const AppContext = createContext<AppState>(undefined as any);
export const AppContext = createContext<Client>(undefined as any);
export const StatusContext = createContext<ClientStatus>(undefined as any);
export const OperationsContext = createContext<ClientOperations>(undefined as any);
type Props = WithDispatcher & {
auth: AuthState;
@@ -78,10 +74,8 @@ function Context({ auth, sync, children, dispatcher }: Props) {
if (status === ClientStatus.INIT) return null;
const value: AppState = {
client,
status,
operations: {
const operations: ClientOperations = useMemo(() => {
return {
login: async data => {
setReconnectDisallowed(true);
@@ -131,14 +125,14 @@ function Context({ auth, sync, children, dispatcher }: Props) {
},
loggedIn: () => typeof auth.active !== "undefined",
ready: () => (
value.operations.loggedIn() &&
operations.loggedIn() &&
typeof client.user !== "undefined"
)
}
};
}, [ client, auth.active ]);
useEffect(
() => registerEvents({ ...value, dispatcher }, setStatus, client),
() => registerEvents({ operations, dispatcher }, setStatus, client),
[ client ]
);
@@ -155,7 +149,7 @@ function Context({ auth, sync, children, dispatcher }: Props) {
return setStatus(ClientStatus.OFFLINE);
}
if (value.operations.ready())
if (operations.ready())
setStatus(ClientStatus.CONNECTING);
if (navigator.onLine) {
@@ -194,7 +188,7 @@ function Context({ auth, sync, children, dispatcher }: Props) {
setStatus(ClientStatus.DISCONNECTED);
const error = takeError(err);
if (error === "Forbidden") {
value.operations.logout(true);
operations.logout(true);
// openScreen({ id: "signed_out" });
} else {
// openScreen({ id: "error", error });
@@ -217,8 +211,12 @@ function Context({ auth, sync, children, dispatcher }: Props) {
}
return (
<AppContext.Provider value={value}>
{ children }
<AppContext.Provider value={client}>
<StatusContext.Provider value={status}>
<OperationsContext.Provider value={operations}>
{ children }
</OperationsContext.Provider>
</StatusContext.Provider>
</AppContext.Provider>
);
}

View File

@@ -1,18 +0,0 @@
export function takeError(
error: any
): string {
const type = error?.response?.data?.type;
let id = type;
if (!type) {
if (error?.response?.status === 403) {
return "Unauthorized";
} else if (error && (!!error.isAxiosError && !error.response)) {
return "NetworkError";
}
console.error(error);
return "UnknownError";
}
return id;
}

View File

@@ -2,7 +2,7 @@ import { ClientboundNotification } from "revolt.js/dist/websocket/notifications"
import { WithDispatcher } from "../../redux/reducers";
import { Client, Message } from "revolt.js/dist";
import {
AppState,
ClientOperations,
ClientStatus
} from "./RevoltClient";
import { StateUpdater } from "preact/hooks";
@@ -17,7 +17,7 @@ export function setReconnectDisallowed(allowed: boolean) {
export function registerEvents({
operations,
dispatcher
}: AppState & WithDispatcher, setStatus: StateUpdater<ClientStatus>, client: Client) {
}: { operations: ClientOperations } & WithDispatcher, setStatus: StateUpdater<ClientStatus>, client: Client) {
const listeners = {
connecting: () =>
operations.ready() && setStatus(ClientStatus.CONNECTING),

View File

@@ -9,7 +9,7 @@ export interface HookContext {
}
export function useForceUpdate(context?: HookContext): HookContext {
const { client } = useContext(AppContext);
const client = useContext(AppContext);
if (context) return context;
const [, updateState] = useState({});
return { client, forceUpdate: useCallback(() => updateState({}), []) };

View File

@@ -1,10 +0,0 @@
import { Message } from "revolt.js/dist/api/objects";
export type MessageObject = Omit<Message, "edited"> & { edited?: string };
export function mapMessage(message: Partial<Message>) {
const { edited, ...msg } = message;
return {
...msg,
edited: edited?.$date,
} as MessageObject;
}

View File

@@ -0,0 +1,49 @@
import { Channel, Message, User } from "revolt.js/dist/api/objects";
import { Children } from "../../types/Preact";
import { Text } from "preact-i18n";
import { Client } from "revolt.js";
export function takeError(
error: any
): string {
const type = error?.response?.data?.type;
let id = type;
if (!type) {
if (error?.response?.status === 403) {
return "Unauthorized";
} else if (error && (!!error.isAxiosError && !error.response)) {
return "NetworkError";
}
console.error(error);
return "UnknownError";
}
return id;
}
export function getChannelName(client: Client, channel: Channel, users: User[], prefixType?: boolean): Children {
if (channel.channel_type === "SavedMessages")
return <Text id="app.navigation.tabs.saved" />;
if (channel.channel_type === "DirectMessage") {
let uid = client.channels.getRecipient(channel._id);
return <>{prefixType && "@"}{users.find(x => x._id === uid)?.username}</>;
}
if (channel.channel_type === "TextChannel" && prefixType) {
return <>#{channel.name}</>;
}
return <>{channel.name}</>;
}
export type MessageObject = Omit<Message, "edited"> & { edited?: string };
export function mapMessage(message: Partial<Message>) {
const { edited, ...msg } = message;
return {
...msg,
edited: edited?.$date,
} as MessageObject;
}