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
90274306
Commit
90274306
authored
Feb 10, 2025
by
Johnny
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: store reactive
parent
01a9bb2d
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
108 additions
and
73 deletions
+108
-73
App.tsx
web/src/App.tsx
+2
-1
PreferencesSection.tsx
web/src/components/Settings/PreferencesSection.tsx
+1
-3
AdminSignIn.tsx
web/src/pages/AdminSignIn.tsx
+2
-2
SignIn.tsx
web/src/pages/SignIn.tsx
+2
-2
SignUp.tsx
web/src/pages/SignUp.tsx
+2
-2
dialog.ts
web/src/store/v2/dialog.ts
+17
-9
user.ts
web/src/store/v2/user.ts
+51
-26
workspace.ts
web/src/store/v2/workspace.ts
+31
-28
No files found.
web/src/App.tsx
View file @
90274306
...
@@ -70,6 +70,7 @@ const App = observer(() => {
...
@@ -70,6 +70,7 @@ const App = observer(() => {
useEffect
(()
=>
{
useEffect
(()
=>
{
const
currentLocale
=
workspaceStore
.
state
.
locale
;
const
currentLocale
=
workspaceStore
.
state
.
locale
;
// This will trigger re-rendering of the whole app.
i18n
.
changeLanguage
(
currentLocale
);
i18n
.
changeLanguage
(
currentLocale
);
document
.
documentElement
.
setAttribute
(
"lang"
,
currentLocale
);
document
.
documentElement
.
setAttribute
(
"lang"
,
currentLocale
);
if
([
"ar"
,
"fa"
].
includes
(
currentLocale
))
{
if
([
"ar"
,
"fa"
].
includes
(
currentLocale
))
{
...
@@ -101,7 +102,7 @@ const App = observer(() => {
...
@@ -101,7 +102,7 @@ const App = observer(() => {
return
;
return
;
}
}
workspaceStore
.
setPartial
({
workspaceStore
.
s
tate
.
s
etPartial
({
locale
:
userSetting
.
locale
||
workspaceStore
.
state
.
locale
,
locale
:
userSetting
.
locale
||
workspaceStore
.
state
.
locale
,
appearance
:
userSetting
.
appearance
||
workspaceStore
.
state
.
appearance
,
appearance
:
userSetting
.
appearance
||
workspaceStore
.
state
.
appearance
,
});
});
...
...
web/src/components/Settings/PreferencesSection.tsx
View file @
90274306
import
{
Divider
,
Option
,
Select
}
from
"@mui/joy"
;
import
{
Divider
,
Option
,
Select
}
from
"@mui/joy"
;
import
{
observer
}
from
"mobx-react-lite"
;
import
{
observer
}
from
"mobx-react-lite"
;
import
{
userStore
,
workspaceStore
}
from
"@/store/v2"
;
import
{
userStore
}
from
"@/store/v2"
;
import
{
Visibility
}
from
"@/types/proto/api/v1/memo_service"
;
import
{
Visibility
}
from
"@/types/proto/api/v1/memo_service"
;
import
{
UserSetting
}
from
"@/types/proto/api/v1/user_service"
;
import
{
UserSetting
}
from
"@/types/proto/api/v1/user_service"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
...
@@ -15,7 +15,6 @@ const PreferencesSection = observer(() => {
...
@@ -15,7 +15,6 @@ const PreferencesSection = observer(() => {
const
setting
=
userStore
.
state
.
userSetting
as
UserSetting
;
const
setting
=
userStore
.
state
.
userSetting
as
UserSetting
;
const
handleLocaleSelectChange
=
async
(
locale
:
Locale
)
=>
{
const
handleLocaleSelectChange
=
async
(
locale
:
Locale
)
=>
{
workspaceStore
.
setPartial
({
locale
});
await
userStore
.
updateUserSetting
(
await
userStore
.
updateUserSetting
(
{
{
locale
,
locale
,
...
@@ -25,7 +24,6 @@ const PreferencesSection = observer(() => {
...
@@ -25,7 +24,6 @@ const PreferencesSection = observer(() => {
};
};
const
handleAppearanceSelectChange
=
async
(
appearance
:
Appearance
)
=>
{
const
handleAppearanceSelectChange
=
async
(
appearance
:
Appearance
)
=>
{
workspaceStore
.
setPartial
({
appearance
});
await
userStore
.
updateUserSetting
(
await
userStore
.
updateUserSetting
(
{
{
appearance
,
appearance
,
...
...
web/src/pages/AdminSignIn.tsx
View file @
90274306
...
@@ -13,11 +13,11 @@ const AdminSignIn = observer(() => {
...
@@ -13,11 +13,11 @@ const AdminSignIn = observer(() => {
workspaceSettingStore
.
getWorkspaceSettingByKey
(
WorkspaceSettingKey
.
GENERAL
).
generalSetting
||
WorkspaceGeneralSetting
.
fromPartial
({});
workspaceSettingStore
.
getWorkspaceSettingByKey
(
WorkspaceSettingKey
.
GENERAL
).
generalSetting
||
WorkspaceGeneralSetting
.
fromPartial
({});
const
handleLocaleSelectChange
=
(
locale
:
Locale
)
=>
{
const
handleLocaleSelectChange
=
(
locale
:
Locale
)
=>
{
workspaceStore
.
setPartial
({
locale
});
workspaceStore
.
s
tate
.
s
etPartial
({
locale
});
};
};
const
handleAppearanceSelectChange
=
(
appearance
:
Appearance
)
=>
{
const
handleAppearanceSelectChange
=
(
appearance
:
Appearance
)
=>
{
workspaceStore
.
setPartial
({
appearance
});
workspaceStore
.
s
tate
.
s
etPartial
({
appearance
});
};
};
return
(
return
(
...
...
web/src/pages/SignIn.tsx
View file @
90274306
...
@@ -43,11 +43,11 @@ const SignIn = observer(() => {
...
@@ -43,11 +43,11 @@ const SignIn = observer(() => {
},
[]);
},
[]);
const
handleLocaleSelectChange
=
(
locale
:
Locale
)
=>
{
const
handleLocaleSelectChange
=
(
locale
:
Locale
)
=>
{
workspaceStore
.
setPartial
({
locale
});
workspaceStore
.
s
tate
.
s
etPartial
({
locale
});
};
};
const
handleAppearanceSelectChange
=
(
appearance
:
Appearance
)
=>
{
const
handleAppearanceSelectChange
=
(
appearance
:
Appearance
)
=>
{
workspaceStore
.
setPartial
({
appearance
});
workspaceStore
.
s
tate
.
s
etPartial
({
appearance
});
};
};
const
handleSignInWithIdentityProvider
=
async
(
identityProvider
:
IdentityProvider
)
=>
{
const
handleSignInWithIdentityProvider
=
async
(
identityProvider
:
IdentityProvider
)
=>
{
...
...
web/src/pages/SignUp.tsx
View file @
90274306
...
@@ -38,11 +38,11 @@ const SignUp = observer(() => {
...
@@ -38,11 +38,11 @@ const SignUp = observer(() => {
};
};
const
handleLocaleSelectChange
=
(
locale
:
Locale
)
=>
{
const
handleLocaleSelectChange
=
(
locale
:
Locale
)
=>
{
workspaceStore
.
setPartial
({
locale
});
workspaceStore
.
s
tate
.
s
etPartial
({
locale
});
};
};
const
handleAppearanceSelectChange
=
(
appearance
:
Appearance
)
=>
{
const
handleAppearanceSelectChange
=
(
appearance
:
Appearance
)
=>
{
workspaceStore
.
setPartial
({
appearance
});
workspaceStore
.
s
tate
.
s
etPartial
({
appearance
});
};
};
const
handleFormSubmit
=
(
e
:
React
.
FormEvent
<
HTMLFormElement
>
)
=>
{
const
handleFormSubmit
=
(
e
:
React
.
FormEvent
<
HTMLFormElement
>
)
=>
{
...
...
web/src/store/v2/dialog.ts
View file @
90274306
import
{
last
}
from
"lodash-es"
;
import
{
last
}
from
"lodash-es"
;
import
{
makeAutoObservable
}
from
"mobx"
;
import
{
makeAutoObservable
,
runInAction
}
from
"mobx"
;
class
LocalState
{
stack
:
string
[]
=
[];
constructor
()
{
makeAutoObservable
(
this
);
}
setPartial
(
partial
:
Partial
<
LocalState
>
)
{
Object
.
assign
(
this
,
partial
);
}
}
const
dialogStore
=
(()
=>
{
const
dialogStore
=
(()
=>
{
const
state
=
makeAutoObservable
<
{
const
state
=
new
LocalState
();
stack
:
string
[];
}
>
({
stack
:
[],
});
const
pushDialog
=
(
name
:
string
)
=>
{
const
pushDialog
=
(
name
:
string
)
=>
{
state
.
stack
.
push
(
name
);
runInAction
(()
=>
state
.
stack
.
push
(
name
)
);
};
};
const
popDialog
=
()
=>
state
.
stack
.
pop
(
);
const
popDialog
=
()
=>
runInAction
(()
=>
state
.
stack
.
pop
()
);
const
removeDialog
=
(
name
:
string
)
=>
{
const
removeDialog
=
(
name
:
string
)
=>
{
state
.
stack
=
state
.
stack
.
filter
((
n
)
=>
n
!==
name
);
runInAction
(()
=>
(
state
.
stack
=
state
.
stack
.
filter
((
n
)
=>
n
!==
name
))
);
};
};
const
topDialog
=
last
(
state
.
stack
);
const
topDialog
=
last
(
state
.
stack
);
...
...
web/src/store/v2/user.ts
View file @
90274306
...
@@ -2,27 +2,26 @@ import { makeAutoObservable } from "mobx";
...
@@ -2,27 +2,26 @@ import { makeAutoObservable } from "mobx";
import
{
authServiceClient
,
inboxServiceClient
,
userServiceClient
}
from
"@/grpcweb"
;
import
{
authServiceClient
,
inboxServiceClient
,
userServiceClient
}
from
"@/grpcweb"
;
import
{
Inbox
}
from
"@/types/proto/api/v1/inbox_service"
;
import
{
Inbox
}
from
"@/types/proto/api/v1/inbox_service"
;
import
{
Shortcut
,
User
,
UserSetting
}
from
"@/types/proto/api/v1/user_service"
;
import
{
Shortcut
,
User
,
UserSetting
}
from
"@/types/proto/api/v1/user_service"
;
import
workspaceStore
from
"./workspace"
;
interface
LocalState
{
class
LocalState
{
// The name of current user. Format: `users/${uid}`
currentUser
?:
string
;
currentUser
?:
string
;
// userSetting is the setting of the current user.
userSetting
?:
UserSetting
;
userSetting
?:
UserSetting
;
// shortcuts is the list of shortcuts of the current user.
shortcuts
:
Shortcut
[]
=
[];
shortcuts
:
Shortcut
[];
inboxes
:
Inbox
[]
=
[];
// inboxes is the list of inboxes of the current user.
userMapByName
:
Record
<
string
,
User
>
=
{};
inboxes
:
Inbox
[];
// userMapByName is used to cache user information.
constructor
()
{
// Key is the `user.name` and value is the `User` object.
makeAutoObservable
(
this
);
userMapByName
:
Record
<
string
,
User
>
;
}
setPartial
(
partial
:
Partial
<
LocalState
>
)
{
Object
.
assign
(
this
,
partial
);
}
}
}
const
userStore
=
(()
=>
{
const
userStore
=
(()
=>
{
const
state
=
makeAutoObservable
<
LocalState
>
({
const
state
=
new
LocalState
();
shortcuts
:
[],
inboxes
:
[],
userMapByName
:
{},
});
const
getOrFetchUserByName
=
async
(
name
:
string
)
=>
{
const
getOrFetchUserByName
=
async
(
name
:
string
)
=>
{
const
userMap
=
state
.
userMapByName
;
const
userMap
=
state
.
userMapByName
;
...
@@ -32,8 +31,12 @@ const userStore = (() => {
...
@@ -32,8 +31,12 @@ const userStore = (() => {
const
user
=
await
userServiceClient
.
getUser
({
const
user
=
await
userServiceClient
.
getUser
({
name
:
name
,
name
:
name
,
});
});
userMap
[
name
]
=
user
;
state
.
setPartial
({
state
.
userMapByName
=
userMap
;
userMapByName
:
{
...
userMap
,
[
name
]:
user
,
},
});
return
user
;
return
user
;
};
};
...
@@ -42,10 +45,12 @@ const userStore = (() => {
...
@@ -42,10 +45,12 @@ const userStore = (() => {
user
,
user
,
updateMask
,
updateMask
,
});
});
state
.
userMapByName
=
{
state
.
setPartial
({
userMapByName
:
{
...
state
.
userMapByName
,
...
state
.
userMapByName
,
[
updatedUser
.
name
]:
updatedUser
,
[
updatedUser
.
name
]:
updatedUser
,
};
},
});
};
};
const
updateUserSetting
=
async
(
userSetting
:
Partial
<
UserSetting
>
,
updateMask
:
string
[])
=>
{
const
updateUserSetting
=
async
(
userSetting
:
Partial
<
UserSetting
>
,
updateMask
:
string
[])
=>
{
...
@@ -53,7 +58,12 @@ const userStore = (() => {
...
@@ -53,7 +58,12 @@ const userStore = (() => {
setting
:
userSetting
,
setting
:
userSetting
,
updateMask
:
updateMask
,
updateMask
:
updateMask
,
});
});
state
.
userSetting
=
UserSetting
.
fromPartial
(
updatedUserSetting
);
state
.
setPartial
({
userSetting
:
UserSetting
.
fromPartial
({
...
state
.
userSetting
,
...
updatedUserSetting
,
}),
});
};
};
const
fetchShortcuts
=
async
()
=>
{
const
fetchShortcuts
=
async
()
=>
{
...
@@ -62,12 +72,16 @@ const userStore = (() => {
...
@@ -62,12 +72,16 @@ const userStore = (() => {
}
}
const
{
shortcuts
}
=
await
userServiceClient
.
listShortcuts
({
parent
:
state
.
currentUser
});
const
{
shortcuts
}
=
await
userServiceClient
.
listShortcuts
({
parent
:
state
.
currentUser
});
state
.
shortcuts
=
shortcuts
;
state
.
setPartial
({
shortcuts
,
});
};
};
const
fetchInboxes
=
async
()
=>
{
const
fetchInboxes
=
async
()
=>
{
const
{
inboxes
}
=
await
inboxServiceClient
.
listInboxes
({});
const
{
inboxes
}
=
await
inboxServiceClient
.
listInboxes
({});
state
.
inboxes
=
inboxes
;
state
.
setPartial
({
inboxes
,
});
};
};
const
updateInbox
=
async
(
inbox
:
Partial
<
Inbox
>
,
updateMask
:
string
[])
=>
{
const
updateInbox
=
async
(
inbox
:
Partial
<
Inbox
>
,
updateMask
:
string
[])
=>
{
...
@@ -75,7 +89,14 @@ const userStore = (() => {
...
@@ -75,7 +89,14 @@ const userStore = (() => {
inbox
,
inbox
,
updateMask
,
updateMask
,
});
});
state
.
inboxes
=
state
.
inboxes
.
map
((
i
)
=>
(
i
.
name
===
updatedInbox
.
name
?
updatedInbox
:
i
));
state
.
setPartial
({
inboxes
:
state
.
inboxes
.
map
((
i
)
=>
{
if
(
i
.
name
===
updatedInbox
.
name
)
{
return
updatedInbox
;
}
return
i
;
}),
});
return
updatedInbox
;
return
updatedInbox
;
};
};
...
@@ -94,7 +115,7 @@ export const initialUserStore = async () => {
...
@@ -94,7 +115,7 @@ export const initialUserStore = async () => {
try
{
try
{
const
currentUser
=
await
authServiceClient
.
getAuthStatus
({});
const
currentUser
=
await
authServiceClient
.
getAuthStatus
({});
const
userSetting
=
await
userServiceClient
.
getUserSetting
({});
const
userSetting
=
await
userServiceClient
.
getUserSetting
({});
Object
.
assign
(
userStore
.
state
,
{
userStore
.
state
.
setPartial
(
{
currentUser
:
currentUser
.
name
,
currentUser
:
currentUser
.
name
,
userSetting
:
UserSetting
.
fromPartial
({
userSetting
:
UserSetting
.
fromPartial
({
...
userSetting
,
...
userSetting
,
...
@@ -103,6 +124,10 @@ export const initialUserStore = async () => {
...
@@ -103,6 +124,10 @@ export const initialUserStore = async () => {
[
currentUser
.
name
]:
currentUser
,
[
currentUser
.
name
]:
currentUser
,
},
},
});
});
workspaceStore
.
state
.
setPartial
({
locale
:
userSetting
.
locale
,
appearance
:
userSetting
.
appearance
,
});
}
catch
{
}
catch
{
// Do nothing.
// Do nothing.
}
}
...
...
web/src/store/v2/workspace.ts
View file @
90274306
import
{
uniqBy
}
from
"lodash-es"
;
import
{
makeAutoObservable
}
from
"mobx"
;
import
{
makeAutoObservable
}
from
"mobx"
;
import
{
workspaceServiceClient
,
workspaceSettingServiceClient
}
from
"@/grpcweb"
;
import
{
workspaceServiceClient
,
workspaceSettingServiceClient
}
from
"@/grpcweb"
;
import
{
WorkspaceProfile
}
from
"@/types/proto/api/v1/workspace_service"
;
import
{
WorkspaceProfile
}
from
"@/types/proto/api/v1/workspace_service"
;
...
@@ -6,38 +7,48 @@ import { WorkspaceSettingKey } from "@/types/proto/store/workspace_setting";
...
@@ -6,38 +7,48 @@ import { WorkspaceSettingKey } from "@/types/proto/store/workspace_setting";
import
{
isValidateLocale
}
from
"@/utils/i18n"
;
import
{
isValidateLocale
}
from
"@/utils/i18n"
;
import
{
workspaceSettingNamePrefix
}
from
"../v1"
;
import
{
workspaceSettingNamePrefix
}
from
"../v1"
;
interface
LocalState
{
class
LocalState
{
locale
:
string
;
locale
:
string
=
"en"
;
appearance
:
string
;
appearance
:
string
=
"system"
;
profile
:
WorkspaceProfile
;
profile
:
WorkspaceProfile
=
WorkspaceProfile
.
fromPartial
({});
settings
:
WorkspaceSetting
[];
settings
:
WorkspaceSetting
[]
=
[];
constructor
()
{
makeAutoObservable
(
this
);
}
setPartial
(
partial
:
Partial
<
LocalState
>
)
{
const
finalState
=
{
...
this
,
...
partial
,
};
if
(
!
isValidateLocale
(
finalState
.
locale
))
{
finalState
.
locale
=
"en"
;
}
if
(
!
[
"system"
,
"light"
,
"dark"
].
includes
(
finalState
.
appearance
))
{
finalState
.
appearance
=
"system"
;
}
Object
.
assign
(
this
,
finalState
);
}
}
}
const
workspaceStore
=
(()
=>
{
const
workspaceStore
=
(()
=>
{
const
state
=
makeAutoObservable
<
LocalState
>
({
const
state
=
new
LocalState
();
locale
:
"en"
,
appearance
:
"system"
,
profile
:
WorkspaceProfile
.
fromPartial
({}),
settings
:
[],
});
const
generalSetting
=
const
generalSetting
=
state
.
settings
.
find
((
setting
)
=>
setting
.
name
===
`
${
workspaceSettingNamePrefix
}${
WorkspaceSettingKey
.
GENERAL
}
`
)?.
generalSetting
||
state
.
settings
.
find
((
setting
)
=>
setting
.
name
===
`
${
workspaceSettingNamePrefix
}${
WorkspaceSettingKey
.
GENERAL
}
`
)?.
generalSetting
||
WorkspaceGeneralSetting
.
fromPartial
({});
WorkspaceGeneralSetting
.
fromPartial
({});
const
setPartial
=
(
partial
:
Partial
<
LocalState
>
)
=>
{
Object
.
assign
(
state
,
partial
);
};
const
fetchWorkspaceSetting
=
async
(
settingKey
:
WorkspaceSettingKey
)
=>
{
const
fetchWorkspaceSetting
=
async
(
settingKey
:
WorkspaceSettingKey
)
=>
{
const
setting
=
await
workspaceSettingServiceClient
.
getWorkspaceSetting
({
name
:
`
${
workspaceSettingNamePrefix
}${
settingKey
}
`
});
const
setting
=
await
workspaceSettingServiceClient
.
getWorkspaceSetting
({
name
:
`
${
workspaceSettingNamePrefix
}${
settingKey
}
`
});
state
.
settings
.
push
(
setting
);
state
.
setPartial
({
settings
:
uniqBy
([
setting
,
...
state
.
settings
],
"name"
),
});
};
};
return
{
return
{
state
,
state
,
generalSetting
,
generalSetting
,
setPartial
,
fetchWorkspaceSetting
,
fetchWorkspaceSetting
,
};
};
})();
})();
...
@@ -50,17 +61,9 @@ export const initialWorkspaceStore = async () => {
...
@@ -50,17 +61,9 @@ export const initialWorkspaceStore = async () => {
}
}
const
workspaceGeneralSetting
=
workspaceStore
.
generalSetting
;
const
workspaceGeneralSetting
=
workspaceStore
.
generalSetting
;
let
locale
=
workspaceGeneralSetting
.
customProfile
?.
locale
;
workspaceStore
.
state
.
setPartial
({
if
(
!
isValidateLocale
(
locale
))
{
locale
:
workspaceGeneralSetting
.
customProfile
?.
locale
,
locale
=
"en"
;
appearance
:
workspaceGeneralSetting
.
customProfile
?.
appearance
,
}
let
appearance
=
workspaceGeneralSetting
.
customProfile
?.
appearance
;
if
(
!
appearance
||
!
[
"system"
,
"light"
,
"dark"
].
includes
(
appearance
))
{
appearance
=
"system"
;
}
workspaceStore
.
setPartial
({
locale
:
locale
,
appearance
:
appearance
,
profile
:
workspaceProfile
,
profile
:
workspaceProfile
,
});
});
};
};
...
...
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