diff --git a/src/api/APIManager.ts b/src/api/APIManager.ts new file mode 100644 index 0000000..f557ee7 --- /dev/null +++ b/src/api/APIManager.ts @@ -0,0 +1,30 @@ +import {APIModel} from './APIModel'; +import {APIRequestResult} from './APIRequestResult'; + +export class APIManager { + apis: APIModel[]; + + constructor() { + this.apis = []; + } + + async query(query: string, types: string[] = []): Promise { + console.log('MDB | api manager queried'); + + let res: APIRequestResult[] = []; + + for (const api of this.apis) { + if (types.length === 0 || api.hasTypeOverlap(types)) { + const apiRes = await api.getByTitle(query); + // console.log(apiRes); + res = res.concat(apiRes); + } + } + + return res; + } + + registerAPI(api: APIModel): void { + this.apis.push(api); + } +} diff --git a/src/api/APIModel.ts b/src/api/APIModel.ts new file mode 100644 index 0000000..91bc6e7 --- /dev/null +++ b/src/api/APIModel.ts @@ -0,0 +1,33 @@ +import {APIRequestResult} from './APIRequestResult'; + +export abstract class APIModel { + name: string; + types: string[]; + + /** + * This function should query the api and return a list of matches. The matches should be caped at 20. + * + * @param title the title to query for + */ + abstract getByTitle(title: string): Promise; + + /** + * This function should return the metadata corresponding to the api result. An implementation should check first, if the result is from this api. + * + * @param item + */ + abstract getMataDataFromResult(item: APIRequestResult): string; + + hasType(type: string): boolean { + return this.types.contains(type); + } + + hasTypeOverlap(types: string[]): boolean { + for (const type of types) { + if (this.hasType(type)) { + return true; + } + } + return false; + } +} diff --git a/src/api/APIResult.ts b/src/api/APIRequestResult.ts similarity index 55% rename from src/api/APIResult.ts rename to src/api/APIRequestResult.ts index b006575..3030089 100644 --- a/src/api/APIResult.ts +++ b/src/api/APIRequestResult.ts @@ -1,6 +1,7 @@ -export interface APIResult { +export interface APIRequestResult { title: string, type: string, description?: string, + apiName: string, data: any, } diff --git a/src/api/apis/TestAPI.ts b/src/api/apis/TestAPI.ts new file mode 100644 index 0000000..42be15c --- /dev/null +++ b/src/api/apis/TestAPI.ts @@ -0,0 +1,27 @@ +import {APIModel} from '../APIModel'; +import {APIRequestResult} from '../APIRequestResult'; + +export class TestAPI extends APIModel { + constructor() { + super(); + this.name = 'testAPI'; + this.types = ['test']; + } + + async getByTitle(title: string): Promise { + console.log(`MDB | api "${this.name}" queried`); + + return [ + {title: 'test1', type: this.types[0], apiName: this.name, data: {length: 126}} as APIRequestResult, + {title: 'test2', type: this.types[0], apiName: this.name, description: 'some test description', data: {}} as APIRequestResult, + ]; + } + + getMataDataFromResult(item: APIRequestResult): string { + if (item.apiName !== this.name) { + return ''; + } + + return ''; + } +} diff --git a/src/main.ts b/src/main.ts index 9bd6953..b80ac82 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,9 +1,12 @@ import {Plugin} from 'obsidian'; import {DEFAULT_SETTINGS, MediaDbPluginSettings, MediaDbSettingTab} from './settings/settings'; import {MediaDbSearchModal} from './modals/MediaDbSearchModal'; +import {APIManager} from './api/APIManager'; +import {TestAPI} from './api/apis/TestAPI'; export default class MediaDbPlugin extends Plugin { settings: MediaDbPluginSettings; + apiManager: APIManager; async onload() { await this.loadSettings(); @@ -23,17 +26,22 @@ export default class MediaDbPlugin extends Plugin { // register the settings tab this.addSettingTab(new MediaDbSettingTab(this.app, this)); + + + this.apiManager = new APIManager(); + // register APIs + this.apiManager.registerAPI(new TestAPI()); } async createMediaDbNote(): Promise { const data = await this.openMediaDbSearchModal(); - console.log('Create new note or something...'); + console.log('MDB | Create new note or something...'); console.log(data); } async openMediaDbSearchModal(): Promise { return new Promise(((resolve, reject) => { - new MediaDbSearchModal(this.app, (err, result) => { + new MediaDbSearchModal(this.app, this.apiManager, (err, result) => { if (err) return reject(err); resolve(result); }).open(); diff --git a/src/modals/MediaDbSearchModal.ts b/src/modals/MediaDbSearchModal.ts index e961d0b..7632ff5 100644 --- a/src/modals/MediaDbSearchModal.ts +++ b/src/modals/MediaDbSearchModal.ts @@ -1,22 +1,22 @@ -import {App, ButtonComponent, SuggestModal} from 'obsidian'; -import {APIResult} from '../api/APIResult'; -import {sleep} from '../utils/utils'; +import {App, SuggestModal} from 'obsidian'; +import {APIRequestResult} from '../api/APIRequestResult'; +import {APIManager} from '../api/APIManager'; -export class MediaDbSearchModal extends SuggestModal { +export class MediaDbSearchModal extends SuggestModal { query: string; - hasChanged: boolean; isBusy: boolean; - okBtn: ButtonComponent; - onChoose: (err: Error, result?: APIResult) => void; + apiManager: APIManager; + onChoose: (err: Error, result?: APIRequestResult) => void; - constructor(app: App, onChoose?: (err: Error, result?: APIResult) => void) { + constructor(app: App, apiManager: APIManager, onChoose?: (err: Error, result?: APIRequestResult) => void) { super(app); + this.apiManager = apiManager; this.onChoose = onChoose; this.isBusy = false; } - async search(force: boolean = false): Promise { + async search(force: boolean = false): Promise { if (!this.query) { return; } @@ -25,72 +25,41 @@ export class MediaDbSearchModal extends SuggestModal { this.isBusy = true; const thisQuery: string = this.query; - console.log('query started with ' + thisQuery) - await sleep(1000); // TODO: replace with real api call + console.log('MDB | query started with ' + thisQuery); + + const res = await this.apiManager.query(thisQuery); + + // console.log(res) + + // await sleep(1000); if (this.query === thisQuery) { this.isBusy = false; - return [ // TODO: replace with real api result - {title: thisQuery, type: 'movie', data: null} as APIResult, - {title: 'test2', type: 'series', data: {episodes: 24}} as APIResult, - ]; + + return res; + + // return [ + // {title: thisQuery, type: 'movie', data: null} as APIRequestResult, + // {title: 'test2', type: 'series', data: {episodes: 24}} as APIRequestResult, + // ]; } else { return await this.search(true); } } } - async getSuggestions(query: string): Promise { + async getSuggestions(query: string): Promise { this.query = query; return await this.search(); } - renderSuggestion(item: APIResult, el: HTMLElement): void { + renderSuggestion(item: APIRequestResult, el: HTMLElement): void { el.createEl('div', {text: item.title}); el.createEl('small', {text: item.type}); } - onChooseSuggestion(item: APIResult, evt: MouseEvent | KeyboardEvent): void { + onChooseSuggestion(item: APIRequestResult, evt: MouseEvent | KeyboardEvent): void { this.onChoose(null, item); } - - - /* - onOpen() { - const { contentEl } = this; - - contentEl.createEl('h2', { text: 'Search Media DB' }); - - const placeholder = 'Search by title'; - const textComponent = new TextComponent(contentEl); - - textComponent.setPlaceholder(placeholder); - textComponent.onChange(value => (this.query = value)); - - textComponent.inputEl.addEventListener('keydown', this.submitCallback.bind(this)); - textComponent.inputEl.style.width = '100%'; - - contentEl.appendChild(textComponent.inputEl); - textComponent.inputEl.focus(); - - const resultsComponent = new - - new Setting(contentEl) - .addButton(btn => btn.setButtonText('Cancel').onClick(() => this.close())) - .addButton(btn => { - return (this.okBtn = btn - .setButtonText('Ok') - .setCta() - .onClick(() => { - this.search(); - })); - }); - } - - onClose() { - const { contentEl } = this; - contentEl.empty(); - } - */ }