squash pdf export + storage permissions

This commit is contained in:
2022-10-31 18:29:58 +00:00
parent 84eef41996
commit 004b7166f7
13 changed files with 207 additions and 31 deletions

View File

@ -20,9 +20,7 @@ class _AppState extends State<App> {
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (ctx) {
final notifier = FileChangeNotifier();
notifier.loadAllNotes();
return notifier;
return FileChangeNotifier()..loadAllNotes();
},
child: Scaffold(
floatingActionButton: _fab(),
@ -48,27 +46,28 @@ class _AppState extends State<App> {
switch (activePage) {
case View.all:
case View.folders:
return FloatingActionButton(
onPressed: () async {
final now = DateTime.now();
final name =
'note-${now.year}_${now.month}_${now.day}-${now.hour}_${now.minute}';
final filename = '$name.dbnote';
return Consumer<FileChangeNotifier>(
builder: (ctx, notifier, child) => FloatingActionButton(
onPressed: () async {
final now = DateTime.now();
final name =
'note-${now.year}_${now.month}_${now.day}-${now.hour}_${now.minute}_${now.second}';
final filename = '$name.dbnote';
Navigator.push(
context,
MaterialPageRoute(
builder: (ctx) => DrawingPage(
filePath: filename,
name: name,
Navigator.push(
ctx,
MaterialPageRoute(
builder: (ctx) => DrawingPage(
filePath: filename,
name: name,
),
),
),
).then((value) =>
Provider.of<FileChangeNotifier>(context, listen: false)
.loadAllNotes());
},
backgroundColor: const Color(0xff3f3f3f),
child: const Icon(Icons.edit_calendar_outlined, color: Colors.orange),
).then((v) => notifier.loadAllNotes());
},
backgroundColor: const Color(0xff3f3f3f),
child:
const Icon(Icons.edit_calendar_outlined, color: Colors.orange),
),
);
default:
return Container();

View File

@ -5,6 +5,7 @@ import 'package:fluentui_system_icons/fluentui_system_icons.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import '../export/export_pdf.dart';
import '../savesystem/note_file.dart';
import '../widgets/icon_material_button.dart';
import '../widgets/tool_bar.dart';
@ -72,6 +73,7 @@ class _DrawingPageState extends State<DrawingPage> {
color: const Color.fromRGBO(255, 255, 255, .85),
onPressed: () {
// todo implement
exportPDF(controller.strokes, '${widget.name}.pdf');
},
),
IconMaterialButton(

View File

@ -128,6 +128,7 @@ class PaintController extends ChangeNotifier {
Point p = Point(offset, newWidth);
strokes.last.addPoint(p);
// todo do a batch commit per stroke
file.addPoint(strokes.last.id, p);
break;
case Pen.selector:

View File

@ -12,6 +12,10 @@ class FileChangeNotifier extends ChangeNotifier {
Future<List<NoteTileData>> loadAllNotes() async {
final path = await getSavePath();
if (!(await path.exists())) {
await path.create(recursive: true);
}
final dta = await path
.list()
.where((fsentity) => fsentity.path.endsWith('.dbnote'))

View File

@ -0,0 +1,58 @@
import 'dart:io';
import 'dart:ui';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
import '../canvas/document_types.dart';
import '../savesystem/path.dart';
const _a4width = 210 * PdfPageFormat.mm;
const _a4height = 297 * PdfPageFormat.mm;
class _StrokePDFPaint extends pw.Widget {
List<Stroke> strokes;
@override
void layout(pw.Context context, pw.BoxConstraints constraints,
{bool parentUsesSize = false}) {
box =
PdfRect.fromPoints(PdfPoint.zero, const PdfPoint(_a4width, _a4height));
}
@override
void paint(pw.Context context) {
super.paint(context);
for (final stroke in strokes) {
context.canvas.setStrokeColor(PdfColor.fromInt(stroke.color.value));
for (int i = 0; i < stroke.points.length - 1; i++) {
Offset pt1 = stroke.points[i].point * PdfPageFormat.mm;
pt1 = Offset(pt1.dx, _a4width - pt1.dy);
Offset pt2 = stroke.points[i + 1].point * PdfPageFormat.mm;
pt2 = Offset(pt2.dx, _a4width - pt2.dy);
context.canvas.setLineWidth(stroke.points[i].thickness);
context.canvas.drawLine(pt1.dx, pt1.dy, pt2.dx, pt2.dy);
context.canvas.strokePath();
}
}
}
_StrokePDFPaint(this.strokes);
}
void exportPDF(List<Stroke> strokes, String name) async {
final pdf = pw.Document();
const PdfPageFormat a4 = PdfPageFormat(_a4width, _a4height);
pdf.addPage(pw.MultiPage(
pageFormat: a4,
build: (context) => [_StrokePDFPaint(strokes)],
));
final path = await getSavePath();
final file = File('${path.path}${Platform.pathSeparator}$name');
await file.writeAsBytes(await pdf.save(), flush: true);
}

View File

@ -1,15 +1,26 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:sqflite/sqflite.dart';
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
import 'app.dart';
void main() {
void main() async {
if (defaultTargetPlatform != TargetPlatform.android &&
defaultTargetPlatform != TargetPlatform.iOS) {
sqfliteFfiInit();
databaseFactory = databaseFactoryFfi;
}
WidgetsFlutterBinding.ensureInitialized();
Map<Permission, PermissionStatus> statuses =
await [Permission.manageExternalStorage, Permission.storage].request();
if (statuses.containsValue(PermissionStatus.denied)) {
// todo some error handling
}
runApp(const MaterialApp(home: App()));
}

View File

@ -34,7 +34,9 @@ class _AllNotesPageState extends State<AllNotesPage> {
IconMaterialButton(
icon: const Icon(Icons.picture_as_pdf_outlined),
color: const Color.fromRGBO(255, 255, 255, .85),
onPressed: () {},
onPressed: () async {
// todo implement pdf import
},
),
IconMaterialButton(
icon: const Icon(Icons.search),

View File

@ -18,11 +18,18 @@ class NoteFile {
final path = (await getSavePath()).path + Platform.pathSeparator + filepath;
_db = await openDatabase(
path,
onCreate: (db, version) {
return db.execute(
'CREATE TABLE strokes(id integer primary key autoincrement, color INTEGER, elevation INTEGER);'
'CREATE TABLE points(id integer primary key autoincrement, x INTEGER, y INTEGER, thickness REAL, strokeid INTEGER)',
);
onCreate: (db, version) async {
Batch batch = db.batch();
batch.execute('DROP TABLE IF EXISTS strokes;');
batch.execute('DROP TABLE IF EXISTS points;');
batch.execute(
'CREATE TABLE strokes(id integer primary key autoincrement, color INTEGER, elevation INTEGER)');
batch.execute(
'CREATE TABLE points(id integer primary key autoincrement, x INTEGER, y INTEGER, thickness REAL, strokeid INTEGER)');
await batch.commit();
return;
},
// Set the version. This executes the onCreate function and provides a
// path to perform database upgrades and downgrades.

View File

@ -7,8 +7,11 @@ Future<Directory> getSavePath() async {
Directory dbpath;
if (defaultTargetPlatform == TargetPlatform.android ||
defaultTargetPlatform == TargetPlatform.iOS) {
final dir =
(await getExternalStorageDirectory())?.parent.parent.parent.parent ??
(await getApplicationDocumentsDirectory());
dbpath = Directory(
'${(await getApplicationDocumentsDirectory()).path}${Platform.pathSeparator}notes');
'${dir.path}${Platform.pathSeparator}Documents${Platform.pathSeparator}notes');
} else {
dbpath = Directory(
'${(await getApplicationDocumentsDirectory()).path}${Platform.pathSeparator}notes');