mirror of
				https://github.com/cinnyapp/cinny.git
				synced 2025-11-04 14:30:29 +03:00 
			
		
		
		
	add room to active thread atom
This commit is contained in:
		
							parent
							
								
									12bcbc2e78
								
							
						
					
					
						commit
						38cc6e6f3a
					
				
					 3 changed files with 139 additions and 3 deletions
				
			
		| 
						 | 
				
			
			@ -8,6 +8,8 @@ import { makeNavToActivePathAtom } from '../../state/navToActivePath';
 | 
			
		|||
import { NavToActivePathProvider } from '../../state/hooks/navToActivePath';
 | 
			
		||||
import { makeOpenedSidebarFolderAtom } from '../../state/openedSidebarFolder';
 | 
			
		||||
import { OpenedSidebarFolderProvider } from '../../state/hooks/openedSidebarFolder';
 | 
			
		||||
import { makeRoomToActiveThreadAtom } from '../../state/roomToActiveThread';
 | 
			
		||||
import { RoomToActiveThreadProvider } from '../../state/hooks/roomToActiveThread';
 | 
			
		||||
 | 
			
		||||
type ClientInitStorageAtomProps = {
 | 
			
		||||
  children: ReactNode;
 | 
			
		||||
| 
						 | 
				
			
			@ -22,15 +24,19 @@ export function ClientInitStorageAtom({ children }: ClientInitStorageAtomProps)
 | 
			
		|||
 | 
			
		||||
  const navToActivePathAtom = useMemo(() => makeNavToActivePathAtom(userId), [userId]);
 | 
			
		||||
 | 
			
		||||
  const roomToActiveThreadAtom = useMemo(() => makeRoomToActiveThreadAtom(userId), [userId]);
 | 
			
		||||
 | 
			
		||||
  const openedSidebarFolderAtom = useMemo(() => makeOpenedSidebarFolderAtom(userId), [userId]);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <ClosedNavCategoriesProvider value={closedNavCategoriesAtom}>
 | 
			
		||||
      <ClosedLobbyCategoriesProvider value={closedLobbyCategoriesAtom}>
 | 
			
		||||
        <NavToActivePathProvider value={navToActivePathAtom}>
 | 
			
		||||
          <OpenedSidebarFolderProvider value={openedSidebarFolderAtom}>
 | 
			
		||||
            {children}
 | 
			
		||||
          </OpenedSidebarFolderProvider>
 | 
			
		||||
          <RoomToActiveThreadProvider value={roomToActiveThreadAtom}>
 | 
			
		||||
            <OpenedSidebarFolderProvider value={openedSidebarFolderAtom}>
 | 
			
		||||
              {children}
 | 
			
		||||
            </OpenedSidebarFolderProvider>
 | 
			
		||||
          </RoomToActiveThreadProvider>
 | 
			
		||||
        </NavToActivePathProvider>
 | 
			
		||||
      </ClosedLobbyCategoriesProvider>
 | 
			
		||||
    </ClosedNavCategoriesProvider>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										55
									
								
								src/app/state/hooks/roomToActiveThread.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/app/state/hooks/roomToActiveThread.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
import { createContext, useCallback, useContext } from 'react';
 | 
			
		||||
import { useAtomValue, useSetAtom } from 'jotai';
 | 
			
		||||
import { RoomToActiveThreadAtom } from '../roomToActiveThread';
 | 
			
		||||
 | 
			
		||||
const RoomToActiveThreadAtomContext = createContext<RoomToActiveThreadAtom | null>(null);
 | 
			
		||||
export const RoomToActiveThreadProvider = RoomToActiveThreadAtomContext.Provider;
 | 
			
		||||
 | 
			
		||||
export const useRoomToActiveThreadAtom = (): RoomToActiveThreadAtom => {
 | 
			
		||||
  const anAtom = useContext(RoomToActiveThreadAtomContext);
 | 
			
		||||
 | 
			
		||||
  if (!anAtom) {
 | 
			
		||||
    throw new Error('RoomToActiveThreadAtom is not provided!');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return anAtom;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const useThreadSelector = (roomId: string): ((threadId: string) => void) => {
 | 
			
		||||
  const roomToActiveThreadAtom = useRoomToActiveThreadAtom();
 | 
			
		||||
  const setRoomToActiveThread = useSetAtom(roomToActiveThreadAtom);
 | 
			
		||||
 | 
			
		||||
  const onThreadSelect = useCallback(
 | 
			
		||||
    (threadId: string) => {
 | 
			
		||||
      setRoomToActiveThread({
 | 
			
		||||
        type: 'PUT',
 | 
			
		||||
        roomId,
 | 
			
		||||
        threadId,
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    [roomId, setRoomToActiveThread]
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  return onThreadSelect;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const useActiveThread = (roomId: string): string | undefined => {
 | 
			
		||||
  const roomToActiveThreadAtom = useRoomToActiveThreadAtom();
 | 
			
		||||
  const roomToActiveThread = useAtomValue(roomToActiveThreadAtom);
 | 
			
		||||
 | 
			
		||||
  return roomToActiveThread.get(roomId);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const useThreadClose = (roomId: string): (() => void) => {
 | 
			
		||||
  const roomToActiveThreadAtom = useRoomToActiveThreadAtom();
 | 
			
		||||
  const setRoomToActiveThread = useSetAtom(roomToActiveThreadAtom);
 | 
			
		||||
 | 
			
		||||
  const closeThread = useCallback(() => {
 | 
			
		||||
    setRoomToActiveThread({
 | 
			
		||||
      type: 'DELETE',
 | 
			
		||||
      roomId,
 | 
			
		||||
    });
 | 
			
		||||
  }, [roomId, setRoomToActiveThread]);
 | 
			
		||||
 | 
			
		||||
  return closeThread;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										75
									
								
								src/app/state/roomToActiveThread.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								src/app/state/roomToActiveThread.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,75 @@
 | 
			
		|||
import { atom, WritableAtom } from 'jotai';
 | 
			
		||||
import produce from 'immer';
 | 
			
		||||
import {
 | 
			
		||||
  atomWithLocalStorage,
 | 
			
		||||
  getLocalStorageItem,
 | 
			
		||||
  setLocalStorageItem,
 | 
			
		||||
} from './utils/atomWithLocalStorage';
 | 
			
		||||
 | 
			
		||||
const ROOM_TO_ACTIVE_THREAD = 'roomToActiveThread';
 | 
			
		||||
 | 
			
		||||
const getStoreKey = (userId: string): string => `${ROOM_TO_ACTIVE_THREAD}${userId}`;
 | 
			
		||||
 | 
			
		||||
type RoomToActiveThread = Map<string, string>;
 | 
			
		||||
 | 
			
		||||
type RoomToActiveThreadAction =
 | 
			
		||||
  | {
 | 
			
		||||
      type: 'PUT';
 | 
			
		||||
      roomId: string;
 | 
			
		||||
      threadId: string;
 | 
			
		||||
    }
 | 
			
		||||
  | {
 | 
			
		||||
      type: 'DELETE';
 | 
			
		||||
      roomId: string;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
export type RoomToActiveThreadAtom = WritableAtom<
 | 
			
		||||
  RoomToActiveThread,
 | 
			
		||||
  [RoomToActiveThreadAction],
 | 
			
		||||
  undefined
 | 
			
		||||
>;
 | 
			
		||||
 | 
			
		||||
export const makeRoomToActiveThreadAtom = (userId: string): RoomToActiveThreadAtom => {
 | 
			
		||||
  const storeKey = getStoreKey(userId);
 | 
			
		||||
 | 
			
		||||
  const baseRoomToActiveThread = atomWithLocalStorage<RoomToActiveThread>(
 | 
			
		||||
    storeKey,
 | 
			
		||||
    (key) => {
 | 
			
		||||
      const obj: Record<string, string> = getLocalStorageItem(key, {});
 | 
			
		||||
      return new Map(Object.entries(obj));
 | 
			
		||||
    },
 | 
			
		||||
    (key, value) => {
 | 
			
		||||
      const obj: Record<string, string> = Object.fromEntries(value);
 | 
			
		||||
      setLocalStorageItem(key, obj);
 | 
			
		||||
    }
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  const navToActivePathAtom = atom<RoomToActiveThread, [RoomToActiveThreadAction], undefined>(
 | 
			
		||||
    (get) => get(baseRoomToActiveThread),
 | 
			
		||||
    (get, set, action) => {
 | 
			
		||||
      if (action.type === 'DELETE') {
 | 
			
		||||
        set(
 | 
			
		||||
          baseRoomToActiveThread,
 | 
			
		||||
          produce(get(baseRoomToActiveThread), (draft) => {
 | 
			
		||||
            draft.delete(action.roomId);
 | 
			
		||||
          })
 | 
			
		||||
        );
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      if (action.type === 'PUT') {
 | 
			
		||||
        set(
 | 
			
		||||
          baseRoomToActiveThread,
 | 
			
		||||
          produce(get(baseRoomToActiveThread), (draft) => {
 | 
			
		||||
            draft.set(action.roomId, action.threadId);
 | 
			
		||||
          })
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  return navToActivePathAtom;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const clearRoomToActiveThreadStore = (userId: string) => {
 | 
			
		||||
  localStorage.removeItem(getStoreKey(userId));
 | 
			
		||||
};
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue