diff --git a/.flutter-plugins b/.flutter-plugins index a822b50..7e7a116 100644 --- a/.flutter-plugins +++ b/.flutter-plugins @@ -1,2 +1,3 @@ # This is a generated file; do not edit or check into version control. qr_code_scanner=C:\\Users\\thoma\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\qr_code_scanner-1.0.0\\ +sqflite=C:\\Users\\thoma\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\sqflite-2.0.3+1\\ diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 21224e1..96ff109 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -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.0\\\\","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.0\\\\","native_build":true,"dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"qr_code_scanner","dependencies":[]}],"date_created":"2022-08-10 17:58:03.305902","version":"3.0.3"} \ No newline at end of file +{"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.0\\\\","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.0\\\\","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-08-12 17:52:32.581414","version":"3.0.3"} \ No newline at end of file diff --git a/.packages b/.packages index 8d6694d..7c3c5e0 100644 --- a/.packages +++ b/.packages @@ -3,7 +3,7 @@ # # For more info see: https://dart.dev/go/dot-packages-deprecation # -# Generated by pub on 2022-08-10 17:15:09.111761. +# Generated by pub on 2022-08-11 17:42:29.200149. _fe_analyzer_shared:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/_fe_analyzer_shared-31.0.0/lib/ analyzer:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/analyzer-2.8.0/lib/ args:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/args-2.3.1/lib/ @@ -34,6 +34,7 @@ file:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/file fixnum:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/fixnum-1.0.1/lib/ flutter:file:///C:/Users/thoma/Documents/flutter/packages/flutter/lib/ flutter_lints:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/flutter_lints-1.0.4/lib/ +flutter_svg:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/flutter_svg-1.1.3/lib/ flutter_test:file:///C:/Users/thoma/Documents/flutter/packages/flutter_test/lib/ flutter_web_plugins:file:///C:/Users/thoma/Documents/flutter/packages/flutter_web_plugins/lib/ glob:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/glob-2.1.0/lib/ @@ -52,13 +53,18 @@ matcher:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/m material_color_utilities:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/material_color_utilities-0.1.4/lib/ meta:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/meta-1.7.0/lib/ mime:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/mime-1.0.2/lib/ +nested:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/nested-1.0.0/lib/ openapi_generator:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/openapi_generator-4.0.0/lib/ openapi_generator_annotations:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/openapi_generator_annotations-4.0.0/lib/ openapi_generator_cli:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/openapi_generator_cli-4.0.0/lib/ package_config:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/package_config-2.1.0/lib/ path:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/path-1.8.1/lib/ +path_drawing:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/path_drawing-1.0.1/lib/ +path_parsing:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/path_parsing-1.0.1/lib/ pedantic:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/pedantic-1.11.1/lib/ +petitparser:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/petitparser-5.0.0/lib/ pool:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/pool-1.5.1/lib/ +provider:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/provider-5.0.0/lib/ pub_semver:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/pub_semver-2.1.1/lib/ pubspec_parse:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/pubspec_parse-1.2.0/lib/ qr_code_scanner:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/qr_code_scanner-1.0.0/lib/ @@ -67,10 +73,13 @@ shelf_web_socket:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartl sky_engine:file:///C:/Users/thoma/Documents/flutter/bin/cache/pkg/sky_engine/lib/ source_gen:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/source_gen-1.0.5/lib/ source_span:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/source_span-1.8.2/lib/ +sqflite:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/sqflite-2.0.3+1/lib/ +sqflite_common:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/sqflite_common-2.2.1+1/lib/ stack_trace:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/stack_trace-1.10.0/lib/ stream_channel:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/stream_channel-2.1.0/lib/ stream_transform:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/stream_transform-2.0.0/lib/ string_scanner:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/string_scanner-1.1.0/lib/ +synchronized:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/synchronized-3.0.0+2/lib/ term_glyph:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/term_glyph-1.2.0/lib/ test_api:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/test_api-0.4.9/lib/ timing:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/timing-1.0.0/lib/ @@ -78,5 +87,6 @@ typed_data:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.or vector_math:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/vector_math-2.1.2/lib/ watcher:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/watcher-1.0.1/lib/ web_socket_channel:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/web_socket_channel-2.2.0/lib/ +xml:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/xml-6.1.0/lib/ yaml:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/yaml-3.1.1/lib/ mymuseum_visitapp:lib/ diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml index 6116c22..717b7a2 100644 --- a/android/app/src/debug/AndroidManifest.xml +++ b/android/app/src/debug/AndroidManifest.xml @@ -4,4 +4,8 @@ to allow setting breakpoints, to provide hot reload, etc. --> + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 057962c..2d1727b 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,8 +1,10 @@ + + + + + + diff --git a/lib/Components/CustomAppBar.dart b/lib/Components/CustomAppBar.dart new file mode 100644 index 0000000..91980c9 --- /dev/null +++ b/lib/Components/CustomAppBar.dart @@ -0,0 +1,64 @@ +import 'package:flutter/material.dart'; +import 'package:mymuseum_visitapp/Screens/Home/home.dart'; +import 'package:mymuseum_visitapp/constants.dart'; +//import 'package:flutter_svg/svg.dart'; +import 'package:provider/provider.dart'; + +class CustomAppBar extends StatefulWidget implements PreferredSizeWidget { + CustomAppBar({Key? key, required this.title, required this.isHomeButton}); + + final String title; + final bool isHomeButton; + final double _preferredHeight = 50; + + @override + State createState() => _CustomAppBarState(); + + @override + Size get preferredSize => Size.fromHeight(_preferredHeight); +} + +class _CustomAppBarState extends State { + final double _preferredHeight = 50; + + @override + Widget build(BuildContext context) { + Size size = MediaQuery.of(context).size; + //final index = Provider.of(context); + final notchInset = MediaQuery.of(context).padding; + return AppBar( + title: Text(widget.title), + centerTitle: true, + leading: widget.isHomeButton ? IconButton( + icon: Icon(Icons.home), + onPressed: () { + // Set new State + setState(() { + Navigator.of(context).pushReplacement(MaterialPageRoute( + builder: (context) => const HomePage(), + )); + }); + } + ) : null, + flexibleSpace: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.centerRight, + end: Alignment.centerLeft, + colors: [ + /*Color(0xFFDD79C2), + Color(0xFFB65FBE), + Color(0xFF9146BA), + Color(0xFF7633B8), + Color(0xFF6528B6), + Color(0xFF6025B6)*/ + Color(0xFF306bac), + Color(0xFF308aae), + Color(0xFF309cb0), + ], + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/Components/ScannerBouton.dart b/lib/Components/ScannerBouton.dart new file mode 100644 index 0000000..89d96a6 --- /dev/null +++ b/lib/Components/ScannerBouton.dart @@ -0,0 +1,48 @@ +import 'package:flutter/material.dart'; +import 'package:mymuseum_visitapp/Screens/Scanner/scanner.dart'; +import 'package:mymuseum_visitapp/constants.dart'; + +import 'ScannerDialog.dart'; + +class ScannerBouton extends StatefulWidget { + const ScannerBouton({Key? key, required this.isReplacement}) : super(key: key); + + final bool isReplacement; + + @override + State createState() => _ScannerBoutonState(); +} + +class _ScannerBoutonState extends State { + + void _onItemTapped() { + setState(() { + showScannerDialog("nn rien", context); + /*if(widget.isReplacement) { + Navigator.of(context).pushReplacement(MaterialPageRoute( + builder: (context) => const ScannerPage(), + )); + } else { + Navigator.of(context).push(MaterialPageRoute( + builder: (context) => const ScannerPage(), + )); + }*/ + }); + } + + @override + Widget build(BuildContext context) { + return Container( + height: 85.0, + width: 85.0, + child: FittedBox( + child: FloatingActionButton( + onPressed: _onItemTapped, + tooltip: 'Scanner', + backgroundColor: kMainColor, + child: const Icon(Icons.qr_code_scanner), + ), + ), + ); + } +} diff --git a/lib/Components/ScannerDialog.dart b/lib/Components/ScannerDialog.dart new file mode 100644 index 0000000..07a8ae4 --- /dev/null +++ b/lib/Components/ScannerDialog.dart @@ -0,0 +1,217 @@ +import 'package:flutter/material.dart'; +import 'package:mymuseum_visitapp/Screens/Scanner/scanner.dart'; +import 'dart:io'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:mymuseum_visitapp/Components/CustomAppBar.dart'; +import 'package:mymuseum_visitapp/Screens/Article/article.dart'; +import 'package:qr_code_scanner/qr_code_scanner.dart'; + + +class ScannerTEST extends StatefulWidget { + const ScannerTEST({Key? key}) : super(key: key); + + @override + State createState() => _ScannerTESTState(); +} + +class _ScannerTESTState extends State { + Barcode? result; + QRViewController? controller; + final GlobalKey qrKey = GlobalKey(debugLabel: 'QR'); + + // In order to get hot reload to work we need to pause the camera if the platform + // is android, or resume the camera if the platform is iOS. + @override + void reassemble() { + print("reassemble "); + super.reassemble(); + if (Platform.isAndroid) { + controller!.pauseCamera(); + } + controller!.resumeCamera(); + } + + @override + Widget build(BuildContext context) { + Size size = MediaQuery.of(context).size; + return Container( + height: size.height *0.6, + width: size.width *0.9, + color: Colors.blueAccent, + child: Column( + children: [ + Expanded(flex: 4, child: _buildQrView(context)), + Expanded( + flex: 1, + child: FittedBox( + fit: BoxFit.contain, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + 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: [ + 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)), + ), + ) + ], + ), + ], + ), + ), + ) + ], + ), + ); + } + + Widget _buildQrView(BuildContext context) { + // For this example we check how width or tall the device is and change the scanArea and overlay accordingly. + var scanArea = (MediaQuery.of(context).size.width < 400 || + 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( + key: qrKey, + onQRViewCreated: _onQRViewCreated, + overlay: QrScannerOverlayShape( + borderColor: Colors.blueAccent, + borderRadius: 10, + borderLength: 25, + borderWidth: 5, + cutOutSize: 225.0), + onPermissionSet: (ctrl, p) => _onPermissionSet(context, ctrl, p), + ); + } + + void _onQRViewCreated(QRViewController controller) { + setState(() { + this.controller = controller; + }); + if (Platform.isAndroid) { + controller!.pauseCamera(); + } + controller!.resumeCamera(); + 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(); + print("QR CODE FOUND"); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('QR CODE FOUND - ${code.toString()}')), + ); + + // TODO search in local if data == Id of Article + //Navigator.of(context).pop(); + + // If so, navigate to article view + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (context) { + return ArticlePage(articleId: code); + }, + ), + ); + + //Navigator.of(context).pop(); + } + }); + }); + } + + void _onPermissionSet(BuildContext context, QRViewController ctrl, bool p) { + //log('${DateTime.now().toIso8601String()}_onPermissionSet $p'); + if (!p) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('no Permission')), + ); + } + } + + @override + void dispose() { + controller?.dispose(); + super.dispose(); + } +} + +showScannerDialog (String question, BuildContext context) { + showDialog( + builder: (BuildContext context) => AlertDialog( + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(10.0)) + ), + content: ScannerTEST( + ), + contentPadding: EdgeInsets.zero, + ), context: context + ); +} + + diff --git a/lib/Models/visitContext.dart b/lib/Models/visitContext.dart new file mode 100644 index 0000000..8f5b618 --- /dev/null +++ b/lib/Models/visitContext.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; + +class VisitAppContext with ChangeNotifier{ + String? userId = ""; + String? token = ""; + String? host = ""; + String? language = ""; + + VisitAppContext({this.userId, this.token, this.host, this.language}); + + Map toMap() { + return { + 'userId': userId, + 'host': host, + 'language': language, + 'token': token + }; + } + + factory VisitAppContext.fromJson(Map json) { + return VisitAppContext( + userId: json['userId'] as String, + host: json['host'] as String, + language: json['language'] as String, + token: json['token'] as String, + ); + } + + // Implement toString to make it easier to see information about + @override + String toString() { + return 'VisitAppContext{userId: $userId, language: $language, host: $host}'; + } +} \ No newline at end of file diff --git a/lib/Screens/Article/article.dart b/lib/Screens/Article/article.dart index c8e3725..d76caef 100644 --- a/lib/Screens/Article/article.dart +++ b/lib/Screens/Article/article.dart @@ -1,87 +1,41 @@ import 'package:flutter/material.dart'; +import 'package:mymuseum_visitapp/Components/CustomAppBar.dart'; +import 'package:mymuseum_visitapp/Components/ScannerBouton.dart'; +import 'package:mymuseum_visitapp/Screens/Scanner/scanner.dart'; +import 'package:mymuseum_visitapp/constants.dart'; class ArticlePage extends StatefulWidget { - const ArticlePage({Key? key, required this.title}) : super(key: key); + const ArticlePage({Key? key, required this.articleId}) : super(key: key); - // This widget is the home page of your application. It is stateful, meaning - // that it has a State object (defined below) that contains fields that affect - // how it looks. - - // This class is the configuration for the state. It holds the values (in this - // case the title) provided by the parent (in this case the App widget) and - // used by the build method of the State. Fields in a Widget subclass are - // always marked "final". - - final String title; + final String articleId; @override State createState() => _ArticlePageState(); } class _ArticlePageState extends State { - int _counter = 0; - - void _incrementCounter() { - setState(() { - // This call to setState tells the Flutter framework that something has - // changed in this State, which causes it to rerun the build method below - // so that the display can reflect the updated values. If we changed - // _counter without calling setState(), then the build method would not be - // called again, and so nothing would appear to happen. - _counter++; - }); - } @override Widget build(BuildContext context) { - // This method is rerun every time setState is called, for instance as done - // by the _incrementCounter method above. - // - // The Flutter framework has been optimized to make rerunning build methods - // fast, so that you can just rebuild anything that needs updating rather - // than having to individually change instances of widgets. return Scaffold( - appBar: AppBar( - // Here we take the value from the MyHomePage object that was created by - // the App.build method, and use it to set our appbar title. - title: Text("ArticlePage"), + appBar: CustomAppBar( + title: "ArticlePage", + isHomeButton: false, ), body: Center( - // Center is a layout widget. It takes a single child and positions it - // in the middle of the parent. child: Column( - // Column is also a layout widget. It takes a list of children and - // arranges them vertically. By default, it sizes itself to fit its - // children horizontally, and tries to be as tall as its parent. - // - // Invoke "debug painting" (press "p" in the console, choose the - // "Toggle Debug Paint" action from the Flutter Inspector in Android - // Studio, or the "Toggle Debug Paint" command in Visual Studio Code) - // to see the wireframe for each widget. - // - // Column has various properties to control how it sizes itself and - // how it positions its children. Here we use mainAxisAlignment to - // center the children vertically; the main axis here is the vertical - // axis because Columns are vertical (the cross axis would be - // horizontal). mainAxisAlignment: MainAxisAlignment.center, children: [ - const Text( - 'You have pushed the button this many times:', - ), + Text(widget.articleId), Text( - '$_counter', + 'coucou', style: Theme.of(context).textTheme.headline4, ), ], ), ), - floatingActionButton: FloatingActionButton( - onPressed: _incrementCounter, - tooltip: 'Increment', - child: const Icon(Icons.add), - ), // This trailing comma makes auto-formatting nicer for build methods. + floatingActionButton: const ScannerBouton(isReplacement: true), ); } } diff --git a/lib/Screens/Home/home.dart b/lib/Screens/Home/home.dart index f8450e6..7df31de 100644 --- a/lib/Screens/Home/home.dart +++ b/lib/Screens/Home/home.dart @@ -2,23 +2,16 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:manager_api/api.dart'; +import 'package:mymuseum_visitapp/Components/CustomAppBar.dart'; +import 'package:mymuseum_visitapp/Components/ScannerBouton.dart'; +import 'package:mymuseum_visitapp/Components/ScannerDialog.dart'; import 'package:mymuseum_visitapp/Screens/Scanner/scanner.dart'; +import 'package:mymuseum_visitapp/Screens/Visit/visit.dart'; import 'package:mymuseum_visitapp/client.dart'; import 'package:mymuseum_visitapp/constants.dart'; class HomePage extends StatefulWidget { - const HomePage({Key? key, required this.title}) : super(key: key); - - // This widget is the home page of your application. It is stateful, meaning - // that it has a State object (defined below) that contains fields that affect - // how it looks. - - // This class is the configuration for the state. It holds the values (in this - // case the title) provided by the parent (in this case the App widget) and - // used by the build method of the State. Fields in a Widget subclass are - // always marked "final". - - final String title; + const HomePage({Key? key}) : super(key: key); @override State createState() => _HomePageState(); @@ -26,19 +19,14 @@ class HomePage extends StatefulWidget { class _HomePageState extends State { List configurations = [ConfigurationDTO(label: "Test 0", isOffline: false), ConfigurationDTO(label: "Test 1", isOffline: true), ConfigurationDTO(label: "Test 2", isOffline: true)]; - //List configurations = []; - void _incrementCounter() { - setState(() { - //_counter++; - }); - } @override Widget build(BuildContext context) { Size size = MediaQuery.of(context).size; return Scaffold( - appBar: AppBar( - title: Text(widget.title), + appBar: CustomAppBar( + title: "Home page - liste parcours", + isHomeButton: false, ), body: SingleChildScrollView( child: Container( @@ -56,14 +44,9 @@ class _HomePageState extends State { print("config selected"); getConfiguration(); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) { - return ScannerPage(title: "test"); - }, - ), - ); + Navigator.of(context).pushReplacement(MaterialPageRoute( + builder: (context) => const VisitPage(configurationId: "TODO"), + )); }); }, child: Container( @@ -101,7 +84,23 @@ class _HomePageState extends State { } ), ), - ), // This trailing comma makes auto-formatting nicer for build methods. + ), + floatingActionButton: const ScannerBouton(isReplacement: false), + //floatingActionButtonLocation: FloatingActionButtonLocation.miniCenterFloat, + /*bottomNavigationBar: BottomNavigationBar( + items: const [ + BottomNavigationBarItem( + icon: Icon(Icons.home), + label: 'Home', + ), + BottomNavigationBarItem( + icon: Icon(Icons.qr_code_scanner), + label: 'Scanner', + ), + ], + selectedItemColor: kMainRed, + onTap: _onItemTapped, + ),*/ ); } diff --git a/lib/Screens/Scanner/scanner.dart b/lib/Screens/Scanner/scanner.dart index dda1e03..5581d29 100644 --- a/lib/Screens/Scanner/scanner.dart +++ b/lib/Screens/Scanner/scanner.dart @@ -3,23 +3,13 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:mymuseum_visitapp/Components/CustomAppBar.dart'; import 'package:mymuseum_visitapp/Screens/Article/article.dart'; import 'package:qr_code_scanner/qr_code_scanner.dart'; class ScannerPage extends StatefulWidget { - const ScannerPage({Key? key, required this.title}) : super(key: key); - - // This widget is the home page of your application. It is stateful, meaning - // that it has a State object (defined below) that contains fields that affect - // how it looks. - - // This class is the configuration for the state. It holds the values (in this - // case the title) provided by the parent (in this case the App widget) and - // used by the build method of the State. Fields in a Widget subclass are - // always marked "final". - - final String title; + const ScannerPage({Key? key}) : super(key: key); @override State createState() => _ScannerPageState(); @@ -34,6 +24,7 @@ class _ScannerPageState extends State { // is android, or resume the camera if the platform is iOS. @override void reassemble() { + print("reassemble "); super.reassemble(); if (Platform.isAndroid) { controller!.pauseCamera(); @@ -44,6 +35,10 @@ class _ScannerPageState extends State { @override Widget build(BuildContext context) { return Scaffold( + appBar: CustomAppBar( + title: "QR Code scan", + isHomeButton: false, + ), body: Column( children: [ Expanded(flex: 4, child: _buildQrView(context)), @@ -77,7 +72,7 @@ class _ScannerPageState extends State { }, )), ), - /*Container( + Container( margin: const EdgeInsets.all(8), child: ElevatedButton( onPressed: () async { @@ -95,7 +90,7 @@ class _ScannerPageState extends State { } }, )), - )*/ + ) ], ), Row( @@ -116,6 +111,7 @@ class _ScannerPageState extends State { margin: const EdgeInsets.all(8), child: ElevatedButton( onPressed: () async { + print(controller); await controller?.resumeCamera(); }, child: const Text('resume', @@ -158,25 +154,31 @@ class _ScannerPageState extends State { setState(() { this.controller = controller; }); - + if (Platform.isAndroid) { + controller!.pauseCamera(); + } + controller!.resumeCamera(); 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(); print("QR CODE FOUND"); ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text('QR CODE FOUND')), + SnackBar(content: Text('QR CODE FOUND - ${code.toString()}')), ); // TODO search in local if data == Id of Article + // If so, navigate to article view - Navigator.push( + Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) { - return ArticlePage(title: "test"); + return ArticlePage(articleId: code); }, ), ); diff --git a/lib/Screens/Visit/visit.dart b/lib/Screens/Visit/visit.dart new file mode 100644 index 0000000..1062d10 --- /dev/null +++ b/lib/Screens/Visit/visit.dart @@ -0,0 +1,36 @@ + +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/material.dart'; +import 'package:manager_api/api.dart'; +import 'package:mymuseum_visitapp/Components/CustomAppBar.dart'; +import 'package:mymuseum_visitapp/Components/ScannerBouton.dart'; +import 'package:mymuseum_visitapp/Screens/Scanner/scanner.dart'; +import 'package:mymuseum_visitapp/client.dart'; +import 'package:mymuseum_visitapp/constants.dart'; + +class VisitPage extends StatefulWidget { + const VisitPage({Key? key, required this.configurationId}) : super(key: key); + + final String configurationId; + + @override + State createState() => _VisitPageState(); +} + +class _VisitPageState extends State { + + @override + Widget build(BuildContext context) { + Size size = MediaQuery.of(context).size; + return Scaffold( + appBar: CustomAppBar( + title: "Visit page", + isHomeButton: true, + ), + body: Text( + "TODO description du parcours puis bouton scanner, ou visite virtuelle ?" + ), + floatingActionButton: const ScannerBouton(isReplacement: false), + ); + } +} \ No newline at end of file diff --git a/lib/app_context.dart b/lib/app_context.dart new file mode 100644 index 0000000..be9d9bd --- /dev/null +++ b/lib/app_context.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; +import 'package:mymuseum_visitapp/client.dart'; + +import 'Models/visitContext.dart'; + + +class AppContext with ChangeNotifier { + VisitAppContext _visitContext; + Client clientAPI = Client(""); + + AppContext(this._visitContext); + + getContext() => _visitContext; + setContext(VisitAppContext appContext) async { + _visitContext = appContext; + + notifyListeners(); + } +} diff --git a/lib/constants.dart b/lib/constants.dart index 42fdc98..6fac6e8 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -2,11 +2,22 @@ import 'package:flutter/material.dart'; // Colors - TO FILL WIT CORRECT COLOR const kBackgroundColor = Color(0xFFFFFFFF); +const kMainColor = Color(0xFF8b0000); + +const List languages = ["FR", "NL", "EN", "DE"]; // hmmmm depends on config.. + +// Text Style +const kHeadingTextStyle = TextStyle( + fontSize: 20, + fontWeight: FontWeight.w600, + color: Color(0xFFFFFFFF) +); + + const kMainGrey = Color(0xFF424242); const kSecondGrey = Color(0xFF555457); const kTestSecondColor = Color(0xFF2F4858); -const kMainRed = Color(0xFF8b0000); const kSecondRed = Color(0xFF622727); const kTextRed = Color(0xFFba0505); const kBackgroundGrey = Color(0xFFb5b7b9); @@ -14,8 +25,6 @@ const kBackgroundSecondGrey = Color(0xFF5b5b63); const kBackgroundLight = Color(0xfff3f3f3); -const List languages = ["FR", "NL", "EN", "DE"]; - const kTitleSize = 40.0; const kDescriptionSize = 25.0; diff --git a/lib/main.dart b/lib/main.dart index dd533cc..1cb871d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,34 +1,71 @@ import 'package:flutter/material.dart'; +import 'package:mymuseum_visitapp/Screens/Article/article.dart'; import 'package:mymuseum_visitapp/Screens/Home/home.dart'; +import 'package:provider/provider.dart'; +import 'Models/visitContext.dart'; import 'Screens/Scanner/scanner.dart'; +import 'app_context.dart'; +import 'constants.dart'; -void main() { - runApp(const MyApp()); +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + String initialRoute; + VisitAppContext localContext = VisitAppContext(language: "FR", host: "http://192.168.31.140:8089"); + + //localContext = await DatabaseHelper.instance.getData(); + + if(localContext != null) { + print("we've got an local db !"); + print(localContext); + } else { + print("NO LOCAL DB !"); + } + + initialRoute = '/home'; + + final MyApp myApp = MyApp( + initialRoute: initialRoute, + visitAppContext: localContext, + ); + + runApp(myApp); } -class MyApp extends StatelessWidget { - const MyApp({Key? key}) : super(key: key); +class MyApp extends StatefulWidget { + String initialRoute = ""; + VisitAppContext visitAppContext; + MyApp({Key? key, required this.initialRoute, required this.visitAppContext}) : super(key: key); + + @override + _MyAppState createState() => _MyAppState(); +} + +class _MyAppState extends State { - // This widget is the root of your application. @override Widget build(BuildContext context) { - - return MaterialApp( - title: 'MyVisit App', - theme: ThemeData( - // This is the theme of your application. - // - // Try running your application with "flutter run". You'll see the - // application has a blue toolbar. Then, without quitting the app, try - // changing the primarySwatch below to Colors.green and then invoke - // "hot reload" (press "r" in the console where you ran "flutter run", - // or simply save your changes to "hot reload" in a Flutter IDE). - // Notice that the counter didn't reset back to zero; the application - // is not restarted. - primarySwatch: Colors.blue, + return ChangeNotifierProvider( + create: (_) => AppContext(widget.visitAppContext), + child: MaterialApp( + debugShowCheckedModeBanner: false, + title: 'MyVisit App Demo', + initialRoute: widget.initialRoute, + /*supportedLocales: [ + const Locale('en', 'US'), + //const Locale('fr', 'FR'), + ],*/ + theme: ThemeData( + primarySwatch: Colors.blue, + scaffoldBackgroundColor: kBackgroundColor, + //fontFamily: "Vollkorn", + textTheme: const TextTheme(bodyText1: TextStyle(color: kTestSecondColor)), + visualDensity: VisualDensity.adaptivePlatformDensity, + ), + routes: { + '/home': (context) => const HomePage(), + } ), - home: const HomePage(title: 'MyVisit App'), // Scanner to test ); } -} +} \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index 9434928..bb30553 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -209,6 +209,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.4" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.3" flutter_test: dependency: "direct dev" description: flutter @@ -331,6 +338,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.2" + nested: + dependency: transitive + description: + name: nested + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" openapi_generator: dependency: "direct main" description: @@ -366,6 +380,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.1" + path_drawing: + dependency: transitive + description: + name: path_drawing + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + path_parsing: + dependency: transitive + description: + name: path_parsing + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" pedantic: dependency: transitive description: @@ -373,6 +401,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.11.1" + petitparser: + dependency: transitive + description: + name: petitparser + url: "https://pub.dartlang.org" + source: hosted + version: "5.0.0" pool: dependency: transitive description: @@ -380,6 +415,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.5.1" + provider: + dependency: "direct main" + description: + name: provider + url: "https://pub.dartlang.org" + source: hosted + version: "5.0.0" pub_semver: dependency: transitive description: @@ -434,6 +476,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.2" + sqflite: + dependency: "direct main" + description: + name: sqflite + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.3+1" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.1+1" stack_trace: dependency: transitive description: @@ -462,6 +518,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.0" + synchronized: + dependency: transitive + description: + name: synchronized + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0+2" term_glyph: dependency: transitive description: @@ -511,6 +574,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.2.0" + xml: + dependency: transitive + description: + name: xml + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.0" yaml: dependency: transitive description: @@ -520,4 +590,4 @@ packages: version: "3.1.1" sdks: dart: ">=2.17.0 <3.0.0" - flutter: ">=1.12.0" + flutter: ">=3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index f3c9d30..aa5b239 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -34,6 +34,9 @@ dependencies: openapi_generator_cli: ^4.0.0 openapi_generator: ^4.0.0 openapi_generator_annotations: ^4.0.0 + sqflite: + provider: ^5.0.0 + flutter_svg: ^1.1.3 manager_api: path: manager_api