mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
feat: customize memo list sorting rules (#312)
* chore: update .gitignore * feat: 添加Memo列表按更新时间排序 * fix go-static-checks * update * update * update Memo.tsx/MemoList.tsx * handle conflict Co-authored-by: boojack <stevenlgtm@gmail.com>
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@ -11,3 +11,6 @@ web/dist
|
|||||||
build
|
build
|
||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
# Jetbrains
|
||||||
|
.idea
|
@ -16,6 +16,8 @@ const (
|
|||||||
UserSettingEditorFontStyleKey UserSettingKey = "editorFontStyle"
|
UserSettingEditorFontStyleKey UserSettingKey = "editorFontStyle"
|
||||||
// UserSettingEditorFontStyleKey is the key type for mobile editor style.
|
// UserSettingEditorFontStyleKey is the key type for mobile editor style.
|
||||||
UserSettingMobileEditorStyleKey UserSettingKey = "mobileEditorStyle"
|
UserSettingMobileEditorStyleKey UserSettingKey = "mobileEditorStyle"
|
||||||
|
// UserSettingMemoSortOptionKey is the key type for sort time option.
|
||||||
|
UserSettingMemoSortOptionKey UserSettingKey = "memoSortOption"
|
||||||
)
|
)
|
||||||
|
|
||||||
// String returns the string format of UserSettingKey type.
|
// String returns the string format of UserSettingKey type.
|
||||||
@ -29,6 +31,8 @@ func (key UserSettingKey) String() string {
|
|||||||
return "editorFontFamily"
|
return "editorFontFamily"
|
||||||
case UserSettingMobileEditorStyleKey:
|
case UserSettingMobileEditorStyleKey:
|
||||||
return "mobileEditorStyle"
|
return "mobileEditorStyle"
|
||||||
|
case UserSettingMemoSortOptionKey:
|
||||||
|
return "memoSortOption"
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@ -38,6 +42,7 @@ var (
|
|||||||
UserSettingMemoVisibilityValue = []Visibility{Privite, Protected, Public}
|
UserSettingMemoVisibilityValue = []Visibility{Privite, Protected, Public}
|
||||||
UserSettingEditorFontStyleValue = []string{"normal", "mono"}
|
UserSettingEditorFontStyleValue = []string{"normal", "mono"}
|
||||||
UserSettingMobileEditorStyleValue = []string{"normal", "float"}
|
UserSettingMobileEditorStyleValue = []string{"normal", "float"}
|
||||||
|
UserSettingSortTimeOptionKeyValue = []string{"created_ts", "updated_ts"}
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserSetting struct {
|
type UserSetting struct {
|
||||||
@ -122,6 +127,23 @@ func (upsert UserSettingUpsert) Validate() error {
|
|||||||
if invalid {
|
if invalid {
|
||||||
return fmt.Errorf("invalid user setting mobile editor style value")
|
return fmt.Errorf("invalid user setting mobile editor style value")
|
||||||
}
|
}
|
||||||
|
} else if upsert.Key == UserSettingMemoSortOptionKey {
|
||||||
|
memoSortOption := "created_ts"
|
||||||
|
err := json.Unmarshal([]byte(upsert.Value), &memoSortOption)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to unmarshal user setting memo sort option")
|
||||||
|
}
|
||||||
|
|
||||||
|
invalid := true
|
||||||
|
for _, value := range UserSettingSortTimeOptionKeyValue {
|
||||||
|
if memoSortOption == value {
|
||||||
|
invalid = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if invalid {
|
||||||
|
return fmt.Errorf("invalid user setting memo sort option value")
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("invalid user setting key")
|
return fmt.Errorf("invalid user setting key")
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import { useNavigate } from "react-router-dom";
|
|||||||
import "dayjs/locale/zh";
|
import "dayjs/locale/zh";
|
||||||
import { UNKNOWN_ID } from "../helpers/consts";
|
import { UNKNOWN_ID } from "../helpers/consts";
|
||||||
import { editorStateService, locationService, memoService, userService } from "../services";
|
import { editorStateService, locationService, memoService, userService } from "../services";
|
||||||
|
import { useAppSelector } from "../store";
|
||||||
import Icon from "./Icon";
|
import Icon from "./Icon";
|
||||||
import toastHelper from "./Toast";
|
import toastHelper from "./Toast";
|
||||||
import MemoContent from "./MemoContent";
|
import MemoContent from "./MemoContent";
|
||||||
@ -22,19 +23,21 @@ interface Props {
|
|||||||
memo: Memo;
|
memo: Memo;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getFormatedMemoCreatedAtStr = (createdTs: number, locale = "en"): string => {
|
export const getFormatedMemoTimeStr = (time: number, locale = "en"): string => {
|
||||||
if (Date.now() - createdTs < 1000 * 60 * 60 * 24) {
|
if (Date.now() - time < 1000 * 60 * 60 * 24) {
|
||||||
return dayjs(createdTs).locale(locale).fromNow();
|
return dayjs(time).locale(locale).fromNow();
|
||||||
} else {
|
} else {
|
||||||
return dayjs(createdTs).locale(locale).format("YYYY/MM/DD HH:mm:ss");
|
return dayjs(time).locale(locale).format("YYYY/MM/DD HH:mm:ss");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const Memo: React.FC<Props> = (props: Props) => {
|
const Memo: React.FC<Props> = (props: Props) => {
|
||||||
const memo = props.memo;
|
const memo = props.memo;
|
||||||
|
const user = useAppSelector((state) => state.user.user);
|
||||||
const { t, i18n } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [createdAtStr, setCreatedAtStr] = useState<string>(getFormatedMemoCreatedAtStr(memo.createdTs, i18n.language));
|
const [createdAtStr, setCreatedAtStr] = useState<string>(getFormatedMemoTimeStr(memo.createdTs, i18n.language));
|
||||||
|
const [updatedAtStr, setUpdatedAtStr] = useState<string>(getFormatedMemoTimeStr(memo.updatedTs, i18n.language));
|
||||||
const memoContainerRef = useRef<HTMLDivElement>(null);
|
const memoContainerRef = useRef<HTMLDivElement>(null);
|
||||||
const isVisitorMode = userService.isVisitorMode();
|
const isVisitorMode = userService.isVisitorMode();
|
||||||
|
|
||||||
@ -42,7 +45,8 @@ const Memo: React.FC<Props> = (props: Props) => {
|
|||||||
let intervalFlag: any = -1;
|
let intervalFlag: any = -1;
|
||||||
if (Date.now() - memo.createdTs < 1000 * 60 * 60 * 24) {
|
if (Date.now() - memo.createdTs < 1000 * 60 * 60 * 24) {
|
||||||
intervalFlag = setInterval(() => {
|
intervalFlag = setInterval(() => {
|
||||||
setCreatedAtStr(getFormatedMemoCreatedAtStr(memo.createdTs, i18n.language));
|
setCreatedAtStr(getFormatedMemoTimeStr(memo.createdTs, i18n.language));
|
||||||
|
setUpdatedAtStr(getFormatedMemoTimeStr(memo.updatedTs, i18n.language));
|
||||||
}, 1000 * 1);
|
}, 1000 * 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,12 +186,13 @@ const Memo: React.FC<Props> = (props: Props) => {
|
|||||||
editorStateService.setEditMemoWithId(memo.id);
|
editorStateService.setEditMemoWithId(memo.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const timeStr = user?.setting.memoSortOption === "created_ts" ? createdAtStr : `${t("common.update-on")} ${updatedAtStr}`;
|
||||||
return (
|
return (
|
||||||
<div className={`memo-wrapper ${"memos-" + memo.id} ${memo.pinned ? "pinned" : ""}`} ref={memoContainerRef}>
|
<div className={`memo-wrapper ${"memos-" + memo.id} ${memo.pinned ? "pinned" : ""}`} ref={memoContainerRef}>
|
||||||
<div className="memo-top-wrapper">
|
<div className="memo-top-wrapper">
|
||||||
<div className="status-text-container">
|
<div className="status-text-container">
|
||||||
<span className="time-text" onClick={handleShowMemoStoryDialog}>
|
<span className="time-text" onClick={handleShowMemoStoryDialog}>
|
||||||
{createdAtStr}
|
{timeStr}
|
||||||
</span>
|
</span>
|
||||||
{memo.visibility !== "PRIVATE" && !isVisitorMode && (
|
{memo.visibility !== "PRIVATE" && !isVisitorMode && (
|
||||||
<span className={`status-text ${memo.visibility.toLocaleLowerCase()}`}>{memo.visibility}</span>
|
<span className={`status-text ${memo.visibility.toLocaleLowerCase()}`}>{memo.visibility}</span>
|
||||||
|
@ -174,6 +174,7 @@ const MemoEditor: React.FC = () => {
|
|||||||
});
|
});
|
||||||
locationService.clearQuery();
|
locationService.clearQuery();
|
||||||
}
|
}
|
||||||
|
locationService.setUpdatedFlag();
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
toastHelper.error(error.response.data.message);
|
toastHelper.error(error.response.data.message);
|
||||||
|
@ -12,6 +12,8 @@ import "../less/memo-list.less";
|
|||||||
const MemoList = () => {
|
const MemoList = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const query = useAppSelector((state) => state.location.query);
|
const query = useAppSelector((state) => state.location.query);
|
||||||
|
const updatedTime = useAppSelector((state) => state.location.updatedTime);
|
||||||
|
const user = useAppSelector((state) => state.user.user);
|
||||||
const { memos, isFetching } = useAppSelector((state) => state.memo);
|
const { memos, isFetching } = useAppSelector((state) => state.memo);
|
||||||
|
|
||||||
const { tag: tagQuery, duration, type: memoType, text: textQuery, shortcutId } = query ?? {};
|
const { tag: tagQuery, duration, type: memoType, text: textQuery, shortcutId } = query ?? {};
|
||||||
@ -70,6 +72,11 @@ const MemoList = () => {
|
|||||||
|
|
||||||
const pinnedMemos = shownMemos.filter((m) => m.pinned);
|
const pinnedMemos = shownMemos.filter((m) => m.pinned);
|
||||||
const unpinnedMemos = shownMemos.filter((m) => !m.pinned);
|
const unpinnedMemos = shownMemos.filter((m) => !m.pinned);
|
||||||
|
const memoSorting = (m1: Memo, m2: Memo) => {
|
||||||
|
return user?.setting.memoSortOption === "created_ts" ? m2.createdTs - m1.createdTs : m2.updatedTs - m1.updatedTs;
|
||||||
|
};
|
||||||
|
pinnedMemos.sort(memoSorting);
|
||||||
|
unpinnedMemos.sort(memoSorting);
|
||||||
const sortedMemos = pinnedMemos.concat(unpinnedMemos).filter((m) => m.rowStatus === "NORMAL");
|
const sortedMemos = pinnedMemos.concat(unpinnedMemos).filter((m) => m.rowStatus === "NORMAL");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -82,14 +89,14 @@ const MemoList = () => {
|
|||||||
console.error(error);
|
console.error(error);
|
||||||
toastHelper.error(error.response.data.message);
|
toastHelper.error(error.response.data.message);
|
||||||
});
|
});
|
||||||
}, []);
|
}, [updatedTime]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const pageWrapper = document.body.querySelector(".page-wrapper");
|
const pageWrapper = document.body.querySelector(".page-wrapper");
|
||||||
if (pageWrapper) {
|
if (pageWrapper) {
|
||||||
pageWrapper.scrollTo(0, 0);
|
pageWrapper.scrollTo(0, 0);
|
||||||
}
|
}
|
||||||
}, [query]);
|
}, [query, updatedTime]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="memo-list-container">
|
<div className="memo-list-container">
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { globalService, userService } from "../../services";
|
import { globalService, userService } from "../../services";
|
||||||
import { useAppSelector } from "../../store";
|
import { useAppSelector } from "../../store";
|
||||||
import { VISIBILITY_SELECTOR_ITEMS } from "../../helpers/consts";
|
import { VISIBILITY_SELECTOR_ITEMS, MEMO_SORT_OPTION_SELECTOR_ITEMS } from "../../helpers/consts";
|
||||||
import Selector from "../common/Selector";
|
import Selector from "../common/Selector";
|
||||||
import "../../less/settings/preferences-section.less";
|
import "../../less/settings/preferences-section.less";
|
||||||
|
|
||||||
@ -52,6 +52,13 @@ const PreferencesSection = () => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const memoSortOptionSelectorItems = MEMO_SORT_OPTION_SELECTOR_ITEMS.map((item) => {
|
||||||
|
return {
|
||||||
|
value: item.value,
|
||||||
|
text: t(`setting.preference-section.${item.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);
|
||||||
@ -69,6 +76,10 @@ const PreferencesSection = () => {
|
|||||||
await userService.upsertUserSetting("mobileEditorStyle", value);
|
await userService.upsertUserSetting("mobileEditorStyle", value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleMemoSortOptionChanged = async (value: string) => {
|
||||||
|
await userService.upsertUserSetting("memoSortOption", 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>
|
||||||
@ -104,6 +115,15 @@ const PreferencesSection = () => {
|
|||||||
handleValueChanged={handleMobileEditorStyleChanged}
|
handleValueChanged={handleMobileEditorStyleChanged}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
<label className="form-label selector">
|
||||||
|
<span className="normal-text">{t("setting.preference-section.default-memo-sort-option")}</span>
|
||||||
|
<Selector
|
||||||
|
className="ml-2 w-32"
|
||||||
|
value={setting.memoSortOption}
|
||||||
|
dataSource={memoSortOptionSelectorItems}
|
||||||
|
handleValueChanged={handleMemoSortOptionChanged}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -13,4 +13,9 @@ export const VISIBILITY_SELECTOR_ITEMS = [
|
|||||||
{ text: "PRIVATE", value: "PRIVATE" },
|
{ text: "PRIVATE", value: "PRIVATE" },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const MEMO_SORT_OPTION_SELECTOR_ITEMS = [
|
||||||
|
{ text: "created_ts", value: "created_ts" },
|
||||||
|
{ text: "created_ts", value: "updated_ts" },
|
||||||
|
];
|
||||||
|
|
||||||
export const TAB_SPACE_WIDTH = 2;
|
export const TAB_SPACE_WIDTH = 2;
|
||||||
|
@ -37,7 +37,8 @@
|
|||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"yourself": "Yourself",
|
"yourself": "Yourself",
|
||||||
"archived-at": "Archived at",
|
"archived-at": "Archived at",
|
||||||
"changed": "changed"
|
"changed": "changed",
|
||||||
|
"update-on": "Update on"
|
||||||
},
|
},
|
||||||
"slogan": "An open source, self-hosted knowledge base that works with a SQLite db file.",
|
"slogan": "An open source, self-hosted knowledge base that works with a SQLite db file.",
|
||||||
"auth": {
|
"auth": {
|
||||||
@ -128,7 +129,10 @@
|
|||||||
"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"
|
"mobile-editor-style": "Mobile editor style",
|
||||||
|
"default-memo-sort-option": "Sort by created time/updated time",
|
||||||
|
"created_ts": "Created Time",
|
||||||
|
"updated_ts": "Updated Time"
|
||||||
},
|
},
|
||||||
"member-section": {
|
"member-section": {
|
||||||
"create-a-member": "Create a member"
|
"create-a-member": "Create a member"
|
||||||
|
@ -37,7 +37,8 @@
|
|||||||
"tags": "Thẻ",
|
"tags": "Thẻ",
|
||||||
"yourself": "Chính bạn",
|
"yourself": "Chính bạn",
|
||||||
"archived-at": "Lưu trữ lúc",
|
"archived-at": "Lưu trữ lúc",
|
||||||
"changed": "đã thay đổi"
|
"changed": "đã thay đổi",
|
||||||
|
"update-on": "Cập nhật"
|
||||||
},
|
},
|
||||||
"slogan": "Một mã nguồn mở, tự bạn lưu lại mọi thứ bạn biết dựa trên SQLite db.",
|
"slogan": "Một mã nguồn mở, tự bạn lưu lại mọi thứ bạn biết dựa trên SQLite db.",
|
||||||
"auth": {
|
"auth": {
|
||||||
@ -128,7 +129,10 @@
|
|||||||
"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"
|
"mobile-editor-style": "Vị trí editor trên mobile",
|
||||||
|
"default-memo-sort-option": "Sắp xếp theo thời gian đã tạo",
|
||||||
|
"created_ts": "tạo thời gian",
|
||||||
|
"updated_ts": "Thời gian cập nhật"
|
||||||
},
|
},
|
||||||
"member-section": {
|
"member-section": {
|
||||||
"create-a-member": "Tạo thành viên"
|
"create-a-member": "Tạo thành viên"
|
||||||
|
@ -37,7 +37,8 @@
|
|||||||
"tags": "全部标签",
|
"tags": "全部标签",
|
||||||
"yourself": "你自己",
|
"yourself": "你自己",
|
||||||
"archived-at": "归档于",
|
"archived-at": "归档于",
|
||||||
"changed": "已更改"
|
"changed": "已更改",
|
||||||
|
"update-on": "更新于"
|
||||||
},
|
},
|
||||||
"slogan": "一个开源的、支持私有化部署的碎片化知识卡片管理工具。",
|
"slogan": "一个开源的、支持私有化部署的碎片化知识卡片管理工具。",
|
||||||
"auth": {
|
"auth": {
|
||||||
@ -128,7 +129,10 @@
|
|||||||
"preference-section": {
|
"preference-section": {
|
||||||
"default-memo-visibility": "默认 Memo 可见性",
|
"default-memo-visibility": "默认 Memo 可见性",
|
||||||
"editor-font-style": "编辑器字体样式",
|
"editor-font-style": "编辑器字体样式",
|
||||||
"mobile-editor-style": "Mobile editor style"
|
"mobile-editor-style": "Mobile editor style",
|
||||||
|
"default-memo-sort-option": "按创建时间/更新时间排序",
|
||||||
|
"created_ts": "创建时间",
|
||||||
|
"updated_ts": "更新时间"
|
||||||
},
|
},
|
||||||
"member-section": {
|
"member-section": {
|
||||||
"create-a-member": "创建成员"
|
"create-a-member": "创建成员"
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { stringify } from "qs";
|
import { stringify } from "qs";
|
||||||
import store from "../store";
|
import store from "../store";
|
||||||
import { setQuery, setPathname, Query, updateStateWithLocation } from "../store/modules/location";
|
import { setQuery, setPathname, setUpdatedTime, Query, updateStateWithLocation } from "../store/modules/location";
|
||||||
|
import { getTimeStampByDate } from "../helpers/utils";
|
||||||
|
|
||||||
const updateLocationUrl = (method: "replace" | "push" = "replace") => {
|
const updateLocationUrl = (method: "replace" | "push" = "replace") => {
|
||||||
const { query, pathname, hash } = store.getState().location;
|
const { query, pathname, hash } = store.getState().location;
|
||||||
@ -112,6 +113,10 @@ const locationService = {
|
|||||||
);
|
);
|
||||||
updateLocationUrl();
|
updateLocationUrl();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setUpdatedFlag: () => {
|
||||||
|
store.dispatch(setUpdatedTime(getTimeStampByDate(new Date()).toString()));
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default locationService;
|
export default locationService;
|
||||||
|
@ -8,6 +8,7 @@ const defauleSetting: Setting = {
|
|||||||
memoVisibility: "PRIVATE",
|
memoVisibility: "PRIVATE",
|
||||||
editorFontStyle: "normal",
|
editorFontStyle: "normal",
|
||||||
mobileEditorStyle: "normal",
|
mobileEditorStyle: "normal",
|
||||||
|
memoSortOption: "created_ts",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const convertResponseModelUser = (user: User): User => {
|
export const convertResponseModelUser = (user: User): User => {
|
||||||
|
@ -17,6 +17,7 @@ interface State {
|
|||||||
pathname: string;
|
pathname: string;
|
||||||
hash: string;
|
hash: string;
|
||||||
query: Query;
|
query: Query;
|
||||||
|
updatedTime: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getValidPathname = (pathname: string): string => {
|
const getValidPathname = (pathname: string): string => {
|
||||||
@ -35,6 +36,7 @@ const getStateFromLocation = () => {
|
|||||||
pathname: getValidPathname(pathname),
|
pathname: getValidPathname(pathname),
|
||||||
hash: hash,
|
hash: hash,
|
||||||
query: {},
|
query: {},
|
||||||
|
updatedTime: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
if (search !== "") {
|
if (search !== "") {
|
||||||
@ -86,9 +88,15 @@ const locationSlice = createSlice({
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
setUpdatedTime: (state, action: PayloadAction<string>) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
updatedTime: action.payload,
|
||||||
|
};
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const { setPathname, setQuery, updateStateWithLocation } = locationSlice.actions;
|
export const { setPathname, setQuery, setUpdatedTime, updateStateWithLocation } = locationSlice.actions;
|
||||||
|
|
||||||
export default locationSlice.reducer;
|
export default locationSlice.reducer;
|
||||||
|
1
web/src/types/modules/setting.d.ts
vendored
1
web/src/types/modules/setting.d.ts
vendored
@ -3,6 +3,7 @@ interface Setting {
|
|||||||
memoVisibility: Visibility;
|
memoVisibility: Visibility;
|
||||||
editorFontStyle: "normal" | "mono";
|
editorFontStyle: "normal" | "mono";
|
||||||
mobileEditorStyle: "normal" | "float";
|
mobileEditorStyle: "normal" | "float";
|
||||||
|
memoSortOption: "created_ts" | "updated_ts";
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UserLocaleSetting {
|
interface UserLocaleSetting {
|
||||||
|
Reference in New Issue
Block a user