Skip to content

Commit

Permalink
Add /giphy command to editor and search modal accepts "enter" instead…
Browse files Browse the repository at this point in the history
… of mount click on btn.
  • Loading branch information
dhurley94 committed Oct 21, 2023
1 parent d0cd9f6 commit 47bef9c
Showing 1 changed file with 105 additions and 13 deletions.
118 changes: 105 additions & 13 deletions main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,52 @@ const DEFAULT_SETTINGS: GiphyPluginSettings = {
apiKey: ''
};

class GiphyImagePickerModal extends Modal {
private onResolve: (value: string | null) => void;
private gifUrls: string[];

constructor(app: App, gifUrls: string[], onResolve: (value: string | null) => void) {
super(app);
this.onResolve = onResolve;
this.gifUrls = gifUrls;
}

onOpen() {
const { contentEl } = this;
contentEl.empty();

this.gifUrls.forEach(url => {
const img = contentEl.createEl('img', {
attr: {
src: url,
width: '100px',
style: 'margin: 5px; cursor: pointer;'
}
});
img.onclick = () => {
this.onResolve(url);
this.close();
};
});
}

onClose() {
const { contentEl } = this;
contentEl.empty();
}
}


export default class GiphyPlugin extends Plugin {
settings: GiphyPluginSettings;

async onload() {
this.settings = { ...DEFAULT_SETTINGS, ...(await this.loadData()) }

this.registerEvent(this.app.workspace.on('active-leaf-change', this.handleActiveLeafChange.bind(this)));



this.addCommand({
id: 'search-giphy',
name: 'Search Giphy for GIFs',
Expand All @@ -27,36 +67,78 @@ export default class GiphyPlugin extends Plugin {
await this.saveData(this.settings);
}


async searchGiphy() {
const keyword = await this.promptForInput();
if (!keyword) return;

const gifUrl = await this.queryGiphy(keyword);
if (!gifUrl) {
return new Notice('No GIF found.');
const gifUrls = await this.queryGiphy(keyword);
if (gifUrls.length === 0) {
new Notice('No GIFs found.');
return;
}


const selectedGifUrl = await this.promptForGifSelection(gifUrls);
if (!selectedGifUrl) return;

const editor = this.getEditor();
if (editor) {
editor.replaceSelection(`![Giphy GIF](${gifUrl})`);
editor.replaceSelection(`![Giphy GIF](${selectedGifUrl})`);
} else {
return new Notice('Failed to get the editor instance.');
new Notice('Failed to get the editor instance.');
}
}

async promptForGifSelection(gifUrls: string[]): Promise<string | null> {
return new Promise((resolve) => {
const modal = new GiphyImagePickerModal(this.app, gifUrls, resolve);
modal.open();
});
}


private handleActiveLeafChange(): void {
const activeLeaf = this.app.workspace.getLeaf();
if (activeLeaf?.view instanceof MarkdownView) {
const editor = activeLeaf.view.editor;
if (editor) {
editor.exec(this.handleEditorChange.bind(this));
}
}
}


private handleEditorChange(cm: any, change: any): void {

Check warning on line 111 in main.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type

Check warning on line 111 in main.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type

Check warning on line 111 in main.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type

Check warning on line 111 in main.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
const insertedText = change?.text?.join('') || '';
if (insertedText.includes('/giphy')) {
this.searchGiphy();

try {
const from = {
line: change.from.line,
ch: change.from.ch - 6
};
cm.replaceRange('', from, change.from);
} catch (err) {
console.error("Error while trying to replace '/giphy':", err);
}
}
}

async promptForInput(): Promise<string> {
return new Promise((resolve) => {
const modal = new GiphyInputModal(this.app, resolve);
const modal = new GiphySearchModal(this.app, resolve);
modal.open();
});
}

async queryGiphy(keyword: string): Promise<string> {
async queryGiphy(keyword: string, limit = 10): Promise<string[]> {
const GIPHY_API_ENDPOINT = 'https://api.giphy.com/v1/gifs/search';
const response = await fetch(`${GIPHY_API_ENDPOINT}?q=${encodeURIComponent(keyword)}&api_key=${this.settings.apiKey}&limit=1`);
const response = await fetch(`${GIPHY_API_ENDPOINT}?q=${encodeURIComponent(keyword)}&api_key=${this.settings.apiKey}&limit=${limit}`);
const data = await response.json();
return data.data[0]?.images?.original?.url || '';
return data.data.map((gif: {images: {original: {url: string}}}) => gif.images.original.url);
}


getEditor(): CodeMirror.Editor | null {
const view = this.app.workspace.getActiveViewOfType(MarkdownView);
Expand Down Expand Up @@ -93,7 +175,7 @@ class GiphyPluginSettingTab extends PluginSettingTab {
}
}

class GiphyInputModal extends Modal {
class GiphySearchModal extends Modal {
private onResolve: (value: string) => void;

constructor(app: App, onResolve: (value: string) => void) {
Expand All @@ -106,11 +188,21 @@ class GiphyInputModal extends Modal {

const inputEl = contentEl.createEl('input', {
type: 'text',
placeholder: 'Enter keyword to search on Giphy...'
placeholder: 'Enter keyword to search on Giphy...',
cls: []
});

const submitBtn = contentEl.createEl('button', {
text: 'Search'
text: 'Search',
cls: []
});

inputEl.addEventListener('keydown', (event: KeyboardEvent) => {
console.log(event)
if (event.key === 'Enter') {
this.onResolve(inputEl.value);
this.close();
}
});

submitBtn.onclick = () => {
Expand Down

0 comments on commit 47bef9c

Please sign in to comment.