Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
canifa_note
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Vũ Hoàng Anh
canifa_note
Commits
c23aebd6
Commit
c23aebd6
authored
May 27, 2025
by
Steven
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactor: memo filter store
parent
f12d7ae8
Changes
17
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
1447 additions
and
1560 deletions
+1447
-1560
package.json
web/package.json
+27
-28
pnpm-lock.yaml
web/pnpm-lock.yaml
+1303
-1498
ShortcutsSection.tsx
web/src/components/HomeSidebar/ShortcutsSection.tsx
+1
-2
TagsSection.tsx
web/src/components/HomeSidebar/TagsSection.tsx
+3
-4
Tag.tsx
web/src/components/MemoContent/Tag.tsx
+4
-4
MemoFilters.tsx
web/src/components/MemoFilters.tsx
+4
-4
SearchBar.tsx
web/src/components/SearchBar.tsx
+1
-2
StatisticsView.tsx
web/src/components/StatisticsView.tsx
+1
-2
TagTree.tsx
web/src/components/TagTree.tsx
+3
-4
RootLayout.tsx
web/src/layouts/RootLayout.tsx
+1
-2
Archived.tsx
web/src/pages/Archived.tsx
+1
-2
Explore.tsx
web/src/pages/Explore.tsx
+1
-2
Home.tsx
web/src/pages/Home.tsx
+1
-2
UserProfile.tsx
web/src/pages/UserProfile.tsx
+1
-2
index.ts
web/src/store/v1/index.ts
+0
-1
index.ts
web/src/store/v2/index.ts
+2
-1
memoFilter.ts
web/src/store/v2/memoFilter.ts
+93
-0
No files found.
web/package.json
View file @
c23aebd6
...
@@ -12,10 +12,10 @@
...
@@ -12,10 +12,10 @@
"@dnd-kit/utilities"
:
"^3.2.2"
,
"@dnd-kit/utilities"
:
"^3.2.2"
,
"@emotion/react"
:
"^11.14.0"
,
"@emotion/react"
:
"^11.14.0"
,
"@emotion/styled"
:
"^11.14.0"
,
"@emotion/styled"
:
"^11.14.0"
,
"@github/relative-time-element"
:
"^4.4.
5
"
,
"@github/relative-time-element"
:
"^4.4.
8
"
,
"@matejmazur/react-katex"
:
"^3.1.3"
,
"@matejmazur/react-katex"
:
"^3.1.3"
,
"@mui/joy"
:
"5.0.0-beta.51"
,
"@mui/joy"
:
"5.0.0-beta.51"
,
"@radix-ui/react-popover"
:
"^1.1.
6
"
,
"@radix-ui/react-popover"
:
"^1.1.
14
"
,
"@usememos/mui"
:
"0.1.0-20250515140125"
,
"@usememos/mui"
:
"0.1.0-20250515140125"
,
"clsx"
:
"^2.1.1"
,
"clsx"
:
"^2.1.1"
,
"copy-to-clipboard"
:
"^3.3.3"
,
"copy-to-clipboard"
:
"^3.3.3"
,
...
@@ -23,60 +23,59 @@
...
@@ -23,60 +23,59 @@
"fuse.js"
:
"^7.1.0"
,
"fuse.js"
:
"^7.1.0"
,
"highlight.js"
:
"^11.11.1"
,
"highlight.js"
:
"^11.11.1"
,
"i18next"
:
"^24.2.3"
,
"i18next"
:
"^24.2.3"
,
"katex"
:
"^0.16.2
1
"
,
"katex"
:
"^0.16.2
2
"
,
"leaflet"
:
"^1.9.4"
,
"leaflet"
:
"^1.9.4"
,
"lodash-es"
:
"^4.17.21"
,
"lodash-es"
:
"^4.17.21"
,
"lucide-react"
:
"^0.486.0"
,
"lucide-react"
:
"^0.486.0"
,
"mermaid"
:
"^11.
4.1
"
,
"mermaid"
:
"^11.
6.0
"
,
"mobx"
:
"^6.13.7"
,
"mobx"
:
"^6.13.7"
,
"mobx-react-lite"
:
"^4.1.0"
,
"mobx-react-lite"
:
"^4.1.0"
,
"react"
:
"^18.3.1"
,
"react"
:
"^18.3.1"
,
"react-datepicker"
:
"^8.
2.1
"
,
"react-datepicker"
:
"^8.
4.0
"
,
"react-dom"
:
"^18.3.1"
,
"react-dom"
:
"^18.3.1"
,
"react-force-graph-2d"
:
"^1.27.
0
"
,
"react-force-graph-2d"
:
"^1.27.
1
"
,
"react-hot-toast"
:
"^2.5.2"
,
"react-hot-toast"
:
"^2.5.2"
,
"react-i18next"
:
"^15.
4.1
"
,
"react-i18next"
:
"^15.
5.2
"
,
"react-leaflet"
:
"^4.2.1"
,
"react-leaflet"
:
"^4.2.1"
,
"react-router-dom"
:
"^7.
3.0
"
,
"react-router-dom"
:
"^7.
6.1
"
,
"react-simple-pull-to-refresh"
:
"^1.3.3"
,
"react-simple-pull-to-refresh"
:
"^1.3.3"
,
"react-use"
:
"^17.6.0"
,
"react-use"
:
"^17.6.0"
,
"tailwind-merge"
:
"^2.6.0"
,
"tailwind-merge"
:
"^2.6.0"
,
"tailwindcss"
:
"^3.4.17"
,
"tailwindcss"
:
"^3.4.17"
,
"tailwindcss-animate"
:
"^1.0.7"
,
"tailwindcss-animate"
:
"^1.0.7"
,
"textarea-caret"
:
"^3.1.0"
,
"textarea-caret"
:
"^3.1.0"
,
"uuid"
:
"^11.1.0"
,
"uuid"
:
"^11.1.0"
"zustand"
:
"^5.0.3"
},
},
"devDependencies"
:
{
"devDependencies"
:
{
"@bufbuild/protobuf"
:
"^2.
2.5
"
,
"@bufbuild/protobuf"
:
"^2.
5.0
"
,
"@eslint/js"
:
"^9.2
3
.0"
,
"@eslint/js"
:
"^9.2
7
.0"
,
"@trivago/prettier-plugin-sort-imports"
:
"^5.2.2"
,
"@trivago/prettier-plugin-sort-imports"
:
"^5.2.2"
,
"@types/d3"
:
"^7.4.3"
,
"@types/d3"
:
"^7.4.3"
,
"@types/katex"
:
"^0.16.7"
,
"@types/katex"
:
"^0.16.7"
,
"@types/leaflet"
:
"^1.9.1
6
"
,
"@types/leaflet"
:
"^1.9.1
8
"
,
"@types/lodash-es"
:
"^4.17.12"
,
"@types/lodash-es"
:
"^4.17.12"
,
"@types/node"
:
"^22.15.
3
"
,
"@types/node"
:
"^22.15.
21
"
,
"@types/qs"
:
"^6.
9.18
"
,
"@types/qs"
:
"^6.
14.0
"
,
"@types/react"
:
"^18.3.
18
"
,
"@types/react"
:
"^18.3.
23
"
,
"@types/react-dom"
:
"^18.3.
5
"
,
"@types/react-dom"
:
"^18.3.
7
"
,
"@types/textarea-caret"
:
"^3.0.
3
"
,
"@types/textarea-caret"
:
"^3.0.
4
"
,
"@types/uuid"
:
"^10.0.0"
,
"@types/uuid"
:
"^10.0.0"
,
"@vitejs/plugin-legacy"
:
"^6.1.1"
,
"@vitejs/plugin-legacy"
:
"^6.1.1"
,
"@vitejs/plugin-react"
:
"^4.
3.4
"
,
"@vitejs/plugin-react"
:
"^4.
5.0
"
,
"autoprefixer"
:
"^10.4.21"
,
"autoprefixer"
:
"^10.4.21"
,
"code-inspector-plugin"
:
"^0.18.3"
,
"code-inspector-plugin"
:
"^0.18.3"
,
"eslint"
:
"^9.2
5.1
"
,
"eslint"
:
"^9.2
7.0
"
,
"eslint-config-prettier"
:
"^10.1.
1
"
,
"eslint-config-prettier"
:
"^10.1.
5
"
,
"eslint-plugin-prettier"
:
"^5.
2.5
"
,
"eslint-plugin-prettier"
:
"^5.
4.0
"
,
"eslint-plugin-react"
:
"^7.37.
4
"
,
"eslint-plugin-react"
:
"^7.37.
5
"
,
"long"
:
"^5.3.
1
"
,
"long"
:
"^5.3.
2
"
,
"nice-grpc-web"
:
"^3.3.7"
,
"nice-grpc-web"
:
"^3.3.7"
,
"postcss"
:
"^8.5.3"
,
"postcss"
:
"^8.5.3"
,
"prettier"
:
"^3.5.3"
,
"prettier"
:
"^3.5.3"
,
"terser"
:
"^5.39.
0
"
,
"terser"
:
"^5.39.
2
"
,
"typescript"
:
"^5.8.
2
"
,
"typescript"
:
"^5.8.
3
"
,
"typescript-eslint"
:
"^8.
28.0
"
,
"typescript-eslint"
:
"^8.
32.1
"
,
"vite"
:
"^6.
2.1
"
"vite"
:
"^6.
3.5
"
},
},
"pnpm"
:
{
"pnpm"
:
{
"onlyBuiltDependencies"
:
[
"onlyBuiltDependencies"
:
[
...
...
web/pnpm-lock.yaml
View file @
c23aebd6
This diff is collapsed.
Click to expand it.
web/src/components/HomeSidebar/ShortcutsSection.tsx
View file @
c23aebd6
...
@@ -4,8 +4,8 @@ import { observer } from "mobx-react-lite";
...
@@ -4,8 +4,8 @@ import { observer } from "mobx-react-lite";
import
{
shortcutServiceClient
}
from
"@/grpcweb"
;
import
{
shortcutServiceClient
}
from
"@/grpcweb"
;
import
useAsyncEffect
from
"@/hooks/useAsyncEffect"
;
import
useAsyncEffect
from
"@/hooks/useAsyncEffect"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
{
useMemoFilterStore
}
from
"@/store/v1"
;
import
{
userStore
}
from
"@/store/v2"
;
import
{
userStore
}
from
"@/store/v2"
;
import
memoFilterStore
from
"@/store/v2/memoFilter"
;
import
{
Shortcut
}
from
"@/types/proto/api/v1/shortcut_service"
;
import
{
Shortcut
}
from
"@/types/proto/api/v1/shortcut_service"
;
import
{
cn
}
from
"@/utils"
;
import
{
cn
}
from
"@/utils"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
...
@@ -16,7 +16,6 @@ const emojiRegex = /^(\p{Emoji_Presentation}|\p{Emoji}\uFE0F)$/u;
...
@@ -16,7 +16,6 @@ const emojiRegex = /^(\p{Emoji_Presentation}|\p{Emoji}\uFE0F)$/u;
const
ShortcutsSection
=
observer
(()
=>
{
const
ShortcutsSection
=
observer
(()
=>
{
const
t
=
useTranslate
();
const
t
=
useTranslate
();
const
user
=
useCurrentUser
();
const
user
=
useCurrentUser
();
const
memoFilterStore
=
useMemoFilterStore
();
const
shortcuts
=
userStore
.
state
.
shortcuts
;
const
shortcuts
=
userStore
.
state
.
shortcuts
;
useAsyncEffect
(
async
()
=>
{
useAsyncEffect
(
async
()
=>
{
...
...
web/src/components/HomeSidebar/TagsSection.tsx
View file @
c23aebd6
...
@@ -4,8 +4,8 @@ import { observer } from "mobx-react-lite";
...
@@ -4,8 +4,8 @@ import { observer } from "mobx-react-lite";
import
toast
from
"react-hot-toast"
;
import
toast
from
"react-hot-toast"
;
import
useLocalStorage
from
"react-use/lib/useLocalStorage"
;
import
useLocalStorage
from
"react-use/lib/useLocalStorage"
;
import
{
memoServiceClient
}
from
"@/grpcweb"
;
import
{
memoServiceClient
}
from
"@/grpcweb"
;
import
{
useMemoFilterStore
}
from
"@/store/v1"
;
import
{
userStore
}
from
"@/store/v2"
;
import
{
userStore
}
from
"@/store/v2"
;
import
memoFilterStore
,
{
MemoFilter
}
from
"@/store/v2/memoFilter"
;
import
{
cn
}
from
"@/utils"
;
import
{
cn
}
from
"@/utils"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
showRenameTagDialog
from
"../RenameTagDialog"
;
import
showRenameTagDialog
from
"../RenameTagDialog"
;
...
@@ -18,16 +18,15 @@ interface Props {
...
@@ -18,16 +18,15 @@ interface Props {
const
TagsSection
=
observer
((
props
:
Props
)
=>
{
const
TagsSection
=
observer
((
props
:
Props
)
=>
{
const
t
=
useTranslate
();
const
t
=
useTranslate
();
const
memoFilterStore
=
useMemoFilterStore
();
const
[
treeMode
,
setTreeMode
]
=
useLocalStorage
<
boolean
>
(
"tag-view-as-tree"
,
false
);
const
[
treeMode
,
setTreeMode
]
=
useLocalStorage
<
boolean
>
(
"tag-view-as-tree"
,
false
);
const
tags
=
Object
.
entries
(
userStore
.
state
.
tagCount
)
const
tags
=
Object
.
entries
(
userStore
.
state
.
tagCount
)
.
sort
((
a
,
b
)
=>
a
[
0
].
localeCompare
(
b
[
0
]))
.
sort
((
a
,
b
)
=>
a
[
0
].
localeCompare
(
b
[
0
]))
.
sort
((
a
,
b
)
=>
b
[
1
]
-
a
[
1
]);
.
sort
((
a
,
b
)
=>
b
[
1
]
-
a
[
1
]);
const
handleTagClick
=
(
tag
:
string
)
=>
{
const
handleTagClick
=
(
tag
:
string
)
=>
{
const
isActive
=
memoFilterStore
.
getFiltersByFactor
(
"tagSearch"
).
some
((
filter
)
=>
filter
.
value
===
tag
);
const
isActive
=
memoFilterStore
.
getFiltersByFactor
(
"tagSearch"
).
some
((
filter
:
MemoFilter
)
=>
filter
.
value
===
tag
);
if
(
isActive
)
{
if
(
isActive
)
{
memoFilterStore
.
removeFilter
((
f
)
=>
f
.
factor
===
"tagSearch"
&&
f
.
value
===
tag
);
memoFilterStore
.
removeFilter
((
f
:
MemoFilter
)
=>
f
.
factor
===
"tagSearch"
&&
f
.
value
===
tag
);
}
else
{
}
else
{
memoFilterStore
.
addFilter
({
memoFilterStore
.
addFilter
({
factor
:
"tagSearch"
,
factor
:
"tagSearch"
,
...
...
web/src/components/MemoContent/Tag.tsx
View file @
c23aebd6
...
@@ -2,7 +2,8 @@ import { useContext } from "react";
...
@@ -2,7 +2,8 @@ import { useContext } from "react";
import
{
useLocation
}
from
"react-router-dom"
;
import
{
useLocation
}
from
"react-router-dom"
;
import
useNavigateTo
from
"@/hooks/useNavigateTo"
;
import
useNavigateTo
from
"@/hooks/useNavigateTo"
;
import
{
Routes
}
from
"@/router"
;
import
{
Routes
}
from
"@/router"
;
import
{
stringifyFilters
,
useMemoFilterStore
}
from
"@/store/v1"
;
import
memoFilterStore
,
{
MemoFilter
}
from
"@/store/v2/memoFilter"
;
import
{
stringifyFilters
}
from
"@/store/v2/memoFilter"
;
import
{
cn
}
from
"@/utils"
;
import
{
cn
}
from
"@/utils"
;
import
{
RendererContext
}
from
"./types"
;
import
{
RendererContext
}
from
"./types"
;
...
@@ -12,7 +13,6 @@ interface Props {
...
@@ -12,7 +13,6 @@ interface Props {
const
Tag
:
React
.
FC
<
Props
>
=
({
content
}:
Props
)
=>
{
const
Tag
:
React
.
FC
<
Props
>
=
({
content
}:
Props
)
=>
{
const
context
=
useContext
(
RendererContext
);
const
context
=
useContext
(
RendererContext
);
const
memoFilterStore
=
useMemoFilterStore
();
const
location
=
useLocation
();
const
location
=
useLocation
();
const
navigateTo
=
useNavigateTo
();
const
navigateTo
=
useNavigateTo
();
...
@@ -31,9 +31,9 @@ const Tag: React.FC<Props> = ({ content }: Props) => {
...
@@ -31,9 +31,9 @@ const Tag: React.FC<Props> = ({ content }: Props) => {
return
;
return
;
}
}
const
isActive
=
memoFilterStore
.
getFiltersByFactor
(
"tagSearch"
).
some
((
filter
)
=>
filter
.
value
===
content
);
const
isActive
=
memoFilterStore
.
getFiltersByFactor
(
"tagSearch"
).
some
((
filter
:
MemoFilter
)
=>
filter
.
value
===
content
);
if
(
isActive
)
{
if
(
isActive
)
{
memoFilterStore
.
removeFilter
((
f
)
=>
f
.
factor
===
"tagSearch"
&&
f
.
value
===
content
);
memoFilterStore
.
removeFilter
((
f
:
MemoFilter
)
=>
f
.
factor
===
"tagSearch"
&&
f
.
value
===
content
);
}
else
{
}
else
{
memoFilterStore
.
addFilter
({
memoFilterStore
.
addFilter
({
factor
:
"tagSearch"
,
factor
:
"tagSearch"
,
...
...
web/src/components/MemoFilters.tsx
View file @
c23aebd6
...
@@ -2,13 +2,13 @@ import { isEqual } from "lodash-es";
...
@@ -2,13 +2,13 @@ import { isEqual } from "lodash-es";
import
{
CalendarIcon
,
CheckCircleIcon
,
CodeIcon
,
EyeIcon
,
HashIcon
,
LinkIcon
,
BookmarkIcon
,
SearchIcon
,
XIcon
}
from
"lucide-react"
;
import
{
CalendarIcon
,
CheckCircleIcon
,
CodeIcon
,
EyeIcon
,
HashIcon
,
LinkIcon
,
BookmarkIcon
,
SearchIcon
,
XIcon
}
from
"lucide-react"
;
import
{
useEffect
}
from
"react"
;
import
{
useEffect
}
from
"react"
;
import
{
useSearchParams
}
from
"react-router-dom"
;
import
{
useSearchParams
}
from
"react-router-dom"
;
import
{
FilterFactor
,
getMemoFilterKey
,
MemoFilter
,
stringifyFilters
,
useMemoFilterStore
}
from
"@/store/v1"
;
import
memoFilterStore
from
"@/store/v2/memoFilter"
;
import
{
FilterFactor
,
getMemoFilterKey
,
MemoFilter
,
stringifyFilters
}
from
"@/store/v2/memoFilter"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
const
MemoFilters
=
()
=>
{
const
MemoFilters
=
()
=>
{
const
t
=
useTranslate
();
const
t
=
useTranslate
();
const
[,
setSearchParams
]
=
useSearchParams
();
const
[,
setSearchParams
]
=
useSearchParams
();
const
memoFilterStore
=
useMemoFilterStore
();
const
filters
=
memoFilterStore
.
filters
;
const
filters
=
memoFilterStore
.
filters
;
useEffect
(()
=>
{
useEffect
(()
=>
{
...
@@ -45,11 +45,11 @@ const MemoFilters = () => {
...
@@ -45,11 +45,11 @@ const MemoFilters = () => {
return
(
return
(
<
div
className=
"w-full mt-2 flex flex-row justify-start items-center flex-wrap gap-x-2 gap-y-1"
>
<
div
className=
"w-full mt-2 flex flex-row justify-start items-center flex-wrap gap-x-2 gap-y-1"
>
{
filters
.
map
((
filter
)
=>
(
{
filters
.
map
((
filter
:
MemoFilter
)
=>
(
<
div
<
div
key=
{
getMemoFilterKey
(
filter
)
}
key=
{
getMemoFilterKey
(
filter
)
}
className=
"w-auto leading-7 h-7 shrink-0 flex flex-row items-center gap-1 bg-white dark:bg-zinc-800 border dark:border-zinc-700 pl-1.5 pr-1 rounded-md hover:line-through cursor-pointer"
className=
"w-auto leading-7 h-7 shrink-0 flex flex-row items-center gap-1 bg-white dark:bg-zinc-800 border dark:border-zinc-700 pl-1.5 pr-1 rounded-md hover:line-through cursor-pointer"
onClick=
{
()
=>
memoFilterStore
.
removeFilter
((
f
)
=>
isEqual
(
f
,
filter
))
}
onClick=
{
()
=>
memoFilterStore
.
removeFilter
((
f
:
MemoFilter
)
=>
isEqual
(
f
,
filter
))
}
>
>
<
FactorIcon
className=
"w-4 h-auto text-gray-500 dark:text-gray-400 opacity-60"
factor=
{
filter
.
factor
}
/>
<
FactorIcon
className=
"w-4 h-auto text-gray-500 dark:text-gray-400 opacity-60"
factor=
{
filter
.
factor
}
/>
<
span
className=
"text-gray-500 dark:text-gray-400 text-sm max-w-32 truncate"
>
{
getFilterDisplayText
(
filter
)
}
</
span
>
<
span
className=
"text-gray-500 dark:text-gray-400 text-sm max-w-32 truncate"
>
{
getFilterDisplayText
(
filter
)
}
</
span
>
...
...
web/src/components/SearchBar.tsx
View file @
c23aebd6
import
{
SearchIcon
}
from
"lucide-react"
;
import
{
SearchIcon
}
from
"lucide-react"
;
import
{
useState
}
from
"react"
;
import
{
useState
}
from
"react"
;
import
{
useMemoFilterStore
}
from
"@/store/v1
"
;
import
memoFilterStore
from
"@/store/v2/memoFilter
"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
MemoDisplaySettingMenu
from
"./MemoDisplaySettingMenu"
;
import
MemoDisplaySettingMenu
from
"./MemoDisplaySettingMenu"
;
const
SearchBar
=
()
=>
{
const
SearchBar
=
()
=>
{
const
t
=
useTranslate
();
const
t
=
useTranslate
();
const
memoFilterStore
=
useMemoFilterStore
();
const
[
queryText
,
setQueryText
]
=
useState
(
""
);
const
[
queryText
,
setQueryText
]
=
useState
(
""
);
const
onTextChange
=
(
event
:
React
.
FormEvent
<
HTMLInputElement
>
)
=>
{
const
onTextChange
=
(
event
:
React
.
FormEvent
<
HTMLInputElement
>
)
=>
{
...
...
web/src/components/StatisticsView.tsx
View file @
c23aebd6
...
@@ -10,8 +10,8 @@ import useAsyncEffect from "@/hooks/useAsyncEffect";
...
@@ -10,8 +10,8 @@ import useAsyncEffect from "@/hooks/useAsyncEffect";
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
i18n
from
"@/i18n"
;
import
i18n
from
"@/i18n"
;
import
{
Routes
}
from
"@/router"
;
import
{
Routes
}
from
"@/router"
;
import
{
useMemoFilterStore
}
from
"@/store/v1"
;
import
{
userStore
}
from
"@/store/v2"
;
import
{
userStore
}
from
"@/store/v2"
;
import
memoFilterStore
from
"@/store/v2/memoFilter"
;
import
{
UserStats_MemoTypeStats
}
from
"@/types/proto/api/v1/user_service"
;
import
{
UserStats_MemoTypeStats
}
from
"@/types/proto/api/v1/user_service"
;
import
{
cn
}
from
"@/utils"
;
import
{
cn
}
from
"@/utils"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
...
@@ -21,7 +21,6 @@ import "react-datepicker/dist/react-datepicker.css";
...
@@ -21,7 +21,6 @@ import "react-datepicker/dist/react-datepicker.css";
const
StatisticsView
=
observer
(()
=>
{
const
StatisticsView
=
observer
(()
=>
{
const
t
=
useTranslate
();
const
t
=
useTranslate
();
const
location
=
useLocation
();
const
location
=
useLocation
();
const
memoFilterStore
=
useMemoFilterStore
();
const
currentUser
=
useCurrentUser
();
const
currentUser
=
useCurrentUser
();
const
[
memoTypeStats
,
setMemoTypeStats
]
=
useState
<
UserStats_MemoTypeStats
>
(
UserStats_MemoTypeStats
.
fromPartial
({}));
const
[
memoTypeStats
,
setMemoTypeStats
]
=
useState
<
UserStats_MemoTypeStats
>
(
UserStats_MemoTypeStats
.
fromPartial
({}));
const
[
activityStats
,
setActivityStats
]
=
useState
<
Record
<
string
,
number
>>
({});
const
[
activityStats
,
setActivityStats
]
=
useState
<
Record
<
string
,
number
>>
({});
...
...
web/src/components/TagTree.tsx
View file @
c23aebd6
import
{
ChevronRightIcon
,
HashIcon
}
from
"lucide-react"
;
import
{
ChevronRightIcon
,
HashIcon
}
from
"lucide-react"
;
import
{
useEffect
,
useState
}
from
"react"
;
import
{
useEffect
,
useState
}
from
"react"
;
import
useToggle
from
"react-use/lib/useToggle"
;
import
useToggle
from
"react-use/lib/useToggle"
;
import
{
useMemoFilterStore
}
from
"@/store/v1
"
;
import
memoFilterStore
,
{
MemoFilter
}
from
"@/store/v2/memoFilter
"
;
interface
Tag
{
interface
Tag
{
key
:
string
;
key
:
string
;
...
@@ -85,15 +85,14 @@ interface TagItemContainerProps {
...
@@ -85,15 +85,14 @@ interface TagItemContainerProps {
const
TagItemContainer
:
React
.
FC
<
TagItemContainerProps
>
=
(
props
:
TagItemContainerProps
)
=>
{
const
TagItemContainer
:
React
.
FC
<
TagItemContainerProps
>
=
(
props
:
TagItemContainerProps
)
=>
{
const
{
tag
}
=
props
;
const
{
tag
}
=
props
;
const
memoFilterStore
=
useMemoFilterStore
();
const
tagFilters
=
memoFilterStore
.
getFiltersByFactor
(
"tagSearch"
);
const
tagFilters
=
memoFilterStore
.
getFiltersByFactor
(
"tagSearch"
);
const
isActive
=
tagFilters
.
some
((
f
)
=>
f
.
value
===
tag
.
text
);
const
isActive
=
tagFilters
.
some
((
f
:
MemoFilter
)
=>
f
.
value
===
tag
.
text
);
const
hasSubTags
=
tag
.
subTags
.
length
>
0
;
const
hasSubTags
=
tag
.
subTags
.
length
>
0
;
const
[
showSubTags
,
toggleSubTags
]
=
useToggle
(
false
);
const
[
showSubTags
,
toggleSubTags
]
=
useToggle
(
false
);
const
handleTagClick
=
()
=>
{
const
handleTagClick
=
()
=>
{
if
(
isActive
)
{
if
(
isActive
)
{
memoFilterStore
.
removeFilter
((
f
)
=>
f
.
factor
===
"tagSearch"
&&
f
.
value
===
tag
.
text
);
memoFilterStore
.
removeFilter
((
f
:
MemoFilter
)
=>
f
.
factor
===
"tagSearch"
&&
f
.
value
===
tag
.
text
);
}
else
{
}
else
{
memoFilterStore
.
addFilter
({
memoFilterStore
.
addFilter
({
factor
:
"tagSearch"
,
factor
:
"tagSearch"
,
...
...
web/src/layouts/RootLayout.tsx
View file @
c23aebd6
...
@@ -7,8 +7,8 @@ import useCurrentUser from "@/hooks/useCurrentUser";
...
@@ -7,8 +7,8 @@ import useCurrentUser from "@/hooks/useCurrentUser";
import
useResponsiveWidth
from
"@/hooks/useResponsiveWidth"
;
import
useResponsiveWidth
from
"@/hooks/useResponsiveWidth"
;
import
Loading
from
"@/pages/Loading"
;
import
Loading
from
"@/pages/Loading"
;
import
{
Routes
}
from
"@/router"
;
import
{
Routes
}
from
"@/router"
;
import
{
useMemoFilterStore
}
from
"@/store/v1"
;
import
{
workspaceStore
}
from
"@/store/v2"
;
import
{
workspaceStore
}
from
"@/store/v2"
;
import
memoFilterStore
from
"@/store/v2/memoFilter"
;
import
{
cn
}
from
"@/utils"
;
import
{
cn
}
from
"@/utils"
;
const
RootLayout
=
observer
(()
=>
{
const
RootLayout
=
observer
(()
=>
{
...
@@ -16,7 +16,6 @@ const RootLayout = observer(() => {
...
@@ -16,7 +16,6 @@ const RootLayout = observer(() => {
const
[
searchParams
]
=
useSearchParams
();
const
[
searchParams
]
=
useSearchParams
();
const
{
sm
}
=
useResponsiveWidth
();
const
{
sm
}
=
useResponsiveWidth
();
const
currentUser
=
useCurrentUser
();
const
currentUser
=
useCurrentUser
();
const
memoFilterStore
=
useMemoFilterStore
();
const
[
initialized
,
setInitialized
]
=
useState
(
false
);
const
[
initialized
,
setInitialized
]
=
useState
(
false
);
const
pathname
=
useMemo
(()
=>
location
.
pathname
,
[
location
.
pathname
]);
const
pathname
=
useMemo
(()
=>
location
.
pathname
,
[
location
.
pathname
]);
const
prevPathname
=
usePrevious
(
pathname
);
const
prevPathname
=
usePrevious
(
pathname
);
...
...
web/src/pages/Archived.tsx
View file @
c23aebd6
...
@@ -3,14 +3,13 @@ import { useMemo } from "react";
...
@@ -3,14 +3,13 @@ import { useMemo } from "react";
import
MemoView
from
"@/components/MemoView"
;
import
MemoView
from
"@/components/MemoView"
;
import
PagedMemoList
from
"@/components/PagedMemoList"
;
import
PagedMemoList
from
"@/components/PagedMemoList"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
{
useMemoFilterStore
}
from
"@/store/v1"
;
import
{
viewStore
}
from
"@/store/v2"
;
import
{
viewStore
}
from
"@/store/v2"
;
import
memoFilterStore
from
"@/store/v2/memoFilter"
;
import
{
Direction
,
State
}
from
"@/types/proto/api/v1/common"
;
import
{
Direction
,
State
}
from
"@/types/proto/api/v1/common"
;
import
{
Memo
}
from
"@/types/proto/api/v1/memo_service"
;
import
{
Memo
}
from
"@/types/proto/api/v1/memo_service"
;
const
Archived
=
()
=>
{
const
Archived
=
()
=>
{
const
user
=
useCurrentUser
();
const
user
=
useCurrentUser
();
const
memoFilterStore
=
useMemoFilterStore
();
const
memoListFilter
=
useMemo
(()
=>
{
const
memoListFilter
=
useMemo
(()
=>
{
const
conditions
=
[];
const
conditions
=
[];
...
...
web/src/pages/Explore.tsx
View file @
c23aebd6
...
@@ -3,14 +3,13 @@ import { useMemo } from "react";
...
@@ -3,14 +3,13 @@ import { useMemo } from "react";
import
MemoView
from
"@/components/MemoView"
;
import
MemoView
from
"@/components/MemoView"
;
import
PagedMemoList
from
"@/components/PagedMemoList"
;
import
PagedMemoList
from
"@/components/PagedMemoList"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
{
useMemoFilterStore
}
from
"@/store/v1"
;
import
{
viewStore
}
from
"@/store/v2"
;
import
{
viewStore
}
from
"@/store/v2"
;
import
memoFilterStore
from
"@/store/v2/memoFilter"
;
import
{
Direction
,
State
}
from
"@/types/proto/api/v1/common"
;
import
{
Direction
,
State
}
from
"@/types/proto/api/v1/common"
;
import
{
Memo
}
from
"@/types/proto/api/v1/memo_service"
;
import
{
Memo
}
from
"@/types/proto/api/v1/memo_service"
;
const
Explore
=
()
=>
{
const
Explore
=
()
=>
{
const
user
=
useCurrentUser
();
const
user
=
useCurrentUser
();
const
memoFilterStore
=
useMemoFilterStore
();
const
memoListFilter
=
useMemo
(()
=>
{
const
memoListFilter
=
useMemo
(()
=>
{
const
conditions
=
[];
const
conditions
=
[];
...
...
web/src/pages/Home.tsx
View file @
c23aebd6
...
@@ -4,14 +4,13 @@ import { useMemo } from "react";
...
@@ -4,14 +4,13 @@ import { useMemo } from "react";
import
MemoView
from
"@/components/MemoView"
;
import
MemoView
from
"@/components/MemoView"
;
import
PagedMemoList
from
"@/components/PagedMemoList"
;
import
PagedMemoList
from
"@/components/PagedMemoList"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
{
useMemoFilterStore
}
from
"@/store/v1"
;
import
{
viewStore
,
userStore
}
from
"@/store/v2"
;
import
{
viewStore
,
userStore
}
from
"@/store/v2"
;
import
memoFilterStore
from
"@/store/v2/memoFilter"
;
import
{
Direction
,
State
}
from
"@/types/proto/api/v1/common"
;
import
{
Direction
,
State
}
from
"@/types/proto/api/v1/common"
;
import
{
Memo
}
from
"@/types/proto/api/v1/memo_service"
;
import
{
Memo
}
from
"@/types/proto/api/v1/memo_service"
;
const
Home
=
observer
(()
=>
{
const
Home
=
observer
(()
=>
{
const
user
=
useCurrentUser
();
const
user
=
useCurrentUser
();
const
memoFilterStore
=
useMemoFilterStore
();
const
selectedShortcut
=
userStore
.
state
.
shortcuts
.
find
((
shortcut
)
=>
shortcut
.
id
===
memoFilterStore
.
shortcut
);
const
selectedShortcut
=
userStore
.
state
.
shortcuts
.
find
((
shortcut
)
=>
shortcut
.
id
===
memoFilterStore
.
shortcut
);
const
memoListFilter
=
useMemo
(()
=>
{
const
memoListFilter
=
useMemo
(()
=>
{
...
...
web/src/pages/UserProfile.tsx
View file @
c23aebd6
...
@@ -10,8 +10,8 @@ import MemoView from "@/components/MemoView";
...
@@ -10,8 +10,8 @@ import MemoView from "@/components/MemoView";
import
PagedMemoList
from
"@/components/PagedMemoList"
;
import
PagedMemoList
from
"@/components/PagedMemoList"
;
import
UserAvatar
from
"@/components/UserAvatar"
;
import
UserAvatar
from
"@/components/UserAvatar"
;
import
useLoading
from
"@/hooks/useLoading"
;
import
useLoading
from
"@/hooks/useLoading"
;
import
{
useMemoFilterStore
}
from
"@/store/v1"
;
import
{
viewStore
,
userStore
}
from
"@/store/v2"
;
import
{
viewStore
,
userStore
}
from
"@/store/v2"
;
import
memoFilterStore
from
"@/store/v2/memoFilter"
;
import
{
Direction
,
State
}
from
"@/types/proto/api/v1/common"
;
import
{
Direction
,
State
}
from
"@/types/proto/api/v1/common"
;
import
{
Memo
}
from
"@/types/proto/api/v1/memo_service"
;
import
{
Memo
}
from
"@/types/proto/api/v1/memo_service"
;
import
{
User
}
from
"@/types/proto/api/v1/user_service"
;
import
{
User
}
from
"@/types/proto/api/v1/user_service"
;
...
@@ -22,7 +22,6 @@ const UserProfile = observer(() => {
...
@@ -22,7 +22,6 @@ const UserProfile = observer(() => {
const
params
=
useParams
();
const
params
=
useParams
();
const
loadingState
=
useLoading
();
const
loadingState
=
useLoading
();
const
[
user
,
setUser
]
=
useState
<
User
>
();
const
[
user
,
setUser
]
=
useState
<
User
>
();
const
memoFilterStore
=
useMemoFilterStore
();
useEffect
(()
=>
{
useEffect
(()
=>
{
const
username
=
params
.
username
;
const
username
=
params
.
username
;
...
...
web/src/store/v1/index.ts
deleted
100644 → 0
View file @
f12d7ae8
export
*
from
"./memoFilter"
;
web/src/store/v2/index.ts
View file @
c23aebd6
import
memoStore
from
"./memo"
;
import
memoStore
from
"./memo"
;
import
memoFilterStore
from
"./memoFilter"
;
import
resourceStore
from
"./resource"
;
import
resourceStore
from
"./resource"
;
import
userStore
from
"./user"
;
import
userStore
from
"./user"
;
import
viewStore
from
"./view"
;
import
viewStore
from
"./view"
;
import
workspaceStore
from
"./workspace"
;
import
workspaceStore
from
"./workspace"
;
export
{
memoStore
,
resourceStore
,
workspaceStore
,
userStore
,
viewStore
};
export
{
memo
FilterStore
,
memo
Store
,
resourceStore
,
workspaceStore
,
userStore
,
viewStore
};
web/src/store/v
1
/memoFilter.ts
→
web/src/store/v
2
/memoFilter.ts
View file @
c23aebd6
import
{
uniqBy
}
from
"lodash-es"
;
import
{
uniqBy
}
from
"lodash-es"
;
import
{
create
}
from
"zustand"
;
import
{
makeAutoObservable
}
from
"mobx"
;
import
{
combine
}
from
"zustand/middleware"
;
export
type
FilterFactor
=
export
type
FilterFactor
=
|
"tagSearch"
|
"tagSearch"
...
@@ -39,26 +38,56 @@ export const stringifyFilters = (filters: MemoFilter[]): string => {
...
@@ -39,26 +38,56 @@ export const stringifyFilters = (filters: MemoFilter[]): string => {
return
filters
.
map
((
filter
)
=>
`
${
filter
.
factor
}
:
${
encodeURIComponent
(
filter
.
value
)}
`
).
join
(
","
);
return
filters
.
map
((
filter
)
=>
`
${
filter
.
factor
}
:
${
encodeURIComponent
(
filter
.
value
)}
`
).
join
(
","
);
};
};
interface
State
{
class
MemoFilterState
{
filters
:
MemoFilter
[];
filters
:
MemoFilter
[]
=
[];
// The id of selected shortcut.
shortcut
?:
string
=
undefined
;
shortcut
?:
string
;
constructor
()
{
makeAutoObservable
(
this
);
this
.
init
();
}
init
()
{
const
searchParams
=
new
URLSearchParams
(
window
.
location
.
search
);
this
.
filters
=
parseFilterQuery
(
searchParams
.
get
(
"filter"
));
}
setState
(
state
:
Partial
<
MemoFilterState
>
)
{
Object
.
assign
(
this
,
state
);
}
getFiltersByFactor
(
factor
:
FilterFactor
)
{
return
this
.
filters
.
filter
((
f
)
=>
f
.
factor
===
factor
);
}
addFilter
(
filter
:
MemoFilter
)
{
this
.
filters
=
uniqBy
([...
this
.
filters
,
filter
],
getMemoFilterKey
);
}
removeFilter
(
filterFn
:
(
f
:
MemoFilter
)
=>
boolean
)
{
this
.
filters
=
this
.
filters
.
filter
((
f
)
=>
!
filterFn
(
f
));
}
setShortcut
(
shortcut
?:
string
)
{
this
.
shortcut
=
shortcut
;
}
}
}
const
getInitialState
=
():
State
=>
{
const
memoFilterStore
=
(()
=>
{
const
searchParams
=
new
URLSearchParams
(
window
.
location
.
search
);
const
state
=
new
MemoFilterState
();
return
{
return
{
filters
:
parseFilterQuery
(
searchParams
.
get
(
"filter"
)),
get
filters
()
{
return
state
.
filters
;
},
get
shortcut
()
{
return
state
.
shortcut
;
},
getFiltersByFactor
:
(
factor
:
FilterFactor
)
=>
state
.
getFiltersByFactor
(
factor
),
addFilter
:
(
filter
:
MemoFilter
)
=>
state
.
addFilter
(
filter
),
removeFilter
:
(
filterFn
:
(
f
:
MemoFilter
)
=>
boolean
)
=>
state
.
removeFilter
(
filterFn
),
setShortcut
:
(
shortcut
?:
string
)
=>
state
.
setShortcut
(
shortcut
),
};
};
};
}
)()
;
export
const
useMemoFilterStore
=
create
(
export
default
memoFilterStore
;
combine
(
getInitialState
(),
(
set
,
get
)
=>
({
setState
:
(
state
:
State
)
=>
set
(
state
),
getState
:
()
=>
get
(),
getFiltersByFactor
:
(
factor
:
FilterFactor
)
=>
get
().
filters
.
filter
((
f
)
=>
f
.
factor
===
factor
),
addFilter
:
(
filter
:
MemoFilter
)
=>
set
((
state
)
=>
({
filters
:
uniqBy
([...
state
.
filters
,
filter
],
getMemoFilterKey
)
})),
removeFilter
:
(
filterFn
:
(
f
:
MemoFilter
)
=>
boolean
)
=>
set
((
state
)
=>
({
filters
:
state
.
filters
.
filter
((
f
)
=>
!
filterFn
(
f
))
})),
setShortcut
:
(
shortcut
?:
string
)
=>
set
({
shortcut
}),
})),
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment