refactor: recreate collection and global hotkey contexts as store (using zustand)

This commit is contained in:
Sonny
2024-11-06 23:06:21 +01:00
committed by Sonny
parent 8bd87b5bba
commit 861906d29b
27 changed files with 247 additions and 148 deletions

View File

@@ -10,8 +10,8 @@ import {
import ModalWrapper from '~/components/common/modal/_modal_wrapper';
import TextEllipsis from '~/components/common/text_ellipsis';
import useClickOutside from '~/hooks/use_click_outside';
import useGlobalHotkeys from '~/hooks/use_global_hotkeys';
import useShortcut from '~/hooks/use_shortcut';
import { useGlobalHotkeysStore } from '~/store/global_hotkeys_store';
interface ModalProps {
title?: string;
@@ -32,7 +32,7 @@ export default function Modal({
close,
}: ModalProps) {
const modalRef = useRef<HTMLDivElement>(null);
const { setGlobalHotkeysEnabled } = useGlobalHotkeys();
const { setGlobalHotkeysEnabled } = useGlobalHotkeysStore();
useClickOutside(modalRef, close);
useShortcut('ESCAPE_KEY', close, { disableGlobalCheck: true });

View File

@@ -4,7 +4,7 @@ import CollectionHeader from '~/components/dashboard/collection/header/collectio
import LinkList from '~/components/dashboard/link/link_list';
import { NoCollection } from '~/components/dashboard/link/no_item';
import Footer from '~/components/footer/footer';
import useActiveCollection from '~/hooks/use_active_collection';
import { useActiveCollection } from '~/store/collection_store';
export interface CollectionHeaderProps {
showButtons: boolean;

View File

@@ -1,6 +1,6 @@
import styled from '@emotion/styled';
import TextEllipsis from '~/components/common/text_ellipsis';
import useActiveCollection from '~/hooks/use_active_collection';
import { useActiveCollection } from '~/store/collection_store';
const CollectionDescriptionStyle = styled.div({
width: '100%',

View File

@@ -6,7 +6,7 @@ import { CollectionHeaderProps } from '~/components/dashboard/collection/collect
import CollectionControls from '~/components/dashboard/collection/header/collection_controls';
import CollectionDescription from '~/components/dashboard/collection/header/collection_description';
import VisibilityBadge from '~/components/visibilty/visibilty';
import useActiveCollection from '~/hooks/use_active_collection';
import { useActiveCollection } from '~/store/collection_store';
const paddingLeft = '1.25em';
const paddingRight = '1.65em';

View File

@@ -5,8 +5,8 @@ import { useEffect, useRef } from 'react';
import { AiFillFolderOpen, AiOutlineFolder } from 'react-icons/ai';
import TextEllipsis from '~/components/common/text_ellipsis';
import { Item } from '~/components/dashboard/side_nav/nav_item';
import useActiveCollection from '~/hooks/use_active_collection';
import { appendCollectionId } from '~/lib/navigation';
import { useActiveCollection } from '~/store/collection_store';
import { CollectionWithLinks } from '~/types/app';
const CollectionItemStyle = styled(Item, {

View File

@@ -2,9 +2,8 @@ import styled from '@emotion/styled';
import { useTranslation } from 'react-i18next';
import CollectionItem from '~/components/dashboard/collection/list/collection_item';
import CollectionListContainer from '~/components/dashboard/collection/list/collection_list_container';
import useActiveCollection from '~/hooks/use_active_collection';
import useCollections from '~/hooks/use_collections';
import useShortcut from '~/hooks/use_shortcut';
import { useActiveCollection, useCollections } from '~/store/collection_store';
const SideMenu = styled.nav(({ theme }) => ({
height: '100%',

View File

@@ -1,17 +1,15 @@
import { Link as InertiaLink } from '@inertiajs/react';
import { route } from '@izzyjs/route/client';
import { ActionIcon, Menu } from '@mantine/core';
import { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { BsThreeDotsVertical } from 'react-icons/bs';
import { FaRegEye } from 'react-icons/fa';
import { GoPencil } from 'react-icons/go';
import { IoTrashOutline } from 'react-icons/io5';
import { MdFavorite, MdFavoriteBorder } from 'react-icons/md';
import useActiveCollection from '~/hooks/use_active_collection';
import useCollections from '~/hooks/use_collections';
import { onFavorite } from '~/lib/favorite';
import { appendCollectionId, appendLinkId } from '~/lib/navigation';
import { useFavorites } from '~/store/collection_store';
import { Link } from '~/types/app';
interface LinksControlsProps {
@@ -22,34 +20,9 @@ export default function LinkControls({
link,
showGoToCollection = false,
}: LinksControlsProps) {
const { collections, setCollections } = useCollections();
const { setActiveCollection } = useActiveCollection();
const { toggleFavorite } = useFavorites();
const { t } = useTranslation('common');
const toggleFavorite = useCallback(
(linkId: Link['id']) => {
let linkIndex = 0;
const collectionIndex = collections.findIndex(({ links }) => {
const lIndex = links.findIndex((l) => l.id === linkId);
if (lIndex !== -1) {
linkIndex = lIndex;
}
return lIndex !== -1;
});
const collectionLink = collections[collectionIndex].links[linkIndex];
const collectionsCopy = [...collections];
collectionsCopy[collectionIndex].links[linkIndex] = {
...collectionLink,
favorite: !collectionLink.favorite,
};
setCollections(collectionsCopy);
setActiveCollection(collectionsCopy[collectionIndex]);
},
[collections, setCollections]
);
const onFavoriteCallback = () => toggleFavorite(link.id);
return (
<Menu withinPortal shadow="md" width={200}>

View File

@@ -2,8 +2,8 @@ import styled from '@emotion/styled';
import { Link } from '@inertiajs/react';
import { route } from '@izzyjs/route/client';
import { useTranslation } from 'react-i18next';
import useActiveCollection from '~/hooks/use_active_collection';
import { appendCollectionId } from '~/lib/navigation';
import { useActiveCollection } from '~/store/collection_store';
import { fadeIn } from '~/styles/keyframes';
const NoCollectionStyle = styled.div({

View File

@@ -7,11 +7,10 @@ import Modal from '~/components/common/modal/modal';
import NoSearchResult from '~/components/dashboard/search/no_search_result';
import SearchResultList from '~/components/dashboard/search/search_result_list';
import { GOOGLE_SEARCH_URL } from '~/constants';
import useActiveCollection from '~/hooks/use_active_collection';
import useCollections from '~/hooks/use_collections';
import useToggle from '~/hooks/use_modal';
import useShortcut from '~/hooks/use_shortcut';
import { makeRequest } from '~/lib/request';
import { useActiveCollection, useCollections } from '~/store/collection_store';
import { SearchResult } from '~/types/search';
const SearchInput = styled.input(({ theme }) => ({

View File

@@ -4,7 +4,7 @@ import { AiOutlineFolder } from 'react-icons/ai';
import Legend from '~/components/common/legend';
import TextEllipsis from '~/components/common/text_ellipsis';
import LinkFavicon from '~/components/dashboard/link/link_favicon';
import useCollections from '~/hooks/use_collections';
import { useCollections } from '~/store/collection_store';
import {
SearchResult,
SearchResultCollection,

View File

@@ -1,11 +1,9 @@
import styled from '@emotion/styled';
import { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { AiFillStar, AiOutlineStar } from 'react-icons/ai';
import { DropdownItemButton } from '~/components/common/dropdown/dropdown_item';
import useActiveCollection from '~/hooks/use_active_collection';
import useCollections from '~/hooks/use_collections';
import { onFavorite } from '~/lib/favorite';
import { useFavorites } from '~/store/collection_store';
import { Link } from '~/types/app';
const StarItem = styled(DropdownItemButton)(({ theme }) => ({
@@ -13,34 +11,9 @@ const StarItem = styled(DropdownItemButton)(({ theme }) => ({
}));
export default function FavoriteDropdownItem({ link }: { link: Link }) {
const { collections, setCollections } = useCollections();
const { setActiveCollection } = useActiveCollection();
const { toggleFavorite } = useFavorites();
const { t } = useTranslation();
const toggleFavorite = useCallback(
(linkId: Link['id']) => {
let linkIndex = 0;
const collectionIndex = collections.findIndex(({ links }) => {
const lIndex = links.findIndex((l) => l.id === linkId);
if (lIndex !== -1) {
linkIndex = lIndex;
}
return lIndex !== -1;
});
const collectionLink = collections[collectionIndex].links[linkIndex];
const collectionsCopy = [...collections];
collectionsCopy[collectionIndex].links[linkIndex] = {
...collectionLink,
favorite: !collectionLink.favorite,
};
setCollections(collectionsCopy);
setActiveCollection(collectionsCopy[collectionIndex]);
},
[collections, setCollections]
);
const onFavoriteCallback = () => toggleFavorite(link.id);
return (
<StarItem

View File

@@ -2,7 +2,7 @@ import styled from '@emotion/styled';
import { useTranslation } from 'react-i18next';
import FavoriteListContainer from '~/components/dashboard/side_nav/favorite/favorite_container';
import FavoriteItem from '~/components/dashboard/side_nav/favorite/favorite_item';
import useFavorites from '~/hooks/use_favorites';
import { useFavorites } from '~/store/collection_store';
const FavoriteLabel = styled.p(({ theme }) => ({
color: theme.colors.grey,

View File

@@ -8,10 +8,10 @@ import FavoriteList from '~/components/dashboard/side_nav/favorite/favorite_list
import { Item, ItemLink } from '~/components/dashboard/side_nav/nav_item';
import UserCard from '~/components/dashboard/side_nav/user_card';
import ModalSettings from '~/components/settings/settings_modal';
import useActiveCollection from '~/hooks/use_active_collection';
import useUser from '~/hooks/use_user';
import { rgba } from '~/lib/color';
import { appendCollectionId } from '~/lib/navigation';
import { useActiveCollection } from '~/store/collection_store';
const SideMenu = styled.nav(({ theme }) => ({
height: '100%',