feat: set editor font style (#174)

feat: editor font style
This commit is contained in:
boojack
2022-08-25 20:44:32 +08:00
committed by GitHub
parent 20d7112a05
commit e9d303326f
10 changed files with 89 additions and 20 deletions

View File

@ -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,13 +23,16 @@ func (key UserSettingKey) String() string {
return "locale" return "locale"
case UserSettingMemoVisibilityKey: case UserSettingMemoVisibilityKey:
return "memoVisibility" return "memoVisibility"
case UserSettingEditorFontStyleKey:
return "editorFontFamily"
} }
return "" return ""
} }
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")
} }

View File

@ -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 (

View File

@ -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>
); );
}; };

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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"

View File

@ -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": "创建成员"

View File

@ -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),

View File

@ -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;