Skip to content

Commit aa7659e

Browse files
committed
cancel and skip buttons #26
1 parent 038d473 commit aa7659e

9 files changed

+144
-51
lines changed

src/main.ts

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {Notice, Plugin, TFile, TFolder} from 'obsidian';
22
import {DEFAULT_SETTINGS, MediaDbPluginSettings, MediaDbSettingTab} from './settings/Settings';
33
import {APIManager} from './api/APIManager';
44
import {MediaTypeModel} from './models/MediaTypeModel';
5-
import {dateTimeToString, markdownTable, replaceIllegalFileNameCharactersInString} from './utils/Utils';
5+
import {dateTimeToString, markdownTable, replaceIllegalFileNameCharactersInString, UserCancelError, UserSkipError} from './utils/Utils';
66
import {OMDbAPI} from './api/apis/OMDbAPI';
77
import {MediaDbAdvancedSearchModal} from './modals/MediaDbAdvancedSearchModal';
88
import {MediaDbSearchResultModal} from './modals/MediaDbSearchResultModal';
@@ -177,10 +177,11 @@ export default class MediaDbPlugin extends Plugin {
177177

178178
async createEntriesFromFolder(folder: TFolder) {
179179
const erroredFiles: { filePath: string, error: string }[] = [];
180+
let canceled: boolean = false;
180181

181-
const {selectedAPI, titleFieldName} = await new Promise((resolve, reject) => {
182-
new MediaDbFolderImportModal(this.app, this, ((selectedAPI, titleFieldName) => {
183-
resolve({selectedAPI, titleFieldName});
182+
const {selectedAPI, titleFieldName, appendContent} = await new Promise((resolve, reject) => {
183+
new MediaDbFolderImportModal(this.app, this, ((selectedAPI, titleFieldName, appendContent) => {
184+
resolve({selectedAPI, titleFieldName, appendContent});
184185
})).open();
185186
});
186187

@@ -193,6 +194,11 @@ export default class MediaDbPlugin extends Plugin {
193194
for (const child of folder.children) {
194195
if (child instanceof TFile) {
195196
const file = child as TFile;
197+
if (canceled) {
198+
erroredFiles.push({filePath: file.path, error: 'user canceled'});
199+
continue;
200+
}
201+
196202
let metadata: any = this.app.metadataCache.getFileCache(file).frontmatter;
197203

198204
let title = metadata[titleFieldName];
@@ -213,22 +219,40 @@ export default class MediaDbPlugin extends Plugin {
213219
continue;
214220
}
215221

216-
let selectedResults: MediaTypeModel[] = await new Promise((resolve, reject) => {
217-
const searchResultModal = new MediaDbSearchResultModal(this.app, this, results, (err, res) => {
218-
if (err) {
219-
return reject(err);
220-
}
221-
resolve(res);
222-
}, () => {
223-
resolve([]);
222+
let selectedResults: MediaTypeModel[] = [];
223+
try {
224+
selectedResults = await new Promise((resolve, reject) => {
225+
const searchResultModal = new MediaDbSearchResultModal(this.app, this, results, true, (err, res) => {
226+
if (err) {
227+
return reject(err);
228+
}
229+
resolve(res);
230+
}, () => {
231+
reject(new UserCancelError('user canceled'));
232+
}, () => {
233+
reject(new UserSkipError('user skipped'));
234+
});
235+
236+
searchResultModal.title = `Results for \'${title}\'`;
237+
searchResultModal.open();
224238
});
225-
226-
searchResultModal.title = `Results for \'${title}\'`;
227-
searchResultModal.open();
228-
});
239+
} catch (e) {
240+
if (e instanceof UserCancelError) {
241+
erroredFiles.push({filePath: file.path, error: e.message});
242+
canceled = true;
243+
continue;
244+
} else if (e instanceof UserSkipError) {
245+
erroredFiles.push({filePath: file.path, error: e.message});
246+
continue;
247+
} else {
248+
erroredFiles.push({filePath: file.path, error: e.message});
249+
continue;
250+
}
251+
}
229252

230253
if (selectedResults.length === 0) {
231254
erroredFiles.push({filePath: file.path, error: `no search results selected`});
255+
continue;
232256
}
233257

234258
await this.createMediaDbNote(async () => selectedResults);
@@ -253,7 +277,7 @@ export default class MediaDbPlugin extends Plugin {
253277
if (err) {
254278
return reject(err);
255279
}
256-
new MediaDbSearchResultModal(this.app, this, results, (err2, res) => {
280+
new MediaDbSearchResultModal(this.app, this, results, false, (err2, res) => {
257281
if (err2) {
258282
return reject(err2);
259283
}

src/modals/MediaDbAdvancedSearchModal.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ export class MediaDbAdvancedSearchModal extends Modal {
8181
contentEl.appendChild(searchComponent.inputEl);
8282
searchComponent.inputEl.focus();
8383

84+
contentEl.createDiv({cls: 'media-db-plugin-spacer'});
8485
contentEl.createEl('h3', {text: 'APIs to search'});
8586

8687
const apiToggleComponents: Component[] = [];
@@ -102,6 +103,7 @@ export class MediaDbAdvancedSearchModal extends Modal {
102103
apiToggleComponentWrapper.appendChild(apiToggleComponent.toggleEl);
103104
}
104105

106+
contentEl.createDiv({cls: 'media-db-plugin-spacer'});
105107

106108
new Setting(contentEl)
107109
.addButton(btn => btn.setButtonText('Cancel').onClick(() => this.close()))

src/modals/MediaDbFolderImportModal.ts

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
1-
import {App, ButtonComponent, DropdownComponent, Modal, Setting, TextComponent} from 'obsidian';
1+
import {App, ButtonComponent, DropdownComponent, Modal, Setting, TextComponent, ToggleComponent} from 'obsidian';
22
import MediaDbPlugin from '../main';
33

44
export class MediaDbFolderImportModal extends Modal {
55
plugin: MediaDbPlugin;
6-
onSubmit: (selectedAPI: string, titleFieldName: string) => void;
6+
onSubmit: (selectedAPI: string, titleFieldName: string, appendContent: boolean) => void;
77
selectedApi: string;
88
searchBtn: ButtonComponent;
99
titleFieldName: string;
10+
appendContent: boolean;
1011

11-
constructor(app: App, plugin: MediaDbPlugin, onSubmit: (selectedAPI: string, titleFieldName: string) => void) {
12+
constructor(app: App, plugin: MediaDbPlugin, onSubmit: (selectedAPI: string, titleFieldName: string, appendContent: boolean) => void) {
1213
super(app);
1314
this.plugin = plugin;
1415
this.onSubmit = onSubmit;
1516
this.selectedApi = plugin.apiManager.apis[0].apiName;
1617
}
1718

1819
submit() {
19-
this.onSubmit(this.selectedApi, this.titleFieldName);
20+
this.onSubmit(this.selectedApi, this.titleFieldName, this.appendContent);
2021
this.close();
2122
}
2223

@@ -39,14 +40,41 @@ export class MediaDbFolderImportModal extends Modal {
3940
apiSelectorWrapper.appendChild(apiSelectorComponent.selectEl);
4041

4142

42-
const placeholder = 'Title metadata field name';
43+
contentEl.createDiv({cls: 'media-db-plugin-spacer'});
44+
contentEl.createEl('h3', {text: 'Append note content to Media DB entry.'});
45+
46+
const appendContentToggleElementWrapper = contentEl.createEl('div', {cls: 'media-db-plugin-list-wrapper'});
47+
const appendContentToggleTextWrapper = appendContentToggleElementWrapper.createEl('div', {cls: 'media-db-plugin-list-text-wrapper'});
48+
appendContentToggleTextWrapper.createEl('span', {
49+
text: 'If this is enabled, the plugin will override meta data fields with the same name.',
50+
cls: 'media-db-plugin-list-text',
51+
});
52+
53+
const appendContentToggleComponentWrapper = appendContentToggleElementWrapper.createEl('div', {cls: 'media-db-plugin-list-toggle'});
54+
55+
const appendContentToggle = new ToggleComponent(appendContentToggleElementWrapper);
56+
appendContentToggle.setValue(false);
57+
appendContentToggle.onChange(value => this.appendContent = value);
58+
appendContentToggleComponentWrapper.appendChild(appendContentToggle.toggleEl);
59+
60+
61+
contentEl.createDiv({cls: 'media-db-plugin-spacer'});
62+
contentEl.createEl('h3', {text: 'The name of the mata data field that should be used as the title to query'});
63+
64+
const placeholder = 'title';
4365
const titleFieldNameComponent = new TextComponent(contentEl);
4466
titleFieldNameComponent.inputEl.style.width = '100%';
4567
titleFieldNameComponent.setPlaceholder(placeholder);
4668
titleFieldNameComponent.onChange(value => this.titleFieldName = value);
47-
69+
titleFieldNameComponent.inputEl.addEventListener('keydown', (ke) => {
70+
if (ke.key === 'Enter') {
71+
this.submit();
72+
}
73+
});
4874
contentEl.appendChild(titleFieldNameComponent.inputEl);
4975

76+
contentEl.createDiv({cls: 'media-db-plugin-spacer'});
77+
5078
new Setting(contentEl)
5179
.addButton(btn => btn.setButtonText('Cancel').onClick(() => this.close()))
5280
.addButton(btn => btn.setButtonText('Ok').setCta().onClick(() => this.submit()));

src/modals/MediaDbIdSearchModal.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ export class MediaDbIdSearchModal extends Modal {
7575
contentEl.appendChild(searchComponent.inputEl);
7676
searchComponent.inputEl.focus();
7777

78+
contentEl.createDiv({cls: 'media-db-plugin-spacer'});
79+
7880
const apiSelectorWrapper = contentEl.createEl('div', {cls: 'media-db-plugin-list-wrapper'});
7981
const apiSelectorTExtWrapper = apiSelectorWrapper.createEl('div', {cls: 'media-db-plugin-list-text-wrapper'});
8082
apiSelectorTExtWrapper.createEl('span', {text: 'API to search', cls: 'media-db-plugin-list-text'});
@@ -88,6 +90,8 @@ export class MediaDbIdSearchModal extends Modal {
8890
}
8991
apiSelectorWrapper.appendChild(apiSelectorComponent.selectEl);
9092

93+
contentEl.createDiv({cls: 'media-db-plugin-spacer'});
94+
9195
new Setting(contentEl)
9296
.addButton(btn => btn.setButtonText('Cancel').onClick(() => this.close()))
9397
.addButton(btn => {

src/modals/MediaDbSearchResultModal.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,24 @@ import {SelectModal} from './SelectModal';
66
export class MediaDbSearchResultModal extends SelectModal<MediaTypeModel> {
77
plugin: MediaDbPlugin;
88
heading: string;
9-
onChoose: (error: Error, result: MediaTypeModel[]) => void;
9+
onSubmit: (error: Error, result: MediaTypeModel[]) => void;
1010
onCancel: () => void;
11+
onSkip: () => void;
1112

12-
constructor(app: App, plugin: MediaDbPlugin, elements: MediaTypeModel[], onChoose: (error: Error, result: MediaTypeModel[]) => void, onCancel: () => void) {
13+
sendCallback: boolean;
14+
15+
constructor(app: App, plugin: MediaDbPlugin, elements: MediaTypeModel[], skipButton: boolean, onSubmit: (error: Error, result: MediaTypeModel[]) => void, onCancel: () => void, onSkip?: () => void) {
1316
super(app, elements);
1417
this.plugin = plugin;
15-
this.onChoose = onChoose;
18+
this.onSubmit = onSubmit;
1619
this.onCancel = onCancel;
20+
this.onSkip = onSkip;
1721

1822
this.title = 'Search Results';
1923
this.description = 'Select one or multiple search results.';
24+
this.skipButton = skipButton;
25+
26+
this.sendCallback = false;
2027
}
2128

2229
// Renders each suggestion item.
@@ -27,12 +34,21 @@ export class MediaDbSearchResultModal extends SelectModal<MediaTypeModel> {
2734
}
2835

2936
// Perform action on the selected suggestion.
30-
onSubmit() {
31-
this.onChoose(null, this.selectModalElements.filter(x => x.isActive()).map(x => x.value));
37+
submit() {
38+
this.onSubmit(null, this.selectModalElements.filter(x => x.isActive()).map(x => x.value));
39+
this.sendCallback = true;
40+
this.close();
41+
}
42+
43+
skip() {
44+
this.onSkip();
45+
this.sendCallback = true;
3246
this.close();
3347
}
3448

3549
onClose() {
36-
this.onCancel();
50+
if (!this.sendCallback) {
51+
this.onCancel();
52+
}
3753
}
3854
}

src/modals/SelectModal.ts

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,33 @@ import {App, Modal, Setting} from 'obsidian';
22
import {SelectModalElement} from './SelectModalElement';
33

44
export abstract class SelectModal<T> extends Modal {
5-
multiSelect: boolean;
65
allowMultiSelect: boolean;
76

87
title: string;
98
description: string;
9+
skipButton: boolean;
1010

1111
elements: T[];
1212
selectModalElements: SelectModalElement<T>[];
1313

1414

15-
constructor(app: App, elements: T[]) {
15+
protected constructor(app: App, elements: T[]) {
1616
super(app);
17-
this.elements = elements;
1817
this.allowMultiSelect = true;
1918

19+
this.title = '';
20+
this.description = '';
21+
this.skipButton = false;
22+
23+
this.elements = elements;
2024
this.selectModalElements = [];
2125
}
2226

2327
abstract renderElement(value: T, el: HTMLElement): any;
2428

25-
abstract onSubmit(): void;
29+
abstract submit(): void;
30+
31+
abstract skip(): void;
2632

2733
disableAllOtherElements(elementId: number) {
2834
for (const selectModalElement of this.selectModalElements) {
@@ -35,23 +41,17 @@ export abstract class SelectModal<T> extends Modal {
3541
async onOpen() {
3642
const {contentEl} = this;
3743

44+
/*
45+
contentEl.id = 'media-db-plugin-modal'
46+
47+
contentEl.on('keydown', '#' + contentEl.id, (ev, delegateTarget) => {
48+
console.log(ev.key);
49+
});
50+
*/
51+
3852
contentEl.createEl('h2', {text: this.title});
3953
contentEl.createEl('p', {text: this.description});
4054

41-
if (this.allowMultiSelect) {
42-
new Setting(contentEl)
43-
.setName('Select Multiple')
44-
.addToggle(cb => {
45-
cb.setValue(this.multiSelect);
46-
cb.onChange(value => {
47-
this.multiSelect = value;
48-
for (const selectModalElement of this.selectModalElements) {
49-
selectModalElement.setActive(false);
50-
}
51-
});
52-
});
53-
}
54-
5555
const elementWrapper = contentEl.createDiv({cls: 'media-db-plugin-select-wrapper'});
5656

5757
let i = 0;
@@ -65,8 +65,11 @@ export abstract class SelectModal<T> extends Modal {
6565
i += 1;
6666
}
6767

68-
new Setting(contentEl)
69-
.addButton(btn => btn.setButtonText('Cancel').onClick(() => this.close()))
70-
.addButton(btn => btn.setButtonText('Ok').setCta().onClick(() => this.onSubmit()));
68+
const bottomSetting = new Setting(contentEl);
69+
bottomSetting.addButton(btn => btn.setButtonText('Cancel').onClick(() => this.close()));
70+
if (this.skipButton) {
71+
bottomSetting.addButton(btn => btn.setButtonText('Skip').onClick(() => this.skip()));
72+
}
73+
bottomSetting.addButton(btn => btn.setButtonText('Ok').setCta().onClick(() => this.submit()));
7174
}
7275
}

src/modals/SelectModalElement.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export class SelectModalElement<T> {
2424
this.element.id = this.getHTMLId();
2525
this.element.on('click', '#' + this.getHTMLId(), () => {
2626
this.setActive(!this.active);
27-
if (!this.selectModal.allowMultiSelect || !this.selectModal.multiSelect) {
27+
if (!this.selectModal.allowMultiSelect) {
2828
this.selectModal.disableAllOtherElements(this.id);
2929
}
3030
});

src/utils/Utils.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,3 +152,15 @@ export function dateTimeToString(dateTime: Date) {
152152
return `${dateToString(dateTime)} ${timeToString(dateTime)}`;
153153
}
154154

155+
export class UserCancelError extends Error {
156+
constructor(message: string) {
157+
super(message);
158+
}
159+
}
160+
161+
export class UserSkipError extends Error {
162+
constructor(message: string) {
163+
super(message);
164+
}
165+
}
166+

styles.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,7 @@ small.media-db-plugin-list-text{
4444
.media-db-plugin-select-element-hover {
4545
background: var(--background-secondary-alt);
4646
}
47+
48+
.media-db-plugin-spacer {
49+
margin-bottom: 10px;
50+
}

0 commit comments

Comments
 (0)