mirror of https://github.com/usememos/memos
refactor: memo filter store
parent
f12d7ae8bc
commit
c23aebd648
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@
|
|||||||
export * from "./memoFilter";
|
|
@ -1,64 +0,0 @@
|
|||||||
import { uniqBy } from "lodash-es";
|
|
||||||
import { create } from "zustand";
|
|
||||||
import { combine } from "zustand/middleware";
|
|
||||||
|
|
||||||
export type FilterFactor =
|
|
||||||
| "tagSearch"
|
|
||||||
| "visibility"
|
|
||||||
| "contentSearch"
|
|
||||||
| "displayTime"
|
|
||||||
| "pinned"
|
|
||||||
| "property.hasLink"
|
|
||||||
| "property.hasTaskList"
|
|
||||||
| "property.hasCode";
|
|
||||||
|
|
||||||
export interface MemoFilter {
|
|
||||||
factor: FilterFactor;
|
|
||||||
value: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getMemoFilterKey = (filter: MemoFilter) => `${filter.factor}:${filter.value}`;
|
|
||||||
|
|
||||||
export const parseFilterQuery = (query: string | null): MemoFilter[] => {
|
|
||||||
if (!query) return [];
|
|
||||||
try {
|
|
||||||
return query.split(",").map((filterStr) => {
|
|
||||||
const [factor, value] = filterStr.split(":");
|
|
||||||
return {
|
|
||||||
factor: factor as FilterFactor,
|
|
||||||
value: decodeURIComponent(value),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Failed to parse filter query:", error);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const stringifyFilters = (filters: MemoFilter[]): string => {
|
|
||||||
return filters.map((filter) => `${filter.factor}:${encodeURIComponent(filter.value)}`).join(",");
|
|
||||||
};
|
|
||||||
|
|
||||||
interface State {
|
|
||||||
filters: MemoFilter[];
|
|
||||||
// The id of selected shortcut.
|
|
||||||
shortcut?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const getInitialState = (): State => {
|
|
||||||
const searchParams = new URLSearchParams(window.location.search);
|
|
||||||
return {
|
|
||||||
filters: parseFilterQuery(searchParams.get("filter")),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useMemoFilterStore = create(
|
|
||||||
combine(getInitialState(), (set, get) => ({
|
|
||||||
setState: (state: State) => set(state),
|
|
||||||
getState: () => get(),
|
|
||||||
getFiltersByFactor: (factor: FilterFactor) => get().filters.filter((f) => f.factor === factor),
|
|
||||||
addFilter: (filter: MemoFilter) => set((state) => ({ filters: uniqBy([...state.filters, filter], getMemoFilterKey) })),
|
|
||||||
removeFilter: (filterFn: (f: MemoFilter) => boolean) => set((state) => ({ filters: state.filters.filter((f) => !filterFn(f)) })),
|
|
||||||
setShortcut: (shortcut?: string) => set({ shortcut }),
|
|
||||||
})),
|
|
||||||
);
|
|
@ -1,7 +1,8 @@
|
|||||||
import memoStore from "./memo";
|
import memoStore from "./memo";
|
||||||
|
import memoFilterStore from "./memoFilter";
|
||||||
import resourceStore from "./resource";
|
import resourceStore from "./resource";
|
||||||
import userStore from "./user";
|
import userStore from "./user";
|
||||||
import viewStore from "./view";
|
import viewStore from "./view";
|
||||||
import workspaceStore from "./workspace";
|
import workspaceStore from "./workspace";
|
||||||
|
|
||||||
export { memoStore, resourceStore, workspaceStore, userStore, viewStore };
|
export { memoFilterStore, memoStore, resourceStore, workspaceStore, userStore, viewStore };
|
||||||
|
@ -0,0 +1,93 @@
|
|||||||
|
import { uniqBy } from "lodash-es";
|
||||||
|
import { makeAutoObservable } from "mobx";
|
||||||
|
|
||||||
|
export type FilterFactor =
|
||||||
|
| "tagSearch"
|
||||||
|
| "visibility"
|
||||||
|
| "contentSearch"
|
||||||
|
| "displayTime"
|
||||||
|
| "pinned"
|
||||||
|
| "property.hasLink"
|
||||||
|
| "property.hasTaskList"
|
||||||
|
| "property.hasCode";
|
||||||
|
|
||||||
|
export interface MemoFilter {
|
||||||
|
factor: FilterFactor;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getMemoFilterKey = (filter: MemoFilter) => `${filter.factor}:${filter.value}`;
|
||||||
|
|
||||||
|
export const parseFilterQuery = (query: string | null): MemoFilter[] => {
|
||||||
|
if (!query) return [];
|
||||||
|
try {
|
||||||
|
return query.split(",").map((filterStr) => {
|
||||||
|
const [factor, value] = filterStr.split(":");
|
||||||
|
return {
|
||||||
|
factor: factor as FilterFactor,
|
||||||
|
value: decodeURIComponent(value),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to parse filter query:", error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const stringifyFilters = (filters: MemoFilter[]): string => {
|
||||||
|
return filters.map((filter) => `${filter.factor}:${encodeURIComponent(filter.value)}`).join(",");
|
||||||
|
};
|
||||||
|
|
||||||
|
class MemoFilterState {
|
||||||
|
filters: MemoFilter[] = [];
|
||||||
|
shortcut?: string = undefined;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
makeAutoObservable(this);
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
const searchParams = new URLSearchParams(window.location.search);
|
||||||
|
this.filters = parseFilterQuery(searchParams.get("filter"));
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(state: Partial<MemoFilterState>) {
|
||||||
|
Object.assign(this, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
getFiltersByFactor(factor: FilterFactor) {
|
||||||
|
return this.filters.filter((f) => f.factor === factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
addFilter(filter: MemoFilter) {
|
||||||
|
this.filters = uniqBy([...this.filters, filter], getMemoFilterKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeFilter(filterFn: (f: MemoFilter) => boolean) {
|
||||||
|
this.filters = this.filters.filter((f) => !filterFn(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
setShortcut(shortcut?: string) {
|
||||||
|
this.shortcut = shortcut;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const memoFilterStore = (() => {
|
||||||
|
const state = new MemoFilterState();
|
||||||
|
|
||||||
|
return {
|
||||||
|
get filters() {
|
||||||
|
return state.filters;
|
||||||
|
},
|
||||||
|
get shortcut() {
|
||||||
|
return state.shortcut;
|
||||||
|
},
|
||||||
|
getFiltersByFactor: (factor: FilterFactor) => state.getFiltersByFactor(factor),
|
||||||
|
addFilter: (filter: MemoFilter) => state.addFilter(filter),
|
||||||
|
removeFilter: (filterFn: (f: MemoFilter) => boolean) => state.removeFilter(filterFn),
|
||||||
|
setShortcut: (shortcut?: string) => state.setShortcut(shortcut),
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
export default memoFilterStore;
|
Loading…
Reference in New Issue