mirror of
https://github.com/firstsun-dev/git-files-sync.git
synced 2026-07-22 17:20:30 +00:00
291 lines
9.1 KiB
TypeScript
291 lines
9.1 KiB
TypeScript
import {App, PluginSettingTab, Setting, Notice} from 'obsidian';
|
|
import GitLabFilesPush from "./main";
|
|
|
|
export interface SyncMetadata {
|
|
lastSyncedSha: string;
|
|
lastSyncedAt: number;
|
|
lastKnownPath?: string;
|
|
}
|
|
|
|
export type GitServiceType = 'gitlab' | 'github' | 'gitea';
|
|
|
|
/**
|
|
* How symbolic links (Git blobs with mode 120000) are synced:
|
|
* - 'real': recreate a real OS symlink on desktop; on mobile (no symlink API)
|
|
* fall back to syncing the link target's content as a normal file.
|
|
* - 'follow': always sync the target file's content as a normal file.
|
|
* - 'skip': ignore symlinks entirely.
|
|
*/
|
|
export type SymlinkHandling = 'real' | 'follow' | 'skip';
|
|
|
|
export interface GitLabFilesPushSettings {
|
|
serviceType: GitServiceType;
|
|
gitlabToken: string;
|
|
gitlabBaseUrl: string;
|
|
projectId: string;
|
|
githubToken: string;
|
|
githubOwner: string;
|
|
githubRepo: string;
|
|
giteaToken: string;
|
|
giteaBaseUrl: string;
|
|
giteaOwner: string;
|
|
giteaRepo: string;
|
|
branch: string;
|
|
syncMetadata: Record<string, SyncMetadata>;
|
|
rootPath: string;
|
|
vaultFolder: string;
|
|
symlinkHandling: SymlinkHandling;
|
|
}
|
|
|
|
export function getServiceName(settings: GitLabFilesPushSettings): string {
|
|
if (settings.serviceType === 'gitlab') return 'GitLab';
|
|
if (settings.serviceType === 'gitea') return 'Gitea';
|
|
return 'GitHub';
|
|
}
|
|
|
|
export const DEFAULT_SETTINGS: GitLabFilesPushSettings = {
|
|
serviceType: 'gitlab',
|
|
gitlabToken: '',
|
|
gitlabBaseUrl: 'https://gitlab.com',
|
|
projectId: '',
|
|
githubToken: '',
|
|
githubOwner: '',
|
|
githubRepo: '',
|
|
giteaToken: '',
|
|
giteaBaseUrl: '',
|
|
giteaOwner: '',
|
|
giteaRepo: '',
|
|
rootPath: "",
|
|
branch: 'main',
|
|
syncMetadata: {},
|
|
vaultFolder: '',
|
|
symlinkHandling: 'real'
|
|
}
|
|
|
|
export class GitLabSyncSettingTab extends PluginSettingTab {
|
|
plugin: GitLabFilesPush;
|
|
|
|
constructor(app: App, plugin: GitLabFilesPush) {
|
|
super(app, plugin);
|
|
this.plugin = plugin;
|
|
}
|
|
|
|
display(): void {
|
|
const {containerEl} = this;
|
|
|
|
containerEl.empty();
|
|
|
|
new Setting(containerEl)
|
|
.setName('Git service')
|
|
.setDesc('Choose your Git hosting service')
|
|
.addDropdown(dropdown => dropdown
|
|
.addOption('gitlab', 'GitLab')
|
|
.addOption('github', 'GitHub')
|
|
.addOption('gitea', 'Gitea')
|
|
.setValue(this.plugin.settings.serviceType)
|
|
.onChange((value: string) => {
|
|
this.plugin.settings.serviceType = value as GitServiceType;
|
|
void this.plugin.saveSettings();
|
|
this.plugin.initializeGitService();
|
|
this.display();
|
|
}));
|
|
|
|
new Setting(containerEl).setName('').setHeading();
|
|
|
|
if (this.plugin.settings.serviceType === 'gitlab') {
|
|
this.displayGitLabSettings(containerEl);
|
|
} else if (this.plugin.settings.serviceType === 'gitea') {
|
|
this.displayGiteaSettings(containerEl);
|
|
} else {
|
|
this.displayGitHubSettings(containerEl);
|
|
}
|
|
|
|
new Setting(containerEl)
|
|
.setName('Branch')
|
|
.setDesc('Branch to push or pull from')
|
|
.addText(text => text
|
|
.setPlaceholder('Main')
|
|
.setValue(this.plugin.settings.branch)
|
|
.onChange((value) => {
|
|
this.plugin.settings.branch = value || 'main';
|
|
void this.plugin.saveSettings();
|
|
}));
|
|
|
|
new Setting(containerEl)
|
|
.setName('Root path')
|
|
.setDesc('Optional: subfolder in repository (e.g. "notes")')
|
|
.addText(text => text
|
|
.setPlaceholder('Enter subfolder path')
|
|
.setValue(this.plugin.settings.rootPath)
|
|
.onChange((value) => {
|
|
this.plugin.settings.rootPath = value.replace(/^\/|\/$/g, '');
|
|
void this.plugin.saveSettings();
|
|
this.plugin.initializeGitService();
|
|
}));
|
|
|
|
new Setting(containerEl)
|
|
.setName('Vault folder')
|
|
.setDesc('Optional: only sync files in this vault folder (e.g. "sync" to only sync files in the sync folder)')
|
|
.addText(text => text
|
|
.setPlaceholder('Leave empty to sync all files')
|
|
.setValue(this.plugin.settings.vaultFolder)
|
|
.onChange((value) => {
|
|
this.plugin.settings.vaultFolder = value.replace(/^\/|\/$/g, '');
|
|
void this.plugin.saveSettings();
|
|
}));
|
|
|
|
new Setting(containerEl)
|
|
.setName('Symbolic links')
|
|
.setDesc('How to sync symlinks: "real" recreates the link on desktop and falls back to the target content on mobile, "follow" always syncs the target content, and "skip" ignores symlinks.')
|
|
.addDropdown(dropdown => dropdown
|
|
.addOption('real', 'Real symlink (recommended)')
|
|
.addOption('follow', 'Follow (sync target content)')
|
|
.addOption('skip', 'Skip')
|
|
.setValue(this.plugin.settings.symlinkHandling)
|
|
.onChange((value: string) => {
|
|
this.plugin.settings.symlinkHandling = value as SymlinkHandling;
|
|
void this.plugin.saveSettings();
|
|
}));
|
|
|
|
new Setting(containerEl)
|
|
.setName('Test connection')
|
|
.setDesc(`Verify your ${getServiceName(this.plugin.settings)} settings`)
|
|
.addButton(button => button
|
|
.setButtonText('Test connection')
|
|
.onClick(async () => {
|
|
try {
|
|
await this.plugin.gitService.testConnection();
|
|
new Notice(`${getServiceName(this.plugin.settings)} connection successful!`);
|
|
} catch (e: unknown) {
|
|
const message = e instanceof Error ? e.message : String(e);
|
|
new Notice(`Connection failed: ${message}`);
|
|
}
|
|
}));
|
|
}
|
|
|
|
private displayGitLabSettings(containerEl: HTMLElement): void {
|
|
new Setting(containerEl)
|
|
.setName('GitLab personal access token')
|
|
.setDesc('Create a token in GitLab user settings > access tokens with "API" scope')
|
|
.addText(text => text
|
|
.setPlaceholder('Enter your token')
|
|
.setValue(this.plugin.settings.gitlabToken)
|
|
.onChange((value) => {
|
|
this.plugin.settings.gitlabToken = value;
|
|
void this.plugin.saveSettings();
|
|
this.plugin.initializeGitService();
|
|
}));
|
|
|
|
new Setting(containerEl)
|
|
.setName('GitLab base URL')
|
|
.setDesc('Defaults to https://gitlab.com')
|
|
.addText(text => text
|
|
.setPlaceholder('https://gitlab.com')
|
|
.setValue(this.plugin.settings.gitlabBaseUrl)
|
|
.onChange((value) => {
|
|
this.plugin.settings.gitlabBaseUrl = value || 'https://gitlab.com';
|
|
void this.plugin.saveSettings();
|
|
this.plugin.initializeGitService();
|
|
}));
|
|
|
|
new Setting(containerEl)
|
|
.setName('Project ID')
|
|
.setDesc('Found in GitLab project overview')
|
|
.addText(text => text
|
|
.setPlaceholder('Enter numeric project ID')
|
|
.setValue(this.plugin.settings.projectId)
|
|
.onChange((value) => {
|
|
this.plugin.settings.projectId = value;
|
|
void this.plugin.saveSettings();
|
|
this.plugin.initializeGitService();
|
|
}));
|
|
}
|
|
|
|
private displayGiteaSettings(containerEl: HTMLElement): void {
|
|
new Setting(containerEl)
|
|
.setName('Gitea personal access token')
|
|
.setDesc('Create a token in user settings > applications > access tokens')
|
|
.addText(text => text
|
|
.setPlaceholder('Enter your token')
|
|
.setValue(this.plugin.settings.giteaToken)
|
|
.onChange((value) => {
|
|
this.plugin.settings.giteaToken = value;
|
|
void this.plugin.saveSettings();
|
|
this.plugin.initializeGitService();
|
|
}));
|
|
|
|
new Setting(containerEl)
|
|
.setName('Gitea base URL')
|
|
.setDesc('URL of your Gitea instance (e.g. https://gitea.example.com)')
|
|
.addText(text => text
|
|
.setPlaceholder('https://gitea.example.com')
|
|
.setValue(this.plugin.settings.giteaBaseUrl)
|
|
.onChange((value) => {
|
|
this.plugin.settings.giteaBaseUrl = value;
|
|
void this.plugin.saveSettings();
|
|
this.plugin.initializeGitService();
|
|
}));
|
|
|
|
new Setting(containerEl)
|
|
.setName('Repository owner')
|
|
.setDesc('Gitea username or organization name')
|
|
.addText(text => text
|
|
.setPlaceholder('Username')
|
|
.setValue(this.plugin.settings.giteaOwner)
|
|
.onChange((value) => {
|
|
this.plugin.settings.giteaOwner = value;
|
|
void this.plugin.saveSettings();
|
|
this.plugin.initializeGitService();
|
|
}));
|
|
|
|
new Setting(containerEl)
|
|
.setName('Repository name')
|
|
.setDesc('Name of the repository')
|
|
.addText(text => text
|
|
.setPlaceholder('My notes')
|
|
.setValue(this.plugin.settings.giteaRepo)
|
|
.onChange((value) => {
|
|
this.plugin.settings.giteaRepo = value;
|
|
void this.plugin.saveSettings();
|
|
this.plugin.initializeGitService();
|
|
}));
|
|
}
|
|
|
|
private displayGitHubSettings(containerEl: HTMLElement): void {
|
|
new Setting(containerEl)
|
|
.setName('GitHub personal access token')
|
|
.setDesc('Create a token in GitHub settings > developer settings > personal access tokens with "repo" scope')
|
|
.addText(text => text
|
|
.setPlaceholder('Enter your token')
|
|
.setValue(this.plugin.settings.githubToken)
|
|
.onChange((value) => {
|
|
this.plugin.settings.githubToken = value;
|
|
void this.plugin.saveSettings();
|
|
this.plugin.initializeGitService();
|
|
}));
|
|
|
|
new Setting(containerEl)
|
|
.setName('Repository owner')
|
|
.setDesc('GitHub username or organization name')
|
|
.addText(text => text
|
|
.setPlaceholder('Username')
|
|
.setValue(this.plugin.settings.githubOwner)
|
|
.onChange((value) => {
|
|
this.plugin.settings.githubOwner = value;
|
|
void this.plugin.saveSettings();
|
|
this.plugin.initializeGitService();
|
|
}));
|
|
|
|
new Setting(containerEl)
|
|
.setName('Repository name')
|
|
.setDesc('Name of the GitHub repository')
|
|
.addText(text => text
|
|
.setPlaceholder('My notes')
|
|
.setValue(this.plugin.settings.githubRepo)
|
|
.onChange((value) => {
|
|
this.plugin.settings.githubRepo = value;
|
|
void this.plugin.saveSettings();
|
|
this.plugin.initializeGitService();
|
|
}));
|
|
}
|
|
}
|