Hide advanced signing options by default

This commit is contained in:
2026-04-27 13:18:49 -05:00
parent b9f5165e38
commit 55837a2982
8 changed files with 107 additions and 34 deletions
+5 -1
View File
@@ -2,10 +2,14 @@
## Versión actual
- Versión base: `1.2.12`
- Versión base: `1.2.13`
## Historial
### 1.2.13 - 2026-04-27
- Web y Android ocultan por defecto los detalles avanzados de `Firmar ahora` y los muestran solo bajo demanda con botón de ojo.
### 1.2.12 - 2026-04-23
- Web reordena el menú principal para mostrar `Firmar ahora` en segunda posición y `Mis documentos` justo debajo.
+1 -1
View File
@@ -1 +1 @@
1.2.12
1.2.13
+2 -2
View File
@@ -18,8 +18,8 @@ android {
applicationId "net.linkedcorp.linkedsign"
minSdk 26
targetSdk 35
versionCode 10212
versionName "1.2.12"
versionCode 10213
versionName "1.2.13"
buildConfigField "String", "API_BASE_URL", "\"${apiBaseUrl}\""
}
@@ -1330,6 +1330,7 @@ private fun SignScreen(
var certPassword by rememberSaveable { mutableStateOf("") }
var reason by rememberSaveable { mutableStateOf("Firmado digitalmente") }
var location by rememberSaveable { mutableStateOf("") }
var showAdvancedOptions by remember { mutableStateOf(false) }
var currentPageIndex by rememberSaveable(selectedDocumentId) { mutableStateOf(0) }
var preview by remember(selectedDocumentId) { mutableStateOf<PdfPreviewState?>(null) }
var placement by remember(selectedDocumentId) { mutableStateOf<SignaturePlacement?>(null) }
@@ -1339,6 +1340,9 @@ private fun SignScreen(
val selectedDocument = state.documents.firstOrNull { it.id.toString() == selectedDocumentId }
val signerLabel = state.userName ?: state.userEmail ?: "Firmante"
val signatureStyle = state.signaturePreferences?.signatureStyle ?: "qr"
val qrPosition = state.signaturePreferences?.qrPosition ?: "left"
val qrBackground = state.signaturePreferences?.qrBackground ?: "transparent"
val qrBorder = state.signaturePreferences?.qrBorder ?: "none"
LaunchedEffect(initialDocumentId, state.documents) {
val documentId = initialDocumentId ?: return@LaunchedEffect
@@ -1360,7 +1364,6 @@ private fun SignScreen(
) {
item {
SectionCard(title = "Vista previa y firma") {
Text("Esta versión usa la configuración visual de firma ya guardada en tu cuenta.", color = TextMuted, fontSize = AppFontSizes.sm)
DropdownSelector(
label = "Documento",
options = state.documents.associate { it.id.toString() to (it.title ?: it.filename ?: "Documento ${it.id}") },
@@ -1374,8 +1377,37 @@ private fun SignScreen(
onSelect = { selectedCertificateId = it }
)
AppTextField(value = certPassword, onValueChange = { certPassword = it }, label = "Contraseña del certificado", isPassword = true)
OutlinedActionButton(
label = if (showAdvancedOptions) "Ocultar detalles" else "Mostrar detalles",
icon = if (showAdvancedOptions) Icons.Outlined.VisibilityOff else Icons.Outlined.Visibility
) {
showAdvancedOptions = !showAdvancedOptions
}
if (showAdvancedOptions) {
Text("Esta versión usa la configuración visual de firma ya guardada en tu cuenta.", color = TextMuted, fontSize = AppFontSizes.sm)
AppTextField(value = reason, onValueChange = { reason = it }, label = "Razón")
AppTextField(value = location, onValueChange = { location = it }, label = "Ubicación")
Surface(
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(18.dp),
color = SurfaceSoft,
border = BorderStroke(1.dp, StrokeSoft)
) {
Column(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(6.dp)
) {
Text("Estilo aplicado", color = BrandDark, fontSize = AppFontSizes.base, fontWeight = FontWeight.SemiBold)
Text("La firma usará tu configuración guardada en el menú Estilo Firma.", color = TextMuted, fontSize = AppFontSizes.sm)
Text("Tipo: $signatureStyle", color = BrandDark, fontSize = AppFontSizes.sm)
if (signatureStyle == "qr") {
Text("Posición QR: ${if (qrPosition == "left") "Izquierda" else "Derecha"}", color = BrandDark, fontSize = AppFontSizes.sm)
Text("Fondo: ${if (qrBackground == "transparent") "Transparente" else "Suave"}", color = BrandDark, fontSize = AppFontSizes.sm)
Text("Borde: ${if (qrBorder == "none") "Sin borde" else "Con borde"}", color = BrandDark, fontSize = AppFontSizes.sm)
}
}
}
}
OutlinedActionButton("Cargar PDF para ubicar firma", Icons.Outlined.Description) {
val documentId = selectedDocumentId.toIntOrNull() ?: return@OutlinedActionButton
scope.launch {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "linkedsign-backend",
"version": "1.2.12",
"version": "1.2.13",
"private": true,
"description": "Initial backend for LinkedSign",
"main": "src/server.js",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "frontend",
"private": true,
"version": "1.2.12",
"version": "1.2.13",
"type": "module",
"scripts": {
"dev": "vite",
+12
View File
@@ -1059,6 +1059,13 @@ select {
justify-content: center;
}
.btn-inline-toggle {
width: fit-content;
display: inline-flex;
align-items: center;
gap: 8px;
}
.sign-form-card form { display: flex; flex-direction: column; gap: 14px; }
.sign-info-panel { display: flex; flex-direction: column; gap: 14px; }
@@ -2314,6 +2321,11 @@ select {
flex: 1;
}
.btn-inline-toggle {
width: 100%;
justify-content: center;
}
.steps-bar {
flex-direction: column;
align-items: stretch;
@@ -3,7 +3,7 @@ import { useSearchParams } from 'react-router-dom';
import { listDocuments, downloadDocument, uploadDocument } from '../../api/documents';
import { listCertificates } from '../../api/certificates';
import { signDocument, getSignatures, downloadSigned } from '../../api/signatures';
import { PenTool, FileText, Shield, CheckCircle, MapPin, Download, Check, Plus } from 'lucide-react';
import { PenTool, FileText, Shield, CheckCircle, MapPin, Download, Check, Plus, Eye, EyeOff } from 'lucide-react';
import toast from 'react-hot-toast';
import PasswordModal from '../../components/ui/PasswordModal';
import PdfSignaturePlacer from '../../components/ui/PdfSignaturePlacer';
@@ -40,6 +40,7 @@ export default function SignaturesPage() {
const [pendingSign, setPendingSign] = useState(null);
const [uploadingDocument, setUploadingDocument] = useState(false);
const [pendingLocalDocument, setPendingLocalDocument] = useState(null);
const [showAdvancedOptions, setShowAdvancedOptions] = useState(false);
const documentInputRef = useRef(null);
useEffect(() => {
@@ -293,6 +294,16 @@ export default function SignaturesPage() {
</select>
{certs.length === 0 && <small className="field-hint">No tienes certificados activos.</small>}
</div>
<button
type="button"
className="btn btn-ghost btn-inline-toggle"
onClick={() => setShowAdvancedOptions((current) => !current)}
>
{showAdvancedOptions ? <EyeOff size={16} /> : <Eye size={16} />}
{showAdvancedOptions ? 'Ocultar detalles' : 'Mostrar detalles'}
</button>
{showAdvancedOptions && (
<>
<div className="field">
<label>Razón de firma</label>
<input type="text" name="reason" value={form.reason} onChange={handleChange} />
@@ -309,6 +320,8 @@ export default function SignaturesPage() {
{form.signatureStyle === 'qr' && <p><strong>Fondo:</strong> {form.qrBackground === 'transparent' ? 'Transparente' : 'Suave'}</p>}
{form.signatureStyle === 'qr' && <p><strong>Borde:</strong> {form.qrBorder === 'none' ? 'Sin borde' : 'Con borde'}</p>}
</div>
</>
)}
<button className="btn btn-primary btn-full" onClick={handleGoToPlace}>
<MapPin size={16} /> Elegir posición de firma →
</button>
@@ -372,7 +385,7 @@ export default function SignaturesPage() {
<div className="step-nav">
<button className="btn btn-ghost" onClick={() => setStep(0)}>← Volver</button>
<p className="step-desc">
Haz clic donde quieres que aparezca la firma en <strong>{selectedDoc?.title}</strong>
Haz clic donde quieres que aparezca la firma en <strong>{selectedDocumentTitle}</strong>
</p>
</div>
<PdfSignaturePlacer
@@ -396,15 +409,27 @@ export default function SignaturesPage() {
<h3>Posición confirmada — listo para firmar</h3>
</div>
<div className="sign-confirm-details">
<p><strong>Documento:</strong> {selectedDoc?.title}</p>
<p><strong>Documento:</strong> {selectedDocumentTitle}</p>
<p><strong>Certificado:</strong> {selectedCert?.alias}</p>
<p><strong>Página:</strong> {(sigPlacement?.page ?? 0) + 1}</p>
<button
type="button"
className="btn btn-ghost btn-inline-toggle"
onClick={() => setShowAdvancedOptions((current) => !current)}
>
{showAdvancedOptions ? <EyeOff size={16} /> : <Eye size={16} />}
{showAdvancedOptions ? 'Ocultar detalles' : 'Mostrar detalles'}
</button>
{showAdvancedOptions && (
<>
<p><strong>Razón:</strong> {form.reason}</p>
{form.location && <p><strong>Ubicación:</strong> {form.location}</p>}
<p><strong>Estilo visual:</strong> {form.signatureStyle}</p>
{form.signatureStyle === 'qr' && <p><strong>Posición QR:</strong> {form.qrPosition === 'left' ? 'Izquierda' : 'Derecha'}</p>}
{form.signatureStyle === 'qr' && <p><strong>Fondo:</strong> {form.qrBackground === 'transparent' ? 'Transparente' : 'Suave'}</p>}
{form.signatureStyle === 'qr' && <p><strong>Borde:</strong> {form.qrBorder === 'none' ? 'Sin borde' : 'Con borde'}</p>}
<p><strong>Página:</strong> {(sigPlacement?.page ?? 0) + 1}</p>
</>
)}
</div>
<div className="sign-confirm-actions">
<button className="btn btn-ghost" onClick={() => setStep(1)}>← Cambiar posición</button>