mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
@ -12,6 +12,8 @@ const (
|
|||||||
UserSettingLocaleKey UserSettingKey = "locale"
|
UserSettingLocaleKey UserSettingKey = "locale"
|
||||||
// UserSettingMemoVisibilityKey is the key type for user preference memo default visibility.
|
// UserSettingMemoVisibilityKey is the key type for user preference memo default visibility.
|
||||||
UserSettingMemoVisibilityKey UserSettingKey = "memoVisibility"
|
UserSettingMemoVisibilityKey UserSettingKey = "memoVisibility"
|
||||||
|
// UserSettingEditorFontStyleKey is the key type for editor font style.
|
||||||
|
UserSettingEditorFontStyleKey UserSettingKey = "editorFontStyle"
|
||||||
)
|
)
|
||||||
|
|
||||||
// String returns the string format of UserSettingKey type.
|
// String returns the string format of UserSettingKey type.
|
||||||
@ -21,6 +23,8 @@ func (key UserSettingKey) String() string {
|
|||||||
return "locale"
|
return "locale"
|
||||||
case UserSettingMemoVisibilityKey:
|
case UserSettingMemoVisibilityKey:
|
||||||
return "memoVisibility"
|
return "memoVisibility"
|
||||||
|
case UserSettingEditorFontStyleKey:
|
||||||
|
return "editorFontFamily"
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@ -28,6 +32,7 @@ func (key UserSettingKey) String() string {
|
|||||||
var (
|
var (
|
||||||
UserSettingLocaleValue = []string{"en", "zh"}
|
UserSettingLocaleValue = []string{"en", "zh"}
|
||||||
UserSettingMemoVisibilityValue = []Visibility{Privite, Protected, Public}
|
UserSettingMemoVisibilityValue = []Visibility{Privite, Protected, Public}
|
||||||
|
UserSettingEditorFontStyleValue = []string{"normal", "mono"}
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserSetting struct {
|
type UserSetting struct {
|
||||||
@ -45,7 +50,7 @@ type UserSettingUpsert struct {
|
|||||||
|
|
||||||
func (upsert UserSettingUpsert) Validate() error {
|
func (upsert UserSettingUpsert) Validate() error {
|
||||||
if upsert.Key == UserSettingLocaleKey {
|
if upsert.Key == UserSettingLocaleKey {
|
||||||
var localeValue string
|
localeValue := "en"
|
||||||
err := json.Unmarshal([]byte(upsert.Value), &localeValue)
|
err := json.Unmarshal([]byte(upsert.Value), &localeValue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to unmarshal user setting locale value")
|
return fmt.Errorf("failed to unmarshal user setting locale value")
|
||||||
@ -62,7 +67,7 @@ func (upsert UserSettingUpsert) Validate() error {
|
|||||||
return fmt.Errorf("invalid user setting locale value")
|
return fmt.Errorf("invalid user setting locale value")
|
||||||
}
|
}
|
||||||
} else if upsert.Key == UserSettingMemoVisibilityKey {
|
} else if upsert.Key == UserSettingMemoVisibilityKey {
|
||||||
var memoVisibilityValue Visibility
|
memoVisibilityValue := Privite
|
||||||
err := json.Unmarshal([]byte(upsert.Value), &memoVisibilityValue)
|
err := json.Unmarshal([]byte(upsert.Value), &memoVisibilityValue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to unmarshal user setting memo visibility value")
|
return fmt.Errorf("failed to unmarshal user setting memo visibility value")
|
||||||
@ -78,6 +83,23 @@ func (upsert UserSettingUpsert) Validate() error {
|
|||||||
if invalid {
|
if invalid {
|
||||||
return fmt.Errorf("invalid user setting memo visibility value")
|
return fmt.Errorf("invalid user setting memo visibility value")
|
||||||
}
|
}
|
||||||
|
} else if upsert.Key == UserSettingEditorFontStyleKey {
|
||||||
|
editorFontStyleValue := "normal"
|
||||||
|
err := json.Unmarshal([]byte(upsert.Value), &editorFontStyleValue)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to unmarshal user setting editor font style")
|
||||||
|
}
|
||||||
|
|
||||||
|
invalid := true
|
||||||
|
for _, value := range UserSettingEditorFontStyleValue {
|
||||||
|
if editorFontStyleValue == value {
|
||||||
|
invalid = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if invalid {
|
||||||
|
return fmt.Errorf("invalid user setting editor font style value")
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("invalid user setting key")
|
return fmt.Errorf("invalid user setting key")
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ interface State {
|
|||||||
|
|
||||||
const MemoEditor: React.FC<Props> = () => {
|
const MemoEditor: React.FC<Props> = () => {
|
||||||
const { t, locale } = useI18n();
|
const { t, locale } = useI18n();
|
||||||
|
const user = useAppSelector((state) => state.user.user);
|
||||||
const editorState = useAppSelector((state) => state.editor);
|
const editorState = useAppSelector((state) => state.editor);
|
||||||
const tags = useAppSelector((state) => state.memo.tags);
|
const tags = useAppSelector((state) => state.memo.tags);
|
||||||
const [state, setState] = useState<State>({
|
const [state, setState] = useState<State>({
|
||||||
@ -27,6 +28,7 @@ const MemoEditor: React.FC<Props> = () => {
|
|||||||
const editorRef = useRef<EditorRefActions>(null);
|
const editorRef = useRef<EditorRefActions>(null);
|
||||||
const prevGlobalStateRef = useRef(editorState);
|
const prevGlobalStateRef = useRef(editorState);
|
||||||
const tagSeletorRef = useRef<HTMLDivElement>(null);
|
const tagSeletorRef = useRef<HTMLDivElement>(null);
|
||||||
|
const editorFontStyle = user?.setting.editorFontStyle || "normal";
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (editorState.markMemoId && editorState.markMemoId !== UNKNOWN_ID) {
|
if (editorState.markMemoId && editorState.markMemoId !== UNKNOWN_ID) {
|
||||||
@ -214,7 +216,7 @@ const MemoEditor: React.FC<Props> = () => {
|
|||||||
|
|
||||||
const editorConfig = useMemo(
|
const editorConfig = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
className: "memo-editor",
|
className: `memo-editor ${editorFontStyle}`,
|
||||||
initialContent: getEditorContentCache(),
|
initialContent: getEditorContentCache(),
|
||||||
placeholder: t("editor.placeholder"),
|
placeholder: t("editor.placeholder"),
|
||||||
fullscreen: state.fullscreen,
|
fullscreen: state.fullscreen,
|
||||||
@ -222,7 +224,7 @@ const MemoEditor: React.FC<Props> = () => {
|
|||||||
onConfirmBtnClick: handleSaveBtnClick,
|
onConfirmBtnClick: handleSaveBtnClick,
|
||||||
onContentChange: handleContentChange,
|
onContentChange: handleContentChange,
|
||||||
}),
|
}),
|
||||||
[isEditing, state.fullscreen, locale]
|
[isEditing, state.fullscreen, locale, editorFontStyle]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -19,6 +19,17 @@ const localeSelectorItems = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const editorFontStyleSelectorItems = [
|
||||||
|
{
|
||||||
|
text: "Normal",
|
||||||
|
value: "normal",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Mono",
|
||||||
|
value: "mono",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const PreferencesSection: React.FC<Props> = () => {
|
const PreferencesSection: React.FC<Props> = () => {
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { setting } = useAppSelector((state) => state.user.user as User);
|
const { setting } = useAppSelector((state) => state.user.user as User);
|
||||||
@ -32,14 +43,21 @@ const PreferencesSection: React.FC<Props> = () => {
|
|||||||
await userService.upsertUserSetting("memoVisibility", value);
|
await userService.upsertUserSetting("memoVisibility", value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleEditorFontStyleChanged = async (value: string) => {
|
||||||
|
await userService.upsertUserSetting("editorFontStyle", value);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="section-container preferences-section-container">
|
<div className="section-container preferences-section-container">
|
||||||
<label className="form-label">
|
<p className="title-text">{t("common.language")}</p>
|
||||||
<span className="normal-text">{t("common.language")}:</span>
|
<label className="form-label selector">
|
||||||
|
<span className="normal-text">
|
||||||
|
{t("common.language")}: <BetaBadge className="ml-2" />
|
||||||
|
</span>
|
||||||
<Selector className="ml-2 w-28" value={setting.locale} dataSource={localeSelectorItems} handleValueChanged={handleLocaleChanged} />
|
<Selector className="ml-2 w-28" value={setting.locale} dataSource={localeSelectorItems} handleValueChanged={handleLocaleChanged} />
|
||||||
<BetaBadge className="ml-2" />
|
|
||||||
</label>
|
</label>
|
||||||
<label className="form-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>
|
<span className="normal-text">{t("setting.preference-section.default-memo-visibility")}:</span>
|
||||||
<Selector
|
<Selector
|
||||||
className="ml-2 w-32"
|
className="ml-2 w-32"
|
||||||
@ -48,6 +66,15 @@ const PreferencesSection: React.FC<Props> = () => {
|
|||||||
handleValueChanged={handleDefaultMemoVisibilityChanged}
|
handleValueChanged={handleDefaultMemoVisibilityChanged}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
<label className="form-label selector">
|
||||||
|
<span className="normal-text">{t("setting.preference-section.editor-font-style")}:</span>
|
||||||
|
<Selector
|
||||||
|
className="ml-2 w-32"
|
||||||
|
value={setting.editorFontStyle}
|
||||||
|
dataSource={editorFontStyleSelectorItems}
|
||||||
|
handleValueChanged={handleEditorFontStyleChanged}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
@import "./mixin.less";
|
@import "./mixin.less";
|
||||||
|
|
||||||
.common-editor-wrapper {
|
.common-editor-wrapper {
|
||||||
.flex(column, flex-start, flex-start);
|
@apply flex flex-col justify-start items-start relative w-full h-auto bg-white;
|
||||||
@apply relative w-full h-auto bg-white;
|
|
||||||
|
&.mono {
|
||||||
|
> .common-editor-inputer {
|
||||||
|
@apply font-mono;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
> .common-editor-inputer {
|
> .common-editor-inputer {
|
||||||
@apply w-full h-full mt-1 mb-1 text-base resize-none overflow-x-hidden overflow-y-auto bg-transparent whitespace-pre-wrap;
|
@apply w-full h-full mt-1 mb-1 text-base resize-none overflow-x-hidden overflow-y-auto bg-transparent whitespace-pre-wrap;
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
> .form-label {
|
> .form-label {
|
||||||
@apply flex flex-row justify-start items-center w-full mb-2;
|
@apply flex flex-row items-center w-full mb-2;
|
||||||
|
|
||||||
> .normal-text {
|
> .normal-text {
|
||||||
@apply shrink-0 select-text;
|
@apply shrink-0 select-text;
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
@import "../mixin.less";
|
@import "../mixin.less";
|
||||||
|
|
||||||
.preferences-section-container {
|
.preferences-section-container {
|
||||||
> .form-label {
|
> .title-text {
|
||||||
@apply mb-2;
|
@apply mt-4 first:mt-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .form-label.selector {
|
||||||
|
@apply mb-2 flex flex-row justify-between items-center;
|
||||||
|
|
||||||
> .normal-text {
|
> .normal-text {
|
||||||
@apply mr-2 text-sm;
|
@apply mr-2 text-sm;
|
||||||
|
@ -56,7 +56,8 @@
|
|||||||
"title": "Account Information"
|
"title": "Account Information"
|
||||||
},
|
},
|
||||||
"preference-section": {
|
"preference-section": {
|
||||||
"default-memo-visibility": "Default memo visibility"
|
"default-memo-visibility": "Default memo visibility",
|
||||||
|
"editor-font-style": "Editor font style"
|
||||||
},
|
},
|
||||||
"member-section": {
|
"member-section": {
|
||||||
"create-a-member": "Create a member"
|
"create-a-member": "Create a member"
|
||||||
|
@ -56,7 +56,8 @@
|
|||||||
"title": "账号信息"
|
"title": "账号信息"
|
||||||
},
|
},
|
||||||
"preference-section": {
|
"preference-section": {
|
||||||
"default-memo-visibility": "默认 Memo 可见性"
|
"default-memo-visibility": "默认 Memo 可见性",
|
||||||
|
"editor-font-style": "编辑器字体样式"
|
||||||
},
|
},
|
||||||
"member-section": {
|
"member-section": {
|
||||||
"create-a-member": "创建成员"
|
"create-a-member": "创建成员"
|
||||||
|
@ -7,6 +7,7 @@ import { setUser, patchUser, setHost, setOwner } from "../store/modules/user";
|
|||||||
const defauleSetting: Setting = {
|
const defauleSetting: Setting = {
|
||||||
locale: "en",
|
locale: "en",
|
||||||
memoVisibility: "PRIVATE",
|
memoVisibility: "PRIVATE",
|
||||||
|
editorFontStyle: "normal",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const convertResponseModelUser = (user: User): User => {
|
export const convertResponseModelUser = (user: User): User => {
|
||||||
@ -16,7 +17,7 @@ export const convertResponseModelUser = (user: User): User => {
|
|||||||
|
|
||||||
if (user.userSettingList) {
|
if (user.userSettingList) {
|
||||||
for (const userSetting of user.userSettingList) {
|
for (const userSetting of user.userSettingList) {
|
||||||
setting[userSetting.key] = JSON.parse(userSetting.value);
|
(setting as any)[userSetting.key] = JSON.parse(userSetting.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +93,7 @@ const userService = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
upsertUserSetting: async (key: string, value: any) => {
|
upsertUserSetting: async (key: keyof Setting, value: any) => {
|
||||||
await api.upsertUserSetting({
|
await api.upsertUserSetting({
|
||||||
key: key as any,
|
key: key as any,
|
||||||
value: JSON.stringify(value),
|
value: JSON.stringify(value),
|
||||||
|
8
web/src/types/modules/setting.d.ts
vendored
8
web/src/types/modules/setting.d.ts
vendored
@ -1,6 +1,7 @@
|
|||||||
interface Setting {
|
interface Setting {
|
||||||
locale: Locale;
|
locale: Locale;
|
||||||
memoVisibility: Visibility;
|
memoVisibility: Visibility;
|
||||||
|
editorFontStyle: "normal" | "mono";
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UserLocaleSetting {
|
interface UserLocaleSetting {
|
||||||
@ -13,7 +14,12 @@ interface UserMemoVisibilitySetting {
|
|||||||
value: Visibility;
|
value: Visibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserSetting = UserLocaleSetting;
|
interface UserEditorFontStyleSetting {
|
||||||
|
key: "editorFontStyle";
|
||||||
|
value: "normal" | "mono";
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserSetting = UserLocaleSetting | UserMemoVisibilitySetting | UserEditorFontStyleSetting;
|
||||||
|
|
||||||
interface UserSettingUpsert {
|
interface UserSettingUpsert {
|
||||||
key: keyof Setting;
|
key: keyof Setting;
|
||||||
|
Reference in New Issue
Block a user