Skip to content

Commit 3ce675c

Browse files
authored
Update home_screen.dart
1 parent 89c58b9 commit 3ce675c

File tree

1 file changed

+161
-124
lines changed

1 file changed

+161
-124
lines changed

lib/ui/screens/home_screen.dart

Lines changed: 161 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -1,151 +1,188 @@
1-
import 'dart:convert';
1+
import 'dart:io';
22
import 'package:flutter/material.dart';
3-
import 'package:fleather/fleather.dart';
4-
import 'package:parchment/parchment.dart';
5-
import 'package:hive/hive.dart';
6-
import 'package:share_plus/share_plus.dart';
3+
import '../../core/storage_service.dart';
4+
import 'document_viewer_screen.dart';
5+
import 'settings_screen.dart';
76

8-
class DocumentViewerScreen extends StatefulWidget {
9-
final String? fileName;
10-
const DocumentViewerScreen({super.key, this.fileName});
7+
class HomeScreen extends StatefulWidget {
8+
const HomeScreen({super.key});
119

1210
@override
13-
State<DocumentViewerScreen> createState() => _DocumentViewerScreenState();
11+
State<HomeScreen> createState() => _HomeScreenState();
1412
}
1513

16-
class _DocumentViewerScreenState extends State<DocumentViewerScreen> {
17-
FleatherController? _controller;
18-
late Box _box;
19-
final String _defaultDocName = "new_note";
20-
final FocusNode _focusNode = FocusNode();
21-
22-
@override
23-
void initState() {
24-
super.initState();
25-
_box = Hive.box('documents_box');
26-
_loadDocument();
27-
_controller!.addListener(_autoSave);
28-
}
29-
30-
void _loadDocument() {
31-
final String key = widget.fileName ?? _defaultDocName;
32-
final String? savedData = _box.get(key);
33-
34-
if (savedData != null) {
35-
try {
36-
final doc = ParchmentDocument.fromJson(jsonDecode(savedData));
37-
_controller = FleatherController(document: doc);
38-
} catch (e) {
39-
_controller = FleatherController();
40-
}
41-
} else {
42-
_controller = FleatherController();
43-
}
14+
class _HomeScreenState extends State<HomeScreen> {
15+
void _refreshList() {
16+
setState(() {});
4417
}
4518

46-
void _autoSave() {
47-
final String key = widget.fileName ?? _defaultDocName;
48-
final deltaData = jsonEncode(_controller!.document.toDelta());
49-
_box.put(key, deltaData);
50-
}
51-
52-
// Funkcija koja pretvara bogat tekst u običan string za deljenje
53-
void _shareDocument() {
54-
final String plainText = _controller!.document.toPlainText();
55-
final String title = widget.fileName ?? 'Untitled Note';
56-
57-
if (plainText.trim().isNotEmpty) {
58-
Share.share(plainText, subject: title);
59-
} else {
60-
ScaffoldMessenger.of(context).showSnackBar(
61-
const SnackBar(content: Text("Cannot share an empty note")),
62-
);
63-
}
19+
Future<void> _showCreateDialog() async {
20+
String newFileName = "";
21+
return showDialog(
22+
context: context,
23+
builder: (context) {
24+
return AlertDialog(
25+
title: const Text("New Document", style: TextStyle(fontWeight: FontWeight.w300)),
26+
content: TextField(
27+
autofocus: true,
28+
onChanged: (value) => newFileName = value,
29+
decoration: const InputDecoration(
30+
hintText: "Enter file name",
31+
border: UnderlineInputBorder(),
32+
),
33+
),
34+
actions: [
35+
TextButton(
36+
onPressed: () => Navigator.pop(context),
37+
child: const Text("Cancel"),
38+
),
39+
TextButton(
40+
onPressed: () {
41+
if (newFileName.isNotEmpty) {
42+
Navigator.pop(context);
43+
Navigator.push(
44+
context,
45+
MaterialPageRoute(
46+
builder: (_) => DocumentViewerScreen(
47+
fileName: newFileName.endsWith('.txt')
48+
? newFileName
49+
: '$newFileName.txt',
50+
),
51+
),
52+
).then((_) => _refreshList());
53+
}
54+
},
55+
child: const Text("Create"),
56+
),
57+
],
58+
);
59+
},
60+
);
6461
}
6562

6663
@override
6764
Widget build(BuildContext context) {
68-
final bottomInset = MediaQuery.of(context).viewInsets.bottom;
69-
final bool isKeyboardVisible = bottomInset > 0;
70-
final safeBottomPadding = MediaQuery.of(context).padding.bottom;
71-
7265
return Scaffold(
73-
resizeToAvoidBottomInset: false,
7466
appBar: AppBar(
75-
title: Text(
76-
widget.fileName ?? 'f.Sentence',
77-
style: const TextStyle(fontWeight: FontWeight.w300),
78-
),
79-
actions: [
80-
IconButton(
81-
icon: const Icon(Icons.share_outlined),
82-
tooltip: 'Share as text',
83-
onPressed: _shareDocument,
67+
title: const Text("f.Sentence", style: TextStyle(fontWeight: FontWeight.w300)),
68+
centerTitle: true,
69+
leading: Builder(
70+
builder: (context) => IconButton(
71+
icon: const Icon(Icons.menu),
72+
onPressed: () => Scaffold.of(context).openDrawer(),
8473
),
85-
],
74+
),
8675
),
87-
body: Stack(
88-
children: [
89-
Positioned.fill(
90-
child: Padding(
91-
padding: const EdgeInsets.symmetric(horizontal: 16),
92-
child: GestureDetector(
93-
onTap: () => _focusNode.requestFocus(),
94-
child: FleatherEditor(
95-
controller: _controller!,
96-
focusNode: _focusNode,
97-
readOnly: false,
98-
enableInteractiveSelection: true,
99-
padding: EdgeInsets.only(
100-
top: 16,
101-
bottom: isKeyboardVisible ? bottomInset + 80 : 100,
102-
),
76+
drawer: Drawer(
77+
child: Column(
78+
children: [
79+
DrawerHeader(
80+
decoration: BoxDecoration(
81+
color: Theme.of(context).colorScheme.surfaceContainerHighest.withOpacity(0.5),
82+
),
83+
child: const Center(
84+
child: Text(
85+
"f.Sentence",
86+
style: TextStyle(fontSize: 28, fontWeight: FontWeight.w200),
10387
),
10488
),
10589
),
106-
),
90+
ListTile(
91+
leading: const Icon(Icons.settings_outlined),
92+
title: const Text("Settings"),
93+
onTap: () {
94+
Navigator.pop(context);
95+
Navigator.push(
96+
context,
97+
MaterialPageRoute(builder: (_) => const SettingsScreen()),
98+
).then((_) => _refreshList());
99+
},
100+
),
101+
const Spacer(),
102+
const Padding(
103+
padding: EdgeInsets.all(16.0),
104+
child: Text(
105+
"v1.0.1",
106+
style: TextStyle(color: Colors.grey, fontSize: 12),
107+
),
108+
),
109+
],
110+
),
111+
),
112+
body: FutureBuilder<List<File>>(
113+
future: StorageService.getLocalFiles(),
114+
builder: (context, snapshot) {
115+
if (snapshot.connectionState == ConnectionState.waiting) {
116+
return const Center(child: CircularProgressIndicator());
117+
}
118+
119+
if (!snapshot.hasData || snapshot.data!.isEmpty) {
120+
return Center(
121+
child: Column(
122+
mainAxisAlignment: MainAxisAlignment.center,
123+
children: [
124+
Icon(Icons.note_add_outlined, size: 64, color: Colors.grey.withOpacity(0.5)),
125+
const SizedBox(height: 16),
126+
const Text("No documents yet.", style: TextStyle(color: Colors.grey)),
127+
],
128+
),
129+
);
130+
}
107131

108-
Positioned(
109-
bottom: isKeyboardVisible
110-
? bottomInset + 16
111-
: safeBottomPadding + 16,
112-
left: 16,
113-
right: 16,
114-
child: Material(
115-
elevation: 6,
116-
shadowColor: Colors.black38,
117-
borderRadius: BorderRadius.circular(30),
118-
color: Theme.of(context).colorScheme.surfaceContainerHighest,
119-
clipBehavior: Clip.antiAlias,
120-
child: Container(
121-
height: 56,
122-
padding: const EdgeInsets.symmetric(horizontal: 12),
123-
child: Theme(
124-
data: Theme.of(context).copyWith(
125-
dividerColor: Colors.transparent,
132+
final files = snapshot.data!;
133+
134+
return ListView.builder(
135+
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
136+
itemCount: files.length,
137+
itemBuilder: (context, index) {
138+
final file = files[index];
139+
final fileName = file.path.split('/').last;
140+
141+
return Card(
142+
elevation: 0,
143+
shape: RoundedRectangleBorder(
144+
borderRadius: BorderRadius.circular(16),
145+
side: BorderSide(
146+
color: Theme.of(context).colorScheme.outlineVariant,
147+
width: 1,
126148
),
127-
child: Center(
128-
child: SingleChildScrollView(
129-
scrollDirection: Axis.horizontal,
130-
child: FleatherToolbar.basic(
131-
controller: _controller!,
132-
),
133-
),
149+
),
150+
margin: const EdgeInsets.only(bottom: 12),
151+
child: ListTile(
152+
contentPadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 8),
153+
leading: CircleAvatar(
154+
backgroundColor: Theme.of(context).colorScheme.primaryContainer,
155+
child: Icon(Icons.article_outlined,
156+
color: Theme.of(context).colorScheme.onPrimaryContainer),
134157
),
158+
title: Text(
159+
fileName,
160+
style: const TextStyle(fontWeight: FontWeight.w400),
161+
),
162+
subtitle: Text(
163+
"Modified: ${file.lastModifiedSync().day}.${file.lastModifiedSync().month}.${file.lastModifiedSync().year}",
164+
style: TextStyle(fontSize: 12, color: Colors.grey[600]),
165+
),
166+
onTap: () {
167+
Navigator.push(
168+
context,
169+
MaterialPageRoute(
170+
builder: (_) => DocumentViewerScreen(fileName: fileName),
171+
),
172+
).then((_) => _refreshList());
173+
},
135174
),
136-
),
137-
),
138-
),
139-
],
175+
);
176+
},
177+
);
178+
},
179+
),
180+
floatingActionButton: FloatingActionButton.extended(
181+
onPressed: _showCreateDialog,
182+
label: const Text("New Note"),
183+
icon: const Icon(Icons.add),
184+
elevation: 2,
140185
),
141186
);
142187
}
143-
144-
@override
145-
void dispose() {
146-
_controller?.removeListener(_autoSave);
147-
_controller?.dispose();
148-
_focusNode.dispose();
149-
super.dispose();
150-
}
151188
}

0 commit comments

Comments
 (0)