mirror of
https://github.com/nathonius/obsidian-github-link.git
synced 2026-07-22 09:20:25 +00:00
commit
240189c961
6 changed files with 349 additions and 197 deletions
|
|
@ -4,6 +4,8 @@ import { createOAuthDeviceAuth } from "@octokit/auth-oauth-device";
|
|||
import { request } from "@octokit/request";
|
||||
import { requestUrl } from "obsidian";
|
||||
|
||||
const defaultClientId = "baf0370cb98e1387d244";
|
||||
|
||||
function getHeaders(headers: HeadersInit | undefined): Record<string, string> | undefined {
|
||||
if (!headers) {
|
||||
return undefined;
|
||||
|
|
@ -71,10 +73,10 @@ async function doFetch(url: RequestInfo | URL, options?: RequestInit | undefined
|
|||
return partialResult as Response;
|
||||
}
|
||||
|
||||
export const auth = (verificationHandler: OnVerificationCallback) =>
|
||||
export const auth = (verificationHandler: OnVerificationCallback, clientId: string = defaultClientId) =>
|
||||
createOAuthDeviceAuth({
|
||||
clientType: "oauth-app",
|
||||
clientId: "baf0370cb98e1387d244",
|
||||
clientId,
|
||||
scopes: ["repo"],
|
||||
onVerification: verificationHandler,
|
||||
request: request.defaults({
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { DEFAULT_SETTINGS, GithubLinkPluginSettingsTab } from "./settings";
|
||||
import { Logger } from "./logger";
|
||||
|
||||
import type { GithubLinkPluginSettings } from "./settings";
|
||||
import type { GithubLinkPluginData, GithubLinkPluginSettings } from "./settings";
|
||||
import { InlineRenderer } from "./inline/inline";
|
||||
import { Plugin } from "obsidian";
|
||||
import { QueryProcessor } from "./query/processor";
|
||||
|
|
@ -9,6 +9,7 @@ import { createInlineViewPlugin } from "./inline/view-plugin";
|
|||
import { RequestCache } from "./github/cache";
|
||||
|
||||
export const PluginSettings: GithubLinkPluginSettings = { ...DEFAULT_SETTINGS };
|
||||
export const PluginData: GithubLinkPluginData = { cache: null, settings: PluginSettings };
|
||||
export const logger = new Logger();
|
||||
let cache: RequestCache;
|
||||
export function getCache(): RequestCache {
|
||||
|
|
@ -18,16 +19,40 @@ export function getCache(): RequestCache {
|
|||
export class GithubLinkPlugin extends Plugin {
|
||||
public cacheInterval: number | undefined;
|
||||
async onload() {
|
||||
Object.assign(PluginSettings, await this.loadData());
|
||||
let data = await this.loadData();
|
||||
|
||||
// Migrate settings from data root to settings -- remove in v1.0.0
|
||||
if (data.accounts) {
|
||||
const newSettings: GithubLinkPluginSettings = {
|
||||
accounts: data.accounts ?? PluginSettings.accounts,
|
||||
cacheIntervalSeconds: data.cacheIntervalSeconds ?? PluginSettings.cacheIntervalSeconds,
|
||||
defaultPageSize: data.defaultPageSize ?? PluginSettings.defaultPageSize,
|
||||
logLevel: data.logLevel ?? PluginSettings.logLevel,
|
||||
maxCacheAgeHours: data.maxCacheAgeHours ?? PluginSettings.maxCacheAgeHours,
|
||||
minRequestSeconds: data.minRequestSeconds ?? PluginSettings.minRequestSeconds,
|
||||
tagShowPRMergeable: data.tagShowPRMergeable ?? PluginSettings.tagShowPRMergeable,
|
||||
tagTooltips: data.tagTooltips ?? PluginSettings.tagTooltips,
|
||||
defaultAccount: data.defaultAccount ?? PluginSettings.defaultAccount,
|
||||
};
|
||||
const newData: GithubLinkPluginData = {
|
||||
cache: data.cache ?? PluginData.cache,
|
||||
settings: newSettings,
|
||||
};
|
||||
await this.saveData(newData);
|
||||
data = newData;
|
||||
}
|
||||
|
||||
Object.assign(PluginSettings, data.settings);
|
||||
Object.assign(PluginData, data);
|
||||
logger.logLevel = PluginSettings.logLevel;
|
||||
|
||||
cache = new RequestCache(PluginSettings.cache);
|
||||
cache = new RequestCache(PluginData.cache);
|
||||
|
||||
// Clean cache
|
||||
const maxAge = new Date(new Date().getTime() - PluginSettings.maxCacheAgeHours * 60 * 60 * 1000);
|
||||
const entriesDeleted = cache.clean(maxAge);
|
||||
if (entriesDeleted > 0) {
|
||||
PluginSettings.cache = cache.toJSON();
|
||||
PluginData.cache = cache.toJSON();
|
||||
await this.saveData(PluginSettings);
|
||||
logger.info(`Cleaned ${entriesDeleted} entries from request cache.`);
|
||||
}
|
||||
|
|
@ -50,10 +75,10 @@ export class GithubLinkPlugin extends Plugin {
|
|||
window.setInterval(async () => {
|
||||
logger.debug("Checking if cache needs a save.");
|
||||
if (cache.cacheUpdated) {
|
||||
PluginSettings.cache = cache.toJSON();
|
||||
await this.saveData(PluginSettings);
|
||||
PluginData.cache = cache.toJSON();
|
||||
await this.saveData(PluginData);
|
||||
cache.cacheUpdated = false;
|
||||
logger.info(`Saved request cache with ${PluginSettings.cache?.length} items.`);
|
||||
logger.info(`Saved request cache with ${PluginData.cache?.length} items.`);
|
||||
}
|
||||
}, PluginSettings.cacheIntervalSeconds * 1000),
|
||||
);
|
||||
|
|
|
|||
236
src/settings/account.ts
Normal file
236
src/settings/account.ts
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
import type { App } from "obsidian";
|
||||
import { Setting } from "obsidian";
|
||||
import type { GithubAccount } from "./types";
|
||||
import { AuthModal } from "src/auth-modal";
|
||||
import { auth } from "src/github/auth";
|
||||
import type { Verification } from "@octokit/auth-oauth-device/dist-types/types";
|
||||
|
||||
export class AccountSettings {
|
||||
authModal: AuthModal | null = null;
|
||||
newAccount: GithubAccount | null = null;
|
||||
|
||||
constructor(
|
||||
private readonly app: App,
|
||||
private readonly container: HTMLElement,
|
||||
private readonly saveCallback: () => Promise<void>,
|
||||
private readonly displayCallback: () => void,
|
||||
private readonly removeCallback: (account: GithubAccount) => void,
|
||||
) {}
|
||||
|
||||
public render(accounts: GithubAccount[]): void {
|
||||
for (const account of accounts) {
|
||||
this.renderAccountSetting(account);
|
||||
}
|
||||
}
|
||||
|
||||
public renderNewAccount(
|
||||
container: HTMLElement,
|
||||
saveNewAccountCallback: (account: GithubAccount) => Promise<void>,
|
||||
): void {
|
||||
if (!this.newAccount) {
|
||||
this.newAccount = { id: crypto.randomUUID(), name: "", orgs: [], token: "", customOAuth: false };
|
||||
}
|
||||
// TODO: Combine the new account and existing account rendering to reduce duplication
|
||||
const accountContainer = container.createDiv();
|
||||
const header = accountContainer.createEl("h3", { text: "New account" });
|
||||
|
||||
new Setting(accountContainer)
|
||||
.setName("Account name")
|
||||
.setDesc("Required.")
|
||||
.addText((text) => {
|
||||
text.setValue(this.newAccount!.name);
|
||||
text.onChange((value) => {
|
||||
this.newAccount!.name = value;
|
||||
header.setText(value ?? "New account");
|
||||
});
|
||||
})
|
||||
.addButton((button) => {
|
||||
button.setIcon("trash");
|
||||
button.setTooltip("Delete account");
|
||||
button.onClick(() => {
|
||||
this.newAccount = null;
|
||||
this.displayCallback();
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(accountContainer)
|
||||
.setName("Orgs and users")
|
||||
.setDesc(
|
||||
"A comma separated list of the GitHub organizations and users this account should be used for. Optional.",
|
||||
)
|
||||
.addTextArea((text) => {
|
||||
text.setValue(this.newAccount!.orgs.join(", "));
|
||||
text.onChange((value) => {
|
||||
this.newAccount!.orgs = value.split(",").map((acc) => acc.trim());
|
||||
});
|
||||
});
|
||||
|
||||
const oauthDesc = createFragment((fragment) => {
|
||||
fragment.appendText(
|
||||
"You can optionally provide your own OAuth app for more control and a larger request rate limit. See the ",
|
||||
);
|
||||
fragment.createEl("a", {
|
||||
text: "plugin documentation",
|
||||
href: "https://github.com/nathonius/obsidian-github-link/wiki/Authentication#custom-oauth-app",
|
||||
});
|
||||
fragment.appendText(" for instructions.");
|
||||
});
|
||||
const customOAuthSetting = new Setting(accountContainer)
|
||||
.setName("Use custom OAuth app")
|
||||
.setDesc(oauthDesc)
|
||||
.addToggle((toggle) => {
|
||||
toggle.setValue(this.newAccount!.customOAuth ?? false);
|
||||
toggle.onChange((value) => {
|
||||
this.newAccount!.customOAuth = value;
|
||||
this.displayCallback();
|
||||
});
|
||||
});
|
||||
if (this.newAccount.customOAuth) {
|
||||
customOAuthSetting.addText((text) => {
|
||||
text.setValue(this.newAccount!.clientId ?? "");
|
||||
text.setPlaceholder("Client ID");
|
||||
text.onChange((value) => {
|
||||
this.newAccount!.clientId = value;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
new Setting(accountContainer)
|
||||
.setName("Token")
|
||||
.setDesc(
|
||||
"A GitHub token, which can be generated automatically (recommended) or by creating a personal access token (not recommended unless org does not allow OAuth tokens). Required.",
|
||||
)
|
||||
.addButton((button) => {
|
||||
button.setButtonText("Generate Token");
|
||||
button.onClick(async () => {
|
||||
const authResult = await auth(this.tokenVerification.bind(this))({
|
||||
type: "oauth",
|
||||
});
|
||||
this.authModal?.close();
|
||||
this.authModal = null;
|
||||
this.newAccount!.token = authResult.token;
|
||||
this.displayCallback();
|
||||
});
|
||||
})
|
||||
.addText((text) => {
|
||||
text.setPlaceholder("Personal Access Token / OAuth Token");
|
||||
text.setValue(this.newAccount!.token);
|
||||
text.onChange((value) => {
|
||||
this.newAccount!.token = value;
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(accountContainer).addButton((button) => {
|
||||
button.setButtonText("Save account");
|
||||
button.setTooltip("Save account");
|
||||
button.setIcon("save");
|
||||
button.onClick(async () => {
|
||||
if (!this.newAccount?.name) {
|
||||
return;
|
||||
}
|
||||
await saveNewAccountCallback(this.newAccount);
|
||||
this.newAccount = null;
|
||||
this.displayCallback();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public renderAccountSetting(account: GithubAccount, parent: HTMLElement = this.container): void {
|
||||
const accountContainer = parent.createDiv();
|
||||
accountContainer.createEl("h3", { text: account.name });
|
||||
|
||||
new Setting(accountContainer)
|
||||
.setName("Account name")
|
||||
.addText((text) => {
|
||||
text.setValue(account.name);
|
||||
text.onChange((value) => {
|
||||
account.name = value;
|
||||
this.saveCallback();
|
||||
});
|
||||
})
|
||||
.addButton((button) => {
|
||||
button.setIcon("trash");
|
||||
button.setTooltip("Delete account");
|
||||
button.onClick(async () => {
|
||||
this.removeCallback(account);
|
||||
await this.saveCallback();
|
||||
this.displayCallback();
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(accountContainer)
|
||||
.setName("Orgs and users")
|
||||
.setDesc("A comma separated list of the GitHub organizations and users this account should be used for.")
|
||||
.addTextArea((text) => {
|
||||
text.setValue(account.orgs.join(", "));
|
||||
text.onChange((value) => {
|
||||
account.orgs = value.split(",").map((org) => org.trim());
|
||||
this.saveCallback();
|
||||
});
|
||||
});
|
||||
|
||||
const oauthDesc = createFragment((fragment) => {
|
||||
fragment.appendText(
|
||||
"You can optionally provide your own OAuth app for more control and a larger request rate limit. See the ",
|
||||
);
|
||||
fragment.createEl("a", { text: "plugin documentation", href: "#" });
|
||||
fragment.appendText(" for instructions.");
|
||||
});
|
||||
const customOAuthSetting = new Setting(accountContainer)
|
||||
.setName("Use custom OAuth app")
|
||||
.setDesc(oauthDesc)
|
||||
.addToggle((toggle) => {
|
||||
toggle.setValue(account.customOAuth ?? false);
|
||||
toggle.onChange((value) => {
|
||||
account.customOAuth = value;
|
||||
this.displayCallback();
|
||||
});
|
||||
});
|
||||
if (account.customOAuth) {
|
||||
customOAuthSetting.addText((text) => {
|
||||
text.setValue(account.clientId ?? "");
|
||||
text.setPlaceholder("Client ID");
|
||||
text.onChange((value) => {
|
||||
account.clientId = value;
|
||||
this.saveCallback();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
new Setting(accountContainer)
|
||||
.setName("Token")
|
||||
.setDesc(
|
||||
"A GitHub token, which can be generated automatically (recommended) or by creating a personal access token (not recommended unless org does not allow OAuth tokens).",
|
||||
)
|
||||
.addButton((button) => {
|
||||
button.setButtonText("Generate Token");
|
||||
button.onClick(async () => {
|
||||
const customClientId = account.customOAuth ? account.clientId : undefined;
|
||||
const authResult = await auth(
|
||||
this.tokenVerification.bind(this),
|
||||
customClientId,
|
||||
)({
|
||||
type: "oauth",
|
||||
});
|
||||
this.authModal?.close();
|
||||
this.authModal = null;
|
||||
account.token = authResult.token;
|
||||
await this.saveCallback();
|
||||
this.displayCallback();
|
||||
});
|
||||
})
|
||||
.addText((text) => {
|
||||
text.setPlaceholder("Personal Access Token / OAuth Token");
|
||||
text.setValue(account.token);
|
||||
text.onChange((value) => {
|
||||
account.token = value;
|
||||
this.saveCallback();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private tokenVerification(verification: Verification) {
|
||||
this.authModal = new AuthModal(this.app, verification);
|
||||
this.authModal.open();
|
||||
}
|
||||
}
|
||||
3
src/settings/index.ts
Normal file
3
src/settings/index.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export type { GithubAccount, GithubLinkPluginData, GithubLinkPluginSettings } from "./types";
|
||||
export { DEFAULT_SETTINGS } from "./types";
|
||||
export { GithubLinkPluginSettingsTab } from "./settings-tab";
|
||||
|
|
@ -2,49 +2,21 @@
|
|||
import { Notice, PluginSettingTab, Setting } from "obsidian";
|
||||
|
||||
import type { App } from "obsidian";
|
||||
import { AuthModal } from "./auth-modal";
|
||||
import type { GithubLinkPlugin } from "./plugin";
|
||||
import { LogLevel } from "./logger";
|
||||
import { PluginSettings, getCache } from "./plugin";
|
||||
import type { Verification } from "@octokit/auth-oauth-device/dist-types/types";
|
||||
import { auth } from "./github/auth";
|
||||
|
||||
export interface GithubAccount {
|
||||
id: string;
|
||||
name: string;
|
||||
orgs: string[];
|
||||
token: string;
|
||||
}
|
||||
|
||||
export interface GithubLinkPluginSettings {
|
||||
accounts: GithubAccount[];
|
||||
defaultAccount?: string;
|
||||
defaultPageSize: number;
|
||||
logLevel: LogLevel;
|
||||
tagTooltips: boolean;
|
||||
tagShowPRMergeable: boolean;
|
||||
cacheIntervalSeconds: number;
|
||||
maxCacheAgeHours: number;
|
||||
minRequestSeconds: number;
|
||||
cache: string[] | null; // TODO: Move this out of settings; it's not a setting it's just part of plugin data.
|
||||
}
|
||||
|
||||
export const DEFAULT_SETTINGS: GithubLinkPluginSettings = {
|
||||
accounts: [],
|
||||
defaultPageSize: 10,
|
||||
logLevel: LogLevel.Error,
|
||||
tagTooltips: false,
|
||||
tagShowPRMergeable: false,
|
||||
cacheIntervalSeconds: 60,
|
||||
maxCacheAgeHours: 120,
|
||||
minRequestSeconds: 60,
|
||||
cache: null,
|
||||
};
|
||||
import type { GithubLinkPlugin } from "../plugin";
|
||||
import { LogLevel } from "../logger";
|
||||
import { PluginData, PluginSettings, getCache } from "../plugin";
|
||||
import type { GithubAccount, GithubLinkPluginData } from "./types";
|
||||
import { DEFAULT_SETTINGS } from "./types";
|
||||
import { AccountSettings } from "./account";
|
||||
|
||||
export class GithubLinkPluginSettingsTab extends PluginSettingTab {
|
||||
authModal: AuthModal | null = null;
|
||||
newAccount: GithubAccount | null = null;
|
||||
|
||||
private readonly accountSettings = new AccountSettings(
|
||||
this.app,
|
||||
this.containerEl,
|
||||
this.saveSettings.bind(this),
|
||||
this.display.bind(this),
|
||||
this.removeAccount.bind(this),
|
||||
);
|
||||
constructor(
|
||||
public app: App,
|
||||
private readonly plugin: GithubLinkPlugin,
|
||||
|
|
@ -52,7 +24,7 @@ export class GithubLinkPluginSettingsTab extends PluginSettingTab {
|
|||
super(app, plugin);
|
||||
}
|
||||
|
||||
display() {
|
||||
public display() {
|
||||
const { containerEl } = this;
|
||||
containerEl.empty();
|
||||
containerEl.createEl("h2", { text: "GitHub authentication" });
|
||||
|
|
@ -61,16 +33,20 @@ export class GithubLinkPluginSettingsTab extends PluginSettingTab {
|
|||
text: "No authentication is required to reference public repositories. Providing a token allows referencing private repos, but the token is stored in plain text. You can create multiple accounts for multiple tokens.",
|
||||
});
|
||||
|
||||
new Setting(containerEl).setName("Add account").addButton((button) => {
|
||||
const newAccountSection = containerEl.createDiv();
|
||||
new Setting(newAccountSection).setName("Add account").addButton((button) => {
|
||||
button.setButtonText("");
|
||||
button.setIcon("plus");
|
||||
button.setTooltip("Add Account");
|
||||
button.onClick(() => {
|
||||
this.newAccount = { id: crypto.randomUUID(), name: "", orgs: [], token: "" };
|
||||
this.display();
|
||||
this.accountSettings.renderNewAccount(newAccountSection, this.saveNewAccount.bind(this));
|
||||
});
|
||||
});
|
||||
|
||||
if (this.accountSettings.newAccount) {
|
||||
this.accountSettings.renderNewAccount(newAccountSection, this.saveNewAccount.bind(this));
|
||||
}
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Default account")
|
||||
.setDesc("The account that will be used if no other users or organizations match.")
|
||||
|
|
@ -90,144 +66,7 @@ export class GithubLinkPluginSettingsTab extends PluginSettingTab {
|
|||
});
|
||||
});
|
||||
|
||||
// TODO: Combine the new account and existing account rendering to reduce duplication
|
||||
if (this.newAccount !== null) {
|
||||
const accountContainer = containerEl.createDiv();
|
||||
const header = accountContainer.createEl("h3", { text: "New account" });
|
||||
|
||||
new Setting(accountContainer)
|
||||
.setName("Account name")
|
||||
.setDesc("Required.")
|
||||
.addText((text) => {
|
||||
text.setValue(this.newAccount!.name);
|
||||
text.onChange((value) => {
|
||||
this.newAccount!.name = value;
|
||||
header.setText(value ?? "New account");
|
||||
});
|
||||
})
|
||||
.addButton((button) => {
|
||||
button.setIcon("trash");
|
||||
button.setTooltip("Delete account");
|
||||
button.onClick(() => {
|
||||
this.newAccount = null;
|
||||
this.display();
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(accountContainer)
|
||||
.setName("Orgs and users")
|
||||
.setDesc(
|
||||
"A comma separated list of the GitHub organizations and users this account should be used for. Optional.",
|
||||
)
|
||||
.addTextArea((text) => {
|
||||
text.setValue(this.newAccount!.orgs.join(", "));
|
||||
text.onChange((value) => {
|
||||
this.newAccount!.orgs = value.split(",");
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(accountContainer)
|
||||
.setName("Token")
|
||||
.setDesc(
|
||||
"A GitHub token, which can be generated automatically (recommended) or by creating a personal access token (not recommended unless org does not allow OAuth tokens). Required.",
|
||||
)
|
||||
.addButton((button) => {
|
||||
button.setButtonText("Generate Token");
|
||||
button.onClick(async () => {
|
||||
const authResult = await auth(this.tokenVerification.bind(this))({
|
||||
type: "oauth",
|
||||
});
|
||||
this.authModal?.close();
|
||||
this.authModal = null;
|
||||
this.newAccount!.token = authResult.token;
|
||||
this.display();
|
||||
});
|
||||
})
|
||||
.addText((text) => {
|
||||
text.setPlaceholder("Personal Access Token / OAuth Token");
|
||||
text.setValue(this.newAccount!.token);
|
||||
text.onChange((value) => {
|
||||
this.newAccount!.token = value;
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(accountContainer).addButton((button) => {
|
||||
button.setButtonText("Save account");
|
||||
button.setTooltip("Save account");
|
||||
button.setIcon("save");
|
||||
button.onClick(async () => {
|
||||
if (!this.newAccount?.name || !this.newAccount.token) {
|
||||
return;
|
||||
}
|
||||
PluginSettings.accounts.unshift(this.newAccount);
|
||||
await this.saveSettings();
|
||||
this.newAccount = null;
|
||||
this.display();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
for (const account of PluginSettings.accounts) {
|
||||
const accountContainer = containerEl.createDiv();
|
||||
accountContainer.createEl("h3", { text: account.name });
|
||||
|
||||
new Setting(accountContainer)
|
||||
.setName("Account name")
|
||||
.addText((text) => {
|
||||
text.setValue(account.name);
|
||||
text.onChange((value) => {
|
||||
account.name = value;
|
||||
this.saveSettings();
|
||||
});
|
||||
})
|
||||
.addButton((button) => {
|
||||
button.setIcon("trash");
|
||||
button.setTooltip("Delete account");
|
||||
button.onClick(async () => {
|
||||
PluginSettings.accounts.remove(account);
|
||||
await this.saveSettings();
|
||||
this.display();
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(accountContainer)
|
||||
.setName("Orgs and users")
|
||||
.setDesc("A comma separated list of the GitHub organizations and users this account should be used for.")
|
||||
.addTextArea((text) => {
|
||||
text.setValue(account.orgs.join(", "));
|
||||
text.onChange((value) => {
|
||||
account.orgs = value.split(",").map((org) => org.trim());
|
||||
this.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(accountContainer)
|
||||
.setName("Token")
|
||||
.setDesc(
|
||||
"A GitHub token, which can be generated automatically (recommended) or by creating a personal access token (not recommended unless org does not allow OAuth tokens).",
|
||||
)
|
||||
.addButton((button) => {
|
||||
button.setButtonText("Generate Token");
|
||||
button.onClick(async () => {
|
||||
const authResult = await auth(this.tokenVerification.bind(this))({
|
||||
type: "oauth",
|
||||
});
|
||||
this.authModal?.close();
|
||||
this.authModal = null;
|
||||
account.token = authResult.token;
|
||||
await this.saveSettings();
|
||||
this.display();
|
||||
});
|
||||
})
|
||||
.addText((text) => {
|
||||
text.setPlaceholder("Personal Access Token / OAuth Token");
|
||||
text.setValue(account.token);
|
||||
text.onChange((value) => {
|
||||
account.token = value;
|
||||
this.saveSettings();
|
||||
});
|
||||
});
|
||||
}
|
||||
this.accountSettings.render(PluginSettings.accounts);
|
||||
|
||||
containerEl.createEl("h2", { text: "Other settings" });
|
||||
|
||||
|
|
@ -374,7 +213,7 @@ export class GithubLinkPluginSettingsTab extends PluginSettingTab {
|
|||
button.setButtonText("Clear cache");
|
||||
button.onClick(async () => {
|
||||
const itemsDeleted = getCache().clean(new Date());
|
||||
PluginSettings.cache = null;
|
||||
PluginData.cache = null;
|
||||
await this.saveSettings();
|
||||
new Notice(`Removed ${itemsDeleted} stored items from GitHub Link cache.`, 3000);
|
||||
});
|
||||
|
|
@ -408,11 +247,20 @@ export class GithubLinkPluginSettingsTab extends PluginSettingTab {
|
|||
}
|
||||
|
||||
private saveSettings() {
|
||||
return this.plugin.saveData(PluginSettings);
|
||||
const newData: GithubLinkPluginData = {
|
||||
cache: PluginData.cache,
|
||||
settings: PluginSettings,
|
||||
};
|
||||
return this.plugin.saveData(newData);
|
||||
}
|
||||
|
||||
private tokenVerification(verification: Verification) {
|
||||
this.authModal = new AuthModal(this.app, verification);
|
||||
this.authModal.open();
|
||||
private async removeAccount(account: GithubAccount): Promise<void> {
|
||||
PluginSettings.accounts.remove(account);
|
||||
await this.saveSettings();
|
||||
}
|
||||
|
||||
private async saveNewAccount(account: GithubAccount): Promise<void> {
|
||||
PluginSettings.accounts.unshift(account);
|
||||
await this.saveSettings();
|
||||
}
|
||||
}
|
||||
38
src/settings/types.ts
Normal file
38
src/settings/types.ts
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import { LogLevel } from "src/logger";
|
||||
|
||||
export interface GithubAccount {
|
||||
id: string;
|
||||
name: string;
|
||||
orgs: string[];
|
||||
token: string;
|
||||
customOAuth?: boolean;
|
||||
clientId?: string;
|
||||
}
|
||||
|
||||
export interface GithubLinkPluginData {
|
||||
settings: GithubLinkPluginSettings;
|
||||
cache: string[] | null;
|
||||
}
|
||||
|
||||
export interface GithubLinkPluginSettings {
|
||||
accounts: GithubAccount[];
|
||||
defaultAccount?: string;
|
||||
defaultPageSize: number;
|
||||
logLevel: LogLevel;
|
||||
tagTooltips: boolean;
|
||||
tagShowPRMergeable: boolean;
|
||||
cacheIntervalSeconds: number;
|
||||
maxCacheAgeHours: number;
|
||||
minRequestSeconds: number;
|
||||
}
|
||||
|
||||
export const DEFAULT_SETTINGS: GithubLinkPluginSettings = {
|
||||
accounts: [],
|
||||
defaultPageSize: 10,
|
||||
logLevel: LogLevel.Error,
|
||||
tagTooltips: false,
|
||||
tagShowPRMergeable: false,
|
||||
cacheIntervalSeconds: 60,
|
||||
maxCacheAgeHours: 120,
|
||||
minRequestSeconds: 60,
|
||||
};
|
||||
Loading…
Reference in a new issue