Live video on the AT Protocol
1import { useEffect } from "react";
2import {
3 SharedValue,
4 useSharedValue,
5 withTiming,
6} from "react-native-reanimated";
7import { useDispatch, useSelector } from "react-redux";
8import { useWindowDimensions } from "tamagui";
9
10import {
11 selectIsSidebarCollapsed,
12 selectIsSidebarHidden,
13 selectSidebarTargetWidth,
14 toggleSidebar,
15} from "../features/base/sidebarSlice";
16import { RootState } from "../store/store";
17
18// Returns *true* if the screen is > 1024px
19function useIsLargeScreen() {
20 const { width } = useWindowDimensions();
21 // gtMd breakpoint
22 return width >= 980 + 1;
23}
24
25export interface UseSidebarOutput {
26 isActive: boolean;
27 isCollapsed: boolean;
28 isHidden: boolean;
29 animatedWidth: SharedValue<number>;
30 toggle: () => void;
31}
32
33/*
34 * useSidebarControl
35 * A hook to control the custom sidebar on desktop, using Redux for state.
36 *
37 * Returns: An interface containing:
38 * - isActive: boolean - True if the screen is considered large (width >= 1024px).
39 * - isCollapsed: boolean - The current collapsed state of the sidebar from Redux.
40 * - animatedWidth: SharedValue<number> - An animated value controlling the sidebar's width.
41 * - toggle: () => void - A function to dispatch the Redux action to toggle the sidebar.
42 */
43export function useSidebarControl(): UseSidebarOutput {
44 const dispatch = useDispatch();
45 const isCollapsed = useSelector((state: RootState) =>
46 selectIsSidebarCollapsed(state),
47 );
48 const targetWidth = useSelector((state: RootState) =>
49 selectSidebarTargetWidth(state),
50 );
51
52 const isHidden = useSelector((state: RootState) =>
53 selectIsSidebarHidden(state),
54 );
55
56 const animatedWidth = useSharedValue(targetWidth);
57
58 const isActive = useIsLargeScreen();
59 useEffect(() => {
60 if (isActive) {
61 if (!isHidden && targetWidth < 64) targetWidth == 64;
62 // Only animate if the sidebar is active
63 animatedWidth.value = withTiming(targetWidth, { duration: 250 });
64 } else {
65 animatedWidth.value = targetWidth;
66 }
67 }, [targetWidth, isActive, animatedWidth]);
68
69 const handleToggle = () => {
70 if (isActive) {
71 // Only allow toggle if the sidebar functionality is active
72 dispatch(toggleSidebar());
73 }
74 };
75
76 return {
77 isActive,
78 isCollapsed,
79 animatedWidth,
80 isHidden,
81 toggle: handleToggle,
82 };
83}