Skip to content
Snippets Groups Projects
hooks.ts 4.57 KiB
Newer Older
insert's avatar
insert committed
import { useCallback, useContext, useEffect, useState } from "preact/hooks";
import { Channels, Servers, Users } from "revolt.js/dist/api/objects";
import { Client, PermissionCalculator } from 'revolt.js';
import { AppContext } from "./RevoltClient";

insert's avatar
insert committed
export interface HookContext {
insert's avatar
insert committed
    client: Client,
    forceUpdate: () => void
}

export function useForceUpdate(context?: HookContext): HookContext {
insert's avatar
insert committed
    const client = useContext(AppContext);
insert's avatar
insert committed
    if (context) return context;
    const [, updateState] = useState({});
    return { client, forceUpdate: useCallback(() => updateState({}), []) };
}

function useObject(type: string, id?: string | string[], context?: HookContext) {
    const ctx = useForceUpdate(context);

    function mutation(target: string) {
        if (typeof id === 'string' ? target === id :
            Array.isArray(id) ? id.includes(target) : true) {
            ctx.forceUpdate();
        }
    }

    const map = (ctx.client as any)[type];
    useEffect(() => {
        map.addListener("update", mutation);
        return () => map.removeListener("update", mutation);
    }, [id]);

    return typeof id === 'string' ? map.get(id)
        : Array.isArray(id) ? id.map(x => map.get(x))
        : map.toArray();
}

export function useUser(id?: string, context?: HookContext) {
    if (typeof id === "undefined") return;
    return useObject('users', id, context) as Readonly<Users.User> | undefined;
}

export function useSelf(context?: HookContext) {
    const ctx = useForceUpdate(context);
    return useUser(ctx.client.user!._id, ctx);
}

export function useUsers(ids?: string[], context?: HookContext) {
    return useObject('users', ids, context) as (Readonly<Users.User> | undefined)[];
}

export function useChannel(id?: string, context?: HookContext) {
    if (typeof id === "undefined") return;
    return useObject('channels', id, context) as Readonly<Channels.Channel> | undefined;
}

export function useChannels(ids?: string[], context?: HookContext) {
    return useObject('channels', ids, context) as (Readonly<Channels.Channel> | undefined)[];
}

export function useServer(id?: string, context?: HookContext) {
    if (typeof id === "undefined") return;
    return useObject('servers', id, context) as Readonly<Servers.Server> | undefined;
}

export function useServers(ids?: string[], context?: HookContext) {
    return useObject('servers', ids, context) as (Readonly<Servers.Server> | undefined)[];
}

insert's avatar
insert committed
export function useDMs(context?: HookContext) {
    const ctx = useForceUpdate(context);

    function mutation(target: string) {
        let channel = ctx.client.channels.get(target);
        if (channel) {
            if ((channel.channel_type === 'DirectMessage' && channel.active) || channel.channel_type === 'Group') {
                ctx.forceUpdate();
            }
        }
    }

    const map = ctx.client.channels;
    useEffect(() => {
        map.addListener("update", mutation);
        return () => map.removeListener("update", mutation);
    }, []);

    return map
        .toArray()
        .filter(x => x.channel_type === 'DirectMessage' || x.channel_type === 'Group' || x.channel_type === 'SavedMessages') as (Channels.GroupChannel | Channels.DirectMessageChannel | Channels.SavedMessagesChannel)[];
}

insert's avatar
insert committed
export function useUserPermission(id: string, context?: HookContext) {
    const ctx = useForceUpdate(context);

    const mutation = (target: string) => (target === id) && ctx.forceUpdate();
    useEffect(() => {
        ctx.client.users.addListener("update", mutation);
        return () => ctx.client.users.removeListener("update", mutation);
    }, [id]);
    
    let calculator = new PermissionCalculator(ctx.client);
    return calculator.forUser(id);
}

export function useChannelPermission(id: string, context?: HookContext) {
    const ctx = useForceUpdate(context);

    const mutation = (target: string) => (target === id) && ctx.forceUpdate();
    useEffect(() => {
        ctx.client.channels.addListener("update", mutation);
        return () => ctx.client.channels.removeListener("update", mutation);
    }, [id]);
    
    let calculator = new PermissionCalculator(ctx.client);
    return calculator.forChannel(id);
}

export function useServerPermission(id: string, context?: HookContext) {
    const ctx = useForceUpdate(context);

    const mutation = (target: string) => (target === id) && ctx.forceUpdate();
    useEffect(() => {
        ctx.client.servers.addListener("update", mutation);
        return () => ctx.client.servers.removeListener("update", mutation);
    }, [id]);
    
    let calculator = new PermissionCalculator(ctx.client);
    return calculator.forServer(id);
}