feat: add search and filtering to batch installer dialog
This commit is contained in:
@@ -10,7 +10,7 @@ One-click batch install plugins from GitHub repositories to your OpenWebUI insta
|
||||
- **Auto-Update**: Automatically updates previously installed plugins
|
||||
- **Public GitHub Support**: Install plugins from any public GitHub repository
|
||||
- **Multi-Type Support**: Supports Pipe, Action, Filter, and Tool plugins
|
||||
- **Interactive Selection Dialog**: Review the filtered list with type tags and plugin descriptions, then install only the checked subset
|
||||
- **Interactive Selection Dialog**: Filter by type, search by keyword, review plugin descriptions, then install only the checked subset
|
||||
- **i18n**: Supports 11 languages
|
||||
|
||||
## Flow
|
||||
@@ -33,7 +33,7 @@ User Input
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ Show Selection Dialog │
|
||||
│ (checkbox list + type tags + desc) │
|
||||
│ (type filter + search + desc) │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
├── [Cancel] → End
|
||||
@@ -59,7 +59,7 @@ User Input
|
||||
|
||||
Each request handles one repository. To mix repositories, send another request after the previous installation completes.
|
||||
|
||||
After plugin discovery and filtering, OpenWebUI opens a browser dialog built with the `execute` event so you can review plugin descriptions, use type tags for quick batch selection, and check exactly which plugins to install before the API calls start.
|
||||
After plugin discovery and filtering, OpenWebUI opens a browser dialog built with the `execute` event so you can filter by plugin type, search by keyword, review plugin descriptions, and check exactly which plugins to install before the API calls start.
|
||||
|
||||
## Quick Start: Install Popular Collections
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
- 自动更新:自动更新之前安装过的插件
|
||||
- 公开 GitHub 支持:支持从任何公开 GitHub 仓库安装插件
|
||||
- 多类型支持:支持 Pipe、Action、Filter 和 Tool 插件
|
||||
- 交互式选择对话框:先查看带类型标签和描述信息的过滤列表,再勾选要安装的插件,只安装所选子集
|
||||
- 交互式选择对话框:先按类型筛选、按关键词搜索并查看描述信息,再勾选要安装的插件,只安装所选子集
|
||||
- 国际化:支持 11 种语言
|
||||
|
||||
## 流程
|
||||
@@ -33,7 +33,7 @@
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ 显示选择对话框 │
|
||||
│ (复选列表 + 类型标签 + 描述) │
|
||||
│ (类型筛选 + 搜索 + 描述) │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
├── [取消] → 结束
|
||||
@@ -59,7 +59,7 @@
|
||||
|
||||
每次请求处理一个仓库。如需混合多个来源,请在上一次安装完成后再发起下一次请求。
|
||||
|
||||
在插件发现和过滤完成后,OpenWebUI 会通过 `execute` 事件打开浏览器选择对话框。你可以先查看插件描述,使用类型标签进行批量勾选,再开始调用安装 API。
|
||||
在插件发现和过滤完成后,OpenWebUI 会通过 `execute` 事件打开浏览器选择对话框。你可以先按类型筛选、通过关键词搜索、查看插件描述,再开始调用安装 API。
|
||||
|
||||
## 快速开始:安装热门插件集
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ One-click batch install plugins from GitHub repositories to your OpenWebUI insta
|
||||
- **Auto-Update**: Automatically updates previously installed plugins
|
||||
- **Public GitHub Support**: Install plugins from any public GitHub repository
|
||||
- **Multi-Type Support**: Supports Pipe, Action, Filter, and Tool plugins
|
||||
- **Interactive Selection Dialog**: Review the filtered list with type tags and plugin descriptions, then install only the checked subset
|
||||
- **Interactive Selection Dialog**: Filter by type, search by keyword, review plugin descriptions, then install only the checked subset
|
||||
- **i18n**: Supports 11 languages
|
||||
|
||||
## Flow
|
||||
@@ -37,7 +37,7 @@ User Input
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ Show Selection Dialog │
|
||||
│ (checkbox list + type tags + desc) │
|
||||
│ (type filter + search + desc) │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
├── [Cancel] → End
|
||||
@@ -63,7 +63,7 @@ User Input
|
||||
|
||||
Each request handles one repository. To mix repositories, send another request after the previous installation completes.
|
||||
|
||||
After plugin discovery and filtering, OpenWebUI opens a browser dialog built with the `execute` event so you can review plugin descriptions, use type tags for quick batch selection, and check exactly which plugins to install before the API calls start.
|
||||
After plugin discovery and filtering, OpenWebUI opens a browser dialog built with the `execute` event so you can filter by plugin type, search by keyword, review plugin descriptions, and check exactly which plugins to install before the API calls start.
|
||||
|
||||
## Quick Start: Install Popular Collections
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
- 自动更新:自动更新之前安装过的插件
|
||||
- 公开 GitHub 支持:支持从任何公开 GitHub 仓库安装插件
|
||||
- 多类型支持:支持 Pipe、Action、Filter 和 Tool 插件
|
||||
- 交互式选择对话框:先查看带类型标签和描述信息的过滤列表,再勾选要安装的插件,只安装所选子集
|
||||
- 交互式选择对话框:先按类型筛选、按关键词搜索并查看描述信息,再勾选要安装的插件,只安装所选子集
|
||||
- 国际化:支持 11 种语言
|
||||
|
||||
## 流程
|
||||
@@ -37,7 +37,7 @@
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ 显示选择对话框 │
|
||||
│ (复选列表 + 类型标签 + 描述) │
|
||||
│ (类型筛选 + 搜索 + 描述) │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
├── [取消] → 结束
|
||||
@@ -63,7 +63,7 @@
|
||||
|
||||
每次请求处理一个仓库。如需混合多个来源,请在上一次安装完成后再发起下一次请求。
|
||||
|
||||
在插件发现和过滤完成后,OpenWebUI 会通过 `execute` 事件打开浏览器选择对话框。你可以先查看插件描述,使用类型标签进行批量勾选,再开始调用安装 API。
|
||||
在插件发现和过滤完成后,OpenWebUI 会通过 `execute` 事件打开浏览器选择对话框。你可以先按类型筛选、通过关键词搜索、查看插件描述,再开始调用安装 API。
|
||||
|
||||
## 快速开始:安装热门插件集
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ Installing plugins in OpenWebUI should not feel like an all-or-nothing jump. Wit
|
||||
|
||||
### 🚀 Interactive Plugin Selection
|
||||
- Uses the OpenWebUI `execute` event to open a custom browser dialog
|
||||
- Displays the filtered plugin list with checkboxes, type tags, plugin descriptions, and repository context
|
||||
- Displays the filtered plugin list with checkboxes, type filters, keyword search, plugin descriptions, and repository context
|
||||
- Installs only the plugins the user keeps selected
|
||||
|
||||
### ✅ Smart Safety Features
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
### 🚀 交互式插件选择
|
||||
- 基于 OpenWebUI 的 `execute` 事件打开自定义浏览器选择对话框
|
||||
- 显示带复选框、类型标签、插件描述和仓库信息的过滤结果
|
||||
- 显示带复选框、类型筛选、关键词搜索、插件描述和仓库信息的过滤结果
|
||||
- 只安装用户保留勾选的插件
|
||||
|
||||
### ✅ 智能安全保障
|
||||
|
||||
@@ -14,7 +14,7 @@ One-click batch install plugins from GitHub repositories to your OpenWebUI insta
|
||||
- **Auto-Update**: Automatically updates previously installed plugins
|
||||
- **Public GitHub Support**: Install plugins from any public GitHub repository
|
||||
- **Multi-Type Support**: Supports Pipe, Action, Filter, and Tool plugins
|
||||
- **Interactive Selection Dialog**: Review the filtered list with type tags and plugin descriptions, then install only the checked subset
|
||||
- **Interactive Selection Dialog**: Filter by type, search by keyword, review plugin descriptions, then install only the checked subset
|
||||
- **i18n**: Supports 11 languages
|
||||
|
||||
## Flow
|
||||
@@ -37,7 +37,7 @@ User Input
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ Show Selection Dialog │
|
||||
│ (checkbox list + type tags + desc) │
|
||||
│ (type filter + search + desc) │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
├── [Cancel] → End
|
||||
@@ -63,7 +63,7 @@ User Input
|
||||
|
||||
Each request handles one repository. To mix repositories, send another request after the previous installation completes.
|
||||
|
||||
After plugin discovery and filtering, OpenWebUI opens a browser dialog built with the `execute` event so you can review plugin descriptions, use type tags for quick batch selection, and check exactly which plugins to install before the API calls start.
|
||||
After plugin discovery and filtering, OpenWebUI opens a browser dialog built with the `execute` event so you can filter by plugin type, search by keyword, review plugin descriptions, and check exactly which plugins to install before the API calls start.
|
||||
|
||||
## Quick Start: Install Popular Collections
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
- 自动更新:自动更新之前安装过的插件
|
||||
- 公开 GitHub 支持:支持从任何公开 GitHub 仓库安装插件
|
||||
- 多类型支持:支持 Pipe、Action、Filter 和 Tool 插件
|
||||
- 交互式选择对话框:先查看带类型标签和描述信息的过滤列表,再勾选要安装的插件,只安装所选子集
|
||||
- 交互式选择对话框:先按类型筛选、按关键词搜索并查看描述信息,再勾选要安装的插件,只安装所选子集
|
||||
- 国际化:支持 11 种语言
|
||||
|
||||
## 流程
|
||||
@@ -37,7 +37,7 @@
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ 显示选择对话框 │
|
||||
│ (复选列表 + 类型标签 + 描述) │
|
||||
│ (类型筛选 + 搜索 + 描述) │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
├── [取消] → 结束
|
||||
@@ -63,7 +63,7 @@
|
||||
|
||||
每次请求处理一个仓库。如需混合多个来源,请在上一次安装完成后再发起下一次请求。
|
||||
|
||||
在插件发现和过滤完成后,OpenWebUI 会通过 `execute` 事件打开浏览器选择对话框。你可以先查看插件描述,使用类型标签进行批量勾选,再开始调用安装 API。
|
||||
在插件发现和过滤完成后,OpenWebUI 会通过 `execute` 事件打开浏览器选择对话框。你可以先按类型筛选、通过关键词搜索、查看插件描述,再开始调用安装 API。
|
||||
|
||||
## 快速开始:安装热门插件集
|
||||
|
||||
|
||||
@@ -303,7 +303,11 @@ SELECTION_DIALOG_TEXTS = {
|
||||
"en-US": {
|
||||
"select_all": "Select all",
|
||||
"clear_all": "Clear all",
|
||||
"quick_select": "Types",
|
||||
"quick_select": "Filter by type",
|
||||
"all_types": "All",
|
||||
"search_label": "Search",
|
||||
"search_placeholder": "Search title, description, file path...",
|
||||
"no_results": "No plugins match the current filter.",
|
||||
"selected_count": "{count} selected",
|
||||
"install_selected": "Install Selected",
|
||||
"cancel": "Cancel",
|
||||
@@ -315,7 +319,11 @@ SELECTION_DIALOG_TEXTS = {
|
||||
"zh-CN": {
|
||||
"select_all": "全选",
|
||||
"clear_all": "清空",
|
||||
"quick_select": "类型标签",
|
||||
"quick_select": "按类型筛选",
|
||||
"all_types": "全部",
|
||||
"search_label": "搜索",
|
||||
"search_placeholder": "搜索标题、描述、文件路径...",
|
||||
"no_results": "当前筛选条件下没有匹配的插件。",
|
||||
"selected_count": "已选 {count} 项",
|
||||
"install_selected": "安装所选插件",
|
||||
"cancel": "取消",
|
||||
@@ -327,7 +335,11 @@ SELECTION_DIALOG_TEXTS = {
|
||||
"zh-HK": {
|
||||
"select_all": "全選",
|
||||
"clear_all": "清空",
|
||||
"quick_select": "類型標籤",
|
||||
"quick_select": "按類型篩選",
|
||||
"all_types": "全部",
|
||||
"search_label": "搜尋",
|
||||
"search_placeholder": "搜尋標題、描述、檔案路徑...",
|
||||
"no_results": "目前篩選條件下沒有相符的外掛。",
|
||||
"selected_count": "已選 {count} 項",
|
||||
"install_selected": "安裝所選外掛",
|
||||
"cancel": "取消",
|
||||
@@ -339,7 +351,11 @@ SELECTION_DIALOG_TEXTS = {
|
||||
"zh-TW": {
|
||||
"select_all": "全選",
|
||||
"clear_all": "清空",
|
||||
"quick_select": "類型標籤",
|
||||
"quick_select": "按類型篩選",
|
||||
"all_types": "全部",
|
||||
"search_label": "搜尋",
|
||||
"search_placeholder": "搜尋標題、描述、檔案路徑...",
|
||||
"no_results": "目前篩選條件下沒有符合的外掛。",
|
||||
"selected_count": "已選 {count} 項",
|
||||
"install_selected": "安裝所選外掛",
|
||||
"cancel": "取消",
|
||||
@@ -351,7 +367,11 @@ SELECTION_DIALOG_TEXTS = {
|
||||
"ko-KR": {
|
||||
"select_all": "전체 선택",
|
||||
"clear_all": "선택 해제",
|
||||
"quick_select": "유형",
|
||||
"quick_select": "유형별 필터",
|
||||
"all_types": "전체",
|
||||
"search_label": "검색",
|
||||
"search_placeholder": "제목, 설명, 파일 경로 검색...",
|
||||
"no_results": "현재 필터와 일치하는 플러그인이 없습니다.",
|
||||
"selected_count": "{count}개 선택됨",
|
||||
"install_selected": "선택한 플러그인 설치",
|
||||
"cancel": "취소",
|
||||
@@ -363,7 +383,11 @@ SELECTION_DIALOG_TEXTS = {
|
||||
"ja-JP": {
|
||||
"select_all": "すべて選択",
|
||||
"clear_all": "クリア",
|
||||
"quick_select": "タイプ",
|
||||
"quick_select": "タイプで絞り込み",
|
||||
"all_types": "すべて",
|
||||
"search_label": "検索",
|
||||
"search_placeholder": "タイトル、説明、ファイルパスを検索...",
|
||||
"no_results": "現在の条件に一致するプラグインはありません。",
|
||||
"selected_count": "{count}件を選択",
|
||||
"install_selected": "選択したプラグインをインストール",
|
||||
"cancel": "キャンセル",
|
||||
@@ -375,7 +399,11 @@ SELECTION_DIALOG_TEXTS = {
|
||||
"fr-FR": {
|
||||
"select_all": "Tout sélectionner",
|
||||
"clear_all": "Tout effacer",
|
||||
"quick_select": "Types",
|
||||
"quick_select": "Filtrer par type",
|
||||
"all_types": "Tous",
|
||||
"search_label": "Rechercher",
|
||||
"search_placeholder": "Rechercher par titre, description, fichier...",
|
||||
"no_results": "Aucun plugin ne correspond au filtre actuel.",
|
||||
"selected_count": "{count} sélectionnés",
|
||||
"install_selected": "Installer la sélection",
|
||||
"cancel": "Annuler",
|
||||
@@ -387,7 +415,11 @@ SELECTION_DIALOG_TEXTS = {
|
||||
"de-DE": {
|
||||
"select_all": "Alle auswählen",
|
||||
"clear_all": "Auswahl löschen",
|
||||
"quick_select": "Typen",
|
||||
"quick_select": "Nach Typ filtern",
|
||||
"all_types": "Alle",
|
||||
"search_label": "Suchen",
|
||||
"search_placeholder": "Titel, Beschreibung, Dateipfad durchsuchen...",
|
||||
"no_results": "Keine Plugins entsprechen dem aktuellen Filter.",
|
||||
"selected_count": "{count} ausgewählt",
|
||||
"install_selected": "Auswahl installieren",
|
||||
"cancel": "Abbrechen",
|
||||
@@ -399,7 +431,11 @@ SELECTION_DIALOG_TEXTS = {
|
||||
"es-ES": {
|
||||
"select_all": "Seleccionar todo",
|
||||
"clear_all": "Limpiar",
|
||||
"quick_select": "Tipos",
|
||||
"quick_select": "Filtrar por tipo",
|
||||
"all_types": "Todos",
|
||||
"search_label": "Buscar",
|
||||
"search_placeholder": "Buscar por titulo, descripcion o archivo...",
|
||||
"no_results": "Ningun plugin coincide con el filtro actual.",
|
||||
"selected_count": "{count} seleccionados",
|
||||
"install_selected": "Instalar seleccionados",
|
||||
"cancel": "Cancelar",
|
||||
@@ -411,7 +447,11 @@ SELECTION_DIALOG_TEXTS = {
|
||||
"it-IT": {
|
||||
"select_all": "Seleziona tutto",
|
||||
"clear_all": "Cancella",
|
||||
"quick_select": "Tipi",
|
||||
"quick_select": "Filtra per tipo",
|
||||
"all_types": "Tutti",
|
||||
"search_label": "Cerca",
|
||||
"search_placeholder": "Cerca per titolo, descrizione o file...",
|
||||
"no_results": "Nessun plugin corrisponde al filtro attuale.",
|
||||
"selected_count": "{count} selezionati",
|
||||
"install_selected": "Installa selezionati",
|
||||
"cancel": "Annulla",
|
||||
@@ -423,7 +463,11 @@ SELECTION_DIALOG_TEXTS = {
|
||||
"vi-VN": {
|
||||
"select_all": "Chọn tất cả",
|
||||
"clear_all": "Bỏ chọn",
|
||||
"quick_select": "Loại",
|
||||
"quick_select": "Lọc theo loại",
|
||||
"all_types": "Tất cả",
|
||||
"search_label": "Tìm kiếm",
|
||||
"search_placeholder": "Tìm theo tiêu đề, mô tả, đường dẫn tệp...",
|
||||
"no_results": "Không có plugin nào khớp với bộ lọc hiện tại.",
|
||||
"selected_count": "Đã chọn {count}",
|
||||
"install_selected": "Cài đặt mục đã chọn",
|
||||
"cancel": "Hủy",
|
||||
@@ -905,6 +949,8 @@ def _build_selection_dialog_js(
|
||||
" return;",
|
||||
" }",
|
||||
" const selected = new Set(options.map((item) => item.id));",
|
||||
" let activeFilter = '';",
|
||||
" let searchTerm = '';",
|
||||
" const escapeHtml = (value) => String(value ?? '').replace(/[&<>\"']/g, (char) => ({",
|
||||
" '&': '&',",
|
||||
" '<': '<',",
|
||||
@@ -949,9 +995,15 @@ def _build_selection_dialog_js(
|
||||
" </div>",
|
||||
" <div id=\"batch-install-plugin-selector-count\" style=\"font-size:13px;font-weight:600;color:#475569\"></div>",
|
||||
" </div>",
|
||||
" <div style=\"display:flex;gap:10px;align-items:center;flex-wrap:wrap\">",
|
||||
" <div style=\"font-size:12px;font-weight:700;color:#475569;text-transform:uppercase;letter-spacing:0.04em\">${escapeHtml(ui.quick_select)}</div>",
|
||||
" <div id=\"batch-install-plugin-selector-types\" style=\"display:flex;gap:8px;flex-wrap:wrap\"></div>",
|
||||
" <div style=\"display:grid;gap:10px\">",
|
||||
" <div style=\"display:flex;gap:10px;align-items:center;flex-wrap:wrap\">",
|
||||
" <div style=\"font-size:12px;font-weight:700;color:#475569;text-transform:uppercase;letter-spacing:0.04em\">${escapeHtml(ui.quick_select)}</div>",
|
||||
" <div id=\"batch-install-plugin-selector-types\" style=\"display:flex;gap:8px;flex-wrap:wrap\"></div>",
|
||||
" </div>",
|
||||
" <div style=\"display:grid;gap:6px\">",
|
||||
" <div style=\"font-size:12px;font-weight:700;color:#475569;text-transform:uppercase;letter-spacing:0.04em\">${escapeHtml(ui.search_label)}</div>",
|
||||
" <input id=\"batch-install-plugin-selector-search\" type=\"text\" placeholder=\"${escapeHtml(ui.search_placeholder)}\" style=\"width:100%;padding:10px 12px;border:1px solid #cbd5e1;border-radius:12px;background:#fff;color:#0f172a;font-size:14px;outline:none;box-sizing:border-box\" />",
|
||||
" </div>",
|
||||
" </div>",
|
||||
" </div>",
|
||||
" <div id=\"batch-install-plugin-selector-list\" style=\"padding:16px 24px 0;overflow:auto;display:grid;gap:12px;flex:1;min-height:0\"></div>",
|
||||
@@ -968,6 +1020,7 @@ def _build_selection_dialog_js(
|
||||
" const countEl = overlay.querySelector('#batch-install-plugin-selector-count');",
|
||||
" const hintEl = overlay.querySelector('#batch-install-plugin-selector-hint');",
|
||||
" const typesEl = overlay.querySelector('#batch-install-plugin-selector-types');",
|
||||
" const searchInput = overlay.querySelector('#batch-install-plugin-selector-search');",
|
||||
" const submitBtn = overlay.querySelector('#batch-install-plugin-selector-submit');",
|
||||
" const cancelBtn = overlay.querySelector('#batch-install-plugin-selector-cancel');",
|
||||
" const selectAllBtn = overlay.querySelector('#batch-install-plugin-selector-select-all');",
|
||||
@@ -980,35 +1033,34 @@ def _build_selection_dialog_js(
|
||||
" return groups;",
|
||||
" }, {});",
|
||||
" const typeEntries = Object.entries(typeMap);",
|
||||
" const getVisibleOptions = () => options.filter((item) => {",
|
||||
" const matchesType = !activeFilter || item.type === activeFilter;",
|
||||
" const haystack = [item.title, item.description, item.file_path, item.type].join(' ').toLowerCase();",
|
||||
" const matchesSearch = !searchTerm || haystack.includes(searchTerm);",
|
||||
" return matchesType && matchesSearch;",
|
||||
" });",
|
||||
" const formatMultilineText = (value) => escapeHtml(value).replace(/\\n+/g, '<br />');",
|
||||
" hintEl.textContent = ui.hint || '';",
|
||||
" hintEl.style.display = ui.hint ? 'block' : 'none';",
|
||||
" const renderTypeButtons = () => {",
|
||||
" typesEl.innerHTML = typeEntries.map(([type, items]) => {",
|
||||
" const allSelected = items.every((item) => selected.has(item.id));",
|
||||
" const anySelected = items.some((item) => selected.has(item.id));",
|
||||
" const background = allSelected ? '#0f172a' : '#ffffff';",
|
||||
" const color = allSelected ? '#ffffff' : '#0f172a';",
|
||||
" const border = anySelected ? '#94a3b8' : '#cbd5e1';",
|
||||
" const filterEntries = [['', options], ...typeEntries];",
|
||||
" typesEl.innerHTML = filterEntries.map(([type, items]) => {",
|
||||
" const isActive = activeFilter === type;",
|
||||
" const background = isActive ? '#0f172a' : '#ffffff';",
|
||||
" const color = isActive ? '#ffffff' : '#0f172a';",
|
||||
" const border = isActive ? '#0f172a' : '#cbd5e1';",
|
||||
" const label = type || ui.all_types;",
|
||||
" return `",
|
||||
" <button type=\"button\" data-plugin-type=\"${escapeHtml(type)}\" style=\"padding:7px 12px;border:1px solid ${border};border-radius:999px;background:${background};color:${color};font-size:12px;font-weight:700;cursor:pointer;display:inline-flex;gap:8px;align-items:center\">",
|
||||
" <span>${escapeHtml(type)}</span>",
|
||||
" <span style=\"display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:20px;padding:0 6px;border-radius:999px;background:${allSelected ? 'rgba(255,255,255,0.16)' : '#e2e8f0'};color:${allSelected ? '#ffffff' : '#334155'}\">${items.length}</span>",
|
||||
" <span>${escapeHtml(label)}</span>",
|
||||
" <span style=\"display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:20px;padding:0 6px;border-radius:999px;background:${isActive ? 'rgba(255,255,255,0.16)' : '#e2e8f0'};color:${isActive ? '#ffffff' : '#334155'}\">${items.length}</span>",
|
||||
" </button>",
|
||||
" `;",
|
||||
" }).join('');",
|
||||
" typesEl.querySelectorAll('button[data-plugin-type]').forEach((button) => {",
|
||||
" button.addEventListener('click', () => {",
|
||||
" const pluginType = button.getAttribute('data-plugin-type') || '';",
|
||||
" const items = typeMap[pluginType] || [];",
|
||||
" const allSelected = items.length > 0 && items.every((item) => selected.has(item.id));",
|
||||
" items.forEach((item) => {",
|
||||
" if (allSelected) {",
|
||||
" selected.delete(item.id);",
|
||||
" } else {",
|
||||
" selected.add(item.id);",
|
||||
" }",
|
||||
" });",
|
||||
" activeFilter = activeFilter === pluginType ? '' : pluginType;",
|
||||
" renderList();",
|
||||
" });",
|
||||
" });",
|
||||
@@ -1021,7 +1073,13 @@ def _build_selection_dialog_js(
|
||||
" renderTypeButtons();",
|
||||
" };",
|
||||
" const renderList = () => {",
|
||||
" listEl.innerHTML = options.map((item) => {",
|
||||
" const visibleOptions = getVisibleOptions();",
|
||||
" if (!visibleOptions.length) {",
|
||||
" listEl.innerHTML = `<div style=\"padding:24px;border:1px dashed #cbd5e1;border-radius:14px;background:#f8fafc;color:#475569;font-size:14px;text-align:center\">${escapeHtml(ui.no_results)}</div>`;",
|
||||
" updateState();",
|
||||
" return;",
|
||||
" }",
|
||||
" listEl.innerHTML = visibleOptions.map((item) => {",
|
||||
" const checked = selected.has(item.id) ? 'checked' : '';",
|
||||
" const description = item.description ? `",
|
||||
" <div style=\"display:grid;gap:4px\">",
|
||||
@@ -1078,11 +1136,15 @@ def _build_selection_dialog_js(
|
||||
" }",
|
||||
" });",
|
||||
" selectAllBtn.addEventListener('click', () => {",
|
||||
" options.forEach((item) => selected.add(item.id));",
|
||||
" getVisibleOptions().forEach((item) => selected.add(item.id));",
|
||||
" renderList();",
|
||||
" });",
|
||||
" clearAllBtn.addEventListener('click', () => {",
|
||||
" selected.clear();",
|
||||
" getVisibleOptions().forEach((item) => selected.delete(item.id));",
|
||||
" renderList();",
|
||||
" });",
|
||||
" searchInput.addEventListener('input', () => {",
|
||||
" searchTerm = searchInput.value.trim().toLowerCase();",
|
||||
" renderList();",
|
||||
" });",
|
||||
" cancelBtn.addEventListener('click', () => finish(false));",
|
||||
@@ -1138,6 +1200,10 @@ async def _request_plugin_selection(
|
||||
"select_all": _selection_t(lang, "select_all"),
|
||||
"clear_all": _selection_t(lang, "clear_all"),
|
||||
"quick_select": _selection_t(lang, "quick_select"),
|
||||
"all_types": _selection_t(lang, "all_types"),
|
||||
"search_label": _selection_t(lang, "search_label"),
|
||||
"search_placeholder": _selection_t(lang, "search_placeholder"),
|
||||
"no_results": _selection_t(lang, "no_results"),
|
||||
"selected_count": _selection_t(lang, "selected_count", count="{count}"),
|
||||
"install_selected": _selection_t(lang, "install_selected"),
|
||||
"cancel": _selection_t(lang, "cancel"),
|
||||
|
||||
@@ -8,7 +8,7 @@ Batch Install Plugins from GitHub v1.1.0 upgrades the install confirmation step
|
||||
|
||||
## Highlights
|
||||
|
||||
- **Interactive Selection Dialog**: Opens a checkbox-based browser dialog with type tags and visible plugin descriptions
|
||||
- **Interactive Selection Dialog**: Opens a checkbox-based browser dialog with type filters, keyword search, and visible plugin descriptions
|
||||
- **Selective Installation**: The install loop now runs only for the plugins the user keeps selected
|
||||
- **Repository Context**: Displays the current repository and only shows useful exclusion information inside the dialog
|
||||
- **Localized UI**: Dialog controls are localized for all supported languages
|
||||
|
||||
@@ -8,7 +8,7 @@ Batch Install Plugins from GitHub v1.1.0 将原本的安装确认步骤升级为
|
||||
|
||||
## 亮点
|
||||
|
||||
- **交互式选择对话框**:不再只使用基础 confirmation 事件,而是打开带类型标签、描述信息和复选框的浏览器对话框
|
||||
- **交互式选择对话框**:不再只使用基础 confirmation 事件,而是打开带类型筛选、关键词搜索、描述信息和复选框的浏览器对话框
|
||||
- **选择性安装**:安装循环只会处理用户最终保留勾选的插件
|
||||
- **仓库上下文**:对话框中会显示当前仓库,并且只展示真正有用的排除信息
|
||||
- **本地化 UI**:对话框控件已为所有支持语言提供本地化文本
|
||||
|
||||
Reference in New Issue
Block a user