From ef44d349442b28401462457cf5aa4701e2947857 Mon Sep 17 00:00:00 2001 From: Claudecio Martins Date: Mon, 12 Oct 2026 13:26:20 -0300 Subject: [PATCH] refactor: redesign main action grid to 3x2 layout and update related UI components and icons --- assets/icons/pdf.svg | 109 +++++++++++++++--- assets/icons/xml.svg | 100 ++++++++++++++-- docs/architecture.md | 2 +- docs/serpro-layout-and-batch.md | 18 +-- .../ui/CyberCoreDesktopApplication.java | 5 +- .../cybercore/signer/ui/view/MainAppView.java | 22 +--- .../ui/view/SignatureValidationDialog.java | 27 ++--- .../src/main/resources/assets/icons/pdf.svg | 109 +++++++++++++++--- .../src/main/resources/assets/icons/xml.svg | 100 ++++++++++++++-- 9 files changed, 398 insertions(+), 94 deletions(-) diff --git a/assets/icons/pdf.svg b/assets/icons/pdf.svg index 3755ded..95d14b5 100644 --- a/assets/icons/pdf.svg +++ b/assets/icons/pdf.svg @@ -1,13 +1,96 @@ - - - - - - - - - - - - PDF - + +PDF diff --git a/assets/icons/xml.svg b/assets/icons/xml.svg index edbf6a9..87a9bec 100644 --- a/assets/icons/xml.svg +++ b/assets/icons/xml.svg @@ -1,13 +1,97 @@ - + + + + - + - + - - - + + + - - <XML> + + <XML> diff --git a/docs/architecture.md b/docs/architecture.md index 6fe8a25..f5396f5 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -35,7 +35,7 @@ O módulo de núcleo é totalmente independente de JavaFX ou bibliotecas visuais ### 1.2 Módulo `cybercore-ui` (Apresentação JavaFX) Responsável por toda a interação com o usuário: -* **Interface Principal (`MainAppView`):** Painel de navegação moderno com alternador dinâmico de tema (Claro/Escuro), grade 3x3 de operações rápidas (PDF, XML, Arquivo Genérico, Assinatura em Lote, Assinatura Atachada, Co-Assinatura, Carimbo de Tempo, Designer de Selos, Validador) e coluna lateral de utilitários (Logs em tempo real, Configurações e Diagnóstico). +* **Interface Principal (`MainAppView`):** Painel de navegação moderno com alternador dinâmico de tema (Claro/Escuro), grade de operações rápidas (PDF, XML, Assinatura Atachada, Designer de Selos, Validar Assinatura, Sair do Agente) e coluna lateral de utilitários (Logs em tempo real, Configurações, Tutorial, Certificados e Sobre). * **Diálogos de Consentimento e PIN:** Modais nativos de aprovação visual para requisições do protocolo CCSP/1 (`SignatureConfirmationDialog`, `ApplicationAuthorizeDialog`) e coleta segura de PIN de tokens (`A1PasswordDialog`). * **Designer de Selos Digitais (`SealDesignerDialog`):** Ferramenta com Live Preview para criação de selos visuais com controle de cores, estilo de brasão, exibição de nome completo sem truncamento e privacidade de CPF. * **Bandeja do Sistema (System Tray):** Execução minimizada com menu de contexto rápido para restauração da tela ou encerramento da sessão. diff --git a/docs/serpro-layout-and-batch.md b/docs/serpro-layout-and-batch.md index cd5cb43..b30203c 100644 --- a/docs/serpro-layout-and-batch.md +++ b/docs/serpro-layout-and-batch.md @@ -30,24 +30,18 @@ Em conformidade com os requisitos do projeto, a interface **não é uma cópia d --- -## 3. Grade Central de Ações (Hub 4x3) +## 3. Grade Central de Ações (Hub 3x2) -A interface principal organiza as operações em 12 cartões modernos com cantos arredondados (8px), sombras suaves e ícones vetoriais SVG nítidos: +A interface principal organiza as operações em 6 cartões modernos com cantos arredondados (8px), sombras suaves e ícones vetoriais SVG nítidos: | Posição | Operação | Descrição | |---|---|---| | (0, 0) | **Assinar PDF** | Assinatura digital de documentos PDF com cálculo de hash SHA-256 e gravação de assinatura. | | (1, 0) | **Assinar XML** | Assinatura de documentos XML (estruturas fiscais, NF-e, XMLDSig). | -| (2, 0) | **Assinar Arquivo** | Assinatura genérica de qualquer arquivo ou binário do sistema. | -| (3, 0) | **Assinar em Lote** | Processamento simultâneo de múltiplos arquivos com barra de progresso em tempo real. | -| (0, 1) | **Assinatura Atachada** | Assinatura embutida/anexada ao documento original (CAdES enveloped). | -| (1, 1) | **Co-Assinar Documento** | Adição de nova assinatura a um documento previamente assinado por outro titular. | -| (2, 1) | **Carimbo do Tempo** | Integração com protocolo RFC 3161 TSP para prova de anterioridade temporal. | -| (3, 1) | **Assinatura LTV** | Perfil de Longa Duração com inclusão de cadeia de certificados e carimbos para validade permanente. | -| (0, 2) | **Validar Assinatura** | Verificação de integridade criptográfica e conformidade do certificado digital. | -| (1, 2) | **Validar Carimbo** | Verificação da autenticidade e validade temporal de tokens TSR/TSP. | -| (2, 2) | *(Reservado)* | Espaço reservado para expansões futuras do agente. | -| (3, 2) | **Sair do Agente** | Encerramento seguro da sessão do agente. | +| (2, 0) | **Assinatura Atachada** | Assinatura embutida/anexada ao documento original (CAdES enveloped). | +| (0, 1) | **Gerenciar Selos** | Abertura do Designer e Gerenciador de Selos Digitais visuais para PAdES. | +| (1, 1) | **Validar Assinatura** | Verificação de integridade criptográfica e conformidade do certificado digital. | +| (2, 1) | **Sair do Agente** | Encerramento seguro da sessão do agente. | --- diff --git a/modules/cybercore-ui/src/main/java/br/com/cybercore/signer/ui/CyberCoreDesktopApplication.java b/modules/cybercore-ui/src/main/java/br/com/cybercore/signer/ui/CyberCoreDesktopApplication.java index 769e0fb..5185923 100644 --- a/modules/cybercore-ui/src/main/java/br/com/cybercore/signer/ui/CyberCoreDesktopApplication.java +++ b/modules/cybercore-ui/src/main/java/br/com/cybercore/signer/ui/CyberCoreDesktopApplication.java @@ -110,11 +110,8 @@ public class CyberCoreDesktopApplication extends Application { mainAppView.setOnSignFile(() -> new FileSignDialog(primaryStage, "Assinar Arquivo", "*.*", SvgIcons.fileIcon(), certificateManager, signingService).show()); mainAppView.setOnBatchSign(() -> new BatchSigningDialog(primaryStage, certificateManager, signingService).show()); mainAppView.setOnAttachedSign(() -> new FileSignDialog(primaryStage, "Assinatura Atachada", "*.*", SvgIcons.attachedIcon(), certificateManager, signingService).show()); - mainAppView.setOnCoSign(() -> new FileSignDialog(primaryStage, "Co-Assinar Documento", "*.*", SvgIcons.coSignIcon(), certificateManager, signingService).show()); - mainAppView.setOnTimestamp(() -> new SignatureValidationDialog(primaryStage, true).show()); mainAppView.setOnLtvSign(() -> new FileSignDialog(primaryStage, "Assinatura de Longa Duração (LTV)", "*.*", SvgIcons.ltvIcon(), certificateManager, signingService).show()); - mainAppView.setOnValidateSignature(() -> new SignatureValidationDialog(primaryStage, false).show()); - mainAppView.setOnValidateTimestamp(() -> new SignatureValidationDialog(primaryStage, true).show()); + mainAppView.setOnValidateSignature(() -> new SignatureValidationDialog(primaryStage).show()); mainAppView.setOnManageSeals(() -> new SealManagementDialog(primaryStage).show()); mainAppView.setOnExit(() -> { logger.info("Ação 'Sair' acionada na interface gráfica."); diff --git a/modules/cybercore-ui/src/main/java/br/com/cybercore/signer/ui/view/MainAppView.java b/modules/cybercore-ui/src/main/java/br/com/cybercore/signer/ui/view/MainAppView.java index e3b7339..5420450 100644 --- a/modules/cybercore-ui/src/main/java/br/com/cybercore/signer/ui/view/MainAppView.java +++ b/modules/cybercore-ui/src/main/java/br/com/cybercore/signer/ui/view/MainAppView.java @@ -35,17 +35,13 @@ public final class MainAppView { private final VBox root = new VBox(16); private final Button themeToggleBtn = new Button(); - // Callbacks das Ações private Runnable onSignPdf; private Runnable onSignXml; private Runnable onSignFile; private Runnable onBatchSign; private Runnable onAttachedSign; - private Runnable onCoSign; - private Runnable onTimestamp; private Runnable onLtvSign; private Runnable onValidateSignature; - private Runnable onValidateTimestamp; private Runnable onManageSeals; private Runnable onExit; @@ -73,7 +69,7 @@ public final class MainAppView { mainContent.setAlignment(Pos.CENTER); VBox.setVgrow(mainContent, Priority.ALWAYS); - // --- Hub Central de Ações (Grid 3 colunas x 3 linhas) --- + // --- Hub Central de Ações (Grid 3 colunas x 2 linhas) --- GridPane actionGrid = new GridPane(); actionGrid.setHgap(12); actionGrid.setVgap(12); @@ -85,15 +81,10 @@ public final class MainAppView { actionGrid.add(createActionButton(SvgIcons.xmlIcon(), "Assinar\nXML", () -> trigger(onSignXml)), 1, 0); actionGrid.add(createActionButton(SvgIcons.attachedIcon(), "Assinatura\nAtachada", () -> trigger(onAttachedSign)), 2, 0); - // Linha 1: Formatos Avançados, Temporais e Identidade Visual - actionGrid.add(createActionButton(SvgIcons.coSignIcon(), "Co-Assinar\nDocumento", () -> trigger(onCoSign)), 0, 1); - actionGrid.add(createActionButton(SvgIcons.timestampIcon(), "Carimbo\ndo Tempo", () -> trigger(onTimestamp)), 1, 1); - actionGrid.add(createActionButton(SvgIcons.sealIcon(), "Gerenciar\nSelos", () -> trigger(onManageSeals)), 2, 1); - - // Linha 2: Auditoria, Validação e Saída - actionGrid.add(createActionButton(SvgIcons.validateIcon(), "Validar\nAssinatura", () -> trigger(onValidateSignature)), 0, 2); - actionGrid.add(createActionButton(SvgIcons.validateTimestampIcon(), "Validar\nCarimbo", () -> trigger(onValidateTimestamp)), 1, 2); - actionGrid.add(createActionButton(SvgIcons.exitIcon(), "Sair do\nAgente", () -> trigger(onExit)), 2, 2); + // Linha 1: Identidade Visual, Auditoria e Saída + actionGrid.add(createActionButton(SvgIcons.sealIcon(), "Gerenciar\nSelos", () -> trigger(onManageSeals)), 0, 1); + actionGrid.add(createActionButton(SvgIcons.validateIcon(), "Validar\nAssinatura", () -> trigger(onValidateSignature)), 1, 1); + actionGrid.add(createActionButton(SvgIcons.exitIcon(), "Sair do\nAgente", () -> trigger(onExit)), 2, 1); // --- Painel Lateral Direito (Ferramentas, Certificados e Diagnóstico) --- VBox sideColumn = new VBox(10); @@ -337,11 +328,8 @@ public final class MainAppView { public void setOnSignFile(Runnable onSignFile) { this.onSignFile = onSignFile; } public void setOnBatchSign(Runnable onBatchSign) { this.onBatchSign = onBatchSign; } public void setOnAttachedSign(Runnable onAttachedSign) { this.onAttachedSign = onAttachedSign; } - public void setOnCoSign(Runnable onCoSign) { this.onCoSign = onCoSign; } - public void setOnTimestamp(Runnable onTimestamp) { this.onTimestamp = onTimestamp; } public void setOnLtvSign(Runnable onLtvSign) { this.onLtvSign = onLtvSign; } public void setOnValidateSignature(Runnable onValidateSignature) { this.onValidateSignature = onValidateSignature; } - public void setOnValidateTimestamp(Runnable onValidateTimestamp) { this.onValidateTimestamp = onValidateTimestamp; } public void setOnManageSeals(Runnable onManageSeals) { this.onManageSeals = onManageSeals; } public void setOnExit(Runnable onExit) { this.onExit = onExit; } diff --git a/modules/cybercore-ui/src/main/java/br/com/cybercore/signer/ui/view/SignatureValidationDialog.java b/modules/cybercore-ui/src/main/java/br/com/cybercore/signer/ui/view/SignatureValidationDialog.java index edcc2a1..0f1c54f 100644 --- a/modules/cybercore-ui/src/main/java/br/com/cybercore/signer/ui/view/SignatureValidationDialog.java +++ b/modules/cybercore-ui/src/main/java/br/com/cybercore/signer/ui/view/SignatureValidationDialog.java @@ -40,7 +40,6 @@ public final class SignatureValidationDialog { private static final Logger logger = LoggerFactory.getLogger(SignatureValidationDialog.class); private final Stage stage; - private final boolean isTimestamp; private final SignatureValidationService validationService = new SignatureValidationService(); private RadioButton rbAttached; @@ -58,15 +57,13 @@ public final class SignatureValidationDialog { private Button btnSaveExtracted; private byte[] lastExtractedContent; - public SignatureValidationDialog(Stage owner, boolean isTimestamp) { - this.isTimestamp = isTimestamp; - + public SignatureValidationDialog(Stage owner) { this.stage = new Stage(); this.stage.initModality(Modality.APPLICATION_MODAL); if (owner != null) { this.stage.initOwner(owner); } - this.stage.setTitle(isTimestamp ? "CyberCore Signer — Validação de Carimbo do Tempo" : "CyberCore Signer — Validação de Assinatura Digital"); + this.stage.setTitle("CyberCore Signer — Validação de Assinatura Digital"); this.stage.setResizable(true); this.stage.setMinWidth(680); this.stage.setMinHeight(520); @@ -82,11 +79,10 @@ public final class SignatureValidationDialog { HBox header = new HBox(12); header.setAlignment(Pos.CENTER_LEFT); header.getChildren().addAll( - isTimestamp ? SvgIcons.validateTimestampIcon() : SvgIcons.validateIcon(), + SvgIcons.validateIcon(), createHeaderLabel( - isTimestamp ? "VALIDAÇÃO DE CARIMBO DO TEMPO" : "VALIDAÇÃO DE ASSINATURA DIGITAL", - isTimestamp ? "Verifique a autenticidade e conformidade RFC 3161 TSP." - : "Verifique a autenticidade, integridade e certificados de assinaturas incorporadas ou destacadas." + "VALIDAÇÃO DE ASSINATURA DIGITAL", + "Verifique a autenticidade, integridade e certificados de assinaturas incorporadas ou destacadas." ) ); @@ -110,11 +106,6 @@ public final class SignatureValidationDialog { radioRow.getChildren().addAll(rbAttached, rbDetached); typeBox.getChildren().addAll(lblTypeTitle, radioRow); - if (isTimestamp) { - typeBox.setVisible(false); - typeBox.setManaged(false); - } - // 1. Arquivo de Assinatura / Arquivo Assinado VBox sigBox = new VBox(8); sigBox.getStyleClass().add("dialog-box"); @@ -197,7 +188,7 @@ public final class SignatureValidationDialog { } private void updateModeView() { - boolean isAttached = rbAttached.isSelected() && !isTimestamp; + boolean isAttached = rbAttached.isSelected(); docBox.setVisible(!isAttached); docBox.setManaged(!isAttached); @@ -205,7 +196,7 @@ public final class SignatureValidationDialog { lblSigPath.setText("Arquivo Assinado (.pdf, .p7m, .p7s, .xml):"); txtSigPath.setPromptText("Selecione o arquivo assinado com dados embutidos..."); } else { - lblSigPath.setText(isTimestamp ? "Arquivo de Carimbo (.tsr, .tsp, .p7s):" : "Arquivo de Assinatura (.p7s, .sig):"); + lblSigPath.setText("Arquivo de Assinatura (.p7s, .sig):"); txtSigPath.setPromptText("Selecione o arquivo de assinatura digital..."); } } @@ -227,7 +218,7 @@ public final class SignatureValidationDialog { if (rbAttached.isSelected()) { ch.getExtensionFilters().add(new FileChooser.ExtensionFilter("Documentos Assinados (*.pdf, *.p7m, *.p7s, *.xml)", "*.pdf", "*.p7m", "*.p7s", "*.xml", "*.*")); } else { - ch.getExtensionFilters().add(new FileChooser.ExtensionFilter("Assinaturas Digitais (*.p7s, *.sig, *.tsr)", "*.p7s", "*.sig", "*.tsr", "*.*")); + ch.getExtensionFilters().add(new FileChooser.ExtensionFilter("Assinaturas Digitais (*.p7s, *.sig)", "*.p7s", "*.sig", "*.*")); } File f = ch.showOpenDialog(stage); @@ -249,7 +240,7 @@ public final class SignatureValidationDialog { return; } - boolean isDetachedMode = rbDetached.isSelected() || isTimestamp; + boolean isDetachedMode = rbDetached.isSelected(); if (isDetachedMode && (docFile == null || !docFile.exists())) { showAlert(Alert.AlertType.WARNING, "Documento Original Não Selecionado", "Para validar assinatura destacada é necessário selecionar tanto o documento original quanto o arquivo de assinatura."); diff --git a/modules/cybercore-ui/src/main/resources/assets/icons/pdf.svg b/modules/cybercore-ui/src/main/resources/assets/icons/pdf.svg index 3755ded..95d14b5 100644 --- a/modules/cybercore-ui/src/main/resources/assets/icons/pdf.svg +++ b/modules/cybercore-ui/src/main/resources/assets/icons/pdf.svg @@ -1,13 +1,96 @@ - - - - - - - - - - - - PDF - + +PDF diff --git a/modules/cybercore-ui/src/main/resources/assets/icons/xml.svg b/modules/cybercore-ui/src/main/resources/assets/icons/xml.svg index edbf6a9..87a9bec 100644 --- a/modules/cybercore-ui/src/main/resources/assets/icons/xml.svg +++ b/modules/cybercore-ui/src/main/resources/assets/icons/xml.svg @@ -1,13 +1,97 @@ - + + + + - + - + - - - + + + - - <XML> + + <XML>