big changes; we have a good TS config now

This commit is contained in:
Moritz Jung 2025-01-14 22:30:28 +01:00
parent cbbaf54b33
commit 4497991344
54 changed files with 750 additions and 671 deletions

View file

@ -1,16 +1,17 @@
import { MediaDbPluginSettings } from '../settings/Settings';
import { MediaType } from './MediaType';
import { MediaTypeModel } from '../models/MediaTypeModel';
import { replaceTags } from './Utils';
import { App, TAbstractFile, TFile, TFolder } from 'obsidian';
import { MovieModel } from '../models/MovieModel';
import { SeriesModel } from '../models/SeriesModel';
import { MangaModel } from '../models/MangaModel';
import { GameModel } from '../models/GameModel';
import { WikiModel } from '../models/WikiModel';
import { MusicReleaseModel } from '../models/MusicReleaseModel';
import type { App, TAbstractFile, TFile } from 'obsidian';
import { TFolder } from 'obsidian';
import { BoardGameModel } from '../models/BoardGameModel';
import { BookModel } from '../models/BookModel';
import { GameModel } from '../models/GameModel';
import { MangaModel } from '../models/MangaModel';
import type { MediaTypeModel } from '../models/MediaTypeModel';
import { MovieModel } from '../models/MovieModel';
import { MusicReleaseModel } from '../models/MusicReleaseModel';
import { SeriesModel } from '../models/SeriesModel';
import type { MediaDbPluginSettings } from '../settings/Settings';
import { MediaType } from './MediaType';
import { replaceTags } from './Utils';
import { WikiModel } from '../models/WikiModel';
export const MEDIA_TYPES: MediaType[] = [
MediaType.Movie,
@ -28,7 +29,11 @@ export class MediaTypeManager {
mediaTemplateMap: Map<MediaType, string>;
mediaFolderMap: Map<MediaType, string>;
constructor() {}
constructor() {
this.mediaFileNameTemplateMap = new Map<MediaType, string>();
this.mediaTemplateMap = new Map<MediaType, string>();
this.mediaFolderMap = new Map<MediaType, string>();
}
updateTemplates(settings: MediaDbPluginSettings): void {
this.mediaFileNameTemplateMap = new Map<MediaType, string>();
@ -66,7 +71,7 @@ export class MediaTypeManager {
getFileName(mediaTypeModel: MediaTypeModel): string {
// Ignore undefined tags since some search APIs do not return all properties in the model and produce clean file names even if errors occur
return replaceTags(this.mediaFileNameTemplateMap.get(mediaTypeModel.getMediaType()), mediaTypeModel, true);
return replaceTags(this.mediaFileNameTemplateMap.get(mediaTypeModel.getMediaType())!, mediaTypeModel, true);
}
async getTemplate(mediaTypeModel: MediaTypeModel, app: App): Promise<string> {
@ -76,7 +81,7 @@ export class MediaTypeManager {
return '';
}
let templateFile = app.vault.getAbstractFileByPath(templateFilePath);
let templateFile = app.vault.getAbstractFileByPath(templateFilePath) ?? undefined;
// WARNING: This was previously selected by filename, but that could lead to collisions and unwanted effects.
// This now falls back to the previous method if no file is found
@ -107,7 +112,7 @@ export class MediaTypeManager {
if (!(await app.vault.adapter.exists(folderPath))) {
await app.vault.createFolder(folderPath);
}
const folder: TAbstractFile = app.vault.getAbstractFileByPath(folderPath);
const folder = app.vault.getAbstractFileByPath(folderPath);
if (!(folder instanceof TFolder)) {
throw Error(`Expected ${folder} to be instance of TFolder`);
@ -141,6 +146,6 @@ export class MediaTypeManager {
return new BookModel(obj);
}
return undefined;
throw new Error(`Unknown media type: ${mediaType}`);
}
}

View file

@ -1,12 +1,12 @@
import { Notice } from 'obsidian';
import { MediaDbPreviewModal } from 'src/modals/MediaDbPreviewModal';
import type MediaDbPlugin from '../main';
import { MediaDbAdvancedSearchModal } from '../modals/MediaDbAdvancedSearchModal';
import { MediaDbIdSearchModal } from '../modals/MediaDbIdSearchModal';
import { MediaTypeModel } from '../models/MediaTypeModel';
import { MediaDbSearchResultModal } from '../modals/MediaDbSearchResultModal';
import { Notice } from 'obsidian';
import MediaDbPlugin from '../main';
import { MediaDbPreviewModal } from 'src/modals/MediaDbPreviewModal';
import { MediaDbSearchModal } from '../modals/MediaDbSearchModal';
import { MediaType } from './MediaType';
import { MediaDbSearchResultModal } from '../modals/MediaDbSearchResultModal';
import type { MediaTypeModel } from '../models/MediaTypeModel';
import type { MediaType } from './MediaType';
export enum ModalResultCode {
SUCCESS = 'SUCCESS',
@ -15,60 +15,59 @@ export enum ModalResultCode {
ERROR = 'ERROR',
}
type ModalResult<T> =
| {
code: ModalResultCode.CLOSE;
}
| {
code: ModalResultCode.ERROR;
error: Error;
}
| {
code: ModalResultCode.SUCCESS;
data: T;
};
type SkippableModalResult<T> =
| ModalResult<T>
| {
code: ModalResultCode.SKIP;
};
/**
* Object containing the data {@link ModalHelper.createSearchModal} returns.
* On {@link ModalResultCode.SUCCESS} this contains {@link SearchModalData}.
* On {@link ModalResultCode.ERROR} this contains a reference to that error.
*/
export interface SearchModalResult {
code: ModalResultCode.SUCCESS | ModalResultCode.CLOSE | ModalResultCode.ERROR;
data?: SearchModalData;
error?: Error;
}
export type SearchModalResult = ModalResult<SearchModalData>;
/**
* Object containing the data {@link ModalHelper.createAdvancedSearchModal} returns.
* On {@link ModalResultCode.SUCCESS} this contains {@link AdvancedSearchModalData}.
* On {@link ModalResultCode.ERROR} this contains a reference to that error.
*/
export interface AdvancedSearchModalResult {
code: ModalResultCode.SUCCESS | ModalResultCode.CLOSE | ModalResultCode.ERROR;
data?: AdvancedSearchModalData;
error?: Error;
}
export type AdvancedSearchModalResult = ModalResult<AdvancedSearchModalData>;
/**
* Object containing the data {@link ModalHelper.createIdSearchModal} returns.
* On {@link ModalResultCode.SUCCESS} this contains {@link IdSearchModalData}.
* On {@link ModalResultCode.ERROR} this contains a reference to that error.
*/
export interface IdSearchModalResult {
code: ModalResultCode.SUCCESS | ModalResultCode.CLOSE | ModalResultCode.ERROR;
data?: IdSearchModalData;
error?: Error;
}
export type IdSearchModalResult = ModalResult<IdSearchModalData>;
/**
* Object containing the data {@link ModalHelper.createSelectModal} returns.
* On {@link ModalResultCode.SUCCESS} this contains {@link SelectModalData}.
* On {@link ModalResultCode.ERROR} this contains a reference to that error.
*/
export interface SelectModalResult {
code: ModalResultCode.SUCCESS | ModalResultCode.CLOSE | ModalResultCode.SKIP | ModalResultCode.ERROR;
data?: SelectModalData;
error?: Error;
}
export type SelectModalResult = SkippableModalResult<SelectModalData>;
/**
* Object containing the data {@link ModalHelper.createPreviewModal} returns.
* On {@link ModalResultCode.SUCCESS} this contains {@link PreviewModalData}.
* On {@link ModalResultCode.ERROR} this contains a reference to that error.
*/
export interface PreviewModalResult {
code: ModalResultCode.SUCCESS | ModalResultCode.CLOSE | ModalResultCode.ERROR;
data?: PreviewModalData;
error?: Error;
}
export type PreviewModalResult = ModalResult<PreviewModalData>;
/**
* The data the search modal returns.
@ -248,7 +247,10 @@ export class ModalHelper {
* @param submitCallback the callback that gets executed after the modal has been submitted, but after it has been closed
* @returns the user input or nothing and a reference to the modal.
*/
async openSearchModal(searchModalOptions: SearchModalOptions, submitCallback: (searchModalData: SearchModalData) => Promise<MediaTypeModel[]>): Promise<MediaTypeModel[]> {
async openSearchModal(
searchModalOptions: SearchModalOptions,
submitCallback: (searchModalData: SearchModalData) => Promise<MediaTypeModel[]>,
): Promise<MediaTypeModel[] | undefined> {
const { searchModalResult, searchModal } = await this.createSearchModal(searchModalOptions);
console.debug(`MDB | searchModal closed with code ${searchModalResult.code}`);
@ -271,7 +273,7 @@ export class ModalHelper {
return callbackRes;
} catch (e) {
console.warn(e);
new Notice(e.toString());
new Notice(`${e}`);
searchModal.close();
return undefined;
}
@ -314,7 +316,7 @@ export class ModalHelper {
async openAdvancedSearchModal(
advancedSearchModalOptions: AdvancedSearchModalOptions,
submitCallback: (advancedSearchModalData: AdvancedSearchModalData) => Promise<MediaTypeModel[]>,
): Promise<MediaTypeModel[]> {
): Promise<MediaTypeModel[] | undefined> {
const { advancedSearchModalResult, advancedSearchModal } = await this.createAdvancedSearchModal(advancedSearchModalOptions);
console.debug(`MDB | advencedSearchModal closed with code ${advancedSearchModalResult.code}`);
@ -337,7 +339,7 @@ export class ModalHelper {
return callbackRes;
} catch (e) {
console.warn(e);
new Notice(e.toString());
new Notice(`${e}`);
advancedSearchModal.close();
return undefined;
}
@ -377,8 +379,8 @@ export class ModalHelper {
*/
async openIdSearchModal(
idSearchModalOptions: IdSearchModalOptions,
submitCallback: (idSearchModalData: IdSearchModalData) => Promise<MediaTypeModel>,
): Promise<MediaTypeModel> {
submitCallback: (idSearchModalData: IdSearchModalData) => Promise<MediaTypeModel | undefined>,
): Promise<MediaTypeModel | undefined> {
const { idSearchModalResult, idSearchModal } = await this.createIdSearchModal(idSearchModalOptions);
console.debug(`MDB | idSearchModal closed with code ${idSearchModalResult.code}`);
@ -396,12 +398,12 @@ export class ModalHelper {
}
try {
const callbackRes: MediaTypeModel = await submitCallback(idSearchModalResult.data);
const callbackRes = await submitCallback(idSearchModalResult.data);
idSearchModal.close();
return callbackRes;
} catch (e) {
console.warn(e);
new Notice(e.toString());
new Notice(`${e}`);
idSearchModal.close();
return undefined;
}
@ -440,7 +442,10 @@ export class ModalHelper {
* @param submitCallback the callback that gets executed after the modal has been submitted, but before it has been closed
* @returns the user input or nothing and a reference to the modal.
*/
async openSelectModal(selectModalOptions: SelectModalOptions, submitCallback: (selectModalData: SelectModalData) => Promise<MediaTypeModel[]>): Promise<MediaTypeModel[]> {
async openSelectModal(
selectModalOptions: SelectModalOptions,
submitCallback: (selectModalData: SelectModalData) => Promise<MediaTypeModel[]>,
): Promise<MediaTypeModel[] | undefined> {
const { selectModalResult, selectModal } = await this.createSelectModal(selectModalOptions);
console.debug(`MDB | selectModal closed with code ${selectModalResult.code}`);
@ -468,7 +473,7 @@ export class ModalHelper {
return callbackRes;
} catch (e) {
console.warn(e);
new Notice(e.toString());
new Notice(`${e}`);
selectModal.close();
return;
}
@ -500,12 +505,12 @@ export class ModalHelper {
console.warn(previewModalResult.error);
new Notice(previewModalResult.error.toString());
previewModal.close();
return undefined;
return true;
}
if (previewModalResult.code === ModalResultCode.CLOSE) {
// modal is already being closed
return undefined;
return true;
}
try {
@ -514,9 +519,9 @@ export class ModalHelper {
return callbackRes;
} catch (e) {
console.warn(e);
new Notice(e.toString());
new Notice(`${e}`);
previewModal.close();
return;
return true;
}
}
}

View file

@ -1,5 +1,5 @@
import { MediaTypeModel } from '../models/MediaTypeModel';
import { TFile, TFolder, App } from 'obsidian';
import type { TFile, TFolder, App } from 'obsidian';
import type { MediaTypeModel } from '../models/MediaTypeModel';
export const pluginName: string = 'obsidian-media-db-plugin';
export const contactEmail: string = 'm.projects.code@gmail.com';
@ -82,7 +82,7 @@ function replaceTag(match: string, mediaTypeModel: MediaTypeModel, ignoreUndefin
return '{{ INVALID TEMPLATE TAG }}';
}
function traverseMetaData(path: Array<string>, mediaTypeModel: MediaTypeModel): any {
function traverseMetaData(path: string[], mediaTypeModel: MediaTypeModel): any {
let o: any = mediaTypeModel;
for (const part of path) {
@ -226,7 +226,11 @@ export function hasTemplaterPlugin(app: App): boolean {
export async function useTemplaterPluginInFile(app: App, file: TFile): Promise<void> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const templater = (app as any).plugins.plugins['templater-obsidian'];
if (templater && !templater?.settings['trigger_on_file_creation']) {
if (templater && !templater?.settings.trigger_on_file_creation) {
await templater.templater.overwrite_file_commands(file);
}
}
export type ModelToData<T> = {
[K in keyof T as T[K] extends Function ? never : K]?: T[K];
};