feat: float mobile editor (#234)

* feat: float mobile editor

* fix: fix pr comment

* lint: fix golangci-lint
This commit is contained in:
f97 2022-09-20 19:42:14 +07:00 committed by GitHub
parent 02c26d5bb4
commit 7a6eb53e0f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 68 additions and 7 deletions

View File

@ -14,6 +14,8 @@ const (
UserSettingMemoVisibilityKey UserSettingKey = "memoVisibility" UserSettingMemoVisibilityKey UserSettingKey = "memoVisibility"
// UserSettingEditorFontStyleKey is the key type for editor font style. // UserSettingEditorFontStyleKey is the key type for editor font style.
UserSettingEditorFontStyleKey UserSettingKey = "editorFontStyle" UserSettingEditorFontStyleKey UserSettingKey = "editorFontStyle"
// UserSettingEditorFontStyleKey is the key type for mobile editor style.
UserSettingMobileEditorStyleKey UserSettingKey = "mobileEditorStyle"
) )
// String returns the string format of UserSettingKey type. // String returns the string format of UserSettingKey type.
@ -25,14 +27,17 @@ func (key UserSettingKey) String() string {
return "memoVisibility" return "memoVisibility"
case UserSettingEditorFontStyleKey: case UserSettingEditorFontStyleKey:
return "editorFontFamily" return "editorFontFamily"
case UserSettingMobileEditorStyleKey:
return "mobileEditorStyle"
} }
return "" return ""
} }
var ( var (
UserSettingLocaleValue = []string{"en", "zh", "vi"} UserSettingLocaleValue = []string{"en", "zh", "vi"}
UserSettingMemoVisibilityValue = []Visibility{Privite, Protected, Public} UserSettingMemoVisibilityValue = []Visibility{Privite, Protected, Public}
UserSettingEditorFontStyleValue = []string{"normal", "mono"} UserSettingEditorFontStyleValue = []string{"normal", "mono"}
UserSettingMobileEditorStyleValue = []string{"normal", "float"}
) )
type UserSetting struct { type UserSetting struct {
@ -100,6 +105,23 @@ func (upsert UserSettingUpsert) Validate() error {
if invalid { if invalid {
return fmt.Errorf("invalid user setting editor font style value") return fmt.Errorf("invalid user setting editor font style value")
} }
} else if upsert.Key == UserSettingMobileEditorStyleKey {
mobileEditorStyleValue := "normal"
err := json.Unmarshal([]byte(upsert.Value), &mobileEditorStyleValue)
if err != nil {
return fmt.Errorf("failed to unmarshal user setting mobile editor style")
}
invalid := true
for _, value := range UserSettingMobileEditorStyleValue {
if mobileEditorStyleValue == value {
invalid = false
break
}
}
if invalid {
return fmt.Errorf("invalid user setting mobile editor style value")
}
} else { } else {
return fmt.Errorf("invalid user setting key") return fmt.Errorf("invalid user setting key")
} }

View File

@ -31,6 +31,7 @@ const MemoEditor = () => {
const prevGlobalStateRef = useRef(editorState); const prevGlobalStateRef = useRef(editorState);
const tagSeletorRef = useRef<HTMLDivElement>(null); const tagSeletorRef = useRef<HTMLDivElement>(null);
const editorFontStyle = user?.setting.editorFontStyle || "normal"; const editorFontStyle = user?.setting.editorFontStyle || "normal";
const mobileEditorStyle = user?.setting.mobileEditorStyle || "normal";
useEffect(() => { useEffect(() => {
if (editorState.markMemoId && editorState.markMemoId !== UNKNOWN_ID) { if (editorState.markMemoId && editorState.markMemoId !== UNKNOWN_ID) {
@ -280,7 +281,7 @@ const MemoEditor = () => {
); );
return ( return (
<div className={`memo-editor-container ${isEditing ? "edit-ing" : ""} ${state.fullscreen ? "fullscreen" : ""}`}> <div className={`memo-editor-container ${mobileEditorStyle} ${isEditing ? "edit-ing" : ""} ${state.fullscreen ? "fullscreen" : ""}`}>
<div className={`tip-container ${isEditing ? "" : "!hidden"}`}> <div className={`tip-container ${isEditing ? "" : "!hidden"}`}>
<span className="tip-text">{t("editor.editing")}</span> <span className="tip-text">{t("editor.editing")}</span>
<button className="cancel-btn" onClick={handleCancelEditingBtnClick}> <button className="cancel-btn" onClick={handleCancelEditingBtnClick}>

View File

@ -31,6 +31,17 @@ const editorFontStyleSelectorItems = [
}, },
]; ];
const mobileEditorStyleSelectorItems = [
{
text: "Normal",
value: "normal",
},
{
text: "Float",
value: "float",
},
];
const PreferencesSection = () => { const PreferencesSection = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { setting } = useAppSelector((state) => state.user.user as User); const { setting } = useAppSelector((state) => state.user.user as User);
@ -54,6 +65,10 @@ const PreferencesSection = () => {
await userService.upsertUserSetting("editorFontStyle", value); await userService.upsertUserSetting("editorFontStyle", value);
}; };
const handleMobileEditorStyleChanged = async (value: string) => {
await userService.upsertUserSetting("mobileEditorStyle", value);
};
return ( return (
<div className="section-container preferences-section-container"> <div className="section-container preferences-section-container">
<p className="title-text">{t("common.basic")}</p> <p className="title-text">{t("common.basic")}</p>
@ -80,6 +95,15 @@ const PreferencesSection = () => {
handleValueChanged={handleEditorFontStyleChanged} handleValueChanged={handleEditorFontStyleChanged}
/> />
</label> </label>
<label className="form-label selector">
<span className="normal-text">{t("setting.preference-section.mobile-editor-style")}</span>
<Selector
className="ml-2 w-32"
value={setting.mobileEditorStyle}
dataSource={mobileEditorStyleSelectorItems}
handleValueChanged={handleMobileEditorStyleChanged}
/>
</label>
</div> </div>
); );
}; };

View File

@ -25,6 +25,15 @@
border-color: @text-blue; border-color: @text-blue;
} }
&.float {
width: calc(100% - 2rem);
@apply fixed bottom-4 sm:relative sm:bottom-0 sm:w-full;
& .emoji-picker-react {
@apply bottom-16 sm:bottom-auto;
}
}
> .tip-container { > .tip-container {
@apply mb-1 w-full flex flex-row justify-start items-center text-xs leading-6; @apply mb-1 w-full flex flex-row justify-start items-center text-xs leading-6;

View File

@ -109,7 +109,8 @@
}, },
"preference-section": { "preference-section": {
"default-memo-visibility": "Default memo visibility", "default-memo-visibility": "Default memo visibility",
"editor-font-style": "Editor font style" "editor-font-style": "Editor font style",
"mobile-editor-style": "Mobile editor style"
}, },
"member-section": { "member-section": {
"create-a-member": "Create a member" "create-a-member": "Create a member"

View File

@ -109,7 +109,8 @@
}, },
"preference-section": { "preference-section": {
"default-memo-visibility": "Chế độ memo mặc định", "default-memo-visibility": "Chế độ memo mặc định",
"editor-font-style": "Thay đổi font cho trình soạn thảo" "editor-font-style": "Thay đổi font cho trình soạn thảo",
"mobile-editor-style": "Vị trí editor trên mobile"
}, },
"member-section": { "member-section": {
"create-a-member": "Tạo thành viên" "create-a-member": "Tạo thành viên"

View File

@ -109,7 +109,8 @@
}, },
"preference-section": { "preference-section": {
"default-memo-visibility": "默认 Memo 可见性", "default-memo-visibility": "默认 Memo 可见性",
"editor-font-style": "编辑器字体样式" "editor-font-style": "编辑器字体样式",
"mobile-editor-style": "Mobile editor style"
}, },
"member-section": { "member-section": {
"create-a-member": "创建成员" "create-a-member": "创建成员"

View File

@ -8,6 +8,7 @@ const defauleSetting: Setting = {
locale: "en", locale: "en",
memoVisibility: "PRIVATE", memoVisibility: "PRIVATE",
editorFontStyle: "normal", editorFontStyle: "normal",
mobileEditorStyle: "normal",
}; };
export const convertResponseModelUser = (user: User): User => { export const convertResponseModelUser = (user: User): User => {

View File

@ -2,6 +2,7 @@ interface Setting {
locale: Locale; locale: Locale;
memoVisibility: Visibility; memoVisibility: Visibility;
editorFontStyle: "normal" | "mono"; editorFontStyle: "normal" | "mono";
mobileEditorStyle: "normal" | "float";
} }
interface UserLocaleSetting { interface UserLocaleSetting {