mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
feat: save folding option with localstorage (#641)
* fix: change folding option need reload * fix: floding option undefied
This commit is contained in:
@ -3,8 +3,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { marked } from "../labs/marked";
|
import { marked } from "../labs/marked";
|
||||||
import { highlightWithWord } from "../labs/highlighter";
|
import { highlightWithWord } from "../labs/highlighter";
|
||||||
import Icon from "./Icon";
|
import Icon from "./Icon";
|
||||||
import { SETTING_IS_FOLDING_ENABLED_KEY, IS_FOLDING_ENABLED_DEFAULT_VALUE } from "../helpers/consts";
|
import { useAppSelector } from "../store";
|
||||||
import useLocalStorage from "../hooks/useLocalStorage";
|
|
||||||
import "../less/memo-content.less";
|
import "../less/memo-content.less";
|
||||||
|
|
||||||
export interface DisplayConfig {
|
export interface DisplayConfig {
|
||||||
@ -37,7 +36,8 @@ const MemoContent: React.FC<Props> = (props: Props) => {
|
|||||||
return firstHorizontalRuleIndex !== -1 ? content.slice(0, firstHorizontalRuleIndex) : content;
|
return firstHorizontalRuleIndex !== -1 ? content.slice(0, firstHorizontalRuleIndex) : content;
|
||||||
}, [content]);
|
}, [content]);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [isFoldingEnabled] = useLocalStorage(SETTING_IS_FOLDING_ENABLED_KEY, IS_FOLDING_ENABLED_DEFAULT_VALUE);
|
const user = useAppSelector((state) => state.user.user);
|
||||||
|
|
||||||
const [state, setState] = useState<State>({
|
const [state, setState] = useState<State>({
|
||||||
expandButtonStatus: -1,
|
expandButtonStatus: -1,
|
||||||
});
|
});
|
||||||
@ -52,15 +52,20 @@ const MemoContent: React.FC<Props> = (props: Props) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (displayConfig.enableExpand && isFoldingEnabled) {
|
if (displayConfig.enableExpand && user && user.localSetting.isFoldingEnabled) {
|
||||||
if (foldedContent.length !== content.length) {
|
if (foldedContent.length !== content.length) {
|
||||||
setState({
|
setState({
|
||||||
...state,
|
...state,
|
||||||
expandButtonStatus: 0,
|
expandButtonStatus: 0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
setState({
|
||||||
|
...state,
|
||||||
|
expandButtonStatus: -1,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, []);
|
}, [user?.localSetting.isFoldingEnabled]);
|
||||||
|
|
||||||
const handleMemoContentClick = async (e: React.MouseEvent) => {
|
const handleMemoContentClick = async (e: React.MouseEvent) => {
|
||||||
if (onMemoContentClick) {
|
if (onMemoContentClick) {
|
||||||
|
@ -2,13 +2,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
import Switch from "@mui/joy/Switch";
|
import Switch from "@mui/joy/Switch";
|
||||||
import { globalService, userService } from "../../services";
|
import { globalService, userService } from "../../services";
|
||||||
import { useAppSelector } from "../../store";
|
import { useAppSelector } from "../../store";
|
||||||
import {
|
import { VISIBILITY_SELECTOR_ITEMS, MEMO_DISPLAY_TS_OPTION_SELECTOR_ITEMS } from "../../helpers/consts";
|
||||||
VISIBILITY_SELECTOR_ITEMS,
|
|
||||||
MEMO_DISPLAY_TS_OPTION_SELECTOR_ITEMS,
|
|
||||||
SETTING_IS_FOLDING_ENABLED_KEY,
|
|
||||||
IS_FOLDING_ENABLED_DEFAULT_VALUE,
|
|
||||||
} from "../../helpers/consts";
|
|
||||||
import useLocalStorage from "../../hooks/useLocalStorage";
|
|
||||||
import Selector from "../common/Selector";
|
import Selector from "../common/Selector";
|
||||||
import "../../less/settings/preferences-section.less";
|
import "../../less/settings/preferences-section.less";
|
||||||
|
|
||||||
@ -33,7 +27,7 @@ const localeSelectorItems = [
|
|||||||
|
|
||||||
const PreferencesSection = () => {
|
const PreferencesSection = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { setting } = useAppSelector((state) => state.user.user as User);
|
const { setting, localSetting } = useAppSelector((state) => state.user.user as User);
|
||||||
const visibilitySelectorItems = VISIBILITY_SELECTOR_ITEMS.map((item) => {
|
const visibilitySelectorItems = VISIBILITY_SELECTOR_ITEMS.map((item) => {
|
||||||
return {
|
return {
|
||||||
value: item.value,
|
value: item.value,
|
||||||
@ -48,8 +42,6 @@ const PreferencesSection = () => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const [isFoldingEnabled, setIsFoldingEnabled] = useLocalStorage(SETTING_IS_FOLDING_ENABLED_KEY, IS_FOLDING_ENABLED_DEFAULT_VALUE);
|
|
||||||
|
|
||||||
const handleLocaleChanged = async (value: string) => {
|
const handleLocaleChanged = async (value: string) => {
|
||||||
await userService.upsertUserSetting("locale", value);
|
await userService.upsertUserSetting("locale", value);
|
||||||
globalService.setLocale(value as Locale);
|
globalService.setLocale(value as Locale);
|
||||||
@ -64,7 +56,7 @@ const PreferencesSection = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleIsFoldingEnabledChanged = (event: React.ChangeEvent<HTMLInputElement>) => {
|
const handleIsFoldingEnabledChanged = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
setIsFoldingEnabled(event.target.checked);
|
userService.upsertLocalSetting("isFoldingEnabled", event.target.checked);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -95,7 +87,7 @@ const PreferencesSection = () => {
|
|||||||
</label>
|
</label>
|
||||||
<label className="form-label selector">
|
<label className="form-label selector">
|
||||||
<span className="normal-text">{t("setting.preference-section.enable-folding-memo")}</span>
|
<span className="normal-text">{t("setting.preference-section.enable-folding-memo")}</span>
|
||||||
<Switch className="ml-2" checked={isFoldingEnabled} onChange={handleIsFoldingEnabledChanged} />
|
<Switch className="ml-2" checked={localSetting.isFoldingEnabled} onChange={handleIsFoldingEnabledChanged} />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -18,9 +18,6 @@ export const MEMO_DISPLAY_TS_OPTION_SELECTOR_ITEMS = [
|
|||||||
{ text: "created_ts", value: "updated_ts" },
|
{ text: "created_ts", value: "updated_ts" },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const IS_FOLDING_ENABLED_DEFAULT_VALUE = true;
|
|
||||||
export const SETTING_IS_FOLDING_ENABLED_KEY = "setting_IS_FOLDING_ENABLED";
|
|
||||||
|
|
||||||
export const TAB_SPACE_WIDTH = 2;
|
export const TAB_SPACE_WIDTH = 2;
|
||||||
|
|
||||||
export const APPERANCE_OPTIONS = ["auto", "light", "dark"] as const;
|
export const APPERANCE_OPTIONS = ["auto", "light", "dark"] as const;
|
||||||
|
@ -10,6 +10,8 @@ interface StorageData {
|
|||||||
editingMemoVisibilityCache: Visibility;
|
editingMemoVisibilityCache: Visibility;
|
||||||
// locale
|
// locale
|
||||||
locale: Locale;
|
locale: Locale;
|
||||||
|
// local setting
|
||||||
|
localSetting: LocalSetting;
|
||||||
// skipped version
|
// skipped version
|
||||||
skippedVersion: string;
|
skippedVersion: string;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { globalService, locationService } from ".";
|
import { globalService, locationService } from ".";
|
||||||
import * as api from "../helpers/api";
|
import * as api from "../helpers/api";
|
||||||
|
import * as storage from "../helpers/storage";
|
||||||
import { UNKNOWN_ID } from "../helpers/consts";
|
import { UNKNOWN_ID } from "../helpers/consts";
|
||||||
import store from "../store";
|
import store from "../store";
|
||||||
import { setLocale } from "../store/modules/global";
|
import { setLocale } from "../store/modules/global";
|
||||||
@ -11,10 +12,19 @@ const defaultSetting: Setting = {
|
|||||||
memoDisplayTsOption: "created_ts",
|
memoDisplayTsOption: "created_ts",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const defaultLocalSetting: LocalSetting = {
|
||||||
|
isFoldingEnabled: true,
|
||||||
|
};
|
||||||
|
|
||||||
export const convertResponseModelUser = (user: User): User => {
|
export const convertResponseModelUser = (user: User): User => {
|
||||||
const setting: Setting = {
|
const setting: Setting = {
|
||||||
...defaultSetting,
|
...defaultSetting,
|
||||||
};
|
};
|
||||||
|
const { localSetting: storageLocalSetting } = storage.get(["localSetting"]);
|
||||||
|
const localSetting: LocalSetting = {
|
||||||
|
...defaultLocalSetting,
|
||||||
|
...storageLocalSetting,
|
||||||
|
};
|
||||||
|
|
||||||
if (user.userSettingList) {
|
if (user.userSettingList) {
|
||||||
for (const userSetting of user.userSettingList) {
|
for (const userSetting of user.userSettingList) {
|
||||||
@ -25,6 +35,7 @@ export const convertResponseModelUser = (user: User): User => {
|
|||||||
return {
|
return {
|
||||||
...user,
|
...user,
|
||||||
setting,
|
setting,
|
||||||
|
localSetting,
|
||||||
createdTs: user.createdTs * 1000,
|
createdTs: user.createdTs * 1000,
|
||||||
updatedTs: user.updatedTs * 1000,
|
updatedTs: user.updatedTs * 1000,
|
||||||
};
|
};
|
||||||
@ -111,6 +122,11 @@ const userService = {
|
|||||||
await userService.doSignIn();
|
await userService.doSignIn();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
upsertLocalSetting: async (key: keyof LocalSetting, value: any) => {
|
||||||
|
storage.set({ localSetting: { [key]: value } });
|
||||||
|
store.dispatch(patchUser({ localSetting: { [key]: value } }));
|
||||||
|
},
|
||||||
|
|
||||||
patchUser: async (userPatch: UserPatch): Promise<void> => {
|
patchUser: async (userPatch: UserPatch): Promise<void> => {
|
||||||
const { data } = (await api.patchUser(userPatch)).data;
|
const { data } = (await api.patchUser(userPatch)).data;
|
||||||
if (userPatch.id === store.getState().user.user?.id) {
|
if (userPatch.id === store.getState().user.user?.id) {
|
||||||
|
4
web/src/types/modules/setting.d.ts
vendored
4
web/src/types/modules/setting.d.ts
vendored
@ -4,6 +4,10 @@ interface Setting {
|
|||||||
memoDisplayTsOption: "created_ts" | "updated_ts";
|
memoDisplayTsOption: "created_ts" | "updated_ts";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface LocalSetting {
|
||||||
|
isFoldingEnabled: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
interface UserLocaleSetting {
|
interface UserLocaleSetting {
|
||||||
key: "locale";
|
key: "locale";
|
||||||
value: Locale;
|
value: Locale;
|
||||||
|
1
web/src/types/modules/user.d.ts
vendored
1
web/src/types/modules/user.d.ts
vendored
@ -16,6 +16,7 @@ interface User {
|
|||||||
userSettingList: UserSetting[];
|
userSettingList: UserSetting[];
|
||||||
|
|
||||||
setting: Setting;
|
setting: Setting;
|
||||||
|
localSetting: LocalSetting;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UserCreate {
|
interface UserCreate {
|
||||||
|
Reference in New Issue
Block a user