From d47c76c0ca9c695afaa87cc01065e2f3c8be0c81 Mon Sep 17 00:00:00 2001 From: Aleix Soler Date: Wed, 6 Aug 2025 18:44:21 +0200 Subject: [PATCH] fix: improve ui; clean unused component --- components/SettingsUI/TemplateEditor.tsx | 2 - components/SettingsUI/TemplateEditorModal.tsx | 1 - components/SettingsUI/TemplateItem.tsx | 32 +-- components/SettingsUI/TemplateSettings.tsx | 9 +- components/SettingsUI/UnifiedTemplateItem.tsx | 139 ------------ .../SettingsUI/UnifiedTemplateSettings.tsx | 202 ------------------ integrations/commands/commandsIntegration.ts | 3 +- .../file-explorer-integration.tsx | 3 +- integrations/status-bar/status-bar.tsx | 2 +- styles/components/template-settings.css | 59 +++-- 10 files changed, 75 insertions(+), 377 deletions(-) delete mode 100644 components/SettingsUI/UnifiedTemplateItem.tsx delete mode 100644 components/SettingsUI/UnifiedTemplateSettings.tsx diff --git a/components/SettingsUI/TemplateEditor.tsx b/components/SettingsUI/TemplateEditor.tsx index a36c45a..602ea89 100644 --- a/components/SettingsUI/TemplateEditor.tsx +++ b/components/SettingsUI/TemplateEditor.tsx @@ -74,8 +74,6 @@ export const TemplateEditor: React.FC = ({ id: template?.id || "", // Will be generated in integration name: templateName.trim(), description: templateDescription.trim(), - isPredefined: template?.isPredefined || false, - isEnabled: template?.isEnabled ?? true, statuses: statuses, }; diff --git a/components/SettingsUI/TemplateEditorModal.tsx b/components/SettingsUI/TemplateEditorModal.tsx index d699718..8459688 100644 --- a/components/SettingsUI/TemplateEditorModal.tsx +++ b/components/SettingsUI/TemplateEditorModal.tsx @@ -52,7 +52,6 @@ export const TemplateEditorModal: React.FC = ({ name: name.trim(), description: description.trim(), statuses: statusesWithTemplateId, - isCustom: true, }; onSave(savedTemplate); diff --git a/components/SettingsUI/TemplateItem.tsx b/components/SettingsUI/TemplateItem.tsx index b2ed256..8f2acfe 100644 --- a/components/SettingsUI/TemplateItem.tsx +++ b/components/SettingsUI/TemplateItem.tsx @@ -78,15 +78,18 @@ export const TemplateItem: React.FC = ({ title="Edit template" > - - + + )} @@ -100,18 +103,21 @@ export const TemplateItem: React.FC = ({ title="Delete template" > - - - - - + + + + + )} diff --git a/components/SettingsUI/TemplateSettings.tsx b/components/SettingsUI/TemplateSettings.tsx index 4502016..e564f9d 100644 --- a/components/SettingsUI/TemplateSettings.tsx +++ b/components/SettingsUI/TemplateSettings.tsx @@ -6,11 +6,14 @@ import { generateTemplateId, isTemplateNameUnique, } from "@/utils/templateUtils"; +import { + DEFAULT_ENABLED_TEMPLATES, + PREDEFINED_TEMPLATES, +} from "@/constants/predefinedTemplates"; interface TemplateSettingsProps { settings: PluginSettings; onChange: (key: keyof PluginSettings, value: unknown) => void; - templates: StatusTemplate[]; } export const TemplateSettings: React.FC = ({ @@ -124,8 +127,8 @@ export const TemplateSettings: React.FC = ({ ); if (!confirmed) return; - onChange("templates", []); - onChange("enabledTemplates", ["colorful"]); + onChange("templates", [...PREDEFINED_TEMPLATES]); + onChange("enabledTemplates", [...DEFAULT_ENABLED_TEMPLATES]); }, [onChange]); const handleCancelEditor = useCallback(() => { diff --git a/components/SettingsUI/UnifiedTemplateItem.tsx b/components/SettingsUI/UnifiedTemplateItem.tsx deleted file mode 100644 index f7ae516..0000000 --- a/components/SettingsUI/UnifiedTemplateItem.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import React from "react"; -import { StatusTemplate } from "../../types/pluginSettings"; -import { StatusDisplay } from "../atoms/StatusDisplay"; - -interface UnifiedTemplateItemProps { - template: StatusTemplate; - onToggle: (templateId: string, enabled: boolean) => void; - onEdit: (template: StatusTemplate) => void; - onDelete: (templateId: string) => void; - onReset: (templateId: string) => void; - onDuplicate: (templateId: string) => void; -} - -export const UnifiedTemplateItem: React.FC = ({ - template, - onToggle, - onEdit, - onDelete, - onReset, - onDuplicate, -}) => { - const handleToggle = () => { - onToggle(template.id, !template.isEnabled); - }; - - const handleEdit = () => { - onEdit(template); - }; - - const handleDelete = () => { - if ( - confirm( - `Are you sure you want to delete the template "${template.name}"?`, - ) - ) { - onDelete(template.id); - } - }; - - const handleReset = () => { - if ( - confirm( - `Reset "${template.name}" to its original state? This will lose any customizations.`, - ) - ) { - onReset(template.id); - } - }; - - const handleDuplicate = () => { - onDuplicate(template.id); - }; - - return ( -
-
-
- -
- -
-
- - {template.name} - - {template.isPredefined && ( - - Predefined - - )} -
- -
- {template.description} -
- -
- {template.statuses.map((status, index) => ( - - ))} -
-
-
- -
- - - - - {template.isPredefined && ( - - )} - - {!template.isPredefined && ( - - )} -
-
- ); -}; diff --git a/components/SettingsUI/UnifiedTemplateSettings.tsx b/components/SettingsUI/UnifiedTemplateSettings.tsx deleted file mode 100644 index 99f3955..0000000 --- a/components/SettingsUI/UnifiedTemplateSettings.tsx +++ /dev/null @@ -1,202 +0,0 @@ -import React, { useState, useCallback } from "react"; -import { PluginSettings, StatusTemplate } from "../../types/pluginSettings"; -import { TemplateIntegration } from "../../integrations/templates/templateIntegration"; -import { UnifiedTemplateItem } from "./UnifiedTemplateItem"; -import { TemplateEditor } from "./TemplateEditor"; - -interface UnifiedTemplateSettingsProps { - settings: PluginSettings; - onChange: (key: keyof PluginSettings, value: unknown) => void; -} - -export const UnifiedTemplateSettings: React.FC< - UnifiedTemplateSettingsProps -> = ({ settings, onChange }) => { - const [isCreating, setIsCreating] = useState(false); - const [editingTemplate, setEditingTemplate] = - useState(null); - - const handleCreateTemplate = useCallback(() => { - setIsCreating(true); - }, []); - - const handleEditTemplate = useCallback((template: StatusTemplate) => { - setEditingTemplate(template); - }, []); - - const handleDeleteTemplate = useCallback( - (templateId: string) => { - const success = TemplateIntegration.deleteTemplate(templateId); - if (success) { - // Trigger settings refresh - onChange("templates", TemplateIntegration.getTemplates()); - } - }, - [onChange], - ); - - const handleResetTemplate = useCallback( - (templateId: string) => { - const success = - TemplateIntegration.resetPredefinedTemplate(templateId); - if (success) { - // Trigger settings refresh - onChange("templates", TemplateIntegration.getTemplates()); - } - }, - [onChange], - ); - - const handleDuplicateTemplate = useCallback( - (templateId: string) => { - const newTemplate = - TemplateIntegration.duplicateTemplate(templateId); - if (newTemplate) { - // Trigger settings refresh - onChange("templates", TemplateIntegration.getTemplates()); - } - }, - [onChange], - ); - - const handleToggleTemplate = useCallback( - (templateId: string, isEnabled: boolean) => { - TemplateIntegration.toggleTemplate(templateId, isEnabled); - // Trigger settings refresh - onChange("templates", TemplateIntegration.getTemplates()); - }, - [onChange], - ); - - const handleSaveTemplate = useCallback( - (template: StatusTemplate) => { - if (editingTemplate) { - // Update existing template - const success = TemplateIntegration.updateTemplate( - editingTemplate.id, - template, - ); - if (success) { - onChange("templates", TemplateIntegration.getTemplates()); - } - } else { - // Create new template - TemplateIntegration.createTemplate( - template.name, - template.description, - template.statuses, - ); - onChange("templates", TemplateIntegration.getTemplates()); - } - - setIsCreating(false); - setEditingTemplate(null); - }, - [editingTemplate, onChange], - ); - - const handleCancel = useCallback(() => { - setIsCreating(false); - setEditingTemplate(null); - }, []); - - const predefinedTemplates = TemplateIntegration.getPredefinedTemplates(); - const customTemplates = TemplateIntegration.getCustomTemplates(); - - return ( -
-
-
Template Management
-
- Manage predefined and custom status templates. You can edit, - enable/disable, and reset predefined templates. -
-
- - {(isCreating || editingTemplate) && ( - t.id !== editingTemplate?.id) - .map((t) => t.name.toLowerCase())} - settings={settings} - /> - )} - - {!isCreating && !editingTemplate && ( - <> -
- -
- - {predefinedTemplates.length > 0 && ( -
-

- Predefined Templates -

-

- Built-in templates that can be customized, - enabled/disabled, or reset to defaults. -

-
- {predefinedTemplates.map((template) => ( - - ))} -
-
- )} - - {customTemplates.length > 0 && ( -
-

- Custom Templates -

-

- Your custom templates that you've created. -

-
- {customTemplates.map((template) => ( - - ))} -
-
- )} - - {customTemplates.length === 0 && ( -
-
-

No custom templates created yet.

-

- Click "Create New Template" to get started. -

-
-
- )} - - )} -
- ); -}; diff --git a/integrations/commands/commandsIntegration.ts b/integrations/commands/commandsIntegration.ts index f210119..07d0f0e 100644 --- a/integrations/commands/commandsIntegration.ts +++ b/integrations/commands/commandsIntegration.ts @@ -31,7 +31,8 @@ export class CommandsIntegration { ({ key }) => { if ( key === "quickStatusCommands" || - key === "useMultipleStatuses" + key === "useMultipleStatuses" || + key === "templates" ) { this.commandsService.destroy(); /// BUG: if removed a command will persist because is not removed, you need the oldStates to send it to be disabled // const oldValue = this.settings[key]; // TODO: Send the old value diff --git a/integrations/file-explorer/file-explorer-integration.tsx b/integrations/file-explorer/file-explorer-integration.tsx index debbb7c..b05bca0 100644 --- a/integrations/file-explorer/file-explorer-integration.tsx +++ b/integrations/file-explorer/file-explorer-integration.tsx @@ -57,7 +57,8 @@ export class FileExplorerIntegration implements IElementProcessor { key === "strictStatuses" || key === "fileExplorerIconPosition" || key === "unknownStatusIcon" || - key === "unknownStatusColor" + key === "unknownStatusColor" || + key === "templates" ) { this.destroy(); this.integrate().catch((r) => console.error(r)); diff --git a/integrations/status-bar/status-bar.tsx b/integrations/status-bar/status-bar.tsx index dfc9436..d6f16c7 100644 --- a/integrations/status-bar/status-bar.tsx +++ b/integrations/status-bar/status-bar.tsx @@ -43,7 +43,7 @@ export class StatusBarIntegration { if (key === "showStatusBar") { this.render(); // INFO: Force a render to set disabled or enabled } - if (key === "enabledTemplates") { + if (key === "enabledTemplates" || key === "templates") { this.handleActiveFileChange().catch(console.error); // INFO: Force a re-read of the statuses and render } if (key === "autoHideStatusBar") { diff --git a/styles/components/template-settings.css b/styles/components/template-settings.css index 0ce184a..d9e5111 100644 --- a/styles/components/template-settings.css +++ b/styles/components/template-settings.css @@ -27,8 +27,8 @@ align-items: center; gap: var(--size-2-2); padding: var(--size-2-3) var(--size-4-3); - background: var(--background-modifier-border); - border: 1px solid var(--background-modifier-border-hover); + background: var(--interactive-normal); + border: 1px solid var(--background-modifier-border); border-radius: var(--radius-s); color: var(--text-normal); cursor: pointer; @@ -37,8 +37,8 @@ } .template-reset-btn:hover { - background: var(--background-modifier-border-hover); - color: var(--text-accent); + background: var(--interactive-hover); + color: var(--text-normal); } /* Template Sections */ @@ -58,8 +58,9 @@ border-bottom: 2px solid var(--background-modifier-border); } -.template-section-title svg { +.template-section-title .lucide { opacity: 0.8; + color: var(--text-muted); } .template-list { @@ -82,12 +83,20 @@ .template-item:hover { background: var(--background-modifier-hover); - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + border-color: var(--background-modifier-border-hover); + box-shadow: 0 2px 8px var(--shadow-color); } .template-item.enabled { - background: var(--background-modifier-success); - border-color: var(--interactive-success); + background: var(--background-modifier-hover); + border-color: var(--interactive-accent); + box-shadow: 0 0 0 1px var(--interactive-accent); +} + +.template-item.enabled:hover { + box-shadow: + 0 2px 8px var(--shadow-color), + 0 0 0 1px var(--interactive-accent); } .template-item-content { @@ -109,6 +118,9 @@ } .template-custom-badge { + display: flex; + align-items: center; + gap: var(--size-2-1); padding: var(--size-2-1) var(--size-2-2); background: var(--interactive-accent); color: var(--text-on-accent); @@ -119,6 +131,11 @@ letter-spacing: 0.05em; } +.template-custom-badge .lucide { + width: 12px; + height: 12px; +} + /* Template Item Actions */ .template-item-actions { display: flex; @@ -143,6 +160,7 @@ cursor: pointer; transition: all var(--anim-duration-fast) ease; color: var(--text-muted); + background: transparent; } .template-action-btn:hover { @@ -150,8 +168,8 @@ } .template-action-btn--edit { - background: var(--background-modifier-border-hover); - color: var(--text-accent); + background: var(--interactive-normal); + color: var(--text-normal); } .template-action-btn--edit:hover { @@ -160,7 +178,7 @@ } .template-action-btn--delete { - background: var(--background-modifier-error); + background: var(--interactive-normal); color: var(--text-error); } @@ -169,6 +187,11 @@ color: var(--text-on-accent); } +.template-action-btn .lucide { + width: 16px; + height: 16px; +} + /* Template Editor Modal */ .template-editor-modal { background: var(--background-primary); @@ -206,10 +229,18 @@ } .template-editor-add-status { + display: flex; + align-items: center; + gap: var(--size-2-2); align-self: flex-start; margin-top: var(--size-4-2); } +.template-editor-add-status .lucide { + width: 16px; + height: 16px; +} + .template-editor-modal__actions { display: flex; gap: var(--size-4-2); @@ -227,16 +258,16 @@ font-weight: var(--font-medium); cursor: pointer; transition: all var(--anim-duration-fast) ease; + border: 1px solid var(--background-modifier-border); } .template-editor-modal__actions button:not(.mod-cta) { - background: var(--background-modifier-border); - border: 1px solid var(--background-modifier-border-hover); + background: var(--interactive-normal); color: var(--text-normal); } .template-editor-modal__actions button:not(.mod-cta):hover { - background: var(--background-modifier-border-hover); + background: var(--interactive-hover); } .template-editor-modal__actions .mod-cta:disabled {