Projekt löschen in drei Stufen mit Artefakt-Vorschau; Listen-Scroll gefixt
Eskalationsleiter: 'integration' nimmt nur die ai-control-Spuren zurück (Registry, .ai-control/, Archiv-Rechte + Todo-Hook in settings.json, Panel-Dateien, .desktop — Ordner, memory/ und Claude-Code-Grundgerüst bleiben), 'archive' löscht zusätzlich das Archiv, 'full' den Projekt- ordner mit Arbeitsordner-Flag. delete_preview liefert die konkrete Artefaktliste; der Dialog zeigt sie je Stufe. Ersetzt delete_project/ remove_project (Handler, App-ACL-Manifest und Capability nachgezogen). Außerdem: main scrollt nicht mehr — Toolbars und Fehlerzeile stehen, nur die Listen scrollen (alle drei Tabs, .list-scroll).
This commit is contained in:
+67
-1
@@ -1,3 +1,69 @@
|
||||
fn main() {
|
||||
tauri_build::build()
|
||||
// App-ACL-Manifest: erzeugt pro Command allow-/deny-Permissions. Sobald das
|
||||
// Manifest existiert, gilt deny-by-default — jedes Command muss in einer
|
||||
// Capability einem Fenster zugeteilt sein (capabilities/*.json), sonst
|
||||
// lehnt Tauri den Aufruf ab. Neue Commands hier UND in der passenden
|
||||
// Capability eintragen.
|
||||
tauri_build::try_build(
|
||||
tauri_build::Attributes::new().app_manifest(tauri_build::AppManifest::new().commands(&[
|
||||
"list_projects",
|
||||
"create_project_full",
|
||||
"add_project",
|
||||
"delete_preview",
|
||||
"delete_project_scoped",
|
||||
"project_work_dirs",
|
||||
"set_project_dir",
|
||||
"add_work_dir",
|
||||
"remove_work_dir",
|
||||
"list_pools",
|
||||
"create_oauth_pool",
|
||||
"create_apikey_pool",
|
||||
"rename_pool",
|
||||
"delete_pool",
|
||||
"assign_pool",
|
||||
"unassign_pool",
|
||||
"set_terminal_config",
|
||||
"project_icon",
|
||||
"pool_label",
|
||||
"todo_state",
|
||||
"set_todo",
|
||||
"usage_stats",
|
||||
"stop_project",
|
||||
"restart_project",
|
||||
"start_or_focus_cmd",
|
||||
"open_main_window",
|
||||
"quit_app",
|
||||
"sync_setting",
|
||||
"set_sync_setting",
|
||||
"terminal_font_size",
|
||||
"set_terminal_font_size",
|
||||
"link_pool_runtime",
|
||||
"oauth_login",
|
||||
"keychain_status",
|
||||
"set_apikey",
|
||||
"panel_archive_dir_cmd",
|
||||
"panel_archive_cmd",
|
||||
"set_archive_home_cmd",
|
||||
"clear_archive_home_cmd",
|
||||
"archive_docs_cmd",
|
||||
"reveal_path_cmd",
|
||||
"spellcheck_lang",
|
||||
"open_terminal",
|
||||
"term_start",
|
||||
"term_log",
|
||||
"term_write",
|
||||
"term_resize",
|
||||
"panel_read",
|
||||
"commands_read",
|
||||
"commands_delete",
|
||||
"panel_set",
|
||||
"search_read",
|
||||
"search_run",
|
||||
"panel_load",
|
||||
"wiki_read",
|
||||
"wiki_open",
|
||||
"open_panel_window",
|
||||
])),
|
||||
)
|
||||
.expect("tauri-build");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "main",
|
||||
"description": "Hauptfenster: komplette Projekt-/Pool-Verwaltung.",
|
||||
"windows": [
|
||||
"main"
|
||||
],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"core:window:allow-start-dragging",
|
||||
"core:window:allow-set-size",
|
||||
"core:window:allow-set-position",
|
||||
"core:window:allow-outer-position",
|
||||
"core:window:allow-inner-size",
|
||||
"core:window:allow-minimize",
|
||||
"core:window:allow-toggle-maximize",
|
||||
"core:window:allow-close",
|
||||
"core:window:allow-hide",
|
||||
"core:window:allow-start-resize-dragging",
|
||||
"autostart:default",
|
||||
"dialog:default",
|
||||
"clipboard-manager:allow-write-text",
|
||||
"allow-list-projects",
|
||||
"allow-create-project-full",
|
||||
"allow-add-project",
|
||||
"allow-project-work-dirs",
|
||||
"allow-set-project-dir",
|
||||
"allow-add-work-dir",
|
||||
"allow-remove-work-dir",
|
||||
"allow-list-pools",
|
||||
"allow-create-oauth-pool",
|
||||
"allow-create-apikey-pool",
|
||||
"allow-rename-pool",
|
||||
"allow-delete-pool",
|
||||
"allow-assign-pool",
|
||||
"allow-unassign-pool",
|
||||
"allow-set-terminal-config",
|
||||
"allow-project-icon",
|
||||
"allow-todo-state",
|
||||
"allow-set-todo",
|
||||
"allow-usage-stats",
|
||||
"allow-stop-project",
|
||||
"allow-restart-project",
|
||||
"allow-open-terminal",
|
||||
"allow-sync-setting",
|
||||
"allow-set-sync-setting",
|
||||
"allow-link-pool-runtime",
|
||||
"allow-oauth-login",
|
||||
"allow-keychain-status",
|
||||
"allow-set-apikey",
|
||||
"allow-panel-archive-dir-cmd",
|
||||
"allow-set-archive-home-cmd",
|
||||
"allow-clear-archive-home-cmd",
|
||||
"allow-archive-docs-cmd",
|
||||
"allow-delete-preview",
|
||||
"allow-delete-project-scoped"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "panel",
|
||||
"description": "Abgelöstes Panel-Fenster: nur Panel-/Archiv-Kanäle, keine PTY, keine Verwaltung.",
|
||||
"windows": [
|
||||
"panel-*"
|
||||
],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"core:window:allow-start-dragging",
|
||||
"core:window:allow-set-size",
|
||||
"core:window:allow-set-position",
|
||||
"core:window:allow-outer-position",
|
||||
"core:window:allow-inner-size",
|
||||
"core:window:allow-minimize",
|
||||
"core:window:allow-toggle-maximize",
|
||||
"core:window:allow-close",
|
||||
"core:window:allow-hide",
|
||||
"core:window:allow-start-resize-dragging",
|
||||
"autostart:default",
|
||||
"dialog:default",
|
||||
"clipboard-manager:allow-write-text",
|
||||
"allow-commands-delete",
|
||||
"allow-commands-read",
|
||||
"allow-list-projects",
|
||||
"allow-panel-archive-cmd",
|
||||
"allow-panel-archive-dir-cmd",
|
||||
"allow-panel-load",
|
||||
"allow-panel-read",
|
||||
"allow-panel-set",
|
||||
"allow-reveal-path-cmd",
|
||||
"allow-search-read",
|
||||
"allow-search-run",
|
||||
"allow-spellcheck-lang",
|
||||
"allow-term-log",
|
||||
"allow-wiki-open",
|
||||
"allow-wiki-read"
|
||||
]
|
||||
}
|
||||
@@ -1,12 +1,9 @@
|
||||
{
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "default",
|
||||
"description": "enables the default permissions",
|
||||
"identifier": "popup",
|
||||
"description": "Tray-Popup: Projektliste anzeigen und starten.",
|
||||
"windows": [
|
||||
"main",
|
||||
"popup",
|
||||
"term-*",
|
||||
"panel-*"
|
||||
"popup"
|
||||
],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
@@ -22,6 +19,11 @@
|
||||
"core:window:allow-start-resize-dragging",
|
||||
"autostart:default",
|
||||
"dialog:default",
|
||||
"clipboard-manager:allow-write-text"
|
||||
"clipboard-manager:allow-write-text",
|
||||
"allow-list-projects",
|
||||
"allow-project-icon",
|
||||
"allow-start-or-focus-cmd",
|
||||
"allow-open-main-window",
|
||||
"allow-quit-app"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "terminal",
|
||||
"description": "Terminal-Fenster: PTY und angedocktes Panel.",
|
||||
"windows": [
|
||||
"term-*"
|
||||
],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"core:window:allow-start-dragging",
|
||||
"core:window:allow-set-size",
|
||||
"core:window:allow-set-position",
|
||||
"core:window:allow-outer-position",
|
||||
"core:window:allow-inner-size",
|
||||
"core:window:allow-minimize",
|
||||
"core:window:allow-toggle-maximize",
|
||||
"core:window:allow-close",
|
||||
"core:window:allow-hide",
|
||||
"core:window:allow-start-resize-dragging",
|
||||
"autostart:default",
|
||||
"dialog:default",
|
||||
"clipboard-manager:allow-write-text",
|
||||
"allow-commands-delete",
|
||||
"allow-commands-read",
|
||||
"allow-list-projects",
|
||||
"allow-open-panel-window",
|
||||
"allow-panel-archive-cmd",
|
||||
"allow-panel-archive-dir-cmd",
|
||||
"allow-panel-load",
|
||||
"allow-panel-read",
|
||||
"allow-panel-set",
|
||||
"allow-pool-label",
|
||||
"allow-project-icon",
|
||||
"allow-reveal-path-cmd",
|
||||
"allow-search-read",
|
||||
"allow-search-run",
|
||||
"allow-set-terminal-font-size",
|
||||
"allow-spellcheck-lang",
|
||||
"allow-term-log",
|
||||
"allow-term-resize",
|
||||
"allow-term-start",
|
||||
"allow-term-write",
|
||||
"allow-terminal-font-size",
|
||||
"allow-wiki-open",
|
||||
"allow-wiki-read"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-add-project"
|
||||
description = "Enables the add_project command without any pre-configured scope."
|
||||
commands.allow = ["add_project"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-add-project"
|
||||
description = "Denies the add_project command without any pre-configured scope."
|
||||
commands.deny = ["add_project"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-add-work-dir"
|
||||
description = "Enables the add_work_dir command without any pre-configured scope."
|
||||
commands.allow = ["add_work_dir"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-add-work-dir"
|
||||
description = "Denies the add_work_dir command without any pre-configured scope."
|
||||
commands.deny = ["add_work_dir"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-archive-docs-cmd"
|
||||
description = "Enables the archive_docs_cmd command without any pre-configured scope."
|
||||
commands.allow = ["archive_docs_cmd"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-archive-docs-cmd"
|
||||
description = "Denies the archive_docs_cmd command without any pre-configured scope."
|
||||
commands.deny = ["archive_docs_cmd"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-assign-pool"
|
||||
description = "Enables the assign_pool command without any pre-configured scope."
|
||||
commands.allow = ["assign_pool"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-assign-pool"
|
||||
description = "Denies the assign_pool command without any pre-configured scope."
|
||||
commands.deny = ["assign_pool"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-clear-archive-home-cmd"
|
||||
description = "Enables the clear_archive_home_cmd command without any pre-configured scope."
|
||||
commands.allow = ["clear_archive_home_cmd"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-clear-archive-home-cmd"
|
||||
description = "Denies the clear_archive_home_cmd command without any pre-configured scope."
|
||||
commands.deny = ["clear_archive_home_cmd"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-commands-delete"
|
||||
description = "Enables the commands_delete command without any pre-configured scope."
|
||||
commands.allow = ["commands_delete"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-commands-delete"
|
||||
description = "Denies the commands_delete command without any pre-configured scope."
|
||||
commands.deny = ["commands_delete"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-commands-read"
|
||||
description = "Enables the commands_read command without any pre-configured scope."
|
||||
commands.allow = ["commands_read"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-commands-read"
|
||||
description = "Denies the commands_read command without any pre-configured scope."
|
||||
commands.deny = ["commands_read"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-create-apikey-pool"
|
||||
description = "Enables the create_apikey_pool command without any pre-configured scope."
|
||||
commands.allow = ["create_apikey_pool"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-create-apikey-pool"
|
||||
description = "Denies the create_apikey_pool command without any pre-configured scope."
|
||||
commands.deny = ["create_apikey_pool"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-create-oauth-pool"
|
||||
description = "Enables the create_oauth_pool command without any pre-configured scope."
|
||||
commands.allow = ["create_oauth_pool"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-create-oauth-pool"
|
||||
description = "Denies the create_oauth_pool command without any pre-configured scope."
|
||||
commands.deny = ["create_oauth_pool"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-create-project-full"
|
||||
description = "Enables the create_project_full command without any pre-configured scope."
|
||||
commands.allow = ["create_project_full"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-create-project-full"
|
||||
description = "Denies the create_project_full command without any pre-configured scope."
|
||||
commands.deny = ["create_project_full"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-delete-pool"
|
||||
description = "Enables the delete_pool command without any pre-configured scope."
|
||||
commands.allow = ["delete_pool"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-delete-pool"
|
||||
description = "Denies the delete_pool command without any pre-configured scope."
|
||||
commands.deny = ["delete_pool"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-delete-preview"
|
||||
description = "Enables the delete_preview command without any pre-configured scope."
|
||||
commands.allow = ["delete_preview"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-delete-preview"
|
||||
description = "Denies the delete_preview command without any pre-configured scope."
|
||||
commands.deny = ["delete_preview"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-delete-project"
|
||||
description = "Enables the delete_project command without any pre-configured scope."
|
||||
commands.allow = ["delete_project"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-delete-project"
|
||||
description = "Denies the delete_project command without any pre-configured scope."
|
||||
commands.deny = ["delete_project"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-delete-project-scoped"
|
||||
description = "Enables the delete_project_scoped command without any pre-configured scope."
|
||||
commands.allow = ["delete_project_scoped"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-delete-project-scoped"
|
||||
description = "Denies the delete_project_scoped command without any pre-configured scope."
|
||||
commands.deny = ["delete_project_scoped"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-keychain-status"
|
||||
description = "Enables the keychain_status command without any pre-configured scope."
|
||||
commands.allow = ["keychain_status"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-keychain-status"
|
||||
description = "Denies the keychain_status command without any pre-configured scope."
|
||||
commands.deny = ["keychain_status"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-link-pool-runtime"
|
||||
description = "Enables the link_pool_runtime command without any pre-configured scope."
|
||||
commands.allow = ["link_pool_runtime"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-link-pool-runtime"
|
||||
description = "Denies the link_pool_runtime command without any pre-configured scope."
|
||||
commands.deny = ["link_pool_runtime"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-list-pools"
|
||||
description = "Enables the list_pools command without any pre-configured scope."
|
||||
commands.allow = ["list_pools"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-list-pools"
|
||||
description = "Denies the list_pools command without any pre-configured scope."
|
||||
commands.deny = ["list_pools"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-list-projects"
|
||||
description = "Enables the list_projects command without any pre-configured scope."
|
||||
commands.allow = ["list_projects"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-list-projects"
|
||||
description = "Denies the list_projects command without any pre-configured scope."
|
||||
commands.deny = ["list_projects"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-oauth-login"
|
||||
description = "Enables the oauth_login command without any pre-configured scope."
|
||||
commands.allow = ["oauth_login"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-oauth-login"
|
||||
description = "Denies the oauth_login command without any pre-configured scope."
|
||||
commands.deny = ["oauth_login"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-open-main-window"
|
||||
description = "Enables the open_main_window command without any pre-configured scope."
|
||||
commands.allow = ["open_main_window"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-open-main-window"
|
||||
description = "Denies the open_main_window command without any pre-configured scope."
|
||||
commands.deny = ["open_main_window"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-open-panel-window"
|
||||
description = "Enables the open_panel_window command without any pre-configured scope."
|
||||
commands.allow = ["open_panel_window"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-open-panel-window"
|
||||
description = "Denies the open_panel_window command without any pre-configured scope."
|
||||
commands.deny = ["open_panel_window"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-open-terminal"
|
||||
description = "Enables the open_terminal command without any pre-configured scope."
|
||||
commands.allow = ["open_terminal"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-open-terminal"
|
||||
description = "Denies the open_terminal command without any pre-configured scope."
|
||||
commands.deny = ["open_terminal"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-panel-archive-cmd"
|
||||
description = "Enables the panel_archive_cmd command without any pre-configured scope."
|
||||
commands.allow = ["panel_archive_cmd"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-panel-archive-cmd"
|
||||
description = "Denies the panel_archive_cmd command without any pre-configured scope."
|
||||
commands.deny = ["panel_archive_cmd"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-panel-archive-dir-cmd"
|
||||
description = "Enables the panel_archive_dir_cmd command without any pre-configured scope."
|
||||
commands.allow = ["panel_archive_dir_cmd"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-panel-archive-dir-cmd"
|
||||
description = "Denies the panel_archive_dir_cmd command without any pre-configured scope."
|
||||
commands.deny = ["panel_archive_dir_cmd"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-panel-load"
|
||||
description = "Enables the panel_load command without any pre-configured scope."
|
||||
commands.allow = ["panel_load"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-panel-load"
|
||||
description = "Denies the panel_load command without any pre-configured scope."
|
||||
commands.deny = ["panel_load"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-panel-read"
|
||||
description = "Enables the panel_read command without any pre-configured scope."
|
||||
commands.allow = ["panel_read"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-panel-read"
|
||||
description = "Denies the panel_read command without any pre-configured scope."
|
||||
commands.deny = ["panel_read"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-panel-set"
|
||||
description = "Enables the panel_set command without any pre-configured scope."
|
||||
commands.allow = ["panel_set"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-panel-set"
|
||||
description = "Denies the panel_set command without any pre-configured scope."
|
||||
commands.deny = ["panel_set"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-pool-label"
|
||||
description = "Enables the pool_label command without any pre-configured scope."
|
||||
commands.allow = ["pool_label"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-pool-label"
|
||||
description = "Denies the pool_label command without any pre-configured scope."
|
||||
commands.deny = ["pool_label"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-project-icon"
|
||||
description = "Enables the project_icon command without any pre-configured scope."
|
||||
commands.allow = ["project_icon"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-project-icon"
|
||||
description = "Denies the project_icon command without any pre-configured scope."
|
||||
commands.deny = ["project_icon"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-project-work-dirs"
|
||||
description = "Enables the project_work_dirs command without any pre-configured scope."
|
||||
commands.allow = ["project_work_dirs"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-project-work-dirs"
|
||||
description = "Denies the project_work_dirs command without any pre-configured scope."
|
||||
commands.deny = ["project_work_dirs"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-quit-app"
|
||||
description = "Enables the quit_app command without any pre-configured scope."
|
||||
commands.allow = ["quit_app"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-quit-app"
|
||||
description = "Denies the quit_app command without any pre-configured scope."
|
||||
commands.deny = ["quit_app"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-remove-project"
|
||||
description = "Enables the remove_project command without any pre-configured scope."
|
||||
commands.allow = ["remove_project"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-remove-project"
|
||||
description = "Denies the remove_project command without any pre-configured scope."
|
||||
commands.deny = ["remove_project"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-remove-work-dir"
|
||||
description = "Enables the remove_work_dir command without any pre-configured scope."
|
||||
commands.allow = ["remove_work_dir"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-remove-work-dir"
|
||||
description = "Denies the remove_work_dir command without any pre-configured scope."
|
||||
commands.deny = ["remove_work_dir"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-rename-pool"
|
||||
description = "Enables the rename_pool command without any pre-configured scope."
|
||||
commands.allow = ["rename_pool"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-rename-pool"
|
||||
description = "Denies the rename_pool command without any pre-configured scope."
|
||||
commands.deny = ["rename_pool"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-restart-project"
|
||||
description = "Enables the restart_project command without any pre-configured scope."
|
||||
commands.allow = ["restart_project"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-restart-project"
|
||||
description = "Denies the restart_project command without any pre-configured scope."
|
||||
commands.deny = ["restart_project"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-reveal-path-cmd"
|
||||
description = "Enables the reveal_path_cmd command without any pre-configured scope."
|
||||
commands.allow = ["reveal_path_cmd"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-reveal-path-cmd"
|
||||
description = "Denies the reveal_path_cmd command without any pre-configured scope."
|
||||
commands.deny = ["reveal_path_cmd"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-search-read"
|
||||
description = "Enables the search_read command without any pre-configured scope."
|
||||
commands.allow = ["search_read"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-search-read"
|
||||
description = "Denies the search_read command without any pre-configured scope."
|
||||
commands.deny = ["search_read"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-search-run"
|
||||
description = "Enables the search_run command without any pre-configured scope."
|
||||
commands.allow = ["search_run"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-search-run"
|
||||
description = "Denies the search_run command without any pre-configured scope."
|
||||
commands.deny = ["search_run"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-set-apikey"
|
||||
description = "Enables the set_apikey command without any pre-configured scope."
|
||||
commands.allow = ["set_apikey"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-set-apikey"
|
||||
description = "Denies the set_apikey command without any pre-configured scope."
|
||||
commands.deny = ["set_apikey"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-set-archive-home-cmd"
|
||||
description = "Enables the set_archive_home_cmd command without any pre-configured scope."
|
||||
commands.allow = ["set_archive_home_cmd"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-set-archive-home-cmd"
|
||||
description = "Denies the set_archive_home_cmd command without any pre-configured scope."
|
||||
commands.deny = ["set_archive_home_cmd"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-set-project-dir"
|
||||
description = "Enables the set_project_dir command without any pre-configured scope."
|
||||
commands.allow = ["set_project_dir"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-set-project-dir"
|
||||
description = "Denies the set_project_dir command without any pre-configured scope."
|
||||
commands.deny = ["set_project_dir"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-set-sync-setting"
|
||||
description = "Enables the set_sync_setting command without any pre-configured scope."
|
||||
commands.allow = ["set_sync_setting"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-set-sync-setting"
|
||||
description = "Denies the set_sync_setting command without any pre-configured scope."
|
||||
commands.deny = ["set_sync_setting"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-set-terminal-config"
|
||||
description = "Enables the set_terminal_config command without any pre-configured scope."
|
||||
commands.allow = ["set_terminal_config"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-set-terminal-config"
|
||||
description = "Denies the set_terminal_config command without any pre-configured scope."
|
||||
commands.deny = ["set_terminal_config"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-set-terminal-font-size"
|
||||
description = "Enables the set_terminal_font_size command without any pre-configured scope."
|
||||
commands.allow = ["set_terminal_font_size"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-set-terminal-font-size"
|
||||
description = "Denies the set_terminal_font_size command without any pre-configured scope."
|
||||
commands.deny = ["set_terminal_font_size"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-set-todo"
|
||||
description = "Enables the set_todo command without any pre-configured scope."
|
||||
commands.allow = ["set_todo"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-set-todo"
|
||||
description = "Denies the set_todo command without any pre-configured scope."
|
||||
commands.deny = ["set_todo"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-spellcheck-lang"
|
||||
description = "Enables the spellcheck_lang command without any pre-configured scope."
|
||||
commands.allow = ["spellcheck_lang"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-spellcheck-lang"
|
||||
description = "Denies the spellcheck_lang command without any pre-configured scope."
|
||||
commands.deny = ["spellcheck_lang"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-start-or-focus-cmd"
|
||||
description = "Enables the start_or_focus_cmd command without any pre-configured scope."
|
||||
commands.allow = ["start_or_focus_cmd"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-start-or-focus-cmd"
|
||||
description = "Denies the start_or_focus_cmd command without any pre-configured scope."
|
||||
commands.deny = ["start_or_focus_cmd"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-stop-project"
|
||||
description = "Enables the stop_project command without any pre-configured scope."
|
||||
commands.allow = ["stop_project"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-stop-project"
|
||||
description = "Denies the stop_project command without any pre-configured scope."
|
||||
commands.deny = ["stop_project"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-sync-setting"
|
||||
description = "Enables the sync_setting command without any pre-configured scope."
|
||||
commands.allow = ["sync_setting"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-sync-setting"
|
||||
description = "Denies the sync_setting command without any pre-configured scope."
|
||||
commands.deny = ["sync_setting"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-term-log"
|
||||
description = "Enables the term_log command without any pre-configured scope."
|
||||
commands.allow = ["term_log"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-term-log"
|
||||
description = "Denies the term_log command without any pre-configured scope."
|
||||
commands.deny = ["term_log"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-term-resize"
|
||||
description = "Enables the term_resize command without any pre-configured scope."
|
||||
commands.allow = ["term_resize"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-term-resize"
|
||||
description = "Denies the term_resize command without any pre-configured scope."
|
||||
commands.deny = ["term_resize"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-term-start"
|
||||
description = "Enables the term_start command without any pre-configured scope."
|
||||
commands.allow = ["term_start"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-term-start"
|
||||
description = "Denies the term_start command without any pre-configured scope."
|
||||
commands.deny = ["term_start"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-term-write"
|
||||
description = "Enables the term_write command without any pre-configured scope."
|
||||
commands.allow = ["term_write"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-term-write"
|
||||
description = "Denies the term_write command without any pre-configured scope."
|
||||
commands.deny = ["term_write"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-terminal-font-size"
|
||||
description = "Enables the terminal_font_size command without any pre-configured scope."
|
||||
commands.allow = ["terminal_font_size"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-terminal-font-size"
|
||||
description = "Denies the terminal_font_size command without any pre-configured scope."
|
||||
commands.deny = ["terminal_font_size"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-todo-state"
|
||||
description = "Enables the todo_state command without any pre-configured scope."
|
||||
commands.allow = ["todo_state"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-todo-state"
|
||||
description = "Denies the todo_state command without any pre-configured scope."
|
||||
commands.deny = ["todo_state"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-unassign-pool"
|
||||
description = "Enables the unassign_pool command without any pre-configured scope."
|
||||
commands.allow = ["unassign_pool"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-unassign-pool"
|
||||
description = "Denies the unassign_pool command without any pre-configured scope."
|
||||
commands.deny = ["unassign_pool"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-usage-stats"
|
||||
description = "Enables the usage_stats command without any pre-configured scope."
|
||||
commands.allow = ["usage_stats"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-usage-stats"
|
||||
description = "Denies the usage_stats command without any pre-configured scope."
|
||||
commands.deny = ["usage_stats"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-wiki-open"
|
||||
description = "Enables the wiki_open command without any pre-configured scope."
|
||||
commands.allow = ["wiki_open"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-wiki-open"
|
||||
description = "Denies the wiki_open command without any pre-configured scope."
|
||||
commands.deny = ["wiki_open"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-wiki-read"
|
||||
description = "Enables the wiki_read command without any pre-configured scope."
|
||||
commands.allow = ["wiki_read"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-wiki-read"
|
||||
description = "Denies the wiki_read command without any pre-configured scope."
|
||||
commands.deny = ["wiki_read"]
|
||||
@@ -247,8 +247,8 @@ fn invoke_handlers() -> impl Fn(tauri::ipc::Invoke<tauri::Wry>) -> bool + Send +
|
||||
commands::list_projects,
|
||||
commands::create_project_full,
|
||||
commands::add_project,
|
||||
commands::remove_project,
|
||||
commands::delete_project,
|
||||
commands::delete_preview,
|
||||
commands::delete_project_scoped,
|
||||
commands::project_work_dirs,
|
||||
commands::set_project_dir,
|
||||
commands::add_work_dir,
|
||||
|
||||
+20
-17
@@ -13,12 +13,12 @@ use crate::domain::pool::{
|
||||
link_pool_runtime_in, list_pools_in, read_pool, rename_pool_in, set_apikey_in, PoolInfo,
|
||||
};
|
||||
use crate::domain::project::{
|
||||
add_project_in, add_work_dir_in, assign_pool_in, create_project_full_in, delete_project_in,
|
||||
display_name_in, is_running, kill_terminals, list_projects_in, project_work_dirs_in,
|
||||
read_project_config_in, remove_work_dir_in, resolve_icon_path, running_projects_using_pool,
|
||||
set_project_dir_in, set_terminal_config_in, unassign_pool_in, Project, TerminalConfig,
|
||||
add_project_in, add_work_dir_in, assign_pool_in, create_project_full_in, delete_preview_in,
|
||||
delete_project_scoped_in, display_name_in, is_running, kill_terminals, list_projects_in,
|
||||
project_work_dirs_in, read_project_config_in, remove_work_dir_in, resolve_icon_path,
|
||||
running_projects_using_pool, set_project_dir_in, set_terminal_config_in, unassign_pool_in,
|
||||
DeletePreview, Project, TerminalConfig,
|
||||
};
|
||||
use crate::domain::registry::unregister_project;
|
||||
use crate::domain::settings;
|
||||
use crate::domain::todo::{set_todo_in, todo_state_in};
|
||||
use crate::domain::usage::{usage_stats_in, UsageRow};
|
||||
@@ -60,16 +60,6 @@ pub(crate) fn add_project(path: String) -> Result<(), String> {
|
||||
add_project_in(&Paths::real(), &path)
|
||||
}
|
||||
|
||||
/// Projekt aus der Registry nehmen; der Ordner bleibt unangetastet.
|
||||
#[tauri::command]
|
||||
pub(crate) fn remove_project(project: String) -> Result<(), String> {
|
||||
if is_running(&project) {
|
||||
let name = display_name_in(&Paths::real(), &project)?;
|
||||
return Err(format!("{name} läuft noch — erst beenden"));
|
||||
}
|
||||
unregister_project(&Paths::real(), &project)
|
||||
}
|
||||
|
||||
/// Projektordner neu zuordnen; bei laufender Session gesperrt.
|
||||
#[tauri::command]
|
||||
pub(crate) fn set_project_dir(project: String, dir: String) -> Result<(), String> {
|
||||
@@ -90,13 +80,26 @@ pub(crate) fn remove_work_dir(project: String, dir: String) -> Result<(), String
|
||||
remove_work_dir_in(&Paths::real(), &project, &dir)
|
||||
}
|
||||
|
||||
/// Artefakt-Vorschau für den Lösch-Dialog.
|
||||
#[tauri::command]
|
||||
pub(crate) fn delete_project(project: String, delete_work_dirs: bool) -> Result<(), String> {
|
||||
pub(crate) fn delete_preview(project: String) -> Result<DeletePreview, String> {
|
||||
delete_preview_in(&Paths::real(), &project)
|
||||
}
|
||||
|
||||
/// Löschen in drei Stufen: "integration" (nur ai-control-Spuren),
|
||||
/// "archive" (zusätzlich Archiv), "full" (zusätzlich Projektordner,
|
||||
/// Arbeitsordner per Flag).
|
||||
#[tauri::command]
|
||||
pub(crate) fn delete_project_scoped(
|
||||
project: String,
|
||||
scope: String,
|
||||
delete_work_dirs: bool,
|
||||
) -> Result<(), String> {
|
||||
if is_running(&project) {
|
||||
let name = display_name_in(&Paths::real(), &project)?;
|
||||
return Err(format!("{name} läuft noch — erst beenden"));
|
||||
}
|
||||
delete_project_in(&Paths::real(), &project, delete_work_dirs)
|
||||
delete_project_scoped_in(&Paths::real(), &project, &scope, delete_work_dirs)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
|
||||
+180
-19
@@ -499,27 +499,125 @@ pub(crate) fn project_work_dirs_in(paths: &Paths, name: &str) -> Result<Vec<Stri
|
||||
)
|
||||
}
|
||||
|
||||
/// Löscht den Projektordner und den Registry-Eintrag; optional auch die
|
||||
/// verknüpften Arbeitsordner. Bei laufender Session wird abgebrochen.
|
||||
pub(crate) fn delete_project_in(
|
||||
/// Vorschau für den Lösch-Dialog: welche Artefakte die drei Stufen
|
||||
/// (Integration / Integration+Archiv / komplett) konkret treffen würden.
|
||||
#[derive(serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct DeletePreview {
|
||||
pub(crate) name: String,
|
||||
pub(crate) project_dir: String,
|
||||
pub(crate) ai_control_dir: bool,
|
||||
pub(crate) archive_permission: bool,
|
||||
pub(crate) todo_hook: bool,
|
||||
pub(crate) panel_files: usize,
|
||||
pub(crate) archive_home: Option<String>,
|
||||
pub(crate) archive_docs: usize,
|
||||
pub(crate) work_dirs: Vec<String>,
|
||||
}
|
||||
|
||||
pub(crate) fn delete_preview_in(paths: &Paths, project: &str) -> Result<DeletePreview, String> {
|
||||
check_name(project)?;
|
||||
let dir = project_dir(paths, project)?;
|
||||
let cfg = read_project_config_in(paths, project)?;
|
||||
let archive_docs = match cfg.archive_home.as_deref() {
|
||||
Some(a) => {
|
||||
let home = expand_home(paths, a);
|
||||
if home.is_dir() {
|
||||
crate::domain::archive_index::scan_archive(&home)?.len()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
None => 0,
|
||||
};
|
||||
Ok(DeletePreview {
|
||||
name: cfg.name.clone().unwrap_or_else(|| project.to_string()),
|
||||
project_dir: contract_home(paths, &dir),
|
||||
ai_control_dir: dir.join(PROJECT_CONFIG_DIR).is_dir(),
|
||||
archive_permission: cfg.archive_home.is_some(),
|
||||
todo_hook: crate::domain::todo::todo_state_in(paths, project)?,
|
||||
panel_files: session_files(paths, project).iter().filter(|f| f.is_file()).count(),
|
||||
archive_home: cfg.archive_home.clone(),
|
||||
archive_docs,
|
||||
work_dirs: project_work_dirs_in(paths, project)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Flüchtige Panel-Kanaldateien des Projekts unter ~/.config/ai-control/panels.
|
||||
fn session_files(paths: &Paths, project: &str) -> [PathBuf; 4] {
|
||||
let panels = paths.config_dir().join("panels");
|
||||
[
|
||||
panels.join(format!("{project}.md")),
|
||||
panels.join(format!("{project}.commands.jsonl")),
|
||||
panels.join(format!("{project}.search.json")),
|
||||
panels.join(format!("{project}.wiki.json")),
|
||||
]
|
||||
}
|
||||
|
||||
/// Löscht ein Projekt in drei Stufen (Eskalationsleiter, jede schließt die
|
||||
/// vorige ein):
|
||||
/// - "integration": nur die ai-control-Spuren — Registry, .ai-control/,
|
||||
/// Archiv-Rechte und Todo-Hook in der settings.json, Panel-Dateien,
|
||||
/// .desktop. Ordner, memory/ und das Claude-Code-Grundgerüst der
|
||||
/// settings.json bleiben.
|
||||
/// - "archive": zusätzlich der Archiv-Ordner samt Dokumenten.
|
||||
/// - "full": zusätzlich der Projektordner; Arbeitsordner per Flag.
|
||||
pub(crate) fn delete_project_scoped_in(
|
||||
paths: &Paths,
|
||||
name: &str,
|
||||
project: &str,
|
||||
scope: &str,
|
||||
delete_work_dirs: bool,
|
||||
) -> Result<(), String> {
|
||||
check_name(name)?;
|
||||
let dir = project_dir(paths, name)?;
|
||||
check_name(project)?;
|
||||
let dir = project_dir(paths, project)?;
|
||||
if !dir.is_dir() {
|
||||
return Err(format!("Projekt nicht gefunden: {name}"));
|
||||
return Err(format!("Projektordner nicht gefunden: {}", dir.display()));
|
||||
}
|
||||
if delete_work_dirs {
|
||||
for wd in project_work_dirs_in(paths, name)? {
|
||||
let wd_path = expand_home(paths, &wd);
|
||||
fs::remove_dir_all(&wd_path).map_err(|e| format!("{}: {e}", wd_path.display()))?;
|
||||
let cfg = read_project_config_in(paths, project)?;
|
||||
|
||||
// Archiv vor der Integration räumen — Stufe 1 löscht die Config, die den
|
||||
// Pfad kennt.
|
||||
if scope == "archive" || scope == "full" {
|
||||
if let Some(a) = cfg.archive_home.as_deref() {
|
||||
let home = expand_home(paths, a);
|
||||
if home.is_dir() {
|
||||
fs::remove_dir_all(&home).map_err(|e| format!("{}: {e}", home.display()))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
fs::remove_dir_all(&dir).map_err(|e| format!("{}: {e}", dir.display()))?;
|
||||
crate::domain::registry::unregister_project(paths, name)?;
|
||||
crate::platform::remove_terminal_desktop(paths, name);
|
||||
|
||||
match scope {
|
||||
"integration" | "archive" => {
|
||||
if let Some(a) = cfg.archive_home.as_deref() {
|
||||
crate::domain::archive::remove_archive_permission(paths, project, a)?;
|
||||
}
|
||||
if crate::domain::todo::todo_state_in(paths, project)? {
|
||||
crate::domain::todo::set_todo_in(paths, project, false)?;
|
||||
}
|
||||
let ac = dir.join(PROJECT_CONFIG_DIR);
|
||||
if ac.is_dir() {
|
||||
fs::remove_dir_all(&ac).map_err(|e| format!("{}: {e}", ac.display()))?;
|
||||
}
|
||||
}
|
||||
"full" => {
|
||||
if delete_work_dirs {
|
||||
for wd in project_work_dirs_in(paths, project)? {
|
||||
let wd_path = expand_home(paths, &wd);
|
||||
fs::remove_dir_all(&wd_path).map_err(|e| format!("{}: {e}", wd_path.display()))?;
|
||||
}
|
||||
}
|
||||
fs::remove_dir_all(&dir).map_err(|e| format!("{}: {e}", dir.display()))?;
|
||||
}
|
||||
other => return Err(format!("unbekannter Lösch-Umfang: {other}")),
|
||||
}
|
||||
|
||||
for f in session_files(paths, project) {
|
||||
if f.is_file() {
|
||||
fs::remove_file(&f).map_err(|e| format!("{}: {e}", f.display()))?;
|
||||
}
|
||||
}
|
||||
crate::domain::registry::unregister_project(paths, project)?;
|
||||
crate::platform::remove_terminal_desktop(paths, project);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1149,7 +1247,7 @@ mod tests {
|
||||
fn projekt_loeschen() {
|
||||
let p = tmp_paths();
|
||||
create_project(&p, "proj").unwrap();
|
||||
delete_project_in(&p, "proj", false).unwrap();
|
||||
delete_project_scoped_in(&p, "proj", "full", false).unwrap();
|
||||
assert!(!p.projects_dir().join("proj").exists());
|
||||
}
|
||||
|
||||
@@ -1158,7 +1256,7 @@ mod tests {
|
||||
let p = tmp_paths();
|
||||
let id = create_project_full_in(&p, "proj", None, None, Some("~/projects/proj"), true, TerminalConfig::default(), false)
|
||||
.unwrap();
|
||||
delete_project_in(&p, &id, false).unwrap();
|
||||
delete_project_scoped_in(&p, &id, "full", false).unwrap();
|
||||
assert!(!p.projects_dir().join("proj").exists());
|
||||
assert!(p.home.join("projects").join("proj").is_dir());
|
||||
}
|
||||
@@ -1168,7 +1266,7 @@ mod tests {
|
||||
let p = tmp_paths();
|
||||
let id = create_project_full_in(&p, "proj", None, None, Some("~/projects/proj"), true, TerminalConfig::default(), false)
|
||||
.unwrap();
|
||||
delete_project_in(&p, &id, true).unwrap();
|
||||
delete_project_scoped_in(&p, &id, "full", true).unwrap();
|
||||
assert!(!p.projects_dir().join("proj").exists());
|
||||
assert!(!p.home.join("projects").join("proj").exists());
|
||||
}
|
||||
@@ -1179,7 +1277,7 @@ mod tests {
|
||||
let id = create_project_full_in(&p, "proj", None, None, Some("~/projects/proj"), true, TerminalConfig::default(), false)
|
||||
.unwrap();
|
||||
fs::remove_dir_all(p.home.join("projects").join("proj")).unwrap();
|
||||
assert!(delete_project_in(&p, &id, true).is_err());
|
||||
assert!(delete_project_scoped_in(&p, &id, "full", true).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1276,9 +1374,72 @@ mod tests {
|
||||
assert!(read_for_panel_in(&p, "proj", "/dev/zero").is_err());
|
||||
}
|
||||
|
||||
/// Stufe „nur Integration": ai-control-Spuren weg, Ordner und
|
||||
/// Claude-Code-Bestand bleiben.
|
||||
#[test]
|
||||
fn loeschen_nur_integration() {
|
||||
let p = tmp_paths();
|
||||
let id = create_project_full_in(&p, "proj", None, None, None, false, TerminalConfig::default(), true)
|
||||
.unwrap();
|
||||
let dir = p.projects_dir().join("proj");
|
||||
// Archiv-Home samt Permission wie über die UI gesetzt
|
||||
let mut cfg = read_project_config_in(&p, &id).unwrap();
|
||||
cfg.archive_home = Some("~/archiv/proj".into());
|
||||
write_project_config_in(&p, &id, &cfg).unwrap();
|
||||
crate::domain::archive::add_archive_permission(&p, &id, "~/archiv/proj").unwrap();
|
||||
fs::create_dir_all(p.home.join("archiv/proj")).unwrap();
|
||||
fs::write(p.home.join("archiv/proj/doc.md"), "inhalt").unwrap();
|
||||
// flüchtige Panel-Datei
|
||||
fs::create_dir_all(p.config_dir().join("panels")).unwrap();
|
||||
fs::write(p.config_dir().join("panels").join(format!("{id}.md")), "x").unwrap();
|
||||
|
||||
let preview = delete_preview_in(&p, &id).unwrap();
|
||||
assert!(preview.ai_control_dir && preview.archive_permission && preview.todo_hook);
|
||||
assert_eq!(preview.panel_files, 1);
|
||||
assert_eq!(preview.archive_docs, 1);
|
||||
|
||||
delete_project_scoped_in(&p, &id, "integration", false).unwrap();
|
||||
|
||||
assert!(dir.is_dir());
|
||||
assert!(!dir.join(PROJECT_CONFIG_DIR).exists());
|
||||
let sp = fs::read_to_string(settings_path(&dir)).unwrap();
|
||||
assert!(!sp.contains("archiv/proj"));
|
||||
assert!(!sp.contains("OFFENE-PUNKTE.md")); // Hook weg (leere Hook-Liste darf bleiben)
|
||||
assert!(sp.contains("autoMemoryDirectory")); // Claude-Code-Bestand bleibt
|
||||
assert!(dir.join(crate::domain::todo::TODO_FILE).is_file()); // Nutzerinhalt bleibt
|
||||
assert!(p.home.join("archiv/proj/doc.md").is_file()); // Archiv bleibt
|
||||
assert!(!p.config_dir().join("panels").join(format!("{id}.md")).exists());
|
||||
assert!(load_registry(&p).unwrap().is_empty());
|
||||
}
|
||||
|
||||
/// Stufe „Integration & Archiv": zusätzlich stirbt der Archiv-Ordner.
|
||||
#[test]
|
||||
fn loeschen_integration_und_archiv() {
|
||||
let p = tmp_paths();
|
||||
let id = create_project_full_in(&p, "proj", None, None, None, false, TerminalConfig::default(), false)
|
||||
.unwrap();
|
||||
let mut cfg = read_project_config_in(&p, &id).unwrap();
|
||||
cfg.archive_home = Some("~/archiv/proj".into());
|
||||
write_project_config_in(&p, &id, &cfg).unwrap();
|
||||
fs::create_dir_all(p.home.join("archiv/proj")).unwrap();
|
||||
|
||||
delete_project_scoped_in(&p, &id, "archive", false).unwrap();
|
||||
|
||||
assert!(p.projects_dir().join("proj").is_dir());
|
||||
assert!(!p.home.join("archiv/proj").exists());
|
||||
assert!(load_registry(&p).unwrap().is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn loeschen_unbekannter_umfang_scheitert() {
|
||||
let p = tmp_paths();
|
||||
create_project(&p, "proj").unwrap();
|
||||
assert!(delete_project_scoped_in(&p, "proj", "halb", false).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn projekt_loeschen_unbekannt_scheitert() {
|
||||
let p = tmp_paths();
|
||||
assert!(delete_project_in(&p, "gibtsnicht", false).is_err());
|
||||
assert!(delete_project_scoped_in(&p, "gibtsnicht", "full", false).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
"macOSPrivateApi": true,
|
||||
"windows": [],
|
||||
"security": {
|
||||
"csp": null
|
||||
"csp": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src ipc: http://ipc.localhost",
|
||||
"devCsp": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src ipc: http://ipc.localhost ws://localhost:1420 http://localhost:1420"
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
|
||||
@@ -201,7 +201,8 @@ onMounted(refresh);
|
||||
|
||||
<p v-if="error" class="error">{{ error }}</p>
|
||||
|
||||
<table v-if="pools.length" class="grid">
|
||||
<div v-if="pools.length" class="list-scroll">
|
||||
<table class="grid">
|
||||
<colgroup>
|
||||
<col />
|
||||
<col class="col-type" />
|
||||
@@ -268,6 +269,7 @@ onMounted(refresh);
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p v-else class="empty">{{ $t("pools.empty") }}</p>
|
||||
|
||||
<div v-if="dialog" class="overlay" @click.self="closeDialog">
|
||||
|
||||
+122
-40
@@ -379,10 +379,25 @@ async function createProject() {
|
||||
}
|
||||
}
|
||||
|
||||
interface DeletePreview {
|
||||
name: string;
|
||||
projectDir: string;
|
||||
aiControlDir: boolean;
|
||||
archivePermission: boolean;
|
||||
todoHook: boolean;
|
||||
panelFiles: number;
|
||||
archiveHome: string | null;
|
||||
archiveDocs: number;
|
||||
workDirs: string[];
|
||||
}
|
||||
|
||||
// Eskalationsleiter: jede Stufe schließt die vorige ein.
|
||||
type DeleteScope = "integration" | "archive" | "full";
|
||||
|
||||
interface PendingDelete {
|
||||
id: string;
|
||||
name: string;
|
||||
workDirs: string[];
|
||||
preview: DeletePreview;
|
||||
scope: DeleteScope;
|
||||
deleteWorkDirs: boolean;
|
||||
}
|
||||
|
||||
@@ -391,10 +406,8 @@ const pendingDelete = ref<PendingDelete | null>(null);
|
||||
async function askDelete(p: Project) {
|
||||
error.value = "";
|
||||
try {
|
||||
const workDirs = await invoke<string[]>("project_work_dirs", {
|
||||
project: p.id,
|
||||
});
|
||||
pendingDelete.value = { id: p.id, name: p.name, workDirs, deleteWorkDirs: false };
|
||||
const preview = await invoke<DeletePreview>("delete_preview", { project: p.id });
|
||||
pendingDelete.value = { id: p.id, preview, scope: "integration", deleteWorkDirs: false };
|
||||
} catch (e) {
|
||||
error.value = String(e);
|
||||
}
|
||||
@@ -403,9 +416,10 @@ async function askDelete(p: Project) {
|
||||
async function confirmDelete() {
|
||||
const d = pendingDelete.value!;
|
||||
try {
|
||||
await invoke("delete_project", {
|
||||
await invoke("delete_project_scoped", {
|
||||
project: d.id,
|
||||
deleteWorkDirs: d.deleteWorkDirs,
|
||||
scope: d.scope,
|
||||
deleteWorkDirs: d.scope === "full" && d.deleteWorkDirs,
|
||||
});
|
||||
pendingDelete.value = null;
|
||||
await refresh();
|
||||
@@ -415,19 +429,6 @@ async function confirmDelete() {
|
||||
}
|
||||
}
|
||||
|
||||
// Nur den Registry-Eintrag entfernen; der Ordner bleibt.
|
||||
async function unlinkProject() {
|
||||
const d = pendingDelete.value!;
|
||||
try {
|
||||
await invoke("remove_project", { project: d.id });
|
||||
pendingDelete.value = null;
|
||||
await refresh();
|
||||
} catch (e) {
|
||||
error.value = String(e);
|
||||
pendingDelete.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
let timer: number;
|
||||
onMounted(() => {
|
||||
refresh();
|
||||
@@ -447,6 +448,7 @@ onUnmounted(() => window.clearInterval(timer));
|
||||
</div>
|
||||
|
||||
<p v-if="error" class="error">{{ error }}</p>
|
||||
<div class="list-scroll">
|
||||
<table class="grid">
|
||||
<colgroup>
|
||||
<col class="col-dot" />
|
||||
@@ -516,6 +518,7 @@ onUnmounted(() => window.clearInterval(timer));
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div v-if="wizard" class="overlay" @click.self="wizard = null">
|
||||
<form class="dialog" @submit.prevent="createProject">
|
||||
@@ -619,30 +622,76 @@ onUnmounted(() => window.clearInterval(timer));
|
||||
|
||||
<div v-if="pendingDelete" class="overlay" @click.self="pendingDelete = null">
|
||||
<div class="dialog">
|
||||
<h3>{{ $t("projects.deleteTitle", { name: pendingDelete.name }) }}</h3>
|
||||
<p class="hint">{{ $t("projects.deleteWarning", { name: pendingDelete.name }) }}</p>
|
||||
<template v-if="pendingDelete.workDirs.length">
|
||||
<label class="checkline">
|
||||
<input v-model="pendingDelete.deleteWorkDirs" type="checkbox" />
|
||||
{{ $t("projects.deleteWorkDirs") }}
|
||||
</label>
|
||||
<ul class="affected">
|
||||
<li v-for="wd in pendingDelete.workDirs" :key="wd">{{ wd }}</li>
|
||||
</ul>
|
||||
<p v-if="!pendingDelete.deleteWorkDirs" class="hint">
|
||||
{{ $t("projects.workDirsStay") }}
|
||||
</p>
|
||||
</template>
|
||||
<p class="hint">{{ $t("projects.unlinkHint") }}</p>
|
||||
<h3>{{ $t("projects.deleteTitle", { name: pendingDelete.preview.name }) }}</h3>
|
||||
|
||||
<label class="scope">
|
||||
<input v-model="pendingDelete.scope" type="radio" value="integration" />
|
||||
<span>
|
||||
<strong>{{ $t("projects.scopeIntegration") }}</strong>
|
||||
<small>{{ $t("projects.scopeIntegrationDesc") }}</small>
|
||||
</span>
|
||||
</label>
|
||||
<label class="scope">
|
||||
<input
|
||||
v-model="pendingDelete.scope"
|
||||
type="radio"
|
||||
value="archive"
|
||||
:disabled="!pendingDelete.preview.archiveHome"
|
||||
/>
|
||||
<span>
|
||||
<strong>{{ $t("projects.scopeArchive") }}</strong>
|
||||
<small v-if="pendingDelete.preview.archiveHome">
|
||||
{{ $t("projects.scopeArchiveDesc", { path: pendingDelete.preview.archiveHome }) }}
|
||||
({{ $t("projects.docCount", pendingDelete.preview.archiveDocs) }})
|
||||
</small>
|
||||
<small v-else>{{ $t("projects.archiveNone") }}</small>
|
||||
</span>
|
||||
</label>
|
||||
<label class="scope">
|
||||
<input v-model="pendingDelete.scope" type="radio" value="full" />
|
||||
<span>
|
||||
<strong>{{ $t("projects.scopeFull") }}</strong>
|
||||
<small>{{ $t("projects.scopeFullDesc", { path: pendingDelete.preview.projectDir }) }}</small>
|
||||
</span>
|
||||
</label>
|
||||
<label
|
||||
v-if="pendingDelete.scope === 'full' && pendingDelete.preview.workDirs.length"
|
||||
class="checkline"
|
||||
>
|
||||
<input v-model="pendingDelete.deleteWorkDirs" type="checkbox" />
|
||||
{{ $t("projects.deleteWorkDirs") }}
|
||||
</label>
|
||||
|
||||
<p class="hint">{{ $t("projects.deletePreviewTitle") }}</p>
|
||||
<ul class="affected">
|
||||
<li>{{ $t("projects.artRegistry") }}</li>
|
||||
<li v-if="pendingDelete.preview.aiControlDir">{{ $t("projects.artAiControl") }}</li>
|
||||
<li v-if="pendingDelete.preview.archivePermission">{{ $t("projects.artArchivePerm") }}</li>
|
||||
<li v-if="pendingDelete.preview.todoHook">{{ $t("projects.artTodoHook") }}</li>
|
||||
<li v-if="pendingDelete.preview.panelFiles">
|
||||
{{ $t("projects.artPanelFiles", pendingDelete.preview.panelFiles) }}
|
||||
</li>
|
||||
<li>{{ $t("projects.artDesktop") }}</li>
|
||||
<li v-if="pendingDelete.scope !== 'integration' && pendingDelete.preview.archiveHome">
|
||||
{{ $t("projects.artArchive", { path: pendingDelete.preview.archiveHome }) }}
|
||||
({{ $t("projects.docCount", pendingDelete.preview.archiveDocs) }})
|
||||
</li>
|
||||
<li v-if="pendingDelete.scope === 'full'">
|
||||
{{ $t("projects.artProjectDir", { path: pendingDelete.preview.projectDir }) }}
|
||||
</li>
|
||||
<template v-if="pendingDelete.scope === 'full' && pendingDelete.deleteWorkDirs">
|
||||
<li v-for="wd in pendingDelete.preview.workDirs" :key="wd">
|
||||
{{ $t("projects.artWorkDir", { path: wd }) }}
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
|
||||
<div class="actions">
|
||||
<button type="button" @click="pendingDelete = null">
|
||||
{{ $t("projects.cancel") }}
|
||||
</button>
|
||||
<button @click="unlinkProject">
|
||||
{{ $t("projects.unlink") }}
|
||||
</button>
|
||||
<button class="danger" @click="confirmDelete">
|
||||
{{ $t("projects.delete") }}
|
||||
{{ $t("projects.deleteConfirm") }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -784,6 +833,39 @@ onUnmounted(() => window.clearInterval(timer));
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/* Lösch-Dialog: drei Stufen als Radio-Zeilen mit Beschreibung. */
|
||||
.scope {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 0.6rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.scope input {
|
||||
margin-top: 0.2rem;
|
||||
}
|
||||
|
||||
.scope span {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.1rem;
|
||||
}
|
||||
|
||||
.scope strong {
|
||||
font-size: 0.9rem;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.scope small {
|
||||
color: var(--overlay);
|
||||
font-size: 0.78rem;
|
||||
}
|
||||
|
||||
.scope:has(input:disabled) {
|
||||
opacity: 0.55;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/* Settings-Dialog: festes Grid Label | Wert | Aktionen in drei Gruppen. */
|
||||
.settings-dialog {
|
||||
position: relative;
|
||||
|
||||
@@ -113,7 +113,8 @@ function cost(n: number): string {
|
||||
|
||||
<p v-if="error" class="error">{{ error }}</p>
|
||||
|
||||
<table v-if="groups.length" class="grid">
|
||||
<div v-if="groups.length" class="list-scroll">
|
||||
<table class="grid">
|
||||
<colgroup>
|
||||
<col />
|
||||
<col class="col-num" />
|
||||
@@ -164,5 +165,6 @@ function cost(n: number): string {
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
<p v-else-if="!loading" class="empty">{{ $t("usage.empty") }}</p>
|
||||
</template>
|
||||
|
||||
+38
-12
@@ -71,13 +71,26 @@ const de = {
|
||||
delete: "Projekt löschen",
|
||||
deleteRunning: "Läuft noch — erst beenden",
|
||||
deleteTitle: "{name} löschen",
|
||||
deleteWarning:
|
||||
"Der Projektordner (inkl. memory/, Settings und Pool-Zuordnung) wird endgültig gelöscht.",
|
||||
deleteConfirm: "Entfernen",
|
||||
deleteWorkDirs: "Arbeitsordner mitlöschen:",
|
||||
workDirsStay: "Die Arbeitsordner bleiben unangetastet.",
|
||||
unlink: "Nur aus Liste nehmen",
|
||||
unlinkHint:
|
||||
"Nur aus Liste nehmen entfernt den Eintrag; der Ordner bleibt unangetastet.",
|
||||
scopeIntegration: "Nur Integration entfernen",
|
||||
scopeIntegrationDesc:
|
||||
"ai-control-Spuren werden entfernt; Projektordner, memory/ und Todoliste bleiben.",
|
||||
scopeArchive: "Integration & Archiv",
|
||||
scopeArchiveDesc: "zusätzlich {path} — endgültig.",
|
||||
scopeFull: "Projekt komplett löschen",
|
||||
scopeFullDesc: "zusätzlich der Projektordner {path} — endgültig.",
|
||||
deletePreviewTitle: "Wird entfernt:",
|
||||
docCount: "kein Dokument | 1 Dokument | {count} Dokumente",
|
||||
artRegistry: "Registry-Eintrag",
|
||||
artAiControl: ".ai-control/ (Config + Icon)",
|
||||
artArchivePerm: "Archiv-Berechtigung in .claude/settings.json",
|
||||
artTodoHook: "Todo-Hook in .claude/settings.json",
|
||||
artPanelFiles: "Panel-Kanaldatei | {count} Panel-Kanaldateien",
|
||||
artDesktop: ".desktop-Starter",
|
||||
artArchive: "Archiv {path}",
|
||||
artProjectDir: "Projektordner {path}",
|
||||
artWorkDir: "Arbeitsordner {path}",
|
||||
todo: "Todoliste",
|
||||
todoDesc: "OFFENE-PUNKTE.md bei jedem Sessionstart einspielen",
|
||||
groupAppearance: "Darstellung",
|
||||
@@ -201,13 +214,26 @@ const en: typeof de = {
|
||||
delete: "Delete project",
|
||||
deleteRunning: "Still running — stop it first",
|
||||
deleteTitle: "Delete {name}",
|
||||
deleteWarning:
|
||||
"The project folder (incl. memory/, settings and pool assignment) will be deleted permanently.",
|
||||
deleteConfirm: "Remove",
|
||||
deleteWorkDirs: "Also delete working folders:",
|
||||
workDirsStay: "The working folders stay untouched.",
|
||||
unlink: "Remove from list only",
|
||||
unlinkHint:
|
||||
"Remove from list only drops the entry; the folder stays untouched.",
|
||||
scopeIntegration: "Remove integration only",
|
||||
scopeIntegrationDesc:
|
||||
"ai-control traces are removed; project folder, memory/ and todo list stay.",
|
||||
scopeArchive: "Integration & archive",
|
||||
scopeArchiveDesc: "additionally {path} — permanent.",
|
||||
scopeFull: "Delete project completely",
|
||||
scopeFullDesc: "additionally the project folder {path} — permanent.",
|
||||
deletePreviewTitle: "Will be removed:",
|
||||
docCount: "no documents | 1 document | {count} documents",
|
||||
artRegistry: "registry entry",
|
||||
artAiControl: ".ai-control/ (config + icon)",
|
||||
artArchivePerm: "archive permission in .claude/settings.json",
|
||||
artTodoHook: "todo hook in .claude/settings.json",
|
||||
artPanelFiles: "panel channel file | {count} panel channel files",
|
||||
artDesktop: ".desktop launcher",
|
||||
artArchive: "archive {path}",
|
||||
artProjectDir: "project folder {path}",
|
||||
artWorkDir: "working folder {path}",
|
||||
todo: "Todo list",
|
||||
todoDesc: "Inject OFFENE-PUNKTE.md at every session start",
|
||||
groupAppearance: "Appearance",
|
||||
|
||||
+11
-1
@@ -123,10 +123,20 @@ input[type="checkbox"] {
|
||||
|
||||
main {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
/* Tab-Inhalte: Toolbar und Fehlerzeile stehen, nur die Liste scrollt. */
|
||||
.list-scroll {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* ---------- Controls ---------- */
|
||||
|
||||
button,
|
||||
|
||||
Reference in New Issue
Block a user