122 lines
3.9 KiB
TypeScript
122 lines
3.9 KiB
TypeScript
import { useConsoleLogger } from "@/app/hooks/useConsoleLogger";
|
||
import React, { createContext, useEffect, useState } from "react";
|
||
|
||
export interface DialogStateContextValue {
|
||
muted: string[];
|
||
pinned: string[];
|
||
muteToggle: (dialogId: string) => void;
|
||
pinToggle: (dialogId: string) => void;
|
||
mentions: DialogMention[];
|
||
pushMention: (dialogMention : DialogMention) => void;
|
||
popMention: (DialogMention: DialogMention) => void;
|
||
isMentioned: (dialogId: string) => boolean;
|
||
getLastMention: (dialogId: string) => DialogMention;
|
||
}
|
||
|
||
export const DialogStateContext = createContext<DialogStateContextValue | null>(null);
|
||
|
||
export interface DialogStateProviderProps {
|
||
children: React.ReactNode;
|
||
}
|
||
|
||
export interface DialogMention {
|
||
dialog_id: string;
|
||
message_id: string;
|
||
}
|
||
|
||
/**
|
||
* Этот провайдер нужен для того, чтобы быстро определить состояние диалога,
|
||
* например, закреплен ли он или нет, или отключены ли в нем уведомления.
|
||
*
|
||
* ВАЖНО! При отключенных уведомлениях все равно
|
||
* будут доставляться сообщния с упоминаниями.
|
||
*/
|
||
export function DialogStateProvider(props : DialogStateProviderProps) {
|
||
const [muted, setMuted] = useState<string[]>([]);
|
||
const [pinned, setPinned] = useState<string[]>([]);
|
||
const [mentions, setDialogMentions] = useState<DialogMention[]>([]);
|
||
const {info} = useConsoleLogger('DialogStateProvider');
|
||
|
||
useEffect(() => {
|
||
let muted = localStorage.getItem("mutedDialogs");
|
||
let pinned = localStorage.getItem("pinnedDialogs");
|
||
let mentions = localStorage.getItem("dialogMentions");
|
||
|
||
if (mentions) {
|
||
setDialogMentions(JSON.parse(mentions));
|
||
}
|
||
if (muted) {
|
||
setMuted(JSON.parse(muted));
|
||
}
|
||
if (pinned) {
|
||
setPinned(JSON.parse(pinned));
|
||
}
|
||
|
||
info("Initial dialog states is loaded");
|
||
}, []);
|
||
|
||
useEffect(() => {
|
||
localStorage.setItem("mutedDialogs", JSON.stringify(muted));
|
||
}, [muted]);
|
||
|
||
useEffect(() => {
|
||
localStorage.setItem("pinnedDialogs", JSON.stringify(pinned));
|
||
}, [pinned]);
|
||
|
||
useEffect(() => {
|
||
localStorage.setItem("dialogMentions", JSON.stringify(mentions));
|
||
}, [mentions]);
|
||
|
||
const muteToggle = (dialogId: string) => {
|
||
setMuted(prev => {
|
||
if (prev.includes(dialogId)) {
|
||
return prev.filter(id => id !== dialogId);
|
||
} else {
|
||
return [...prev, dialogId];
|
||
}
|
||
});
|
||
}
|
||
|
||
const pinToggle = (dialogId: string) => {
|
||
setPinned(prev => {
|
||
if (prev.includes(dialogId)) {
|
||
return prev.filter(id => id !== dialogId);
|
||
} else {
|
||
return [...prev, dialogId];
|
||
}
|
||
});
|
||
}
|
||
|
||
const pushMention = (dialogMention: DialogMention) => {
|
||
setDialogMentions((prev) => [...prev, dialogMention]);
|
||
}
|
||
|
||
const popMention = (dialogMention: DialogMention) => {
|
||
setDialogMentions((prev) => prev.filter(m => !(m.dialog_id === dialogMention.dialog_id && m.message_id === dialogMention.message_id)));
|
||
}
|
||
|
||
const isMentioned = (dialogId: string) => {
|
||
return mentions.some(m => m.dialog_id === dialogId);
|
||
}
|
||
|
||
const getLastMention = (dialogId: string) : DialogMention => {
|
||
const dialogMentions = mentions.filter(m => m.dialog_id === dialogId);
|
||
return dialogMentions[dialogMentions.length - 1];
|
||
}
|
||
|
||
return (
|
||
<DialogStateContext.Provider value={{
|
||
muted,
|
||
pinned,
|
||
muteToggle,
|
||
pinToggle,
|
||
pushMention,
|
||
popMention,
|
||
mentions,
|
||
isMentioned,
|
||
getLastMention
|
||
}}>
|
||
{props.children}
|
||
</DialogStateContext.Provider>
|
||
)
|
||
} |