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
7c6d7226
Unverified
Commit
7c6d7226
authored
Dec 01, 2022
by
boojack
Committed by
GitHub
Dec 01, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: update appearance selector (#645)
parent
eaebc6dc
Changes
23
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
157 additions
and
118 deletions
+157
-118
server.go
server/server.go
+0
-3
App.tsx
web/src/App.tsx
+2
-2
AppearanceSelect.tsx
web/src/components/AppearanceSelect.tsx
+19
-11
ChangePasswordDialog.tsx
web/src/components/ChangePasswordDialog.tsx
+2
-0
SearchBar.tsx
web/src/components/SearchBar.tsx
+8
-1
MemberSection.tsx
web/src/components/Settings/MemberSection.tsx
+11
-22
PreferencesSection.tsx
web/src/components/Settings/PreferencesSection.tsx
+5
-0
ShareMemoImageDialog.tsx
web/src/components/ShareMemoImageDialog.tsx
+3
-3
consts.ts
web/src/helpers/consts.ts
+0
-3
useAppearance.ts
web/src/hooks/useAppearance.ts
+65
-0
useApperance.ts
web/src/hooks/useApperance.ts
+0
-30
useLocalStorage.ts
web/src/hooks/useLocalStorage.ts
+0
-26
en.json
web/src/locales/en.json
+3
-3
fr.json
web/src/locales/fr.json
+1
-1
vi.json
web/src/locales/vi.json
+1
-1
zh.json
web/src/locales/zh.json
+3
-3
Auth.tsx
web/src/pages/Auth.tsx
+2
-2
index.tsx
web/src/router/index.tsx
+5
-0
globalService.ts
web/src/services/globalService.ts
+6
-1
userService.ts
web/src/services/userService.ts
+1
-0
global.ts
web/src/store/modules/global.ts
+9
-1
index.ts
web/src/theme/index.ts
+2
-4
setting.d.ts
web/src/types/modules/setting.d.ts
+9
-1
No files found.
server/server.go
View file @
7c6d7226
...
...
@@ -61,9 +61,6 @@ func NewServer(profile *profile.Profile) *Server {
rootGroup
:=
e
.
Group
(
""
)
s
.
registerRSSRoutes
(
rootGroup
)
webhookGroup
:=
e
.
Group
(
"/h"
)
s
.
registerResourcePublicRoutes
(
webhookGroup
)
publicGroup
:=
e
.
Group
(
"/o"
)
s
.
registerResourcePublicRoutes
(
publicGroup
)
s
.
registerGetterPublicRoutes
(
publicGroup
)
...
...
web/src/App.tsx
View file @
7c6d7226
...
...
@@ -6,12 +6,12 @@ import { useAppSelector } from "./store";
import
Loading
from
"./pages/Loading"
;
import
router
from
"./router"
;
import
*
as
storage
from
"./helpers/storage"
;
import
useAppe
rance
from
"./hooks/useAppe
rance"
;
import
useAppe
arance
from
"./hooks/useAppea
rance"
;
function
App
()
{
const
{
i18n
}
=
useTranslation
();
const
{
locale
,
systemStatus
}
=
useAppSelector
((
state
)
=>
state
.
global
);
useApperance
();
useAppe
a
rance
();
useEffect
(()
=>
{
locationService
.
updateStateWithLocation
();
...
...
web/src/components/ApperanceSelect.tsx
→
web/src/components/Appe
a
ranceSelect.tsx
View file @
7c6d7226
import
{
Option
,
Select
}
from
"@mui/joy"
;
import
{
useTranslation
}
from
"react-i18next"
;
import
{
globalService
}
from
"../services"
;
import
{
useAppSelector
}
from
"../store"
;
import
Icon
from
"./Icon"
;
import
{
APPERANCE_OPTIONS
}
from
"../helpers/consts"
;
import
useApperance
,
{
Apperance
}
from
"../hooks/useApperance"
;
const
ApperanceSelect
=
()
=>
{
const
[
apperance
,
setApperance
]
=
useApperance
();
const
appearanceList
=
[
"system"
,
"light"
,
"dark"
];
const
AppearanceSelect
=
()
=>
{
const
appearance
=
useAppSelector
((
state
)
=>
state
.
global
.
appearance
);
const
{
t
}
=
useTranslation
();
const
getPrefixIcon
=
(
apperance
:
Apperance
)
=>
{
const
getPrefixIcon
=
(
apperance
:
Appe
a
rance
)
=>
{
const
className
=
"w-4 h-auto"
;
if
(
apperance
===
"light"
)
{
return
<
Icon
.
Sun
className=
{
className
}
/>;
...
...
@@ -19,16 +21,22 @@ const ApperanceSelect = () => {
}
};
const
handleSelectChange
=
(
appearance
:
Appearance
)
=>
{
globalService
.
setAppearance
(
appearance
);
};
return
(
<
Select
className=
"!min-w-[10rem] w-auto text-sm"
value=
{
apperance
}
onChange=
{
(
_
,
value
)
=>
{
setApperance
(
value
as
Apperance
);
value=
{
appearance
}
onChange=
{
(
_
,
appearance
)
=>
{
if
(
appearance
)
{
handleSelectChange
(
appearance
);
}
}
}
startDecorator=
{
getPrefixIcon
(
apperance
)
}
startDecorator=
{
getPrefixIcon
(
appe
a
rance
)
}
>
{
APPERANCE_OPTIONS
.
map
((
item
)
=>
(
{
appearanceList
.
map
((
item
)
=>
(
<
Option
key=
{
item
}
value=
{
item
}
className=
"whitespace-nowrap"
>
{
t
(
`setting.apperance-option.${item}`
)
}
</
Option
>
...
...
@@ -37,4 +45,4 @@ const ApperanceSelect = () => {
);
};
export
default
ApperanceSelect
;
export
default
Appe
a
ranceSelect
;
web/src/components/ChangePasswordDialog.tsx
View file @
7c6d7226
...
...
@@ -82,6 +82,7 @@ const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
<
p
className=
"text-sm mb-1"
>
{
t
(
"common.new-password"
)
}
</
p
>
<
input
type=
"password"
autoComplete=
"new-password"
className=
"input-text"
placeholder=
{
t
(
"common.repeat-new-password"
)
}
value=
{
newPassword
}
...
...
@@ -90,6 +91,7 @@ const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
<
p
className=
"text-sm mb-1 mt-2"
>
{
t
(
"common.repeat-new-password"
)
}
</
p
>
<
input
type=
"password"
autoComplete=
"new-password"
className=
"input-text"
placeholder=
{
t
(
"common.repeat-new-password"
)
}
value=
{
newPasswordAgain
}
...
...
web/src/components/SearchBar.tsx
View file @
7c6d7226
...
...
@@ -34,7 +34,14 @@ const SearchBar = () => {
<
div
className=
"search-bar-container"
>
<
div
className=
"search-bar-inputer"
>
<
Icon
.
Search
className=
"icon-img"
/>
<
input
className=
"text-input"
autoComplete=
"off"
type=
"text"
placeholder=
""
value=
{
queryText
}
onChange=
{
handleTextQueryInput
}
/>
<
input
className=
"text-input"
autoComplete=
"new-password"
type=
"text"
placeholder=
""
value=
{
queryText
}
onChange=
{
handleTextQueryInput
}
/>
</
div
>
<
div
className=
"quickly-action-wrapper"
>
<
div
className=
"quickly-action-container"
>
...
...
web/src/components/Settings/MemberSection.tsx
View file @
7c6d7226
...
...
@@ -12,7 +12,6 @@ import "../../less/settings/member-section.less";
interface
State
{
createUserUsername
:
string
;
createUserPassword
:
string
;
repeatUserPassword
:
string
;
}
const
PreferencesSection
=
()
=>
{
...
...
@@ -21,7 +20,6 @@ const PreferencesSection = () => {
const
[
state
,
setState
]
=
useState
<
State
>
({
createUserUsername
:
""
,
createUserPassword
:
""
,
repeatUserPassword
:
""
,
});
const
[
userList
,
setUserList
]
=
useState
<
User
[]
>
([]);
...
...
@@ -48,22 +46,11 @@ const PreferencesSection = () => {
});
};
const
handleRepeatPasswordInputChange
=
(
event
:
React
.
ChangeEvent
<
HTMLInputElement
>
)
=>
{
setState
({
...
state
,
repeatUserPassword
:
event
.
target
.
value
,
});
};
const
handleCreateUserBtnClick
=
async
()
=>
{
if
(
state
.
createUserUsername
===
""
||
state
.
createUserPassword
===
""
)
{
toastHelper
.
error
(
t
(
"message.fill-form"
));
return
;
}
if
(
state
.
createUserPassword
!==
state
.
repeatUserPassword
)
{
toastHelper
.
error
(
t
(
"message.password-not-match"
));
return
;
}
const
userCreate
:
UserCreate
=
{
username
:
state
.
createUserUsername
,
...
...
@@ -80,7 +67,6 @@ const PreferencesSection = () => {
setState
({
createUserUsername
:
""
,
createUserPassword
:
""
,
repeatUserPassword
:
""
,
});
};
...
...
@@ -131,19 +117,22 @@ const PreferencesSection = () => {
<
div
className=
"create-member-container"
>
<
div
className=
"input-form-container"
>
<
span
className=
"field-text"
>
{
t
(
"common.username"
)
}
</
span
>
<
input
type=
"text"
placeholder=
{
t
(
"common.username"
)
}
value=
{
state
.
createUserUsername
}
onChange=
{
handleUsernameInputChange
}
/>
<
input
type=
"text"
autoComplete=
"new-password"
placeholder=
{
t
(
"common.username"
)
}
value=
{
state
.
createUserUsername
}
onChange=
{
handleUsernameInputChange
}
/>
</
div
>
<
div
className=
"input-form-container"
>
<
span
className=
"field-text"
>
{
t
(
"common.password"
)
}
</
span
>
<
input
type=
"password"
placeholder=
{
t
(
"common.password"
)
}
value=
{
state
.
createUserPassword
}
onChange=
{
handlePasswordInputChange
}
/>
</
div
>
<
div
className=
"input-form-container"
>
<
span
className=
"field-text"
>
{
t
(
"common.repeat-password-short"
)
}
</
span
>
<
input
type=
"password"
placeholder=
{
t
(
"common.repeat-password"
)
}
value=
{
state
.
repeatUserPassword
}
onChange=
{
handleRepeatPasswordInputChange
}
autoComplete=
"new-password"
placeholder=
{
t
(
"common.password"
)
}
value=
{
state
.
createUserPassword
}
onChange=
{
handlePasswordInputChange
}
/>
</
div
>
<
div
className=
"btns-container"
>
...
...
web/src/components/Settings/PreferencesSection.tsx
View file @
7c6d7226
...
...
@@ -4,6 +4,7 @@ import { globalService, userService } from "../../services";
import
{
useAppSelector
}
from
"../../store"
;
import
{
VISIBILITY_SELECTOR_ITEMS
,
MEMO_DISPLAY_TS_OPTION_SELECTOR_ITEMS
}
from
"../../helpers/consts"
;
import
Selector
from
"../common/Selector"
;
import
AppearanceSelect
from
"../AppearanceSelect"
;
import
"../../less/settings/preferences-section.less"
;
const
localeSelectorItems
=
[
...
...
@@ -66,6 +67,10 @@ const PreferencesSection = () => {
<
span
className=
"normal-text"
>
{
t
(
"common.language"
)
}
</
span
>
<
Selector
className=
"ml-2 w-32"
value=
{
setting
.
locale
}
dataSource=
{
localeSelectorItems
}
handleValueChanged=
{
handleLocaleChanged
}
/>
</
label
>
<
label
className=
"form-label selector"
>
<
span
className=
"normal-text"
>
Theme
</
span
>
<
AppearanceSelect
/>
</
label
>
<
p
className=
"title-text"
>
{
t
(
"setting.preference"
)
}
</
p
>
<
label
className=
"form-label selector"
>
<
span
className=
"normal-text"
>
{
t
(
"setting.preference-section.default-memo-visibility"
)
}
</
span
>
...
...
web/src/components/ShareMemoImageDialog.tsx
View file @
7c6d7226
...
...
@@ -14,8 +14,8 @@ import toastHelper from "./Toast";
import
MemoContent
from
"./MemoContent"
;
import
MemoResources
from
"./MemoResources"
;
import
Selector
from
"./common/Selector"
;
import
useAppearance
from
"../hooks/useAppearance"
;
import
"../less/share-memo-image-dialog.less"
;
import
useApperance
from
"../hooks/useApperance"
;
interface
Props
extends
DialogProps
{
memo
:
Memo
;
...
...
@@ -36,7 +36,7 @@ const ShareMemoImageDialog: React.FC<Props> = (props: Props) => {
shortcutImgUrl
:
""
,
memoVisibility
:
propsMemo
.
visibility
,
});
const
[
appe
rance
]
=
useAppe
rance
();
const
[
appe
arance
]
=
useAppea
rance
();
const
loadingState
=
useLoading
();
const
memoElRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
memo
=
{
...
...
@@ -72,7 +72,7 @@ const ShareMemoImageDialog: React.FC<Props> = (props: Props) => {
}
toImage
(
memoElRef
.
current
,
{
backgroundColor
:
apperance
===
"light"
?
"#f4f4f5"
:
"#27272a"
,
backgroundColor
:
appe
a
rance
===
"light"
?
"#f4f4f5"
:
"#27272a"
,
pixelRatio
:
window
.
devicePixelRatio
*
2
,
})
.
then
((
url
)
=>
{
...
...
web/src/helpers/consts.ts
View file @
7c6d7226
...
...
@@ -19,6 +19,3 @@ export const MEMO_DISPLAY_TS_OPTION_SELECTOR_ITEMS = [
];
export
const
TAB_SPACE_WIDTH
=
2
;
export
const
APPERANCE_OPTIONS
=
[
"auto"
,
"light"
,
"dark"
]
as
const
;
export
const
APPERANCE_OPTIONS_STORAGE_KEY
=
"setting_APPERANCE_OPTIONS"
;
web/src/hooks/useAppearance.ts
0 → 100644
View file @
7c6d7226
import
{
useEffect
}
from
"react"
;
import
{
useColorScheme
}
from
"@mui/joy/styles"
;
import
{
useAppSelector
}
from
"../store"
;
import
{
globalService
}
from
"../services"
;
const
getSystemColorScheme
=
()
=>
{
if
(
window
.
matchMedia
&&
window
.
matchMedia
(
"(prefers-color-scheme: dark)"
).
matches
)
{
return
"dark"
;
}
else
{
return
"light"
;
}
};
const
useAppearance
=
()
=>
{
const
user
=
useAppSelector
((
state
)
=>
state
.
user
.
user
);
const
appearance
=
useAppSelector
((
state
)
=>
state
.
global
.
appearance
);
const
{
mode
,
setMode
}
=
useColorScheme
();
useEffect
(()
=>
{
if
(
user
)
{
globalService
.
setAppearance
(
user
.
setting
.
appearance
);
}
},
[
user
]);
useEffect
(()
=>
{
let
mode
=
appearance
;
if
(
appearance
===
"system"
)
{
mode
=
getSystemColorScheme
();
}
setMode
(
mode
);
},
[
appearance
]);
useEffect
(()
=>
{
const
colorSchemeChangeHandler
=
(
event
:
MediaQueryListEvent
)
=>
{
const
newColorScheme
=
event
.
matches
?
"dark"
:
"light"
;
if
(
globalService
.
getState
().
appearance
===
"system"
)
{
setMode
(
newColorScheme
);
}
};
if
(
appearance
!==
"system"
)
{
window
.
matchMedia
(
"(prefers-color-scheme: dark)"
).
removeEventListener
(
"change"
,
colorSchemeChangeHandler
);
return
;
}
window
.
matchMedia
(
"(prefers-color-scheme: dark)"
).
addEventListener
(
"change"
,
colorSchemeChangeHandler
);
return
()
=>
{
window
.
matchMedia
(
"(prefers-color-scheme: dark)"
).
removeEventListener
(
"change"
,
colorSchemeChangeHandler
);
};
},
[
appearance
]);
useEffect
(()
=>
{
const
root
=
document
.
documentElement
;
if
(
mode
===
"dark"
)
{
root
.
classList
.
add
(
"dark"
);
}
else
if
(
mode
===
"light"
)
{
root
.
classList
.
remove
(
"dark"
);
}
},
[
mode
]);
return
[
appearance
,
globalService
.
setAppearance
]
as
const
;
};
export
default
useAppearance
;
web/src/hooks/useApperance.ts
deleted
100644 → 0
View file @
eaebc6dc
import
{
useEffect
}
from
"react"
;
import
{
useColorScheme
}
from
"@mui/joy/styles"
;
import
{
APPERANCE_OPTIONS
,
APPERANCE_OPTIONS_STORAGE_KEY
}
from
"../helpers/consts"
;
import
useLocalStorage
from
"./useLocalStorage"
;
import
useMediaQuery
from
"./useMediaQuery"
;
export
type
Apperance
=
typeof
APPERANCE_OPTIONS
[
number
];
const
useApperance
=
()
=>
{
const
[
apperance
,
setApperance
]
=
useLocalStorage
<
Apperance
>
(
APPERANCE_OPTIONS_STORAGE_KEY
,
APPERANCE_OPTIONS
[
0
]);
const
prefersDarkMode
=
useMediaQuery
(
"(prefers-color-scheme: dark)"
);
const
{
setMode
}
=
useColorScheme
();
useEffect
(()
=>
{
const
root
=
document
.
documentElement
;
if
(
apperance
===
"dark"
||
(
apperance
===
"auto"
&&
prefersDarkMode
))
{
root
.
classList
.
add
(
"dark"
);
setMode
(
"dark"
);
}
else
{
root
.
classList
.
remove
(
"dark"
);
setMode
(
"light"
);
}
},
[
apperance
,
prefersDarkMode
]);
return
[
apperance
,
setApperance
]
as
const
;
};
export
default
useApperance
;
web/src/hooks/useLocalStorage.ts
deleted
100644 → 0
View file @
eaebc6dc
import
{
useState
}
from
"react"
;
const
useLocalStorage
=
<
T
>
(
key
:
string
,
initialValue
:
T
)
=>
{
const
[
storedValue
,
setStoredValue
]
=
useState
<
T
>
(()
=>
{
try
{
const
item
=
window
.
localStorage
.
getItem
(
key
);
return
item
?
JSON
.
parse
(
item
)
:
initialValue
;
}
catch
(
error
)
{
return
initialValue
;
}
});
const
setValue
=
(
value
:
T
|
((
val
:
T
)
=>
T
))
=>
{
try
{
const
valueToStore
=
value
instanceof
Function
?
value
(
storedValue
)
:
value
;
setStoredValue
(
valueToStore
);
window
.
localStorage
.
setItem
(
key
,
JSON
.
stringify
(
valueToStore
));
}
catch
(
error
)
{
console
.
log
(
error
);
}
};
return
[
storedValue
,
setValue
]
as
const
;
};
export
default
useLocalStorage
;
web/src/locales/en.json
View file @
7c6d7226
...
...
@@ -152,7 +152,7 @@
"enable-folding-memo"
:
"Enable folding memo"
,
"editor-font-style"
:
"Editor font style"
,
"mobile-editor-style"
:
"Mobile editor style"
,
"default-memo-sort-option"
:
"
Display by created/updated
time"
,
"default-memo-sort-option"
:
"
Memo display
time"
,
"created_ts"
:
"Created Time"
,
"updated_ts"
:
"Updated Time"
},
...
...
@@ -168,9 +168,9 @@
"additional-script-placeholder"
:
"Additional JavaScript codes"
},
"apperance-option"
:
{
"auto"
:
"Follow system"
,
"light"
:
"Always light"
,
"dark"
:
"Always dark"
"dark"
:
"Always dark"
,
"system"
:
"Follow system"
}
},
"amount-text"
:
{
...
...
web/src/locales/fr.json
View file @
7c6d7226
...
...
@@ -152,7 +152,7 @@
"enable-folding-memo"
:
"Activer le mémo pliable"
,
"editor-font-style"
:
"Style de police de l'éditeur"
,
"mobile-editor-style"
:
"Style de l'éditeur mobile"
,
"default-memo-sort-option"
:
"
Affichage par heure de création/mise à jour
"
,
"default-memo-sort-option"
:
"
Memo display time
"
,
"created_ts"
:
"Heure de création"
,
"updated_ts"
:
"Heure de mise à jour"
},
...
...
web/src/locales/vi.json
View file @
7c6d7226
...
...
@@ -151,7 +151,7 @@
"enable-folding-memo"
:
"Enable folding memo"
,
"editor-font-style"
:
"Thay đổi font cho trình soạn thảo"
,
"mobile-editor-style"
:
"Vị trí editor trên mobile"
,
"default-memo-sort-option"
:
"
Sắp xếp theo thời gian đã tạo
"
,
"default-memo-sort-option"
:
"
Memo display time
"
,
"created_ts"
:
"tạo thời gian"
,
"updated_ts"
:
"Thời gian cập nhật"
},
...
...
web/src/locales/zh.json
View file @
7c6d7226
...
...
@@ -152,7 +152,7 @@
"enable-folding-memo"
:
"开启折叠 Memo"
,
"editor-font-style"
:
"编辑器字体样式"
,
"mobile-editor-style"
:
"移动端编辑器样式"
,
"default-memo-sort-option"
:
"
按创建时间/更新时间显示
"
,
"default-memo-sort-option"
:
"
Memo 显示时间
"
,
"created_ts"
:
"创建时间"
,
"updated_ts"
:
"更新时间"
},
...
...
@@ -168,9 +168,9 @@
"additional-script-placeholder"
:
"自定义 JavaScript 代码"
},
"apperance-option"
:
{
"auto"
:
"跟随系统"
,
"light"
:
"总是浅色"
,
"dark"
:
"总是深色"
"dark"
:
"总是深色"
,
"system"
:
"跟随系统"
}
},
"amount-text"
:
{
...
...
web/src/pages/Auth.tsx
View file @
7c6d7226
...
...
@@ -9,7 +9,7 @@ import useLoading from "../hooks/useLoading";
import
{
globalService
,
userService
}
from
"../services"
;
import
Icon
from
"../components/Icon"
;
import
toastHelper
from
"../components/Toast"
;
import
Appe
ranceSelect
from
"../components/Appe
ranceSelect"
;
import
Appe
aranceSelect
from
"../components/Appea
ranceSelect"
;
import
"../less/auth.less"
;
const
validateConfig
:
ValidatorConfig
=
{
...
...
@@ -177,7 +177,7 @@ const Auth = () => {
<
Option
value=
"vi"
>
Tiếng Việt
</
Option
>
<
Option
value=
"fr"
>
French
</
Option
>
</
Select
>
<
ApperanceSelect
/>
<
Appe
a
ranceSelect
/>
</
div
>
</
div
>
</
div
>
...
...
web/src/router/index.tsx
View file @
7c6d7226
...
...
@@ -18,6 +18,7 @@ const router = createBrowserRouter([
}
catch
(
error
)
{
// do nth
}
return
null
;
},
},
{
...
...
@@ -37,6 +38,7 @@ const router = createBrowserRouter([
}
else
if
(
isNullorUndefined
(
user
))
{
return
redirect
(
"/explore"
);
}
return
null
;
},
},
{
...
...
@@ -54,6 +56,7 @@ const router = createBrowserRouter([
if
(
isNullorUndefined
(
host
))
{
return
redirect
(
"/auth"
);
}
return
null
;
},
},
{
...
...
@@ -71,6 +74,7 @@ const router = createBrowserRouter([
if
(
isNullorUndefined
(
host
))
{
return
redirect
(
"/auth"
);
}
return
null
;
},
},
{
...
...
@@ -88,6 +92,7 @@ const router = createBrowserRouter([
if
(
isNullorUndefined
(
host
))
{
return
redirect
(
"/auth"
);
}
return
null
;
},
},
]);
...
...
web/src/services/globalService.ts
View file @
7c6d7226
import
store
from
"../store"
;
import
*
as
api
from
"../helpers/api"
;
import
*
as
storage
from
"../helpers/storage"
;
import
{
setGlobalState
,
setLocale
}
from
"../store/modules/global"
;
import
{
set
Appearance
,
set
GlobalState
,
setLocale
}
from
"../store/modules/global"
;
const
globalService
=
{
getState
:
()
=>
{
...
...
@@ -11,6 +11,7 @@ const globalService = {
initialState
:
async
()
=>
{
const
defaultGlobalState
=
{
locale
:
"en"
as
Locale
,
appearance
:
"system"
as
Appearance
,
systemStatus
:
{
allowSignUp
:
false
,
additionalStyle
:
""
,
...
...
@@ -38,6 +39,10 @@ const globalService = {
setLocale
:
(
locale
:
Locale
)
=>
{
store
.
dispatch
(
setLocale
(
locale
));
},
setAppearance
:
(
appearance
:
Appearance
)
=>
{
store
.
dispatch
(
setAppearance
(
appearance
));
},
};
export
default
globalService
;
web/src/services/userService.ts
View file @
7c6d7226
...
...
@@ -8,6 +8,7 @@ import { setUser, patchUser, setHost, setOwner } from "../store/modules/user";
const
defaultSetting
:
Setting
=
{
locale
:
"en"
,
appearance
:
"system"
,
memoVisibility
:
"PRIVATE"
,
memoDisplayTsOption
:
"created_ts"
,
};
...
...
web/src/store/modules/global.ts
View file @
7c6d7226
...
...
@@ -2,6 +2,7 @@ import { createSlice, PayloadAction } from "@reduxjs/toolkit";
interface
State
{
locale
:
Locale
;
appearance
:
Appearance
;
systemStatus
:
SystemStatus
;
}
...
...
@@ -9,6 +10,7 @@ const globalSlice = createSlice({
name
:
"global"
,
initialState
:
{
locale
:
"en"
,
appearance
:
"system"
,
systemStatus
:
{
host
:
undefined
,
profile
:
{
...
...
@@ -31,9 +33,15 @@ const globalSlice = createSlice({
locale
:
action
.
payload
,
};
},
setAppearance
:
(
state
,
action
:
PayloadAction
<
Appearance
>
)
=>
{
return
{
...
state
,
appearance
:
action
.
payload
,
};
},
},
});
export
const
{
setGlobalState
,
setLocale
}
=
globalSlice
.
actions
;
export
const
{
setGlobalState
,
setLocale
,
setAppearance
}
=
globalSlice
.
actions
;
export
default
globalSlice
.
reducer
;
web/src/theme/index.ts
View file @
7c6d7226
...
...
@@ -3,10 +3,8 @@ import { extendTheme } from "@mui/joy";
const
theme
=
extendTheme
({
components
:
{
JoySelect
:
{
styleOverrides
:
{
root
:
{
fontSize
:
"0.875rem"
,
},
defaultProps
:
{
size
:
"sm"
,
},
},
},
...
...
web/src/types/modules/setting.d.ts
View file @
7c6d7226
type
Appearance
=
"light"
|
"dark"
|
"system"
;
interface
Setting
{
locale
:
Locale
;
appearance
:
Appearance
;
memoVisibility
:
Visibility
;
memoDisplayTsOption
:
"created_ts"
|
"updated_ts"
;
}
...
...
@@ -13,12 +16,17 @@ interface UserLocaleSetting {
value
:
Locale
;
}
interface
UserAppearanceSetting
{
key
:
"appearance"
;
value
:
Appearance
;
}
interface
UserMemoVisibilitySetting
{
key
:
"memoVisibility"
;
value
:
Visibility
;
}
type
UserSetting
=
UserLocaleSetting
|
UserMemoVisibilitySetting
;
type
UserSetting
=
UserLocaleSetting
|
User
AppearanceSetting
|
User
MemoVisibilitySetting
;
interface
UserSettingUpsert
{
key
:
keyof
Setting
;
...
...
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