feat: Update window bootstrap logic and improve note editor UI layout

This commit is contained in:
2026-05-18 23:09:11 +02:00
parent e80ae52c08
commit 6de318786b
2 changed files with 169 additions and 133 deletions
+6 -3
View File
@@ -9,18 +9,21 @@ Future<void> bootstrapWindow() async {
} }
await windowManager.ensureInitialized(); await windowManager.ensureInitialized();
final Size initialSize = final Size initialSize =
await WindowStateStore.instance.loadWindowSize() ?? const Size(900, 700); await WindowStateStore.instance.loadWindowSize() ?? const Size(900, 700);
final WindowOptions windowOptions = WindowOptions( final WindowOptions windowOptions = WindowOptions(
size: initialSize, size: initialSize,
minimumSize: Size(400, 600), minimumSize: Size(400, 600),
center: true, center: false,
titleBarStyle: TitleBarStyle.hidden, titleBarStyle: TitleBarStyle.hidden,
); );
windowManager.waitUntilReadyToShow(windowOptions, () async { await windowManager.waitUntilReadyToShow(windowOptions, () async {
// Re-apply size after the window is ready to ensure it takes effect.
try {
await windowManager.setSize(initialSize);
} catch (_) {}
await windowManager.show(); await windowManager.show();
await windowManager.setMinimumSize(const Size(400, 600)); await windowManager.setMinimumSize(const Size(400, 600));
await windowManager.setSize(initialSize); await windowManager.setSize(initialSize);
+161 -128
View File
@@ -1,3 +1,5 @@
import 'dart:math' as math;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
@@ -21,7 +23,7 @@ class NoteEditorScreen extends StatefulWidget {
return showGeneralDialog<dynamic>( return showGeneralDialog<dynamic>(
context: context, context: context,
barrierDismissible: false, barrierDismissible: false,
barrierColor: const Color.fromARGB(127, 0, 0, 0).withValues(alpha: 0.5), barrierColor: Colors.transparent,
transitionDuration: const Duration(milliseconds: 200), transitionDuration: const Duration(milliseconds: 200),
pageBuilder: (context, animation, secondaryAnimation) { pageBuilder: (context, animation, secondaryAnimation) {
return NoteEditorScreen(note: note); return NoteEditorScreen(note: note);
@@ -96,7 +98,10 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
builder: (BuildContext context) { builder: (BuildContext context) {
return AlertDialog( return AlertDialog(
backgroundColor: const Color(0xFF303134), backgroundColor: const Color(0xFF303134),
title: const Text('Eliminar nota', style: TextStyle(color: Colors.white)), title: const Text(
'Eliminar nota',
style: TextStyle(color: Colors.white),
),
content: const Text( content: const Text(
'¿Estás seguro de que deseas eliminar esta nota?', '¿Estás seguro de que deseas eliminar esta nota?',
style: TextStyle(color: Colors.white70), style: TextStyle(color: Colors.white70),
@@ -104,14 +109,20 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
actions: [ actions: [
TextButton( TextButton(
onPressed: () => Navigator.of(context).pop(), onPressed: () => Navigator.of(context).pop(),
child: const Text('Cancelar', style: TextStyle(color: Colors.white70)), child: const Text(
'Cancelar',
style: TextStyle(color: Colors.white70),
),
), ),
TextButton( TextButton(
onPressed: () { onPressed: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
Navigator.of(context).pop('delete'); Navigator.of(context).pop('delete');
}, },
child: const Text('Eliminar', style: TextStyle(color: Colors.red)), child: const Text(
'Eliminar',
style: TextStyle(color: Colors.red),
),
), ),
], ],
); );
@@ -136,137 +147,159 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Dialog( return Material(
backgroundColor: Colors.transparent, color: Colors.transparent,
elevation: 0, child: LayoutBuilder(
child: Container( builder: (BuildContext context, BoxConstraints constraints) {
constraints: const BoxConstraints(maxWidth: 600), final double maxWidth = math.min(600, constraints.maxWidth - 48);
decoration: BoxDecoration( final double maxHeight = math.min(constraints.maxHeight * 0.88, 720);
color: const Color.fromRGBO(24, 25, 26, 1), final double overlayTop = MediaQuery.paddingOf(context).top + 32;
borderRadius: BorderRadius.circular(16),
border: Border.all(color: Colors.white24, width: 1), return Stack(
boxShadow: [ children: [
BoxShadow( Positioned.fill(
color: Colors.black.withValues(alpha: 0.5), top: overlayTop,
blurRadius: 24, child: Container(
offset: const Offset(0, 8), color: const Color.fromARGB(127, 0, 0, 0).withValues(alpha: 0.5),
),
],
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Header con botones y fechas
Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(color: Colors.white12, width: 1),
), ),
), ),
child: Row( SafeArea(
children: [ child: Center(
IconButton( child: Padding(
onPressed: _closeWithoutSaving, padding: EdgeInsets.only(top: overlayTop),
icon: const Icon(Icons.close, color: Colors.white70), child: ConstrainedBox(
tooltip: 'Cerrar sin guardar', constraints: BoxConstraints(
), maxWidth: maxWidth,
const SizedBox(width: 8), maxHeight: maxHeight,
Expanded( ),
child: Column( child: Container(
crossAxisAlignment: CrossAxisAlignment.start, decoration: BoxDecoration(
mainAxisSize: MainAxisSize.min, color: const Color.fromRGBO(24, 25, 26, 1),
children: [ borderRadius: BorderRadius.circular(16),
Text( border: Border.all(color: Colors.white24, width: 1),
'Creado: ${_formatDate(_currentNote.createdAt)}', boxShadow: [
style: const TextStyle(color: Colors.white54, fontSize: 12), BoxShadow(
color: Colors.black.withValues(alpha: 0.5),
blurRadius: 24,
offset: const Offset(0, 8),
),
],
), ),
if (_currentNote.updatedAt != _currentNote.createdAt) child: Column(
Text( mainAxisSize: MainAxisSize.min,
'Modificado: ${_formatDate(_currentNote.updatedAt)}', children: [
style: const TextStyle(color: Colors.white54, fontSize: 12), Container(
), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
], decoration: BoxDecoration(
border: Border(
bottom: BorderSide(color: Colors.white12, width: 1),
),
),
child: Row(
children: [
IconButton(
onPressed: _closeWithoutSaving,
icon: const Icon(Icons.close, color: Colors.white70),
tooltip: 'Cerrar sin guardar',
),
const SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
'Creado: ${_formatDate(_currentNote.createdAt)}',
style: const TextStyle(color: Colors.white54, fontSize: 12),
),
if (_currentNote.updatedAt != _currentNote.createdAt)
Text(
'Modificado: ${_formatDate(_currentNote.updatedAt)}',
style: const TextStyle(color: Colors.white54, fontSize: 12),
),
],
),
),
],
),
),
Expanded(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
controller: _titleController,
style: const TextStyle(
color: Colors.white,
fontSize: 28,
fontWeight: FontWeight.bold,
),
decoration: const InputDecoration(
hintText: 'Título',
hintStyle: TextStyle(color: Colors.white30),
border: InputBorder.none,
contentPadding: EdgeInsets.zero,
),
),
const SizedBox(height: 16),
TextField(
controller: _bodyController,
maxLines: null,
style: const TextStyle(
color: Colors.white,
fontSize: 16,
height: 1.6,
),
decoration: const InputDecoration(
hintText: 'Escribe tu nota...',
hintStyle: TextStyle(color: Colors.white30),
border: InputBorder.none,
contentPadding: EdgeInsets.zero,
),
),
],
),
),
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
border: Border(
top: BorderSide(color: Colors.white12, width: 1),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
if (!_isNewNote)
IconButton(
onPressed: _deleteNote,
icon: const Icon(Icons.delete_outline, color: Colors.red),
tooltip: 'Eliminar nota',
)
else
const SizedBox(width: 48),
FilledButton(
onPressed: _saveNote,
child: const Text('Guardar'),
),
],
),
),
],
),
),
), ),
), ),
],
),
),
// Contenido editable
Expanded(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Título
TextField(
controller: _titleController,
style: const TextStyle(
color: Colors.white,
fontSize: 28,
fontWeight: FontWeight.bold,
),
decoration: const InputDecoration(
hintText: 'Título',
hintStyle: TextStyle(color: Colors.white30),
border: InputBorder.none,
contentPadding: EdgeInsets.zero,
),
),
const SizedBox(height: 16),
// Cuerpo de la nota
TextField(
controller: _bodyController,
maxLines: null,
style: const TextStyle(
color: Colors.white,
fontSize: 16,
height: 1.6,
),
decoration: const InputDecoration(
hintText: 'Escribe tu nota...',
hintStyle: TextStyle(color: Colors.white30),
border: InputBorder.none,
contentPadding: EdgeInsets.zero,
),
),
],
),
), ),
), ),
), ],
// Footer con botones de acción );
Container( },
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
border: Border(
top: BorderSide(color: Colors.white12, width: 1),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// Botón de borrar (izquierda) - solo para notas existentes
if (!_isNewNote)
IconButton(
onPressed: _deleteNote,
icon: const Icon(Icons.delete_outline, color: Colors.red),
tooltip: 'Eliminar nota',
)
else
const SizedBox(width: 48), // Espacio para mantener alineación
// Botón de guardar (derecha)
FilledButton(
onPressed: _saveNote,
child: const Text('Guardar'),
),
],
),
),
],
),
), ),
); );
} }