generated from tpl/obsidian-sample-plugin
157 lines
3.5 KiB
TypeScript
157 lines
3.5 KiB
TypeScript
import { STATUS_READ } from "@src/const";
|
|
import type { CachedMetadata, TFile } from "obsidian";
|
|
import { getContext, setContext } from "svelte";
|
|
import type BookTrackerPlugin from "@src/main";
|
|
import {
|
|
createDateFilter,
|
|
type DateFilterStore,
|
|
type DateFilterStoreOptions,
|
|
} from "./date-filter.svelte";
|
|
import type { BookMetadata, ReadingState } from "@src/types";
|
|
|
|
export type FileMetadata = {
|
|
file: TFile;
|
|
book: BookMetadata;
|
|
};
|
|
|
|
export type FileProperty = {
|
|
file: TFile;
|
|
value: any;
|
|
};
|
|
|
|
export interface MetadataStore extends DateFilterStore {
|
|
get metadata(): FileMetadata[];
|
|
|
|
destroy(): void;
|
|
}
|
|
|
|
function getMetadata(
|
|
plugin: BookTrackerPlugin,
|
|
state: ReadingState | null
|
|
): FileMetadata[] {
|
|
const metadata: FileMetadata[] = [];
|
|
for (const file of plugin.app.vault.getMarkdownFiles()) {
|
|
const book = plugin.getBookMetadata(file);
|
|
if (!book) {
|
|
continue;
|
|
}
|
|
|
|
if (state && book.status !== state) {
|
|
continue;
|
|
}
|
|
|
|
metadata.push({ file, book });
|
|
}
|
|
return metadata;
|
|
}
|
|
|
|
interface MetadataStoreOptions extends DateFilterStoreOptions {
|
|
/**
|
|
* The reading state to filter by
|
|
*/
|
|
statusFilter?: ReadingState | null;
|
|
}
|
|
|
|
export function createMetadata(
|
|
plugin: BookTrackerPlugin,
|
|
{ statusFilter = STATUS_READ, ...dateFilterOpts }: MetadataStoreOptions = {}
|
|
): MetadataStore {
|
|
const initialMetadata = getMetadata(plugin, statusFilter);
|
|
let metadata: FileMetadata[] = $state(initialMetadata);
|
|
|
|
$effect(() => {
|
|
metadata = getMetadata(plugin, statusFilter);
|
|
});
|
|
|
|
function onChanged(file: TFile, _data: string, cache: CachedMetadata) {
|
|
metadata = metadata.map((f) => {
|
|
if (f.file.path === file.path) {
|
|
return {
|
|
file: f.file,
|
|
book: plugin.frontmatterToMetadata(cache.frontmatter),
|
|
};
|
|
}
|
|
return f;
|
|
});
|
|
}
|
|
plugin.registerEvent(plugin.app.metadataCache.on("changed", onChanged));
|
|
|
|
function onDeleted(file: TFile) {
|
|
metadata = metadata.filter((f) => f.file.path !== file.path);
|
|
}
|
|
plugin.registerEvent(plugin.app.metadataCache.on("deleted", onDeleted));
|
|
|
|
const dateFilter = createDateFilter(
|
|
() => metadata,
|
|
(f) => f.book.endDate,
|
|
dateFilterOpts
|
|
);
|
|
|
|
return {
|
|
get metadata() {
|
|
return statusFilter === STATUS_READ
|
|
? dateFilter.filteredData
|
|
: metadata;
|
|
},
|
|
get filterYear() {
|
|
return dateFilter.filterYear;
|
|
},
|
|
set filterYear(value) {
|
|
dateFilter.filterYear = value;
|
|
},
|
|
get filterMonth() {
|
|
return dateFilter.filterMonth;
|
|
},
|
|
set filterMonth(value) {
|
|
dateFilter.filterMonth = value;
|
|
},
|
|
get filterYears() {
|
|
return dateFilter.filterYears;
|
|
},
|
|
get filterMonths() {
|
|
return dateFilter.filterMonths;
|
|
},
|
|
destroy() {
|
|
plugin.app.metadataCache.off("changed", onChanged);
|
|
plugin.app.metadataCache.off("deleted", onDeleted);
|
|
},
|
|
};
|
|
}
|
|
|
|
const METADATA_KEY = Symbol("metadata");
|
|
|
|
export function setMetadataContext(state: MetadataStore) {
|
|
setContext(METADATA_KEY, state);
|
|
}
|
|
|
|
export function getMetadataContext(): MetadataStore {
|
|
return getContext(METADATA_KEY) as MetadataStore;
|
|
}
|
|
|
|
function notEmpty(value: any): boolean {
|
|
return value !== undefined && value !== null && value !== "" && value !== 0;
|
|
}
|
|
|
|
interface PropertyStore {
|
|
get propertyData(): FileProperty[];
|
|
}
|
|
|
|
export function createPropertyStore<T extends keyof BookMetadata>(
|
|
property: T,
|
|
filter: (value: BookMetadata[T]) => boolean = notEmpty
|
|
): PropertyStore {
|
|
const store = getMetadataContext();
|
|
|
|
const propertyData = $derived(
|
|
store.metadata
|
|
.map((f) => ({ file: f.file, value: f.book[property] }))
|
|
.filter((f) => (filter ? filter(f.value) : true))
|
|
);
|
|
|
|
return {
|
|
get propertyData() {
|
|
return propertyData;
|
|
},
|
|
};
|
|
}
|