Merge pull request #277 from ltctceplrm/api-key-popup
Add legacy api key popup so users can copy old keys
This commit is contained in:
commit
63e8359895
4 changed files with 199 additions and 56 deletions
|
|
@ -16,6 +16,8 @@ import { TMDBSeasonAPI } from 'packages/obsidian/src/api/apis/TMDBSeasonAPI';
|
|||
import { TMDBSeriesAPI } from 'packages/obsidian/src/api/apis/TMDBSeriesAPI';
|
||||
import { VNDBAPI } from 'packages/obsidian/src/api/apis/VNDBAPI';
|
||||
import { WikipediaAPI } from 'packages/obsidian/src/api/apis/WikipediaAPI';
|
||||
import type { LegacyApiKeyEntry } from 'packages/obsidian/src/modals/LegacyApiKeysModal';
|
||||
import { LegacyApiKeysModal } from 'packages/obsidian/src/modals/LegacyApiKeysModal';
|
||||
import { PropertyMapper } from 'packages/obsidian/src/settings/PropertyMapper';
|
||||
import { PropertyMappingModel } from 'packages/obsidian/src/settings/PropertyMapping';
|
||||
import type { MediaDbPluginSettings } from 'packages/obsidian/src/settings/Settings';
|
||||
|
|
@ -168,35 +170,42 @@ export default class MediaDbPlugin extends Plugin {
|
|||
});
|
||||
}
|
||||
|
||||
async loadSettings(): Promise<void> {
|
||||
const diskSettings: MediaDbPluginSettings = (await this.loadData()) as MediaDbPluginSettings;
|
||||
const defaultSettings: MediaDbPluginSettings = getDefaultSettings(this);
|
||||
const loadedSettings: MediaDbPluginSettings = Object.assign({}, defaultSettings, diskSettings);
|
||||
private getLegacyApiKeyEntries(diskSettings: Record<string, unknown>): LegacyApiKeyEntry[] {
|
||||
return this.settings.LegacyApiKeys.filter(key => typeof diskSettings[key] === 'string' && diskSettings[key].length > 0).map(key => ({
|
||||
key,
|
||||
value: diskSettings[key] as string,
|
||||
}));
|
||||
}
|
||||
|
||||
// delete old api keys
|
||||
// @ts-ignore
|
||||
delete loadedSettings.BoardgameGeekKey;
|
||||
// @ts-ignore
|
||||
delete loadedSettings.ComicVineKey;
|
||||
// @ts-ignore
|
||||
delete loadedSettings.GiantBombKey;
|
||||
// @ts-ignore
|
||||
delete loadedSettings.MobyGamesKey;
|
||||
// @ts-ignore
|
||||
delete loadedSettings.OMDbKey;
|
||||
// @ts-ignore
|
||||
delete loadedSettings.TMDBKey;
|
||||
private removeLegacyApiKeys(settings: Record<string, unknown>): void {
|
||||
for (const key of this.settings.LegacyApiKeys) {
|
||||
delete settings[key];
|
||||
}
|
||||
}
|
||||
|
||||
async loadSettings(): Promise<void> {
|
||||
const diskSettings = (await this.loadData()) as Record<string, unknown>;
|
||||
const defaultSettings: MediaDbPluginSettings = getDefaultSettings(this);
|
||||
const loadedSettings = Object.assign({}, defaultSettings, diskSettings) as MediaDbPluginSettings;
|
||||
|
||||
const migratedModels = PropertyMappingModel.migrateModels(
|
||||
loadedSettings.propertyMappingModels || [],
|
||||
defaultSettings.propertyMappingModels.map(m => PropertyMappingModel.fromJSON(m)),
|
||||
);
|
||||
|
||||
loadedSettings.propertyMappingModels = migratedModels.map(m => m.toJSON());
|
||||
|
||||
this.settings = loadedSettings;
|
||||
|
||||
await this.saveSettings();
|
||||
const legacyEntries = this.getLegacyApiKeyEntries(diskSettings);
|
||||
if (legacyEntries.length > 0) {
|
||||
this.app.workspace.onLayoutReady((): void => {
|
||||
window.setTimeout((): void => {
|
||||
new LegacyApiKeysModal(this.app, legacyEntries, (): void => {
|
||||
this.removeLegacyApiKeys(this.settings as unknown as Record<string, unknown>);
|
||||
void this.saveSettings();
|
||||
}).open();
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async saveSettings(): Promise<void> {
|
||||
|
|
|
|||
93
packages/obsidian/src/modals/LegacyApiKeysModal.ts
Normal file
93
packages/obsidian/src/modals/LegacyApiKeysModal.ts
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
import type { App } from 'obsidian';
|
||||
import { Modal, Setting, Notice } from 'obsidian';
|
||||
|
||||
export interface LegacyApiKeyEntry {
|
||||
key: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export class LegacyApiKeysModal extends Modal {
|
||||
private entries: LegacyApiKeyEntry[];
|
||||
private onConfirm: () => void;
|
||||
|
||||
constructor(app: App, entries: LegacyApiKeyEntry[], onConfirm: () => void) {
|
||||
super(app);
|
||||
this.entries = entries;
|
||||
this.onConfirm = onConfirm;
|
||||
}
|
||||
|
||||
onOpen(): void {
|
||||
const { contentEl } = this;
|
||||
contentEl.addClass('media-db-plugin-legacy-keys-modal');
|
||||
|
||||
contentEl.createEl('h2', { text: 'Media DB plugin: Legacy API keys found' });
|
||||
|
||||
const wrapper = contentEl.createDiv({ cls: 'media-db-plugin-legacy-keys-wrapper' });
|
||||
|
||||
const intro = wrapper.createDiv({ cls: 'media-db-plugin-legacy-keys-intro' });
|
||||
intro.createEl('p', {
|
||||
text: 'Media DB plugin has found old plaintext API keys in your settings. Copy them now if needed, they should be removed for safety.',
|
||||
});
|
||||
|
||||
intro.createEl('p', {
|
||||
text: 'The new keychain-backed system will be used instead. The plugin will not be usable until the old plaintext keys have been deleted.',
|
||||
});
|
||||
|
||||
const textarea = wrapper.createEl('textarea', {
|
||||
cls: 'media-db-plugin-legacy-keys-textarea',
|
||||
attr: {
|
||||
readonly: 'true',
|
||||
spellcheck: 'false',
|
||||
},
|
||||
});
|
||||
|
||||
textarea.value = this.entries.map(e => `${e.key}: ${e.value}`).join('\n');
|
||||
textarea.addClass('media-db-plugin-hidden');
|
||||
|
||||
contentEl.createDiv({ cls: 'media-db-plugin-spacer' });
|
||||
|
||||
const bottomSettingRow = new Setting(contentEl);
|
||||
|
||||
bottomSettingRow.addButton(btn => {
|
||||
btn.setButtonText('Copy');
|
||||
btn.onClick(async () => {
|
||||
await navigator.clipboard.writeText(textarea.value);
|
||||
new Notice('Legacy API keys copied to clipboard.');
|
||||
});
|
||||
btn.buttonEl.addClass('media-db-plugin-button');
|
||||
});
|
||||
|
||||
bottomSettingRow.addButton(btn => {
|
||||
btn.setButtonText('Show keys');
|
||||
|
||||
btn.onClick(() => {
|
||||
const isHidden = textarea.hasClass('media-db-plugin-hidden');
|
||||
if (isHidden) {
|
||||
textarea.removeClass('media-db-plugin-hidden');
|
||||
btn.setButtonText('Hide keys');
|
||||
} else {
|
||||
textarea.addClass('media-db-plugin-hidden');
|
||||
btn.setButtonText('Show keys');
|
||||
}
|
||||
});
|
||||
|
||||
btn.buttonEl.addClass('media-db-plugin-button');
|
||||
});
|
||||
|
||||
bottomSettingRow.addButton(btn => {
|
||||
btn.setButtonText('Delete plaintext keys');
|
||||
btn.setCta();
|
||||
btn.onClick(() => {
|
||||
this.close();
|
||||
this.onConfirm();
|
||||
});
|
||||
btn.buttonEl.addClass('media-db-plugin-button');
|
||||
btn.buttonEl.addClass('mod-warning');
|
||||
btn.buttonEl.addClass('mod-danger');
|
||||
});
|
||||
}
|
||||
|
||||
onClose(): void {
|
||||
this.contentEl.empty();
|
||||
}
|
||||
}
|
||||
|
|
@ -50,14 +50,16 @@ function createPropertyMappingsDescription(): DocumentFragment {
|
|||
export interface MediaDbPluginSettings {
|
||||
OMDbKeyId: string;
|
||||
TMDBKeyId: string;
|
||||
MobyGamesKeyId: string;
|
||||
GiantBombKeyId: string;
|
||||
//MobyGamesKeyId: string;
|
||||
//GiantBombKeyId: string;
|
||||
IGDBClientId: string;
|
||||
IGDBClientSecret: string;
|
||||
RAWGAPIKeyId: string;
|
||||
ComicVineKeyId: string;
|
||||
BoardgameGeekKeyId: string;
|
||||
|
||||
LegacyApiKeys: readonly ['OMDbKey', 'TMDBKey', 'MobyGamesKey', 'GiantBombKey', 'ComicVineKey', 'BoardgameGeekKey'];
|
||||
|
||||
sfwFilter: boolean;
|
||||
templates: boolean;
|
||||
customDateFormat: string;
|
||||
|
|
@ -69,12 +71,12 @@ export interface MediaDbPluginSettings {
|
|||
|
||||
BoardgameGeekAPI_disabledMediaTypes: MediaType[];
|
||||
ComicVineAPI_disabledMediaTypes: MediaType[];
|
||||
GiantBombAPI_disabledMediaTypes: MediaType[];
|
||||
//GiantBombAPI_disabledMediaTypes: MediaType[];
|
||||
IGDBAPI_disabledMediaTypes: MediaType[];
|
||||
RAWGAPI_disabledMediaTypes: MediaType[];
|
||||
MALAPI_disabledMediaTypes: MediaType[];
|
||||
MALAPIManga_disabledMediaTypes: MediaType[];
|
||||
MobyGamesAPI_disabledMediaTypes: MediaType[];
|
||||
//MobyGamesAPI_disabledMediaTypes: MediaType[];
|
||||
MusicBrainzAPI_disabledMediaTypes: MediaType[];
|
||||
OMDbAPI_disabledMediaTypes: MediaType[];
|
||||
OpenLibraryAPI_disabledMediaTypes: MediaType[];
|
||||
|
|
@ -309,14 +311,16 @@ class MediaTypeMappedSettings {
|
|||
const DEFAULT_SETTINGS: MediaDbPluginSettings = {
|
||||
OMDbKeyId: '',
|
||||
TMDBKeyId: '',
|
||||
MobyGamesKeyId: '',
|
||||
GiantBombKeyId: '',
|
||||
//MobyGamesKeyId: '',
|
||||
//GiantBombKeyId: '',
|
||||
IGDBClientId: '',
|
||||
IGDBClientSecret: '',
|
||||
RAWGAPIKeyId: '',
|
||||
ComicVineKeyId: '',
|
||||
BoardgameGeekKeyId: '',
|
||||
|
||||
LegacyApiKeys: ['OMDbKey', 'TMDBKey', 'MobyGamesKey', 'GiantBombKey', 'ComicVineKey', 'BoardgameGeekKey'],
|
||||
|
||||
sfwFilter: true,
|
||||
templates: true,
|
||||
customDateFormat: 'L',
|
||||
|
|
@ -328,12 +332,12 @@ const DEFAULT_SETTINGS: MediaDbPluginSettings = {
|
|||
|
||||
BoardgameGeekAPI_disabledMediaTypes: [],
|
||||
ComicVineAPI_disabledMediaTypes: [],
|
||||
GiantBombAPI_disabledMediaTypes: [],
|
||||
//GiantBombAPI_disabledMediaTypes: [],
|
||||
IGDBAPI_disabledMediaTypes: [],
|
||||
RAWGAPI_disabledMediaTypes: [],
|
||||
MALAPI_disabledMediaTypes: [],
|
||||
MALAPIManga_disabledMediaTypes: [],
|
||||
MobyGamesAPI_disabledMediaTypes: [],
|
||||
//MobyGamesAPI_disabledMediaTypes: [],
|
||||
MusicBrainzAPI_disabledMediaTypes: [],
|
||||
OMDbAPI_disabledMediaTypes: [],
|
||||
OpenLibraryAPI_disabledMediaTypes: [],
|
||||
|
|
@ -610,38 +614,38 @@ export class MediaDbSettingTab extends PluginSettingTab {
|
|||
return component;
|
||||
}),
|
||||
);
|
||||
apiKeyGroup.addSetting(
|
||||
setting =>
|
||||
void setting
|
||||
.setName('Moby Games key')
|
||||
.setDesc('API key for "www.mobygames.com".')
|
||||
.addComponent(el => {
|
||||
const component = new SecretComponent(this.app, el);
|
||||
// apiKeyGroup.addSetting(
|
||||
// setting =>
|
||||
// void setting
|
||||
// .setName('Moby Games key')
|
||||
// .setDesc('API key for "www.mobygames.com".')
|
||||
// .addComponent(el => {
|
||||
// const component = new SecretComponent(this.app, el);
|
||||
|
||||
component.setValue(this.plugin.settings.MobyGamesKeyId).onChange(data => {
|
||||
this.plugin.settings.MobyGamesKeyId = data;
|
||||
void this.plugin.saveSettings();
|
||||
});
|
||||
// component.setValue(this.plugin.settings.MobyGamesKeyId).onChange(data => {
|
||||
// this.plugin.settings.MobyGamesKeyId = data;
|
||||
// void this.plugin.saveSettings();
|
||||
// });
|
||||
|
||||
return component;
|
||||
}),
|
||||
);
|
||||
apiKeyGroup.addSetting(
|
||||
setting =>
|
||||
void setting
|
||||
.setName('Giant Bomb Key')
|
||||
.setDesc('API key for "www.giantbomb.com".')
|
||||
.addComponent(el => {
|
||||
const component = new SecretComponent(this.app, el);
|
||||
// return component;
|
||||
// }),
|
||||
// );
|
||||
// apiKeyGroup.addSetting(
|
||||
// setting =>
|
||||
// void setting
|
||||
// .setName('Giant Bomb Key')
|
||||
// .setDesc('API key for "www.giantbomb.com".')
|
||||
// .addComponent(el => {
|
||||
// const component = new SecretComponent(this.app, el);
|
||||
|
||||
component.setValue(this.plugin.settings.GiantBombKeyId).onChange(data => {
|
||||
this.plugin.settings.GiantBombKeyId = data;
|
||||
void this.plugin.saveSettings();
|
||||
});
|
||||
// component.setValue(this.plugin.settings.GiantBombKeyId).onChange(data => {
|
||||
// this.plugin.settings.GiantBombKeyId = data;
|
||||
// void this.plugin.saveSettings();
|
||||
// });
|
||||
|
||||
return component;
|
||||
}),
|
||||
);
|
||||
// return component;
|
||||
// }),
|
||||
// );
|
||||
apiKeyGroup.addSetting(
|
||||
setting =>
|
||||
void setting
|
||||
|
|
|
|||
|
|
@ -295,3 +295,40 @@ small.media-db-plugin-list-text {
|
|||
width: var(--checkbox-size);
|
||||
height: var(--checkbox-size);
|
||||
}
|
||||
|
||||
.media-db-plugin-legacy-keys-modal {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
.media-db-plugin-legacy-keys-intro {
|
||||
color: var(--text-normal);
|
||||
}
|
||||
|
||||
.media-db-plugin-legacy-keys-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--size-4-3);
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.media-db-plugin-legacy-keys-textarea {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
min-height: var(--size-4-5);
|
||||
min-width: var(--size-4-7);
|
||||
box-sizing: border-box;
|
||||
resize: vertical;
|
||||
padding: var(--size-4-3);
|
||||
border-radius: var(--radius-s);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
background: var(--background-primary);
|
||||
color: var(--text-normal);
|
||||
font-family: var(--font-monospace);
|
||||
font-size: var(--font-ui-smaller);
|
||||
line-height: 1.5;
|
||||
white-space: pre;
|
||||
}
|
||||
.media-db-plugin-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue