Add check QRcode + add translation when invalid QR Code

This commit is contained in:
Fransolet Thomas 2022-09-10 23:56:46 +02:00
parent 329f9299c5
commit e27ce8db34
12 changed files with 86 additions and 165 deletions

View File

@ -1 +1 @@
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"qr_code_scanner","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\qr_code_scanner-1.0.1\\\\","native_build":true,"dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.3+1\\\\","native_build":true,"dependencies":[]}],"android":[{"name":"qr_code_scanner","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\qr_code_scanner-1.0.1\\\\","native_build":true,"dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.3+1\\\\","native_build":true,"dependencies":[]}],"macos":[{"name":"sqflite","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.3+1\\\\","native_build":true,"dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"qr_code_scanner","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2022-09-10 22:13:09.391856","version":"3.0.3"}
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"qr_code_scanner","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\qr_code_scanner-1.0.1\\\\","native_build":true,"dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.3+1\\\\","native_build":true,"dependencies":[]}],"android":[{"name":"qr_code_scanner","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\qr_code_scanner-1.0.1\\\\","native_build":true,"dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.3+1\\\\","native_build":true,"dependencies":[]}],"macos":[{"name":"sqflite","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.3+1\\\\","native_build":true,"dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"qr_code_scanner","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2022-09-10 23:41:31.829523","version":"3.0.3"}

View File

@ -60,20 +60,17 @@ class _LanguageSelection extends State<LanguageSelection> with TickerProviderSta
return menuItems;
},
onSelected:(value) async {
// Update App context + update local DB
VisitAppContext visitAppContext = appContext.getContext();
visitAppContext.language = languagesEnable![int.parse(value.toString())];
appContext.setContext(visitAppContext);
String chosenLanguage = languagesEnable![int.parse(value.toString())];
// Update local DB
await DatabaseHelper.instance.insert(DatabaseTableType.main, visitAppContext.toMap());
/*if(value == 0){
print("My account menu is selected.");
}else if(value == 1){
print("Settings menu is selected.");
}else if(value == 2){
print("Logout menu is selected.");
}*/
if(visitAppContext.language != chosenLanguage) {
// Update App context + update local DB
visitAppContext.language = languagesEnable![int.parse(value.toString())];
appContext.setContext(visitAppContext);
// Update local DB
await DatabaseHelper.instance.insert(DatabaseTableType.main, visitAppContext.toMap());
}
}
);
}

View File

@ -17,10 +17,6 @@ class _LoadingState extends State<Loading> with TickerProviderStateMixin {
duration: const Duration(milliseconds: 5000),
vsync: this,
)..repeat();
/*_controller = widget.tween.animate(
CurvedAnimation(parent: _controller, curve: Curves.easeIn));*/
super.initState();
}

View File

@ -1,11 +1,13 @@
import 'package:flutter/material.dart';
import 'package:mymuseum_visitapp/app_context.dart';
import 'package:mymuseum_visitapp/constants.dart';
import 'ScannerDialog.dart';
class ScannerBouton extends StatefulWidget {
const ScannerBouton({Key? key, required this.isReplacement}) : super(key: key);
ScannerBouton({Key? key, required this.appContext, required this.isReplacement}) : super(key: key);
final AppContext appContext;
final bool isReplacement;
@override
@ -14,9 +16,9 @@ class ScannerBouton extends StatefulWidget {
class _ScannerBoutonState extends State<ScannerBouton> {
void _onItemTapped() {
_onItemTapped() {
setState(() {
showScannerDialog(context);
showScannerDialog(context, widget.appContext);
});
}

View File

@ -1,19 +1,24 @@
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:mymuseum_visitapp/Helpers/translationHelper.dart';
import 'package:mymuseum_visitapp/Models/visitContext.dart';
import 'package:mymuseum_visitapp/Screens/Article/article.dart';
import 'package:mymuseum_visitapp/app_context.dart';
import 'package:mymuseum_visitapp/constants.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
class ScannerTEST extends StatefulWidget {
const ScannerTEST({Key? key}) : super(key: key);
class ScannerDialog extends StatefulWidget {
const ScannerDialog({Key? key, required this.appContext}) : super(key: key);
final AppContext? appContext;
@override
State<ScannerTEST> createState() => _ScannerTESTState();
State<ScannerDialog> createState() => _ScannerDialogState();
}
class _ScannerTESTState extends State<ScannerTEST> {
class _ScannerDialogState extends State<ScannerDialog> {
Barcode? result;
QRViewController? controller;
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
@ -22,7 +27,6 @@ class _ScannerTESTState extends State<ScannerTEST> {
// is android, or resume the camera if the platform is iOS.
@override
void reassemble() {
//print("reassemble ");
super.reassemble();
if (Platform.isAndroid) {
controller!.pauseCamera();
@ -92,95 +96,8 @@ class _ScannerTESTState extends State<ScannerTEST> {
return const Icon(Icons.flip_camera_android, color: Colors.white);
},
)),
/*child: FutureBuilder(
future: controller?.getFlashStatus(),
builder: (context, snapshot) {
return Icon(Icons.flip_camera_android, color: Colors.white);
},
)*/),
),
),
/*Column(
children: <Widget>[
Expanded(flex: 4, child: _buildQrView(context)),
Expanded(
flex: 1,
child: FittedBox(
fit: BoxFit.contain,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
margin: const EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () async {
await controller?.toggleFlash();
setState(() {});
},
child: FutureBuilder(
future: controller?.getFlashStatus(),
builder: (context, snapshot) {
return Icon(Icons.flash_on);
},
)),
),
Container(
margin: const EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () async {
await controller?.flipCamera();
setState(() {});
},
child: FutureBuilder(
future: controller?.getCameraInfo(),
builder: (context, snapshot) {
if (snapshot.data != null) {
return Text(
'Camera facing ${describeEnum(snapshot.data!)}');
} else {
return const Text('loading');
}
},
)),
)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
margin: const EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () async {
await controller?.pauseCamera();
},
child: const Text('pause',
style: TextStyle(fontSize: 20)),
),
),
Container(
margin: const EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () async {
print(controller);
await controller?.resumeCamera();
},
child: const Text('resume',
style: TextStyle(fontSize: 20)),
),
)
],
),
],
),
),
)
],
),*/
],
),
);
@ -192,6 +109,7 @@ class _ScannerTESTState extends State<ScannerTEST> {
MediaQuery.of(context).size.height < 400)
? 225.0
: 300.0;
// To ensure the Scanner view is properly sizes after rotation
// we need to listen for Flutter SizeChanged notification and update controller
return QRView(
@ -207,7 +125,7 @@ class _ScannerTESTState extends State<ScannerTEST> {
);
}
void _onQRViewCreated(QRViewController controller) {
_onQRViewCreated(QRViewController controller) {
setState(() {
this.controller = controller;
});
@ -218,8 +136,6 @@ class _ScannerTESTState extends State<ScannerTEST> {
controller.scannedDataStream.listen((scanData) {
setState(() {
result = scanData;
/*print(result);
print(result!.code.toString());*/
var code = result == null ? "" : result!.code.toString();
if(result!.format == BarcodeFormat.qrcode) {
controller.pauseCamera();
@ -228,20 +144,24 @@ class _ScannerTESTState extends State<ScannerTEST> {
SnackBar(content: Text('QR CODE FOUND - ${code.toString()}')),
);*/
// TODO search in local if data == Id of Article
//Navigator.of(context).pop();
VisitAppContext visitAppContext = widget.appContext!.getContext();
// If so, navigate to article view
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) {
return ArticlePage(articleId: code);
},
),
);
if(!visitAppContext!.sectionIds!.contains(code)) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(TranslationHelper.getFromLocale('invalidQRCode', widget.appContext!)), backgroundColor: kBlue2),
);
Navigator.of(context).pop();
//Navigator.of(context).pop();
} else {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) {
return ArticlePage(articleId: code);
},
),
);
}
}
});
});
@ -263,14 +183,13 @@ class _ScannerTESTState extends State<ScannerTEST> {
}
}
showScannerDialog (BuildContext context) {
showScannerDialog (BuildContext context, AppContext appContext) {
showDialog(
builder: (BuildContext context) => const AlertDialog(
shape: RoundedRectangleBorder(
builder: (BuildContext context) => AlertDialog(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0))
),
content: ScannerTEST(
),
content: ScannerDialog(appContext: appContext),
contentPadding: EdgeInsets.zero,
), context: context
);

View File

@ -159,12 +159,22 @@ class DatabaseHelper {
return res;
}
Future<List<Map<String, dynamic>>> queryWithId(DatabaseTableType type, String id) async {
Future<List<Map<String, dynamic>>> queryWithColumnId(DatabaseTableType type, String id) async {
Database db = await instance.database;
var res = await db.query(_getTableName(type), where: '$columnId = ?', whereArgs: [id]);
return res;
}
Future<List<SectionDTO>> queryWithConfigurationId(DatabaseTableType type, String id) async {
List<SectionDTO> sections = [];
Database db = await instance.database;
var res = await db.query(_getTableName(type), where: '$columnConfigurationId = ?', whereArgs: [id]);
res.forEach((element) {
sections.add(getSectionFromDB(element));
});
return sections;
}
Future<int> delete(String id, DatabaseTableType type) async {
Database db = await instance.database;
return await db.delete(_getTableName(type), where: '$columnId = ?', whereArgs: [id]);

View File

@ -1,37 +1,30 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:manager_api/api.dart';
class VisitAppContext with ChangeNotifier{
String? id = "";
//String? token = "";
//String? host = "";
String? language = "";
List<ConfigurationDTO>? configurations;
ConfigurationDTO? configuration;
List<String?>? sectionIds; // Use to valid QR code found
VisitAppContext({this.language, this.id, this.configuration});
Map<String, dynamic> toMap() {
return {
'id': id,
//'host': host,
'language': language,
//'configuration': configuration == null ? null : jsonEncode(configuration?.toJson()),
};
}
factory VisitAppContext.fromJson(Map<String, dynamic> json) {
return VisitAppContext(
id: json['id'] as String,
/*host: json['host'] as String,*/
language: json['language'] as String,
configuration: json['configuration'] == null ? null : ConfigurationDTO.fromJson(json['configuration']),
);
}
// Implement toString to make it easier to see information about
@override
String toString() {
return 'VisitAppContext{id: $id, language: $language, configuration: $configuration}';

View File

@ -11,6 +11,7 @@ import 'package:mymuseum_visitapp/Helpers/DatabaseHelper.dart';
import 'package:mymuseum_visitapp/Helpers/networkCheck.dart';
import 'package:mymuseum_visitapp/Helpers/translationHelper.dart';
import 'package:mymuseum_visitapp/Models/resourceModel.dart';
import 'package:mymuseum_visitapp/Models/visitContext.dart';
import 'package:mymuseum_visitapp/app_context.dart';
import 'package:mymuseum_visitapp/client.dart';
import 'package:mymuseum_visitapp/constants.dart';
@ -36,6 +37,7 @@ class _ArticlePageState extends State<ArticlePage> {
final appContext = Provider.of<AppContext>(context);
Size size = MediaQuery.of(context).size;
final notchInset = MediaQuery.of(context).padding;
return Scaffold(
key: _scaffoldKey,
appBar: CustomAppBar(
@ -215,7 +217,7 @@ class _ArticlePageState extends State<ArticlePage> {
try {
bool isOnline = await hasNetwork();
if(sectionDTO == null || articleDTO == null) {
await DatabaseHelper.instance.queryWithId(DatabaseTableType.sections, articleId).then((value) async {
await DatabaseHelper.instance.queryWithColumnId(DatabaseTableType.sections, articleId).then((value) async {
setState(() {
sectionDTO = DatabaseHelper.instance.getSectionFromDB(value.first);
if(sectionDTO!.type == SectionType.Article) {
@ -223,13 +225,13 @@ class _ArticlePageState extends State<ArticlePage> {
}
});
if(sectionDTO!.imageId != null) {
await DatabaseHelper.instance.queryWithId(DatabaseTableType.resources, sectionDTO!.imageId!).then((value) {
await DatabaseHelper.instance.queryWithColumnId(DatabaseTableType.resources, sectionDTO!.imageId!).then((value) {
resourcesModel.add(DatabaseHelper.instance.getResourceFromDB(value.first));
});
}
if(articleDTO!.images!.isNotEmpty) {
for (var image in articleDTO!.images!) {
await DatabaseHelper.instance.queryWithId(DatabaseTableType.resources, image.resourceId!).then((value) {
await DatabaseHelper.instance.queryWithColumnId(DatabaseTableType.resources, image.resourceId!).then((value) {
resourcesModel.add(DatabaseHelper.instance.getResourceFromDB(value.first));
});
}

View File

@ -18,7 +18,6 @@ import 'package:mymuseum_visitapp/app_context.dart';
import 'package:mymuseum_visitapp/client.dart';
import 'package:mymuseum_visitapp/constants.dart';
import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@ -30,12 +29,14 @@ class HomePage extends StatefulWidget {
class _HomePageState extends State<HomePage> {
List<ConfigurationDTO> configurations = [];
List<String?> alreadyDownloaded = [];
VisitAppContext? visitAppContext;
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
final appContext = Provider.of<AppContext>(context);
VisitAppContext visitAppContext = appContext.getContext();
visitAppContext = appContext.getContext();
return Scaffold(
appBar: CustomAppBar(
title: TranslationHelper.getFromLocale("visitTitle", appContext),
@ -61,14 +62,14 @@ class _HomePageState extends State<HomePage> {
//physics: NeverScrollableScrollPhysics(),//This prevents scrolling, but may inhibit refresh indicator, remove as you need
itemBuilder: (BuildContext context, int index) {
return InkWell(
onTap: () {
//print(configurations[index].label);
// Update context
VisitAppContext visitAppContext = appContext.getContext();
visitAppContext.configuration = configurations[index];
appContext.setContext(visitAppContext);
onTap: () async {
if(configurations[index].isOffline! && alreadyDownloaded.any((c) => c == configurations[index].id)) {
// Update context
VisitAppContext visitAppContext = appContext.getContext();
visitAppContext.configuration = configurations[index];
visitAppContext.sectionIds = List<SectionDTO>.from(await DatabaseHelper.instance.queryWithConfigurationId(DatabaseTableType.sections, visitAppContext.configuration!.id!)).map((e) => e.id).toList();
appContext.setContext(visitAppContext);
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => VisitPage(configurationId: configurations[index].id!),
));
@ -117,7 +118,6 @@ class _HomePageState extends State<HomePage> {
),
)
)
],
),
),
@ -140,7 +140,7 @@ class _HomePageState extends State<HomePage> {
),
),
),
floatingActionButton: const ScannerBouton(isReplacement: false),
floatingActionButton: ScannerBouton(isReplacement: false, appContext: appContext!),
//floatingActionButtonLocation: FloatingActionButtonLocation.miniCenterFloat,
);
}
@ -212,7 +212,7 @@ class _HomePageState extends State<HomePage> {
//return file;
} else {
//return null; // TODO return local list..
//return null;
}
} catch (e) {
print(e);
@ -249,7 +249,6 @@ class _HomePageState extends State<HomePage> {
newOrder = newOrder + 1;
}
}
}
Map<String, dynamic> sectionToMap(SectionDTO section) {
@ -267,7 +266,6 @@ class _HomePageState extends State<HomePage> {
'data': section.data,
'dateCreation': section.dateCreation!.toUtc().toIso8601String(),
'orderOfElement': section.order,
//'token': token
};
}
}

View File

@ -32,7 +32,7 @@ class SectionCard extends StatelessWidget {
ResourceModel? resourceModel;
getResource(String? imageId) async {
await DatabaseHelper.instance.queryWithId(DatabaseTableType.resources, sectionDTO!.imageId!).then((value) {
await DatabaseHelper.instance.queryWithColumnId(DatabaseTableType.resources, sectionDTO!.imageId!).then((value) {
resourceModel = DatabaseHelper.instance.getResourceFromDB(value.first);
});
}

View File

@ -34,7 +34,7 @@ class _VisitPageState extends State<VisitPage> {
),
backgroundColor: kBackgroundGrey,
body: Body(configurationId: configuration!.id), // TODO handle error..
floatingActionButton: const ScannerBouton(isReplacement: false),
floatingActionButton: ScannerBouton(isReplacement: false, appContext: appContext),
);
}
}

View File

@ -4,21 +4,25 @@ List<Translation> translations = [
Translation(language: "FR", data: {
"visitTitle": "Liste des visites",
"visitDownloadWarning": "Pour suivre cette visite, il faut d'abord la télécharger",
"noData": "Pas de données"
"noData": "Pas de données",
"invalidQRCode": "code QR invalide"
}),
Translation(language: "EN", data: {
"visitTitle": "List of tours",
"visitDownloadWarning": "To follow this tour, you must first download it",
"noData": "No data"
"noData": "No data",
"invalidQRCode": "Invalid QR code"
}),
Translation(language: "DE", data: {
"visitTitle": "Liste der Touren",
"visitDownloadWarning": "Um dieser Tour zu folgen, müssen Sie sie zuerst herunterladen",
"noData": "keine Daten"
"noData": "keine Daten",
"invalidQRCode": "Ungültiger QR-Code"
}),
Translation(language: "NL", data: {
"visitTitle": "Lijst met rondleidingen",
"visitDownloadWarning": "Om deze tour te volgen, moet je deze eerst downloaden",
"noData": "Geen gegevens"
"noData": "Geen gegevens",
"invalidQRCode": "Ongeldige QR-code"
}),
];