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
a6a1898c
Unverified
Commit
a6a1898c
authored
Jul 29, 2023
by
boojack
Committed by
GitHub
Jul 29, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactor: user v1 store (#2047)
parent
f5793c14
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
97 additions
and
46 deletions
+97
-46
package.json
web/package.json
+1
-1
pnpm-lock.yaml
web/pnpm-lock.yaml
+4
-4
Memo.tsx
web/src/components/Memo.tsx
+19
-6
ChatMessage.tsx
web/src/components/MemoChat/ChatMessage.tsx
+1
-1
ConversationTab.tsx
web/src/components/MemoChat/ConversationTab.tsx
+1
-1
RelationListView.tsx
web/src/components/MemoEditor/RelationListView.tsx
+1
-1
MemoRelationListView.tsx
web/src/components/MemoRelationListView.tsx
+1
-1
UserAvatar.tsx
web/src/components/UserAvatar.tsx
+3
-1
api.ts
web/src/helpers/api.ts
+1
-24
MemoChat.tsx
web/src/pages/MemoChat.tsx
+26
-3
memo.ts
web/src/store/module/memo.ts
+1
-1
conversation.ts
web/src/store/v1/conversation.ts
+0
-0
index.ts
web/src/store/v1/index.ts
+4
-0
memo.ts
web/src/store/v1/memo.ts
+3
-1
message.ts
web/src/store/v1/message.ts
+0
-0
user.ts
web/src/store/v1/user.ts
+31
-0
index.ts
web/src/store/zustand/index.ts
+0
-1
No files found.
web/package.json
View file @
a6a1898c
...
...
@@ -20,7 +20,7 @@
"i18next"
:
"^21.9.2"
,
"i18next-browser-languagedetector"
:
"^7.0.1"
,
"lodash-es"
:
"^4.17.21"
,
"lucide-react"
:
"^0.
105
.0"
,
"lucide-react"
:
"^0.
263
.0"
,
"qrcode.react"
:
"^3.1.0"
,
"react"
:
"^18.2.0"
,
"react-dom"
:
"^18.2.0"
,
...
...
web/pnpm-lock.yaml
View file @
a6a1898c
...
...
@@ -42,8 +42,8 @@ dependencies:
specifier
:
^4.17.21
version
:
4.17.21
lucide-react
:
specifier
:
^0.
105
.0
version
:
0.
105
.0(react@18.2.0)
specifier
:
^0.
263
.0
version
:
0.
263
.0(react@18.2.0)
qrcode.react
:
specifier
:
^3.1.0
version
:
3.1.0(react@18.2.0)
...
...
@@ -2428,8 +2428,8 @@ packages:
dependencies
:
yallist
:
4.0.0
/lucide-react@0.
105
.0(react@18.2.0)
:
resolution
:
{
integrity
:
sha512-
iHaIkd4Wq6aNIVrFMXt3If8E/+2lnJd4WlCyntoJNIzZ8nWhdSSHWpsw7XM4rlw2319LZ2t4WLdnM8Z0ECDTOQ
==
}
/lucide-react@0.
263
.0(react@18.2.0)
:
resolution
:
{
integrity
:
sha512-
F+rHswbbI1xuDZ/OzofiJZJVlBPOIYVVST705cPdRLImJ5aOJNXYaFBPNo3qdUV0iEG/4nZeiUtLSHO2qU2ISw
==
}
peerDependencies
:
react
:
^16.5.1 || ^17.0.0 || ^18.0.0
dependencies
:
...
...
web/src/components/Memo.tsx
View file @
a6a1898c
...
...
@@ -8,7 +8,7 @@ import { Link } from "react-router-dom";
import
{
useFilterStore
,
useMemoStore
,
useUserStore
}
from
"@/store/module"
;
import
{
UNKNOWN_ID
}
from
"@/helpers/consts"
;
import
{
getRelativeTimeString
}
from
"@/helpers/datetime"
;
import
{
useMemoCacheStore
}
from
"@/store/zustand
"
;
import
{
useMemoCacheStore
,
useUserV1Store
}
from
"@/store/v1
"
;
import
{
showCommonDialog
}
from
"./Dialog/CommonDialog"
;
import
Icon
from
"./Icon"
;
import
MemoContent
from
"./MemoContent"
;
...
...
@@ -18,6 +18,7 @@ import showShareMemo from "./ShareMemoDialog";
import
showPreviewImageDialog
from
"./PreviewImageDialog"
;
import
showChangeMemoCreatedTsDialog
from
"./ChangeMemoCreatedTsDialog"
;
import
showMemoEditorDialog
from
"./MemoEditor/MemoEditorDialog"
;
import
UserAvatar
from
"./UserAvatar"
;
import
"@/less/memo.less"
;
interface
Props
{
...
...
@@ -36,11 +37,19 @@ const Memo: React.FC<Props> = (props: Props) => {
const
userStore
=
useUserStore
();
const
memoStore
=
useMemoStore
();
const
memoCacheStore
=
useMemoCacheStore
();
const
userV1Store
=
useUserV1Store
();
const
[
createdTimeStr
,
setCreatedTimeStr
]
=
useState
<
string
>
(
getRelativeTimeString
(
memo
.
displayTs
));
const
[
relatedMemoList
,
setRelatedMemoList
]
=
useState
<
Memo
[]
>
([]);
const
memoContainerRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
readonly
=
userStore
.
isVisitorMode
()
||
userStore
.
getCurrentUsername
()
!==
memo
.
creatorUsername
;
const
creator
=
userV1Store
.
getUserByUsername
(
memo
.
creatorUsername
);
// Prepare memo creator.
useEffect
(()
=>
{
userV1Store
.
getOrFetchUserByUsername
(
memo
.
creatorUsername
);
},
[
memo
.
creatorUsername
]);
// Prepare related memos.
useEffect
(()
=>
{
Promise
.
allSettled
(
memo
.
relationList
.
map
((
memoRelation
)
=>
memoCacheStore
.
getOrFetchMemoById
(
memoRelation
.
relatedMemoId
))).
then
(
(
results
)
=>
{
...
...
@@ -217,14 +226,18 @@ const Memo: React.FC<Props> = (props: Props) => {
<
div
className=
{
`memo-wrapper ${"memos-" + memo.id} ${memo.pinned && !readonly ? "pinned" : ""}`
}
ref=
{
memoContainerRef
}
>
<
div
className=
"memo-top-wrapper"
>
<
div
className=
"status-text-container"
>
{
showCreator
&&
creator
&&
(
<>
<
Link
className=
"flex flex-row justify-start items-center"
to=
{
`/u/${memo.creatorUsername}`
}
>
<
UserAvatar
className=
"!w-5 !h-auto mr-1"
avatarUrl=
{
creator
.
avatarUrl
}
/>
<
span
className=
"text-sm text-gray-600 dark:text-zinc-300"
>
{
creator
.
nickname
}
</
span
>
</
Link
>
<
Icon
.
Dot
className=
"w-4 h-auto text-gray-400 dark:text-zinc-400"
/>
</>
)
}
<
Link
className=
"time-text"
to=
{
`/m/${memo.id}`
}
onClick=
{
handleMemoCreatedTimeClick
}
>
{
createdTimeStr
}
</
Link
>
{
showCreator
&&
(
<
Link
className=
"name-text"
to=
{
`/u/${memo.creatorUsername}`
}
>
@
{
memo
.
creatorName
}
</
Link
>
)
}
</
div
>
<
div
className=
"btns-container space-x-2"
>
{
showVisibility
&&
memo
.
visibility
!==
"PRIVATE"
&&
(
...
...
web/src/components/MemoChat/ChatMessage.tsx
View file @
a6a1898c
import
{
Message
}
from
"@/store/
zustand
/message"
;
import
{
Message
}
from
"@/store/
v1
/message"
;
import
{
marked
}
from
"@/labs/marked"
;
import
Icon
from
"@/components/Icon"
;
import
Dropdown
from
"../kit/Dropdown"
;
...
...
web/src/components/MemoChat/ConversationTab.tsx
View file @
a6a1898c
import
{
Conversation
}
from
"@/store/
zustand
/conversation"
;
import
{
Conversation
}
from
"@/store/
v1
/conversation"
;
import
Icon
from
"@/components/Icon"
;
interface
ConversationTabProps
{
...
...
web/src/components/MemoEditor/RelationListView.tsx
View file @
a6a1898c
import
{
useEffect
,
useState
}
from
"react"
;
import
{
useMemoCacheStore
}
from
"@/store/
zustand
"
;
import
{
useMemoCacheStore
}
from
"@/store/
v1
"
;
import
Icon
from
"../Icon"
;
interface
Props
{
...
...
web/src/components/MemoRelationListView.tsx
View file @
a6a1898c
import
{
useEffect
,
useState
}
from
"react"
;
import
{
useMemoCacheStore
}
from
"@/store/
zustand
"
;
import
{
useMemoCacheStore
}
from
"@/store/
v1
"
;
import
Icon
from
"./Icon"
;
interface
Props
{
...
...
web/src/components/UserAvatar.tsx
View file @
a6a1898c
import
classNames
from
"classnames"
;
interface
Props
{
avatarUrl
?:
string
;
className
?:
string
;
...
...
@@ -6,7 +8,7 @@ interface Props {
const
UserAvatar
=
(
props
:
Props
)
=>
{
const
{
avatarUrl
,
className
}
=
props
;
return
(
<
div
className=
{
`${className ?? ""} w-8 h-8 overflow-clip`
}
>
<
div
className=
{
classNames
(
`w-8 h-8 overflow-clip`
,
className
)
}
>
<
img
className=
"w-full h-auto rounded-full min-w-full min-h-full object-cover"
src=
{
avatarUrl
||
"/logo.webp"
}
alt=
""
/>
</
div
>
);
...
...
web/src/helpers/api.ts
View file @
a6a1898c
import
axios
from
"axios"
;
import
{
fetchEventSource
}
from
"@microsoft/fetch-event-source"
;
import
{
Message
}
from
"@/store/zustand/message"
;
export
function
getSystemStatus
()
{
return
axios
.
get
<
SystemStatus
>
(
"/api/v1/status"
);
...
...
@@ -139,32 +137,11 @@ export function unpinMemo(memoId: MemoId) {
export
function
deleteMemo
(
memoId
:
MemoId
)
{
return
axios
.
delete
(
`/api/v1/memo/
${
memoId
}
`
);
}
export
function
checkOpenAIEnabled
()
{
return
axios
.
get
<
boolean
>
(
`/api/openai/enabled`
);
}
export
async
function
chatStreaming
(
messageList
:
Array
<
Message
>
,
onmessage
:
any
,
onclose
:
any
)
{
await
fetchEventSource
(
"/api/v1/openai/chat-streaming"
,
{
method
:
"POST"
,
headers
:
{
"Content-Type"
:
"application/json"
,
},
body
:
JSON
.
stringify
(
messageList
),
async
onopen
()
{
// to do nth
},
onmessage
(
event
:
any
)
{
onmessage
(
event
);
},
onclose
()
{
onclose
();
},
onerror
(
error
:
any
)
{
console
.
log
(
"error"
,
error
);
},
});
}
export
function
getShortcutList
(
shortcutFind
?:
ShortcutFind
)
{
const
queryList
=
[];
if
(
shortcutFind
?.
creatorUsername
)
{
...
...
web/src/pages/MemoChat.tsx
View file @
a6a1898c
import
{
Button
,
Stack
}
from
"@mui/joy"
;
import
{
fetchEventSource
}
from
"@microsoft/fetch-event-source"
;
import
{
head
}
from
"lodash-es"
;
import
React
,
{
useEffect
,
useState
}
from
"react"
;
import
{
toast
}
from
"react-hot-toast"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
*
as
api
from
"@/helpers/api"
;
import
useLoading
from
"@/hooks/useLoading"
;
import
{
useMessageStore
}
from
"@/store/zustand
/message"
;
import
{
Conversation
,
useConversationStore
}
from
"@/store/
zustand
/conversation"
;
import
{
Message
,
useMessageStore
}
from
"@/store/v1
/message"
;
import
{
Conversation
,
useConversationStore
}
from
"@/store/
v1
/conversation"
;
import
Icon
from
"@/components/Icon"
;
import
{
generateUUID
}
from
"@/utils/uuid"
;
import
MobileHeader
from
"@/components/MobileHeader"
;
...
...
@@ -15,6 +16,28 @@ import ChatInput from "@/components/MemoChat/ChatInput";
import
ConversationTab
from
"@/components/MemoChat/ConversationTab"
;
import
Empty
from
"@/components/Empty"
;
const
chatStreaming
=
async
(
messageList
:
Array
<
Message
>
,
onmessage
:
any
,
onclose
:
any
)
=>
{
await
fetchEventSource
(
"/api/v1/openai/chat-streaming"
,
{
method
:
"POST"
,
headers
:
{
"Content-Type"
:
"application/json"
,
},
body
:
JSON
.
stringify
(
messageList
),
async
onopen
()
{
// to do nth
},
onmessage
(
event
:
any
)
{
onmessage
(
event
);
},
onclose
()
{
onclose
();
},
onerror
(
error
:
any
)
{
console
.
log
(
"error"
,
error
);
},
});
};
const
MemoChat
=
()
=>
{
const
t
=
useTranslate
();
const
fetchingState
=
useLoading
(
false
);
...
...
@@ -91,7 +114,7 @@ const MemoChat = () => {
const
fetchChatStreaming
=
async
(
messageId
:
string
)
=>
{
const
messageList
=
messageStore
.
getState
().
messageList
;
await
api
.
chatStreaming
(
await
chatStreaming
(
messageList
,
async
(
event
:
any
)
=>
{
messageStore
.
updateMessage
(
messageId
,
event
.
data
);
...
...
web/src/store/module/memo.ts
View file @
a6a1898c
...
...
@@ -4,7 +4,7 @@ import { DEFAULT_MEMO_LIMIT } from "@/helpers/consts";
import
{
useUserStore
}
from
"./"
;
import
store
,
{
useAppSelector
}
from
"../"
;
import
{
createMemo
,
deleteMemo
,
patchMemo
,
setIsFetching
,
upsertMemos
}
from
"../reducer/memo"
;
import
{
useMemoCacheStore
}
from
"../
zustand/memo
"
;
import
{
useMemoCacheStore
}
from
"../
v1
"
;
export
const
convertResponseModelMemo
=
(
memo
:
Memo
):
Memo
=>
{
return
{
...
...
web/src/store/
zustand
/conversation.ts
→
web/src/store/
v1
/conversation.ts
View file @
a6a1898c
File moved
web/src/store/v1/index.ts
0 → 100644
View file @
a6a1898c
import
useMemoCacheStore
from
"./memo"
;
import
useUserV1Store
from
"./user"
;
export
{
useUserV1Store
,
useMemoCacheStore
};
web/src/store/
zustand
/memo.ts
→
web/src/store/
v1
/memo.ts
View file @
a6a1898c
...
...
@@ -3,7 +3,7 @@ import { combine } from "zustand/middleware";
import
*
as
api
from
"@/helpers/api"
;
import
{
convertResponseModelMemo
}
from
"../module"
;
export
const
useMemoCacheStore
=
create
(
const
useMemoCacheStore
=
create
(
combine
({
memoById
:
new
Map
<
MemoId
,
Memo
>
()
},
(
set
,
get
)
=>
({
getState
:
()
=>
get
(),
getOrFetchMemoById
:
async
(
memoId
:
MemoId
)
=>
{
...
...
@@ -39,3 +39,5 @@ export const useMemoCacheStore = create(
},
}))
);
export
default
useMemoCacheStore
;
web/src/store/
zustand
/message.ts
→
web/src/store/
v1
/message.ts
View file @
a6a1898c
File moved
web/src/store/v1/user.ts
0 → 100644
View file @
a6a1898c
import
{
create
}
from
"zustand"
;
import
*
as
api
from
"@/helpers/api"
;
import
{
convertResponseModelUser
}
from
"../module"
;
interface
UserV1Store
{
userMapByUsername
:
Record
<
string
,
User
>
;
getOrFetchUserByUsername
:
(
username
:
string
)
=>
Promise
<
User
>
;
getUserByUsername
:
(
username
:
string
)
=>
User
;
}
const
useUserV1Store
=
create
<
UserV1Store
>
()((
set
,
get
)
=>
({
userMapByUsername
:
{},
getOrFetchUserByUsername
:
async
(
username
:
string
)
=>
{
const
userMap
=
get
().
userMapByUsername
;
if
(
userMap
[
username
])
{
return
userMap
[
username
]
as
User
;
}
const
{
data
}
=
await
api
.
getUserByUsername
(
username
);
const
user
=
convertResponseModelUser
(
data
);
userMap
[
username
]
=
user
;
set
(
userMap
);
return
user
;
},
getUserByUsername
:
(
username
:
string
)
=>
{
const
userMap
=
get
().
userMapByUsername
;
return
userMap
[
username
]
as
User
;
},
}));
export
default
useUserV1Store
;
web/src/store/zustand/index.ts
deleted
100644 → 0
View file @
f5793c14
export
{
useMemoCacheStore
}
from
"./memo"
;
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