62 lines
2.5 KiB
TypeScript
62 lines
2.5 KiB
TypeScript
import { Component, inject, input, OnChanges, output, signal } from '@angular/core';
|
|
import { FormsModule } from '@angular/forms';
|
|
import { RouterLink } from '@angular/router';
|
|
import { InstalledPlugin, PluginService } from '../../services/plugin.service';
|
|
|
|
export interface TaskPluginOptions {
|
|
plugins?: { id: string; profile: string; version?: string }[];
|
|
}
|
|
|
|
@Component({
|
|
selector: 'app-task-plugins', standalone: true, imports: [FormsModule, RouterLink],
|
|
templateUrl: './task-plugins.component.html', styleUrl: './task-plugins.component.scss'
|
|
})
|
|
export class TaskPluginsComponent implements OnChanges {
|
|
target = input<'android' | 'computer'>('android');
|
|
changed = output<TaskPluginOptions>();
|
|
private api = inject(PluginService);
|
|
automatic = true;
|
|
selected: Record<string, string> = {};
|
|
open = signal(false);
|
|
loading = signal(false);
|
|
error = signal('');
|
|
plugins = signal<InstalledPlugin[]>([]);
|
|
|
|
summary() {
|
|
return this.automatic ? '自动' : Object.keys(this.selected).length ? `已选 ${Object.keys(this.selected).length} 个` : '本次停用';
|
|
}
|
|
available() {
|
|
return this.plugins().filter(p => p.enabled && (!p.manifest.workspace || !!p.manifest.server || !!p.manifest.skill) && p.profiles.some(profile => profile.authorized) &&
|
|
p.manifest.targets.some(target => target === this.target() || (this.target() === 'android' && target === 'mixed')));
|
|
}
|
|
ngOnChanges() {
|
|
const allowed = new Set(this.available().map(p => p.manifest.id));
|
|
this.selected = Object.fromEntries(Object.entries(this.selected).filter(([id]) => allowed.has(id)));
|
|
this.emit();
|
|
}
|
|
authorizedProfiles(plugin: InstalledPlugin) { return plugin.profiles.filter(p => p.authorized); }
|
|
toggle() {
|
|
this.open.update(v => !v);
|
|
if (this.open()) this.load();
|
|
}
|
|
load() {
|
|
this.loading.set(true); this.error.set('');
|
|
this.api.list().subscribe({
|
|
next: value => { this.plugins.set(value.plugins); this.loading.set(false); },
|
|
error: () => { this.error.set('暂时无法读取插件。'); this.loading.set(false); }
|
|
});
|
|
}
|
|
choose(plugin: InstalledPlugin, event: Event) {
|
|
if ((event.target as HTMLInputElement).checked) {
|
|
const profiles = this.authorizedProfiles(plugin);
|
|
this.selected[plugin.manifest.id] = (profiles.find(p => p.is_default) || profiles[0]).name;
|
|
} else delete this.selected[plugin.manifest.id];
|
|
this.emit();
|
|
}
|
|
emit() {
|
|
this.changed.emit(this.automatic ? {} : {
|
|
plugins: Object.entries(this.selected).map(([id, profile]) => ({ id, profile }))
|
|
});
|
|
}
|
|
}
|