'init'
This commit is contained in:
122
app/providers/DialogStateProvider.tsx/DialogStateProvider.tsx
Normal file
122
app/providers/DialogStateProvider.tsx/DialogStateProvider.tsx
Normal file
@@ -0,0 +1,122 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
15
app/providers/DialogStateProvider.tsx/useDialogMute.ts
Normal file
15
app/providers/DialogStateProvider.tsx/useDialogMute.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { useContext } from "react";
|
||||
import { DialogStateContext } from "./DialogStateProvider";
|
||||
|
||||
export function useDialogMute(dialog_id: string) {
|
||||
const context = useContext(DialogStateContext);
|
||||
if(!context){
|
||||
throw new Error("useDialogState must be used within a DialogStateProvider");
|
||||
}
|
||||
|
||||
const isMuted = context.muted.includes(dialog_id);
|
||||
return {
|
||||
isMuted,
|
||||
muteToggle: context.muteToggle
|
||||
}
|
||||
}
|
||||
16
app/providers/DialogStateProvider.tsx/useDialogPin.ts
Normal file
16
app/providers/DialogStateProvider.tsx/useDialogPin.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { useContext } from "react";
|
||||
import { DialogStateContext } from "./DialogStateProvider";
|
||||
|
||||
export function useDialogPin(dialog_id: string){
|
||||
const context = useContext(DialogStateContext);
|
||||
if(!context){
|
||||
throw new Error("useDialogState must be used within a DialogStateProvider");
|
||||
}
|
||||
|
||||
const isPinned = context.pinned.includes(dialog_id);
|
||||
|
||||
return {
|
||||
isPinned,
|
||||
pinToggle: context.pinToggle
|
||||
}
|
||||
}
|
||||
11
app/providers/DialogStateProvider.tsx/useDialogState.ts
Normal file
11
app/providers/DialogStateProvider.tsx/useDialogState.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { useContext } from "react";
|
||||
import { DialogStateContext, DialogStateContextValue } from "./DialogStateProvider";
|
||||
|
||||
export function useDialogState() : DialogStateContextValue {
|
||||
const context = useContext(DialogStateContext);
|
||||
if(!context){
|
||||
throw new Error("useDialogState must be used within a DialogStateProvider");
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
16
app/providers/DialogStateProvider.tsx/useMentions.ts
Normal file
16
app/providers/DialogStateProvider.tsx/useMentions.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { useContext } from "react";
|
||||
import { DialogStateContext } from "./DialogStateProvider";
|
||||
|
||||
export function useMentions() {
|
||||
const context = useContext(DialogStateContext);
|
||||
if (!context) {
|
||||
throw new Error("useMentions must be used within a DialogStateProvider");
|
||||
}
|
||||
return {
|
||||
pushMention: context.pushMention,
|
||||
popMention: context.popMention,
|
||||
isMentioned: context.isMentioned,
|
||||
mentions: context.mentions,
|
||||
getLastMention: context.getLastMention
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user