mirror of
https://github.com/cyberbread-ru/notepad.git
synced 2026-07-14 12:51:01 +03:00
initial vibecoded release
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../models/note.dart';
|
||||
import '../viewmodels/note_view_model.dart';
|
||||
|
||||
class NoteEditorScreen extends StatefulWidget {
|
||||
final String noteId;
|
||||
|
||||
const NoteEditorScreen({super.key, required this.noteId});
|
||||
|
||||
@override
|
||||
State<NoteEditorScreen> createState() => _NoteEditorScreenState();
|
||||
}
|
||||
|
||||
class _NoteEditorScreenState extends State<NoteEditorScreen> {
|
||||
late final TextEditingController _titleController;
|
||||
late final TextEditingController _contentController;
|
||||
late Note _note;
|
||||
bool _isDirty = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
final vm = context.read<NoteViewModel>();
|
||||
_note = vm.notes.firstWhere((n) => n.id == widget.noteId);
|
||||
_titleController = TextEditingController(text: _note.title);
|
||||
_contentController = TextEditingController(text: _note.content);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_titleController.dispose();
|
||||
_contentController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _save() async {
|
||||
if (!_isDirty) return;
|
||||
final vm = context.read<NoteViewModel>();
|
||||
final updated = _note.copyWith(
|
||||
title: _titleController.text,
|
||||
content: _contentController.text,
|
||||
);
|
||||
await vm.updateNote(updated);
|
||||
setState(() => _isDirty = false);
|
||||
}
|
||||
|
||||
void _onChanged() {
|
||||
if (!_isDirty) setState(() => _isDirty = true);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return PopScope(
|
||||
onPopInvokedWithResult: (didPop, _) {
|
||||
if (didPop) _save();
|
||||
},
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
titleSpacing: 0,
|
||||
title: TextField(
|
||||
controller: _titleController,
|
||||
onChanged: (_) => _onChanged(),
|
||||
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600),
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'Title',
|
||||
border: InputBorder.none,
|
||||
contentPadding: EdgeInsets.zero,
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
if (_isDirty)
|
||||
IconButton(
|
||||
icon: const Icon(Icons.check),
|
||||
onPressed: _save,
|
||||
tooltip: 'Save',
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 8, 16, 16),
|
||||
child: TextField(
|
||||
controller: _contentController,
|
||||
onChanged: (_) => _onChanged(),
|
||||
maxLines: null,
|
||||
expands: true,
|
||||
keyboardType: TextInputType.multiline,
|
||||
style: const TextStyle(fontSize: 16, height: 1.5),
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'Start writing...',
|
||||
border: InputBorder.none,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user