5180 fichiers 38.5 Mo 0 téléchargements 191 vues mis à jour il y a 5 heures ui
nitro-v36-with-renderer-v36 / src / hooks / mod-tools / modWindowTrackerStore.ts
modWindowTrackerStore.ts 5.5 Ko Télécharger le fichier
import { createOctaneStore } from '../../state/createOctaneStore';

export type ModWindowType = 'issueHandler' | 'issueBrowser' | 'roomTool' | 'userInfo' | 'sendMessage' | 'modAction' | 'roomVisits' | 'userChatlog' | 'roomChatlog' | 'cfhChatlog' | 'userClassification';

export const MOD_WINDOW_SIZE: Record<ModWindowType, { width: number; height: number }> = {
    roomTool: { width: 240, height: 437 },
    userInfo: { width: 292, height: 225 },
    sendMessage: { width: 212, height: 168 },
    modAction: { width: 383, height: 295 },
    roomVisits: { width: 292, height: 224 },
    userClassification: { width: 292, height: 224 },
    userChatlog: { width: 480, height: 565 },
    roomChatlog: { width: 480, height: 565 },
    cfhChatlog: { width: 480, height: 565 },
    issueBrowser: { width: 585, height: 273 },
    issueHandler: { width: 750, height: 650 }
};

export interface ModWindowRect {
    x: number;
    y: number;
    width: number;
    height: number;
}

export interface ModWindow extends ModWindowRect {
    type: ModWindowType;
    key: string;
    /** Bumped when the window is shown again while open: the replacement instance starts over (and asks for its data again). */
    revision: number;
    /** The window was closed with its close button but keeps its frame (the issue browser is only hidden): showing it again puts it back where it was. */
    hidden?: boolean;
    /** What the window needs besides its key (the user a message goes to, ...). */
    params: Record<string, string | number>;
}

export interface ModWindowShowRequest {
    type: ModWindowType;
    key: string;
    width: number;
    height: number;
    /** The frame the new window is placed next to; without one the window is centred on the desktop. */
    parent?: ModWindowRect | null;
    /** Place the window under its parent (parent.y + parent.height + 5) instead of to its right (parent.x + parent.width + 5). */
    below?: boolean;
    /** Show nothing when no window of that type and key is open (used for refreshes). */
    silent?: boolean;
    /** Close the window instead when one of that type and key is open already. */
    toggle?: boolean;
    /** An explicit position (the classic show() with its "explicit position" flag): the window is placed there instead of next to a parent. */
    at?: { x: number; y: number };
    params?: Record<string, string | number>;
}

interface ModWindowTrackerState {
    /** The start panel frame (the parent of the first tool windows); follows the panel when it is dragged. */
    startPanel: ModWindowRect;
    setStartPanel: (rect: ModWindowRect) => void;
    windows: ModWindow[];
    show: (request: ModWindowShowRequest) => void;
    close: (type: ModWindowType, key: string) => void;
    hide: (type: ModWindowType, key: string) => void;
    move: (type: ModWindowType, key: string, x: number, y: number) => void;
    resize: (type: ModWindowType, key: string, width: number, height: number) => void;
    get: (type: ModWindowType, key: string) => ModWindow | null;
}

const clampToDesktop = (rect: ModWindowRect): ModWindowRect => ({
    ...rect,
    x: Math.max(0, Math.min(rect.x, window.innerWidth - rect.width)),
    y: Math.max(0, Math.min(rect.y, window.innerHeight - rect.height))
});

// Classic v75 WindowTracker (qn): one window per type and key. Showing an open window again closes it when `toggle` is set and otherwise replaces it in place;
// a new window goes right of (or below) its parent frame, centred on the desktop without a parent, and is kept inside the desktop.
export const useModWindowTrackerStore = createOctaneStore<ModWindowTrackerState>()((set, get) => ({
    startPanel: { x: 120, y: 64, width: 170, height: 170 },
    setStartPanel: (rect) => set({ startPanel: rect }),
    windows: [],
    get: (type, key) => get().windows.find((entry) => entry.type === type && entry.key === key) ?? null,
    show: ({ type, key, width, height, parent = null, below = false, silent = false, toggle = false, at = null, params = {} }) => {
        const existing = get().windows.find((entry) => entry.type === type && entry.key === key);

        if (existing) {
            set((state) => ({
                windows: toggle ? state.windows.filter((entry) => entry !== existing) : state.windows.map((entry) => (entry === existing ? { ...entry, hidden: false, revision: entry.revision + 1 } : entry))
            }));

            return;
        }

        if (silent) return;

        const placed = at
            ? at
            : parent
            ? below
                ? { x: parent.x, y: parent.y + parent.height + 5 }
                : { x: parent.x + parent.width + 5, y: parent.y }
            : { x: Math.floor(window.innerWidth / 2 - width / 2), y: Math.floor(window.innerHeight / 2 - height / 2) };

        set((state) => ({ windows: [...state.windows, { type, key, width, height, revision: 0, params, ...clampToDesktop({ ...placed, width, height }) }] }));
    },
    hide: (type, key) => set((state) => ({ windows: state.windows.map((entry) => (entry.type === type && entry.key === key ? { ...entry, hidden: true } : entry)) })),
    close: (type, key) => set((state) => ({ windows: state.windows.filter((entry) => entry.type !== type || entry.key !== key) })),
    move: (type, key, x, y) => set((state) => ({ windows: state.windows.map((entry) => (entry.type === type && entry.key === key ? { ...entry, x, y } : entry)) })),
    resize: (type, key, width, height) => set((state) => ({ windows: state.windows.map((entry) => (entry.type === type && entry.key === key ? { ...entry, width, height } : entry)) }))
}));
15Sujets
1Dépôts
20Membres
2En ligne
Profile
Inscrit
Dernière visite
Messages
0
Votes positifs
0
Votes négatifs
0

Nous utilisons des cookies pour assurer le bon fonctionnement du site et améliorer votre expérience. en savoir plus

Autoriser