diff --git a/lib/all_notes_page.dart b/lib/all_notes_page.dart index 9448630..311b801 100644 --- a/lib/all_notes_page.dart +++ b/lib/all_notes_page.dart @@ -1,6 +1,9 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:notes/icon_material_button.dart'; import 'package:notes/note_tile.dart'; +import 'package:notes/savesystem/path.dart'; class AllNotesPage extends StatefulWidget { const AllNotesPage({Key? key}) : super(key: key); @@ -10,6 +13,8 @@ class AllNotesPage extends StatefulWidget { } class _AllNotesPageState extends State { + List tileData = []; + @override Widget build(BuildContext context) { return Column( @@ -63,9 +68,35 @@ class _AllNotesPageState extends State { crossAxisCount: 5, ), padding: const EdgeInsets.all(2), - itemBuilder: (BuildContext context, int index) => const NoteTile(), - itemCount: 3, + itemBuilder: (BuildContext context, int idx) => + NoteTile(data: tileData[idx]), + itemCount: tileData.length, ), ); } + + @override + void initState() { + super.initState(); + loadAllNotes(); + } + + Future loadAllNotes() async { + final path = await getSavePath(); + final dta = await path + .list() + .where((fsentity) => fsentity.path.endsWith('.dbnote')) + .asyncMap((fsentity) async { + final lastmodified = (await fsentity.stat()).modified; + final filename = fsentity.path.split(Platform.pathSeparator).last; + final name = filename.substring(0, filename.length - 7); + return NoteTileData(name, filename, lastmodified); + }).toList(); + dta.sort( + (a, b) => a.lastModified.isAfter(b.lastModified) ? -1 : 1, + ); + setState(() { + tileData = dta; + }); + } } diff --git a/lib/canvas/document_types.dart b/lib/canvas/document_types.dart index d89aafc..a5dd561 100644 --- a/lib/canvas/document_types.dart +++ b/lib/canvas/document_types.dart @@ -9,6 +9,7 @@ class Stroke { double _maxy = double.negativeInfinity; final int id; + final Color color; @override String toString() { @@ -33,8 +34,8 @@ class Stroke { return Rect.fromPoints(Offset(_minx, _miny), Offset(_maxx, _maxy)); } - Stroke.fromPoints(this.points, this.id); - Stroke(this.id); + Stroke.fromPoints(this.points, this.id, this.color); + Stroke(this.id, this.color); } class Point { diff --git a/lib/canvas/drawing_page.dart b/lib/canvas/drawing_page.dart index e6a59c9..8da476d 100644 --- a/lib/canvas/drawing_page.dart +++ b/lib/canvas/drawing_page.dart @@ -1,6 +1,7 @@ import 'dart:math'; import 'dart:ui'; import 'package:fluentui_system_icons/fluentui_system_icons.dart'; +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:notes/savesystem/note_file.dart'; import 'my_painter.dart'; @@ -133,9 +134,11 @@ class _DrawingPageState extends State { return; } - controller.pointMoveEvent(pos, event.kind, event.tilt); + controller.pointMoveEvent(pos, event); - if (event.kind == PointerDeviceKind.touch) { + if (event.kind == PointerDeviceKind.touch || + (event.kind == PointerDeviceKind.mouse && + event.buttons == kSecondaryMouseButton)) { _calcNewPageOffset(event.delta, size.width); } } @@ -147,14 +150,14 @@ class _DrawingPageState extends State { return Listener( behavior: HitTestBehavior.opaque, onPointerMove: (e) => _onPointerMove(e, canvasSize), - onPointerDown: (event) { - Offset pos = event.localPosition; + onPointerDown: (d) { + Offset pos = d.localPosition; final scale = calcPageDependentScale(zoom, a4Page, canvasSize); pos = translateScreenToDocumentPoint(pos, scale, offset); - controller.pointDownEvent(pos, event.kind, event.tilt); + controller.pointDownEvent(pos, d); }, - onPointerUp: (event) { - controller.pointUpEvent(event.kind); + onPointerUp: (e) { + controller.pointUpEvent(e); }, child: GestureDetector( onScaleUpdate: (details) { diff --git a/lib/canvas/my_painter.dart b/lib/canvas/my_painter.dart index 09d6d36..f0c29db 100644 --- a/lib/canvas/my_painter.dart +++ b/lib/canvas/my_painter.dart @@ -51,6 +51,7 @@ class MyPainter extends CustomPainter { backgroundPaint); for (final stroke in controller.strokes) { + paint.color = stroke.color; for (int i = 0; i < stroke.points.length - 1; i++) { Offset pt1 = stroke.points[i].point; pt1 = _translatept(pt1, size); diff --git a/lib/canvas/paint_controller.dart b/lib/canvas/paint_controller.dart index 27dcb85..bd295b7 100644 --- a/lib/canvas/paint_controller.dart +++ b/lib/canvas/paint_controller.dart @@ -1,9 +1,9 @@ import 'dart:math'; import 'dart:ui'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; -import 'package:flutter/foundation.dart'; -import 'package:notes/savesystem/line_loader.dart'; - +import '../savesystem/line_loader.dart'; import '../savesystem/note_file.dart'; import 'document_types.dart'; import 'my_painter.dart'; @@ -46,29 +46,31 @@ class PaintController extends ChangeNotifier { return thickness; } - void pointDownEvent( - Offset offset, PointerDeviceKind pointer, double tilt) async { - if (_allowDrawWithFinger || pointer != PointerDeviceKind.touch) { + void pointDownEvent(Offset offset, PointerDownEvent e) async { + if (_allowedToDraw(e)) { // todo line drawn on edge where line left page if (!a4Page.contains(offset)) return; // todo handle other pens - if (activePen != Pen.pen) return; + if (activePen == Pen.eraser || activePen == Pen.selector) return; int strokeid = strokes.isNotEmpty ? strokes.last.id + 1 : 0; strokes.add(Stroke.fromPoints( - [Point(offset, _calcTiltedWidth(3.0, tilt))], - strokes.isNotEmpty ? strokes.last.id + 1 : 0)); + [Point(offset, _calcTiltedWidth(3.0, e.tilt))], + strokeid, + activePen == Pen.pen + ? Colors.black26 + : Colors.yellow.withOpacity(.5))); file.addStroke(strokeid); notifyListeners(); } } - void pointUpEvent(PointerDeviceKind pointer) { + void pointUpEvent(PointerUpEvent e) { if (activePen == Pen.eraser) return; - if (_allowDrawWithFinger || pointer != PointerDeviceKind.touch) { + if (_allowedToDraw(e)) { final lastStroke = strokes.last; if (lastStroke.points.length <= 1) { // if the line consists only of one point (point) add endpoint as the same to allow drawing a line @@ -79,12 +81,20 @@ class PaintController extends ChangeNotifier { } } - void pointMoveEvent(Offset offset, PointerDeviceKind pointer, double tilt) { + /// check if pointer event is allowed to draw points + bool _allowedToDraw(PointerEvent event) { + return (_allowDrawWithFinger && event.kind == PointerDeviceKind.touch) || + event.kind == PointerDeviceKind.stylus || + (event.kind == PointerDeviceKind.mouse && + event.buttons == kPrimaryMouseButton); + } + + void pointMoveEvent(Offset offset, PointerMoveEvent event) { if (!a4Page.contains(offset)) { return; } - if (_allowDrawWithFinger || pointer != PointerDeviceKind.touch) { + if (_allowedToDraw(event)) { switch (activePen) { case Pen.eraser: // todo dynamic eraser size @@ -105,10 +115,11 @@ class PaintController extends ChangeNotifier { } break; case Pen.pen: + case Pen.highlighter: final pts = strokes.last.points; if (pts.last.point == offset) return; - double newWidth = _calcTiltedWidth(5.0, tilt); + double newWidth = _calcTiltedWidth(5.0, event.tilt); if (strokes.last.points.length > 1) { newWidth = _calcAngleDependentWidth( pts.last, pts[pts.length - 2], newWidth); @@ -118,9 +129,6 @@ class PaintController extends ChangeNotifier { strokes.last.addPoint(p); file.addPoint(strokes.last.id, p); break; - case Pen.highlighter: - // TODO: Handle this case. - break; case Pen.selector: // TODO: Handle this case. break; diff --git a/lib/main.dart b/lib/main.dart index 0b6d052..d31108f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,12 +3,14 @@ import 'package:flutter/material.dart'; import 'package:notes/collapse_drawer.dart'; import 'package:notes/all_notes_page.dart'; import 'package:notes/canvas/drawing_page.dart'; +import 'package:sqflite/sqflite.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; void main() { if (defaultTargetPlatform != TargetPlatform.android && defaultTargetPlatform != TargetPlatform.iOS) { sqfliteFfiInit(); + databaseFactory = databaseFactoryFfi; } runApp(const MyApp()); } @@ -69,9 +71,10 @@ class _MyHomePageState extends State { case View.folders: return FloatingActionButton( onPressed: () { - //final now = DateTime.now(); - //String filename = 'note-${now.year}_${now.month}_${now.day}-${now.hour}_${now.minute}.dbnote'; - String filename = 'test.dbnote'; + final now = DateTime.now(); + String filename = + 'note-${now.year}_${now.month}_${now.day}-${now.hour}_${now.minute}.dbnote'; + Navigator.push( context, MaterialPageRoute( diff --git a/lib/note_tile.dart b/lib/note_tile.dart index 1e4a745..8651a5b 100644 --- a/lib/note_tile.dart +++ b/lib/note_tile.dart @@ -1,28 +1,51 @@ import 'package:flutter/material.dart'; +import 'canvas/drawing_page.dart'; + +class NoteTileData { + final String name; + final String relativePath; + final DateTime lastModified; + + NoteTileData(this.name, this.relativePath, this.lastModified); +} + class NoteTile extends StatelessWidget { - const NoteTile({Key? key}) : super(key: key); + const NoteTile({Key? key, required this.data}) : super(key: key); + + final NoteTileData data; @override Widget build(BuildContext context) { - return SizedBox( - width: 100, - child: Column( - children: [ - SizedBox( - height: 150, - width: 100, - child: Container( - color: Colors.white, + return GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => DrawingPage(filePath: data.relativePath), + ), + ); + }, + child: SizedBox( + width: 100, + child: Column( + children: [ + SizedBox( + height: 150, + width: 100, + child: Container( + color: Colors.white, + ), ), - ), - const Text( - 'This is a very long text mimimim lolo', - style: TextStyle(color: Colors.white), - overflow: TextOverflow.ellipsis, - ), - const Text('11:40') - ], + Text( + data.name, + style: const TextStyle(color: Colors.white), + overflow: TextOverflow.ellipsis, + ), + Text('${data.lastModified.hour}:${data.lastModified.minute}', + style: const TextStyle(color: Colors.white)) + ], + ), ), ); } diff --git a/lib/savesystem/line_loader.dart b/lib/savesystem/line_loader.dart index 2b3c041..bb20e75 100644 --- a/lib/savesystem/line_loader.dart +++ b/lib/savesystem/line_loader.dart @@ -1,4 +1,4 @@ -import 'dart:ui'; +import 'package:flutter/material.dart'; import 'note_file.dart'; import '../canvas/document_types.dart'; @@ -15,7 +15,7 @@ extension LineLoading on NoteFile { final int csid = i['strokeid'] as int; if (csid != strokeid) { strokeid = csid; - strokes.add(Stroke(strokeid)); + strokes.add(Stroke(strokeid, Colors.green)); } final Point p = Point( Offset(i['x'] as double, i['y'] as double), i['thickness'] as double); diff --git a/lib/savesystem/note_file.dart b/lib/savesystem/note_file.dart index bc50219..98f3352 100644 --- a/lib/savesystem/note_file.dart +++ b/lib/savesystem/note_file.dart @@ -1,29 +1,22 @@ -import 'package:flutter/foundation.dart'; +import 'dart:io'; + +import 'package:notes/savesystem/path.dart'; import 'package:sqflite/sqflite.dart'; -import 'package:sqflite_common_ffi/sqflite_ffi.dart'; class NoteFile { late Database _db; - String filename; + String filepath; Database db() { return _db; } - NoteFile(this.filename); + NoteFile(this.filepath); Future init() async { - String dbpath = filename; - if (defaultTargetPlatform == TargetPlatform.android || - defaultTargetPlatform == TargetPlatform.iOS) { - dbpath = '${await getDatabasesPath()}/$filename'; - } else { - // Change the default factory - databaseFactory = databaseFactoryFfi; - } - + final path = (await getSavePath()).path + Platform.pathSeparator + filepath; _db = await openDatabase( - dbpath, + path, onCreate: (db, version) { return db.execute( 'CREATE TABLE strokes(id integer primary key autoincrement, color INTEGER, elevation INTEGER);' diff --git a/lib/savesystem/path.dart b/lib/savesystem/path.dart new file mode 100644 index 0000000..e215719 --- /dev/null +++ b/lib/savesystem/path.dart @@ -0,0 +1,17 @@ +import 'dart:io'; + +import 'package:flutter/foundation.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:sqflite/sqflite.dart'; + +Future getSavePath() async { + Directory dbpath; + if (defaultTargetPlatform == TargetPlatform.android || + defaultTargetPlatform == TargetPlatform.iOS) { + dbpath = Directory(await getDatabasesPath()); + } else { + dbpath = Directory( + '${(await getApplicationDocumentsDirectory()).path}${Platform.pathSeparator}notes'); + } + return dbpath; +}