diff --git a/src/api/types.ts b/src/api/types.ts index c975311a..f2790d8f 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -1,4 +1,5 @@ import type { RxCollection, RxDatabase, RxDocument } from 'rxdb'; +import type { QueryConstructor } from 'rxdb-hooks'; export type NoteDocType = { date_created: string, @@ -11,6 +12,7 @@ export type NoteDocType = { export type NoteDocument = RxDocument; export type NoteCollection = RxCollection; +export type NoteQuery = QueryConstructor; export type MyDatabaseCollections = { notes: NoteCollection, diff --git a/src/components/FolderList/FolderListItem.tsx b/src/components/FolderList/FolderListItem.tsx index a5721e87..660ae19f 100644 --- a/src/components/FolderList/FolderListItem.tsx +++ b/src/components/FolderList/FolderListItem.tsx @@ -2,12 +2,11 @@ import { Disclosure } from '@headlessui/react'; import { ChevronUpIcon } from '@heroicons/react/24/outline'; import { useAtomValue } from 'jotai'; import { useCallback } from 'react'; -import { useRxData, type QueryConstructor } from 'rxdb-hooks'; +import { useRxData } from 'rxdb-hooks'; -import { type NoteDocType } from '@/api/types'; +import type { NoteDocType, NoteQuery } from '@/api/types'; import { Button } from '@/components/Button'; -// import { FolderContextMenu } from './FolderContextMenu'; -import { NotesList } from '@/components/NotesList'; +import { NotesList } from '@/components/NotesList'; // eslint-disable-line import/no-cycle import { notesSearchAtom } from '@/context/notesSearch'; import { notesSortAtom, notesSortOptions } from '@/context/notesSort'; import { classNames } from '@/utils/classNames'; @@ -18,7 +17,7 @@ export function FolderListItem({ }: FolderListItemProps) { const search = useAtomValue(notesSearchAtom); const sort = useAtomValue(notesSortAtom); - const notesQuery: QueryConstructor = useCallback( + const notesQuery: NoteQuery = useCallback( (collection) => collection.find({ selector: { folder: { @@ -34,6 +33,7 @@ export function FolderListItem({ ); const { result: notes, isFetching } = useRxData('notes', notesQuery); + return (
  • {folder} - + diff --git a/src/components/FolderList/index.tsx b/src/components/FolderList/index.tsx deleted file mode 100644 index d5e2bb2c..00000000 --- a/src/components/FolderList/index.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { useAtom, useAtomValue } from 'jotai'; -import { useCallback, useEffect, useRef } from 'react'; -import { ViewportList } from 'react-viewport-list'; -import { useRxData, type QueryConstructor } from 'rxdb-hooks'; - -import type { NoteDocType } from '@/api/types'; -import { foldersAtom } from '@/context/folders'; -import { notesSearchAtom } from '@/context/notesSearch'; -import { notesSortAtom, notesSortOptions } from '@/context/notesSort'; -import { FolderListItem } from './FolderListItem'; - -export function FolderList() { - const ref = useRef(null); - // const setFolders = useSetAtom(foldersAtom); - const [folders, setFolders] = useAtom(foldersAtom); - const search = useAtomValue(notesSearchAtom); - const sort = useAtomValue(notesSortAtom); - const notesQuery: QueryConstructor = useCallback( - (collection) => collection.find({ - selector: { - folder: { - $exists: true, - }, - text: { - $regex: RegExp(search, 'i'), - }, - }, - sort: notesSortOptions[sort].value, - }), - [search, sort], - ); - - const { result: notes, isFetching } = useRxData('notes', notesQuery); - - useEffect(() => { - const allFolders = notes.map((note) => note.folder ?? '').filter(Boolean); - const newFolders = [...new Set(allFolders)].sort(); - // console.log(newFolders); - setFolders(newFolders); - }, [notes, setFolders]); - - return ( -
      - {isFetching && ( -
    • Loading...
    • - )} - - {/* TODO: Maybe I should be passing this through to query the database less? */} - {/* // folderNotes={notes.filter((note) => note.folder === folder)} */} - {(folder) => } - -
    - ); -} diff --git a/src/components/FolderList/types.ts b/src/components/FolderList/types.ts index 82e547bd..ca903623 100644 --- a/src/components/FolderList/types.ts +++ b/src/components/FolderList/types.ts @@ -1,8 +1,3 @@ -// import type { RxDocument } from 'rxdb'; - -// import type { NoteDocType } from '@/api/types'; - export type FolderListItemProps = { folder: string, - // folderNotes: RxDocument[], }; diff --git a/src/components/NotesList/index.tsx b/src/components/NotesList/index.tsx index 81558f30..702f2dbb 100644 --- a/src/components/NotesList/index.tsx +++ b/src/components/NotesList/index.tsx @@ -1,20 +1,27 @@ import { useAtomValue } from 'jotai'; -import { useRef } from 'react'; +import { useMemo, useRef } from 'react'; import { ViewportList } from 'react-viewport-list'; +import { FolderListItem } from '@/components/FolderList/FolderListItem'; import { foldersAtom } from '@/context/folders'; import { classNames } from '@/utils/classNames'; import { NotesListItem } from './NotesListItem'; import { NotesListProps } from './types'; export function NotesList({ - notes, + includeFolders, isFetching, - padding = false, + notes, + padding, }: NotesListProps) { const ref = useRef(null); const folders = useAtomValue(foldersAtom); + const items = useMemo(() => [ + ...(includeFolders ? folders : []), + ...notes.filter((note) => (includeFolders ? !note.folder : true)), + ], [folders, includeFolders, notes]); + return (
      - {(note) => } + {(note) => { + if (typeof note === 'string') { + return ( + + ); + } + return ( + + ); + }}
    ); diff --git a/src/components/NotesList/types.ts b/src/components/NotesList/types.ts index 9e704a6f..29aab8c5 100644 --- a/src/components/NotesList/types.ts +++ b/src/components/NotesList/types.ts @@ -1,14 +1,14 @@ import type { ReactNode } from 'react'; -import type { RxDocument } from 'rxdb'; -import type { NoteDocType, NoteDocument } from '@/api/types'; +import type { NoteDocument } from '@/api/types'; export type NotesProps = { note: NoteDocument, }; export type NotesListProps = { - notes?: RxDocument[], + includeFolders?: boolean, isFetching: boolean, + notes: NoteDocument[], padding?: boolean, }; export type NotesContextMenuItemProps = { diff --git a/src/components/Sidebar/Content.tsx b/src/components/Sidebar/Content.tsx index 20a6a56f..a2754a93 100644 --- a/src/components/Sidebar/Content.tsx +++ b/src/components/Sidebar/Content.tsx @@ -1,31 +1,21 @@ -import { useAtomValue } from 'jotai'; -import { useCallback } from 'react'; -import { useRxData, type QueryConstructor } from 'rxdb-hooks'; +import { useAtomValue, useSetAtom } from 'jotai'; +import { useCallback, useEffect } from 'react'; +import { useRxData } from 'rxdb-hooks'; -import type { NoteDocType } from '@/api/types'; +import type { NoteDocType, NoteQuery } from '@/api/types'; import { Card } from '@/components/Card'; -import { FolderList } from '@/components/FolderList'; import { NotesList } from '@/components/NotesList'; +import { foldersAtom } from '@/context/folders'; import { notesSearchAtom } from '@/context/notesSearch'; import { notesSortAtom, notesSortOptions } from '@/context/notesSort'; export function Content() { const search = useAtomValue(notesSearchAtom); const sort = useAtomValue(notesSortAtom); - const notesQuery: QueryConstructor = useCallback( + const setFolders = useSetAtom(foldersAtom); + const notesQuery: NoteQuery = useCallback( (collection) => collection.find({ selector: { - $or: [ - { - folder: { $exists: false }, - }, - { - folder: { $eq: '' }, - }, - { - folder: { $eq: null }, - }, - ], text: { $regex: RegExp(search, 'i'), }, @@ -38,16 +28,24 @@ export function Content() { const { result: notes, isFetching } = useRxData('notes', notesQuery); // console.log(notes.map((folder) => folder.toJSON())); + useEffect(() => { + const allFolders = notes.map((note) => note.folder ?? '').filter(Boolean); + const newFolders = [...new Set(allFolders)].sort(); + // console.log(newFolders); + setFolders(newFolders); + }, [notes, setFolders]); + return ( - ); diff --git a/src/routes/Note.tsx b/src/routes/Note.tsx index 2b2b6a9d..682607e2 100644 --- a/src/routes/Note.tsx +++ b/src/routes/Note.tsx @@ -8,13 +8,13 @@ import { import { StarIcon as StarSolidIcon, } from '@heroicons/react/24/solid'; -import { useEffect, useState } from 'react'; +import { useCallback, useEffect, useState } from 'react'; import { useHotkeys } from 'react-hotkeys-hook'; import { useNavigate, useParams } from 'react-router-dom'; import { useRxData } from 'rxdb-hooks'; import { deleteNote, favouriteNote, updateNote } from '@/api/notes'; -import type { NoteDocType } from '@/api/types'; +import type { NoteDocType, NoteQuery } from '@/api/types'; import { Button } from '@/components/Button'; import { Markdown } from '@/components/Markdown'; import { ModalConfirm } from '@/components/ModalConfirm'; @@ -30,10 +30,11 @@ export function Note() { const [showMoreInformation, setShowMoreInformation] = useState(false); const [showDeleteNoteModal, setShowDeleteNoteModal] = useState(false); const [text, setText] = useState(''); - const { result: [note] } = useRxData( - 'notes', + const notesQuery: NoteQuery = useCallback( (collection) => collection.findOne(id), + [id], ); + const { result: [note] } = useRxData('notes', notesQuery); const handleDeleteNote = () => { setShowDeleteNoteModal(false);