feat: Implement note positioning logic and tests for position conversion

This commit is contained in:
2026-05-22 17:31:40 +02:00
parent cdfd4f9342
commit 729e575a60
6 changed files with 228 additions and 87 deletions
+27 -36
View File
@@ -87,7 +87,9 @@ class _HomeScreenState extends State<HomeScreen> {
_loadNotesAndCategories();
}
Future<void> _loadNotesAndCategories({bool showLoadingIndicator = true}) async {
Future<void> _loadNotesAndCategories({
bool showLoadingIndicator = true,
}) async {
if (showLoadingIndicator) {
setState(() {
_isLoading = true;
@@ -97,8 +99,8 @@ class _HomeScreenState extends State<HomeScreen> {
final Future<List<Note>> notesFuture = _showDeletedNotes
? widget.repository.loadDeletedNotes()
: widget.repository.loadNotes();
final Future<List<Category>> categoriesFuture =
widget.repository.loadCategories();
final Future<List<Category>> categoriesFuture = widget.repository
.loadCategories();
List<Note> notesResult = <Note>[];
List<Category> categoriesResult = <Category>[];
@@ -362,7 +364,8 @@ class _HomeScreenState extends State<HomeScreen> {
final Category? currentCategory = _currentCategory();
final Map<String, Color> categoryBorderColors = <String, Color>{
for (final Category category in _categories)
if (category.colorValue != null) category.id: Color(category.colorValue!),
if (category.colorValue != null)
category.id: Color(category.colorValue!),
};
final Widget body = _isLoading
@@ -421,9 +424,12 @@ class _HomeScreenState extends State<HomeScreen> {
_lastPointerKind,
);
final Widget draggableNote = _DraggableNote(
final Widget
draggableNote = _DraggableNote(
note: filteredNotes[index],
borderColor: categoryBorderColors[filteredNotes[index].categoryId],
borderColor:
categoryBorderColors[filteredNotes[index]
.categoryId],
dataIndex: _notes.indexOf(
filteredNotes[index],
),
@@ -582,7 +588,7 @@ class _HomeScreenState extends State<HomeScreen> {
child: MenuDrawer(
onMenuItemTapped: _handleMenuItemTapped,
selectedItem: _selectedCategoryId != null
? 'category_$_selectedCategoryId'
? 'category_$_selectedCategoryId'
: (_showDeletedNotes
? 'deleted_notes'
: 'all_notes'),
@@ -840,12 +846,11 @@ class _CategoryDialogState extends State<_CategoryDialog> {
void initState() {
super.initState();
_controller = TextEditingController(text: widget.category?.name ?? '');
_selectedColor =
widget.category == null
_selectedColor = widget.category == null
? CategoryStyle.colors.first
: widget.category!.colorValue != null
? Color(widget.category!.colorValue!)
: null;
? Color(widget.category!.colorValue!)
: null;
if (widget.category != null && widget.category!.iconCodePoint != null) {
_selectedIcon = CategoryStyle.icons.firstWhere(
(IconData icon) => icon.codePoint == widget.category!.iconCodePoint,
@@ -906,7 +911,6 @@ class _CategoryDialogState extends State<_CategoryDialog> {
}
widget.onRequestSync().catchError((_) {});
} catch (e) {
debugPrint('ERROR creating category: $e');
if (mounted) {
@@ -922,24 +926,6 @@ class _CategoryDialogState extends State<_CategoryDialog> {
}
}
Future<void> _runPostSaveCallbacks({
required Future<void> Function() onCategoriesChanged,
required Future<void> Function() onRequestSync,
required Future<void> Function() onCategoryDeleted,
}) async {
try {
await onCategoriesChanged();
} catch (_) {}
try {
await onCategoryDeleted();
} catch (_) {}
unawaited(
onRequestSync().catchError((_) {}),
);
}
Future<void> _deleteCategory() async {
final bool? confirm = await showDialog<bool>(
context: context,
@@ -1002,11 +988,14 @@ class _CategoryDialogState extends State<_CategoryDialog> {
});
}
},
decoration: const InputDecoration(
hintText: 'Nombre de la categoría',
).copyWith(
errorText: _nameHasError ? 'El nombre es obligatorio' : null,
),
decoration:
const InputDecoration(
hintText: 'Nombre de la categoría',
).copyWith(
errorText: _nameHasError
? 'El nombre es obligatorio'
: null,
),
),
const SizedBox(height: 16),
Container(
@@ -1084,7 +1073,9 @@ class _CategoryDialogState extends State<_CategoryDialog> {
key: const ValueKey<String>('icons'),
spacing: 10,
runSpacing: 10,
children: CategoryStyle.icons.map((IconData icon) {
children: CategoryStyle.icons.map((
IconData icon,
) {
final bool isSelected = _selectedIcon == icon;
return GestureDetector(
onTap: () => setState(() {
+14 -4
View File
@@ -336,7 +336,9 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
Widget _buildCategorySelectorBox({Category? category}) {
final String label = category?.name ?? 'Sin categoría';
final IconData icon = CategoryStyle.iconForCodePoint(category?.iconCodePoint);
final IconData icon = CategoryStyle.iconForCodePoint(
category?.iconCodePoint,
);
final Color backgroundColor = _categoryBackgroundColor(category);
final Color foregroundColor = _categoryForegroundColor(category);
@@ -475,7 +477,9 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
}) {
final Color backgroundColor = _categoryBackgroundColor(category);
final Color foregroundColor = _categoryForegroundColor(category);
final IconData icon = CategoryStyle.iconForCodePoint(category?.iconCodePoint);
final IconData icon = CategoryStyle.iconForCodePoint(
category?.iconCodePoint,
);
return InkWell(
onTap: onTap,
@@ -510,8 +514,7 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
),
),
),
if (isSelected)
Icon(Icons.check, color: foregroundColor, size: 18),
if (isSelected) Icon(Icons.check, color: foregroundColor, size: 18),
],
),
),
@@ -565,6 +568,13 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
'Posicion: ${_currentNote.position}',
style: const TextStyle(
color: Colors.white54,
fontSize: 12,
),
),
Text(
'Creado: ${_formatDate(_currentNote.createdAt)}',
style: const TextStyle(