()
| 44 | } |
| 45 | |
| 46 | private display() { |
| 47 | this.contentEl.empty(); |
| 48 | this.modalEl.addClass("qa-ai-wide-modal"); |
| 49 | this.contentEl.addClass("qa-ai-scroll-content"); |
| 50 | |
| 51 | this.contentEl.createEl("h2", { |
| 52 | text: `Browse models for ${this.provider.name}`, |
| 53 | cls: "qa-modal-title", |
| 54 | }); |
| 55 | |
| 56 | // Search/filter |
| 57 | new Setting(this.contentEl) |
| 58 | .setName("Search") |
| 59 | .addText((text) => { |
| 60 | text.setPlaceholder("Filter by name").onChange((value) => { |
| 61 | const q = value.trim().toLowerCase(); |
| 62 | this.filtered = this.allModels.filter((m) => m.name.toLowerCase().includes(q)); |
| 63 | this.renderList(); |
| 64 | }); |
| 65 | }) |
| 66 | .addExtraButton((btn) => { |
| 67 | btn.setIcon("check"); |
| 68 | btn.setTooltip("Select all"); |
| 69 | btn.onClick(() => { |
| 70 | this.filtered.forEach((m) => this.selectedIds.add(m.name)); |
| 71 | this.renderList(); |
| 72 | }); |
| 73 | }) |
| 74 | .addExtraButton((btn) => { |
| 75 | btn.setIcon("x"); |
| 76 | btn.setTooltip("Clear selection"); |
| 77 | btn.onClick(() => { |
| 78 | this.selectedIds.clear(); |
| 79 | this.renderList(); |
| 80 | }); |
| 81 | }); |
| 82 | |
| 83 | // Mode toggle |
| 84 | new Setting(this.contentEl) |
| 85 | .setName("Import mode") |
| 86 | .setDesc("Add will append new models. Replace will overwrite existing models with the selected list.") |
| 87 | .addDropdown((dd) => { |
| 88 | dd.addOption("add", "Add only"); |
| 89 | dd.addOption("replace", "Replace existing"); |
| 90 | dd.setValue(this.mode); |
| 91 | dd.onChange((v) => (this.mode = v as "add" | "replace")); |
| 92 | }) |
| 93 | .addButton((b) => { |
| 94 | b.setButtonText("Import selected").setCta().onClick(() => this.importSelected()); |
| 95 | }); |
| 96 | |
| 97 | // List container |
| 98 | this.contentEl.createDiv({ cls: "qa-model-directory" }); |
| 99 | |
| 100 | this.renderList(); |
| 101 | } |
| 102 | |
| 103 | private renderList() { |
no test coverage detected