Skip to content

Commit

Permalink
split view and add dynamic color
Browse files Browse the repository at this point in the history
  • Loading branch information
merlinschumacher committed Dec 23, 2024
1 parent 9c81eb6 commit e5b0580
Show file tree
Hide file tree
Showing 12 changed files with 274 additions and 199 deletions.
16 changes: 8 additions & 8 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
Expand All @@ -38,8 +38,8 @@
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
<action android:name="android.intent.action.PROCESS_TEXT" />
<data android:mimeType="text/plain" />
</intent>
</queries>
</manifest>
</manifest>
5 changes: 3 additions & 2 deletions android/app/src/main/res/values-night/styles.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode
setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
Expand All @@ -15,4 +16,4 @@
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
</resources>
5 changes: 3 additions & 2 deletions android/app/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode
setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
Expand All @@ -15,4 +16,4 @@
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
</resources>
3 changes: 3 additions & 0 deletions devtools_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
description: This file stores settings for Dart & Flutter DevTools.
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
extensions:
56 changes: 30 additions & 26 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:google_mlkit_document_scanner/google_mlkit_document_scanner.dart';
import 'package:super_simple_scan/views/document_result_view.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flex_color_scheme/flex_color_scheme.dart';
import 'package:dynamic_color/dynamic_color.dart';

void main() {
WidgetsFlutterBinding.ensureInitialized();
Expand All @@ -15,34 +15,38 @@ void main() {
class SuperSimpleScan extends StatelessWidget {
const SuperSimpleScan({super.key});

static final _defaultLightColorScheme =
ColorScheme.fromSwatch(primarySwatch: Colors.blue);

static final _defaultDarkColorScheme = ColorScheme.fromSwatch(
primarySwatch: Colors.blue, brightness: Brightness.dark);

// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Super Simple Scan',
theme: FlexThemeData.light(
appBarElevation: 0.5,
useMaterial3: true,
typography:
Typography.material2021(platform: TargetPlatform.android)),
darkTheme: FlexThemeData.dark(
appBarElevation: 1,
useMaterial3: true,
typography:
Typography.material2021(platform: TargetPlatform.android)),
themeMode: ThemeMode.system,
localizationsDelegates: [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [
Locale('en'),
Locale('de'),
],
home: HomePage(title: "Super Simple Scan"),
);
return DynamicColorBuilder(builder: (lightColorScheme, darkColorScheme) {
return MaterialApp(
title: 'Super Simple Scan',
theme: ThemeData(
colorScheme: lightColorScheme ?? _defaultLightColorScheme,
),
darkTheme: ThemeData(
colorScheme: darkColorScheme ?? _defaultDarkColorScheme,
),
themeMode: ThemeMode.system,
localizationsDelegates: [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [
Locale('en'),
Locale('de'),
],
home: HomePage(title: "Super Simple Scan"),
);
});
}
}

Expand Down
177 changes: 33 additions & 144 deletions lib/views/document_result_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_pdfview/flutter_pdfview.dart';
import 'package:google_mlkit_document_scanner/google_mlkit_document_scanner.dart';
import 'package:share_plus/share_plus.dart';
import 'package:super_simple_scan/widgets/filenameform_widget.dart';
import 'package:super_simple_scan/widgets/pdfdisplay_widget.dart';

class DocumentResultView extends StatefulWidget {
final DocumentScanningResult document;
Expand All @@ -20,25 +21,12 @@ class DocumentResultViewState extends State<DocumentResultView>
with WidgetsBindingObserver {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final fileNameFieldController = TextEditingController(text: "");
int currentPage = 0;
int? totalPages = 0;
bool isReady = false;
String errorMessage = '';

// Add a pdf suffix to the file name if it is missing
String _addPdfSuffix(String fileName) {
if (!fileName.toLowerCase().endsWith('.pdf')) {
return '$fileName.pdf';
}
return fileName;
}

void setDefaultFileName() {
DateTime now = DateTime.now();
fileNameFieldController.text =
AppLocalizations.of(context)!.defaultFileName(now, now);
fileNameFieldController.selection = TextSelection(
baseOffset: 0, extentOffset: fileNameFieldController.text.length);
@override
void dispose() {
// Clean up the controller when the widget is disposed.
fileNameFieldController.dispose();
super.dispose();
}

@override
Expand All @@ -60,131 +48,35 @@ class DocumentResultViewState extends State<DocumentResultView>
Expanded(
child: SizedBox(
height: pdfHeight,
child: Stack(children: [
PDFView(
enableSwipe: true,
pageFling: true,
pageSnap: true,
autoSpacing: true,
filePath: widget.document.pdf!.uri,
defaultPage: currentPage,
swipeHorizontal: true,
fitPolicy: FitPolicy.BOTH,
fitEachPage: true,
preventLinkNavigation: false,
backgroundColor:
Theme.of(context).scaffoldBackgroundColor,
onRender: (pages) {
setState(() {
totalPages = pages;
isReady = true;
setDefaultFileName();
});
},
onPageChanged: (page, total) {
setState(() {
currentPage = page ?? 0;
totalPages = total;
});
},
onPageError: (page, error) {
setState(() {
errorMessage = '$page: ${error.toString()}';
});
print('$page: ${error.toString()}');
},
),
errorMessage.isEmpty
? !isReady
? Center(
child: CircularProgressIndicator(),
)
: Container()
: Center(
child: Text(errorMessage),
),
Positioned(
bottom: 0,
width: MediaQuery.of(context).size.width - 32,
child: Container(
height: 50,
alignment: Alignment.center,
padding: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Theme.of(context)
.scaffoldBackgroundColor
.withAlpha(0),
Theme.of(context).scaffoldBackgroundColor,
],
),
),
child: Text(
"${currentPage + 1} / $totalPages",
style: TextStyle(
color: Theme.of(context).colorScheme.primary,
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
)
])),
child: PdfDisplayWidget(pdfUrl: widget.document.pdf!.uri)),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
),
Form(
key: _formKey,
child: Column(
children: [
TextFormField(
controller: fileNameFieldController,
autofocus: true,
decoration: InputDecoration(
hintText:
AppLocalizations.of(context)!.enterFileNamePrompt,
suffixText: '.pdf',
),
validator: (String? value) {
if (value == null || value.isEmpty) {
return AppLocalizations.of(context)!.fileNameIsRequired;
}
return null;
},
onTap: () => fileNameFieldController.selection =
TextSelection(
baseOffset: 0,
extentOffset: fileNameFieldController.text.length),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: FilledButton.icon(
style: ElevatedButton.styleFrom(
textStyle: TextStyle(fontSize: 20),
),
onPressed: () {
if (_formKey.currentState!.validate()) {
_shareDocument(widget.document.pdf!,
_addPdfSuffix(fileNameFieldController.text));
}
},
label: Text(AppLocalizations.of(context)!.shareButton),
icon: Icon(Icons.share),
),
),
],
),
),
FileNameFormWidget(
formKey: _formKey,
fileNameFieldController: fileNameFieldController,
onSubmitted: _shareDocument,
defaultFileName: _getDefaultFileName()),
],
),
),
);
}

// Add a pdf suffix to the file name if it is missing
String _addPdfSuffix(String fileName) {
if (!fileName.toLowerCase().endsWith('.pdf')) {
return '$fileName.pdf';
}
return fileName;
}

String _getDefaultFileName() {
DateTime now = DateTime.now();
return AppLocalizations.of(context)!.defaultFileName(now, now);
}

Future<Uint8List?> _readFileByte(String filePath) async {
Uri myUri = Uri.parse(filePath);
File audioFile = File.fromUri(myUri);
Expand All @@ -198,22 +90,19 @@ class DocumentResultViewState extends State<DocumentResultView>
return bytes;
}

void _shareDocument(
DocumentScanningResultPdf document, String fileName) async {
Uint8List? bytes = await _readFileByte(document.uri);
void _shareDocument() async {
if (!_formKey.currentState!.validate()) {
return;
}

Uint8List? bytes = await _readFileByte(widget.document.pdf!.uri);
if (bytes == null) {
return;
}
String fileName = _addPdfSuffix(fileNameFieldController.text);
Share.shareXFiles(
[XFile.fromData(bytes, name: fileName, mimeType: 'application/pdf')],
fileNameOverrides: [fileName],
);
}

@override
void dispose() {
// Clean up the controller when the widget is disposed.
fileNameFieldController.dispose();
super.dispose();
}
}
Loading

0 comments on commit e5b0580

Please sign in to comment.