1
1
import { uniqBy } from "lodash-es" ;
2
- import { LinkIcon , X } from "lucide-react" ;
3
- import React , { useContext , useState } from "react" ;
2
+ import { LinkIcon } from "lucide-react" ;
3
+ import { useContext , useState } from "react" ;
4
4
import { toast } from "react-hot-toast" ;
5
5
import useDebounce from "react-use/lib/useDebounce" ;
6
- import { Badge } from "@/components/ui/badge" ;
7
6
import { Button } from "@/components/ui/button" ;
8
- import { Checkbox } from "@/components/ui/checkbox" ;
9
7
import { Input } from "@/components/ui/input" ;
10
8
import { Popover , PopoverContent , PopoverTrigger } from "@/components/ui/popover" ;
11
9
import { memoServiceClient } from "@/grpcweb" ;
12
10
import { DEFAULT_LIST_MEMOS_PAGE_SIZE } from "@/helpers/consts" ;
13
11
import useCurrentUser from "@/hooks/useCurrentUser" ;
14
- import { extractMemoIdFromName } from "@/store/common" ;
12
+ import { extractUserIdFromName } from "@/store/common" ;
15
13
import { Memo , MemoRelation_Memo , MemoRelation_Type } from "@/types/proto/api/v1/memo_service" ;
16
14
import { useTranslate } from "@/utils/i18n" ;
17
- import { EditorRefActions } from "../Editor" ;
18
15
import { MemoEditorContext } from "../types" ;
19
16
20
- interface Props {
21
- editorRef : React . RefObject < EditorRefActions > ;
22
- }
23
-
24
- const AddMemoRelationPopover = ( props : Props ) => {
25
- const { editorRef } = props ;
17
+ const AddMemoRelationPopover = ( ) => {
26
18
const t = useTranslate ( ) ;
27
19
const context = useContext ( MemoEditorContext ) ;
28
20
const user = useCurrentUser ( ) ;
29
21
const [ searchText , setSearchText ] = useState < string > ( "" ) ;
30
22
const [ isFetching , setIsFetching ] = useState < boolean > ( true ) ;
31
23
const [ fetchedMemos , setFetchedMemos ] = useState < Memo [ ] > ( [ ] ) ;
32
- const [ selectedMemos , setSelectedMemos ] = useState < Memo [ ] > ( [ ] ) ;
33
- const [ embedded , setEmbedded ] = useState < boolean > ( false ) ;
34
24
const [ popoverOpen , setPopoverOpen ] = useState < boolean > ( false ) ;
35
25
36
26
const filteredMemos = fetchedMemos . filter (
37
- ( memo ) =>
38
- ! selectedMemos . includes ( memo ) &&
39
- memo . name !== context . memoName &&
40
- ! context . relationList . some ( ( relation ) => relation . relatedMemo ?. name === memo . name ) ,
27
+ ( memo ) => memo . name !== context . memoName && ! context . relationList . some ( ( relation ) => relation . relatedMemo ?. name === memo . name ) ,
41
28
) ;
42
29
43
30
useDebounce (
@@ -46,10 +33,7 @@ const AddMemoRelationPopover = (props: Props) => {
46
33
47
34
setIsFetching ( true ) ;
48
35
try {
49
- const conditions = [ ] ;
50
- // Extract user ID from user name (format: users/{user_id})
51
- const userId = user . name . replace ( "users/" , "" ) ;
52
- conditions . push ( `creator_id == ${ userId } ` ) ;
36
+ const conditions = [ `creator_id == ${ extractUserIdFromName ( user . name ) } ` ] ;
53
37
if ( searchText ) {
54
38
conditions . push ( `content.contains("${ searchText } ")` ) ;
55
39
}
@@ -92,42 +76,20 @@ const AddMemoRelationPopover = (props: Props) => {
92
76
) ;
93
77
} ;
94
78
95
- const addMemoRelations = async ( ) => {
96
- // If embedded mode is enabled, embed the memo instead of creating a relation.
97
- if ( embedded ) {
98
- if ( ! editorRef . current ) {
99
- toast . error ( t ( "message.failed-to-embed-memo" ) ) ;
100
- return ;
101
- }
102
-
103
- const cursorPosition = editorRef . current . getCursorPosition ( ) ;
104
- const prevValue = editorRef . current . getContent ( ) . slice ( 0 , cursorPosition ) ;
105
- if ( prevValue !== "" && ! prevValue . endsWith ( "\n" ) ) {
106
- editorRef . current . insertText ( "\n" ) ;
107
- }
108
- for ( const memo of selectedMemos ) {
109
- editorRef . current . insertText ( `![[memos/${ extractMemoIdFromName ( memo . name ) } ]]\n` ) ;
110
- }
111
- setTimeout ( ( ) => {
112
- editorRef . current ?. scrollToCursor ( ) ;
113
- editorRef . current ?. focus ( ) ;
114
- } ) ;
115
- } else {
116
- context . setRelationList (
117
- uniqBy (
118
- [
119
- ...selectedMemos . map ( ( memo ) => ( {
120
- memo : MemoRelation_Memo . fromPartial ( { name : memo . name } ) ,
121
- relatedMemo : MemoRelation_Memo . fromPartial ( { name : memo . name } ) ,
122
- type : MemoRelation_Type . REFERENCE ,
123
- } ) ) ,
124
- ...context . relationList ,
125
- ] . filter ( ( relation ) => relation . relatedMemo !== context . memoName ) ,
126
- "relatedMemo" ,
127
- ) ,
128
- ) ;
129
- }
130
- setSelectedMemos ( [ ] ) ;
79
+ const addMemoRelations = async ( memo : Memo ) => {
80
+ context . setRelationList (
81
+ uniqBy (
82
+ [
83
+ {
84
+ memo : MemoRelation_Memo . fromPartial ( { name : memo . name } ) ,
85
+ relatedMemo : MemoRelation_Memo . fromPartial ( { name : memo . name } ) ,
86
+ type : MemoRelation_Type . REFERENCE ,
87
+ } ,
88
+ ...context . relationList ,
89
+ ] . filter ( ( relation ) => relation . relatedMemo !== context . memoName ) ,
90
+ "relatedMemo" ,
91
+ ) ,
92
+ ) ;
131
93
setPopoverOpen ( false ) ;
132
94
} ;
133
95
@@ -140,24 +102,6 @@ const AddMemoRelationPopover = (props: Props) => {
140
102
</ PopoverTrigger >
141
103
< PopoverContent align = "center" >
142
104
< div className = "w-[16rem] p-1 flex flex-col justify-start items-start" >
143
- { /* Selected memos display */ }
144
- { selectedMemos . length > 0 && (
145
- < div className = "w-full mb-2 flex flex-wrap gap-1" >
146
- { selectedMemos . map ( ( memo ) => (
147
- < Badge key = { memo . name } variant = "outline" className = "max-w-full flex items-center gap-1 p-2" >
148
- < div className = "flex-1 min-w-0" >
149
- < p className = "text-xs text-muted-foreground select-none" > { memo . displayTime ?. toLocaleString ( ) } </ p >
150
- < span className = "text-sm leading-5 truncate block" > { memo . content } </ span >
151
- </ div >
152
- < X
153
- className = "w-3 h-3 cursor-pointer hover:text-destructive flex-shrink-0"
154
- onClick = { ( ) => setSelectedMemos ( ( memos ) => memos . filter ( ( m ) => m . name !== memo . name ) ) }
155
- />
156
- </ Badge >
157
- ) ) }
158
- </ div >
159
- ) }
160
-
161
105
{ /* Search and selection interface */ }
162
106
< div className = "w-full" >
163
107
< Input
@@ -177,7 +121,7 @@ const AddMemoRelationPopover = (props: Props) => {
177
121
key = { memo . name }
178
122
className = "relative flex cursor-pointer items-start gap-2 rounded-sm px-2 py-1.5 text-sm hover:bg-accent hover:text-accent-foreground"
179
123
onClick = { ( ) => {
180
- setSelectedMemos ( ( prev ) => [ ... prev , memo ] ) ;
124
+ addMemoRelations ( memo ) ;
181
125
} }
182
126
>
183
127
< div className = "w-full flex flex-col justify-start items-start" >
@@ -191,18 +135,6 @@ const AddMemoRelationPopover = (props: Props) => {
191
135
) }
192
136
</ div >
193
137
</ div >
194
-
195
- < div className = "mt-2 w-full flex flex-row justify-end items-center gap-2" >
196
- < div className = "flex items-center space-x-2" >
197
- < Checkbox id = "embed-checkbox" checked = { embedded } onCheckedChange = { ( checked ) => setEmbedded ( checked === true ) } />
198
- < label htmlFor = "embed-checkbox" className = "text-sm" >
199
- Embed
200
- </ label >
201
- </ div >
202
- < Button onClick = { addMemoRelations } disabled = { selectedMemos . length === 0 } >
203
- { t ( "common.add" ) }
204
- </ Button >
205
- </ div >
206
138
</ div >
207
139
</ PopoverContent >
208
140
</ Popover >
0 commit comments