Skip to content
Snippets Groups Projects
Commit 38a849d8 authored by Adrien Morel's avatar Adrien Morel
Browse files

Notifications + Background refresh for notifications done

parent 41ac7c32
Branches
No related tags found
No related merge requests found
Pipeline #21803 passed
# Docker container with flutter installed to run on Univ-Lille's servers
image: cirrusci/flutter image: cirrusci/flutter
stages: stages:
......
...@@ -4,13 +4,8 @@ A new Flutter project. ...@@ -4,13 +4,8 @@ A new Flutter project.
## Getting Started ## Getting Started
This project is a starting point for a Flutter application. ## Testing
A few resources to get you started if this is your first Flutter project: ```bash
adb shell cmd jobscheduler run -f com.example.is_eat_safe 999
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) ```
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
...@@ -26,10 +26,11 @@ apply plugin: 'kotlin-android' ...@@ -26,10 +26,11 @@ apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android { android {
compileSdkVersion flutter.compileSdkVersion compileSdkVersion 33
ndkVersion flutter.ndkVersion ndkVersion flutter.ndkVersion
compileOptions { compileOptions {
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8
} }
...@@ -48,6 +49,7 @@ android { ...@@ -48,6 +49,7 @@ android {
// You can update the following values to match your application needs. // You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
minSdkVersion 18 minSdkVersion 18
multiDexEnabled true
targetSdkVersion flutter.targetSdkVersion targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()
versionName flutterVersionName versionName flutterVersionName
...@@ -67,5 +69,9 @@ flutter { ...@@ -67,5 +69,9 @@ flutter {
} }
dependencies { dependencies {
implementation 'androidx.window:window:1.0.0'
implementation 'androidx.window:window-java:1.0.0'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
implementation 'androidx.multidex:multidex:2.0.1'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
} }
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.is_eat_safe"> package="com.example.is_eat_safe">
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<application <application
tools:replace="android:label"
android:label="is_eat_safe" android:label="is_eat_safe"
android:name="${applicationName}" android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"> android:icon="@mipmap/ic_launcher">
......
buildscript { buildscript {
ext.kotlin_version = '1.6.10' ext.kotlin_version = '1.6.10'
ext {
compileSdkVersion = 33 // or latest
targetSdkVersion = 33 // or latest
appCompatVersion = "1.4.2" // or latest
}
repositories { repositories {
google() google()
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:7.1.2' classpath 'com.android.tools.build:gradle:7.1.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
} }
} }
...@@ -15,6 +20,9 @@ allprojects { ...@@ -15,6 +20,9 @@ allprojects {
repositories { repositories {
google() google()
mavenCentral() mavenCentral()
maven{
url "${project(':background_fetch').projectDir}/libs"
}
} }
} }
......
PODS: PODS:
- background_fetch (1.1.2):
- Flutter
- barcode_scan2 (0.0.1): - barcode_scan2 (0.0.1):
- Flutter - Flutter
- MTBBarcodeScanner - MTBBarcodeScanner
- SwiftProtobuf - SwiftProtobuf
- Flutter (1.0.0) - Flutter (1.0.0)
- flutter_background_service_ios (0.0.3):
- Flutter
- flutter_barcode_scanner (2.0.0): - flutter_barcode_scanner (2.0.0):
- Flutter - Flutter
- flutter_local_notifications (0.0.1):
- Flutter
- MTBBarcodeScanner (5.0.11) - MTBBarcodeScanner (5.0.11)
- shared_preferences_ios (0.0.1): - shared_preferences_ios (0.0.1):
- Flutter - Flutter
- SwiftProtobuf (1.20.3) - SwiftProtobuf (1.20.3)
DEPENDENCIES: DEPENDENCIES:
- background_fetch (from `.symlinks/plugins/background_fetch/ios`)
- barcode_scan2 (from `.symlinks/plugins/barcode_scan2/ios`) - barcode_scan2 (from `.symlinks/plugins/barcode_scan2/ios`)
- Flutter (from `Flutter`) - Flutter (from `Flutter`)
- flutter_background_service_ios (from `.symlinks/plugins/flutter_background_service_ios/ios`)
- flutter_barcode_scanner (from `.symlinks/plugins/flutter_barcode_scanner/ios`) - flutter_barcode_scanner (from `.symlinks/plugins/flutter_barcode_scanner/ios`)
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
- shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`) - shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
SPEC REPOS: SPEC REPOS:
...@@ -23,19 +32,28 @@ SPEC REPOS: ...@@ -23,19 +32,28 @@ SPEC REPOS:
- SwiftProtobuf - SwiftProtobuf
EXTERNAL SOURCES: EXTERNAL SOURCES:
background_fetch:
:path: ".symlinks/plugins/background_fetch/ios"
barcode_scan2: barcode_scan2:
:path: ".symlinks/plugins/barcode_scan2/ios" :path: ".symlinks/plugins/barcode_scan2/ios"
Flutter: Flutter:
:path: Flutter :path: Flutter
flutter_background_service_ios:
:path: ".symlinks/plugins/flutter_background_service_ios/ios"
flutter_barcode_scanner: flutter_barcode_scanner:
:path: ".symlinks/plugins/flutter_barcode_scanner/ios" :path: ".symlinks/plugins/flutter_barcode_scanner/ios"
flutter_local_notifications:
:path: ".symlinks/plugins/flutter_local_notifications/ios"
shared_preferences_ios: shared_preferences_ios:
:path: ".symlinks/plugins/shared_preferences_ios/ios" :path: ".symlinks/plugins/shared_preferences_ios/ios"
SPEC CHECKSUMS: SPEC CHECKSUMS:
background_fetch: aaf8fc9d1da7f04e5373aabd4bb239704a5be6eb
barcode_scan2: 0af2bb63c81b4565aab6cd78278e4c0fa136dbb0 barcode_scan2: 0af2bb63c81b4565aab6cd78278e4c0fa136dbb0
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_background_service_ios: e30e0d3ee69e4cee66272d0c78eacd48c2e94aac
flutter_barcode_scanner: 7a1144744c28dc0c57a8de7218ffe5ec59a9e4bf flutter_barcode_scanner: 7a1144744c28dc0c57a8de7218ffe5ec59a9e4bf
flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
SwiftProtobuf: b02b5075dcf60c9f5f403000b3b0c202a11b6ae1 SwiftProtobuf: b02b5075dcf60c9f5f403000b3b0c202a11b6ae1
......
...@@ -8,6 +8,9 @@ import Flutter ...@@ -8,6 +8,9 @@ import Flutter
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool { ) -> Bool {
GeneratedPluginRegistrant.register(with: self) GeneratedPluginRegistrant.register(with: self)
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions) return super.application(application, didFinishLaunchingWithOptions: launchOptions)
} }
} }
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies> <dependencies>
<deployment identifier="iOS"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<scenes> <scenes>
<!--Flutter View Controller--> <!--Flutter View Controller-->
...@@ -14,13 +16,14 @@ ...@@ -14,13 +16,14 @@
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/> <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides> </layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/> <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view> </view>
</viewController> </viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects> </objects>
<point key="canvasLocation" x="-26" y="-76"/>
</scene> </scene>
</scenes> </scenes>
</document> </document>
...@@ -2,8 +2,13 @@ ...@@ -2,8 +2,13 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>NSCameraUsageDescription</key> <key>BGTaskSchedulerPermittedIdentifiers</key>
<string>Autorisez l'accès à la caméra pour pouvoir scanner un produit.</string> <array>
<string>com.transistorsoft.fetch</string>
<string>com.transistorsoft.customtask</string>
</array>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string> <string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
...@@ -26,6 +31,15 @@ ...@@ -26,6 +31,15 @@
<string>$(FLUTTER_BUILD_NUMBER)</string> <string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>NSCameraUsageDescription</key>
<string>Autorisez l'accès à la caméra pour pouvoir scanner un produit.</string>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>processing</string>
</array>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>
<string>LaunchScreen</string> <string>LaunchScreen</string>
<key>UIMainStoryboardFile</key> <key>UIMainStoryboardFile</key>
...@@ -45,9 +59,5 @@ ...@@ -45,9 +59,5 @@
</array> </array>
<key>UIViewControllerBasedStatusBarAppearance</key> <key>UIViewControllerBasedStatusBarAppearance</key>
<false/> <false/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict> </dict>
</plist> </plist>
import 'dart:ffi';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:background_fetch/background_fetch.dart';
import 'package:is_eat_safe/Notifications/custom_notifications.dart';
import 'package:is_eat_safe/models/watchlist_item.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../api_utils.dart';
class BackgroundUtils{
@pragma('vm:entry-point')
static void backgroundFetchHeadlessTask(HeadlessTask task) async {
String taskId = task.taskId;
bool isTimeout = task.timeout;
if (isTimeout) {
// This task has exceeded its allowed running-time.
// You must stop what you're doing and immediately .finish(taskId)
print("[BackgroundFetch] Headless task timed-out: $taskId");
BackgroundFetch.finish(taskId);
return;
}
print('[BackgroundFetch] Headless event received.');
onHeadlessBackgroundFetch();
BackgroundFetch.finish(taskId);
}
static Future<void> configureBackgroundFetch(SharedPreferences prefs, FlutterLocalNotificationsPlugin fln) async {
int status = await BackgroundFetch.configure(BackgroundFetchConfig(
minimumFetchInterval: 15,
requiredNetworkType: NetworkType.ANY
), (String taskId) async { // <-- Event callback.
// This is the fetch-event callback.
print("[BackgroundFetch] taskId: $taskId");
// Use a switch statement to route task-handling.
switch (taskId) {
case 'com.transistorsoft.customtask':
print("Received custom task");
break;
default:
print("Default fetch task");
}
onBackgroundFetch(prefs,fln);
// Finish, providing received taskId.
BackgroundFetch.finish(taskId);
}, (String taskId) async { // <-- Event timeout callback
// This task has exceeded its allowed running-time. You must stop what you're doing and immediately .finish(taskId)
print("[BackgroundFetch] TIMEOUT taskId: $taskId");
BackgroundFetch.finish(taskId);
});
// Step 2: Schedule a custom "oneshot" task "com.transistorsoft.customtask" to execute 5000ms from now.
BackgroundFetch.scheduleTask(TaskConfig(
taskId: "com.transistorsoft.customtask",
delay: 5000 // <-- milliseconds
));
}
static Future<void> onBackgroundFetch(SharedPreferences prefs, FlutterLocalNotificationsPlugin fln) async{
final List<String> items = prefs.getStringList('watchlist_items') ?? [];
//CustomNotifications.showBigTextNotification(title: "Danger", body: "Un article de votre liste a été rapplé", fln: fln);
for (var e in items) {
WatchlistItem item = await ApiUtils.fetchWLItem(e);
if(item.isRecalled){
CustomNotifications.showBigTextNotification(title: "Danger", body: "Un article de votre liste a été rappelé", fln: fln);
return;
}
}
}
static Future<void> onHeadlessBackgroundFetch() async {
final prefs = await SharedPreferences.getInstance();
FlutterLocalNotificationsPlugin fln = FlutterLocalNotificationsPlugin();
CustomNotifications.initialize(fln);
onBackgroundFetch(prefs,fln);
}
}
\ No newline at end of file
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
class CustomNotifications{
static Future initialize(FlutterLocalNotificationsPlugin fln) async {
var androidInit = const AndroidInitializationSettings('mipmap/ic_launcher');
var iosInit = const DarwinInitializationSettings();
var initSettings = InitializationSettings(
android: androidInit,
iOS: iosInit);
await fln.initialize(initSettings);
}
static Future showBigTextNotification({required String title, required String body, required FlutterLocalNotificationsPlugin fln
} ) async {
AndroidNotificationDetails androidPlatformChannelSpecifics =
const AndroidNotificationDetails(
'watchlist_warning',
'iseatsafe_channel',
importance: Importance.max,
priority: Priority.high,
);
var not = NotificationDetails(android: androidPlatformChannelSpecifics,
iOS: const DarwinNotificationDetails()
);
await fln.show(0, title, body, not);
}
}
\ No newline at end of file
...@@ -40,8 +40,6 @@ class WatchlistBloc extends Bloc<WatchlistEvent, WatchlistState> { ...@@ -40,8 +40,6 @@ class WatchlistBloc extends Bloc<WatchlistEvent, WatchlistState> {
try { try {
var it = await ApiUtils.fetchWLItem(toBeAddedItemId); var it = await ApiUtils.fetchWLItem(toBeAddedItemId);
//TODO Api call to get real data
if (state is WatchlistInitial) { if (state is WatchlistInitial) {
var tmp = <WatchlistItem>[]; var tmp = <WatchlistItem>[];
tmp.add(it); tmp.add(it);
......
import 'dart:async';
import 'dart:io' show Platform;
import 'dart:ui';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:is_eat_safe/BackgroundTasks/background_tasks_utils.dart';
import 'package:is_eat_safe/Notifications/custom_notifications.dart';
import 'package:is_eat_safe/api_utils.dart'; import 'package:is_eat_safe/api_utils.dart';
import 'package:is_eat_safe/bloc/watchlist_bloc.dart'; import 'package:is_eat_safe/bloc/watchlist_bloc.dart';
import 'package:is_eat_safe/models/watchlist_item.dart'; import 'package:is_eat_safe/models/watchlist_item.dart';
...@@ -8,6 +14,8 @@ import 'package:is_eat_safe/views/rappel_listview.dart'; ...@@ -8,6 +14,8 @@ import 'package:is_eat_safe/views/rappel_listview.dart';
import 'package:barcode_scan2/barcode_scan2.dart'; import 'package:barcode_scan2/barcode_scan2.dart';
import 'package:is_eat_safe/views/watchlist_view.dart'; import 'package:is_eat_safe/views/watchlist_view.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:background_fetch/background_fetch.dart';
import 'bloc/produit_bloc.dart'; import 'bloc/produit_bloc.dart';
...@@ -15,6 +23,11 @@ late WatchlistBloc _watchlistBloc; ...@@ -15,6 +23,11 @@ late WatchlistBloc _watchlistBloc;
late ProduitBloc _produitBloc; late ProduitBloc _produitBloc;
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
...@@ -35,6 +48,15 @@ void main() async { ...@@ -35,6 +48,15 @@ void main() async {
theme: ThemeData(primarySwatch: Colors.orange), theme: ThemeData(primarySwatch: Colors.orange),
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
home: const MyApp(),)); home: const MyApp(),));
//Fetch data from api and compares it to local data, if data matches emit local notification
//See https://pub.dev/packages/background_fetch for more info
if(Platform.isAndroid) {
BackgroundFetch.registerHeadlessTask(BackgroundUtils.backgroundFetchHeadlessTask);
}
CustomNotifications.initialize(flutterLocalNotificationsPlugin);
BackgroundUtils.configureBackgroundFetch(prefs, flutterLocalNotificationsPlugin);
} }
class MyApp extends StatefulWidget { class MyApp extends StatefulWidget {
...@@ -58,7 +80,8 @@ class _MyAppState extends State<MyApp> { ...@@ -58,7 +80,8 @@ class _MyAppState extends State<MyApp> {
return Scaffold( return Scaffold(
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
appBar: AppBar( appBar: AppBar(
title: _searchBoolean && _index == 0 ? _searchTextField() : const Text('IsEatSafe'), title: _searchBoolean && _index == 0 ? _searchTextField() : const Text(
'IsEatSafe'),
actions: [ actions: [
//add //add
if (_index == 0) if (_index == 0)
...@@ -109,7 +132,9 @@ class _MyAppState extends State<MyApp> { ...@@ -109,7 +132,9 @@ class _MyAppState extends State<MyApp> {
onPressed: () async { onPressed: () async {
var result = await BarcodeScanner.scan(); var result = await BarcodeScanner.scan();
if (await ApiUtils.isItemRecalled(result.rawContent)) { if (await ApiUtils.isItemRecalled(result.rawContent)) {
ApiUtils.getOneRecalledProduct(result.rawContent).then((value) => Navigator.push(context, MaterialPageRoute(builder: (context) => DetailledProductView(value)))); ApiUtils.getOneRecalledProduct(result.rawContent).then((value) =>
Navigator.push(context, MaterialPageRoute(
builder: (context) => DetailledProductView(value))));
} else { } else {
showDialog( showDialog(
context: context, context: context,
...@@ -143,7 +168,10 @@ class _MyAppState extends State<MyApp> { ...@@ -143,7 +168,10 @@ class _MyAppState extends State<MyApp> {
elevation: 0, elevation: 0,
showSelectedLabels: false, showSelectedLabels: false,
showUnselectedLabels: false, showUnselectedLabels: false,
backgroundColor: Theme.of(context).primaryColor.withAlpha(0), backgroundColor: Theme
.of(context)
.primaryColor
.withAlpha(0),
fixedColor: Colors.white, fixedColor: Colors.white,
currentIndex: _index, currentIndex: _index,
onTap: (int index) { onTap: (int index) {
...@@ -211,7 +239,8 @@ class _MyAppState extends State<MyApp> { ...@@ -211,7 +239,8 @@ class _MyAppState extends State<MyApp> {
Widget _productIsOkDialog() { Widget _productIsOkDialog() {
return AlertDialog( return AlertDialog(
title: const Text("Produit OK"), title: const Text("Produit OK"),
content: const Text("Selon nos informations ce produit ne fait pas l'objet d'un rappel"), content: const Text(
"Selon nos informations ce produit ne fait pas l'objet d'un rappel"),
actions: <Widget>[ actions: <Widget>[
TextButton( TextButton(
child: const Text('Bien reçu!'), child: const Text('Bien reçu!'),
...@@ -223,3 +252,4 @@ class _MyAppState extends State<MyApp> { ...@@ -223,3 +252,4 @@ class _MyAppState extends State<MyApp> {
); );
} }
} }
...@@ -5,8 +5,10 @@ ...@@ -5,8 +5,10 @@
import FlutterMacOS import FlutterMacOS
import Foundation import Foundation
import flutter_local_notifications
import shared_preferences_macos import shared_preferences_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
} }
# Generated by pub # Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile # See https://dart.dev/tools/pub/glossary#lockfile
packages: packages:
args:
dependency: transitive
description:
name: args
url: "https://pub.dartlang.org"
source: hosted
version: "2.3.1"
async: async:
dependency: transitive dependency: transitive
description: description:
...@@ -8,6 +15,13 @@ packages: ...@@ -8,6 +15,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.9.0" version: "2.9.0"
background_fetch:
dependency: "direct main"
description:
name: background_fetch
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.2"
barcode_scan2: barcode_scan2:
dependency: "direct main" dependency: "direct main"
description: description:
...@@ -57,6 +71,13 @@ packages: ...@@ -57,6 +71,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.5" version: "1.0.5"
dbus:
dependency: transitive
description:
name: dbus
url: "https://pub.dartlang.org"
source: hosted
version: "0.7.8"
equatable: equatable:
dependency: "direct main" dependency: "direct main"
description: description:
...@@ -97,6 +118,34 @@ packages: ...@@ -97,6 +118,34 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_background_service:
dependency: "direct main"
description:
name: flutter_background_service
url: "https://pub.dartlang.org"
source: hosted
version: "2.4.6"
flutter_background_service_android:
dependency: transitive
description:
name: flutter_background_service_android
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.3"
flutter_background_service_ios:
dependency: transitive
description:
name: flutter_background_service_ios
url: "https://pub.dartlang.org"
source: hosted
version: "2.4.0"
flutter_background_service_platform_interface:
dependency: transitive
description:
name: flutter_background_service_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.0"
flutter_barcode_scanner: flutter_barcode_scanner:
dependency: "direct main" dependency: "direct main"
description: description:
...@@ -118,6 +167,27 @@ packages: ...@@ -118,6 +167,27 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.1" version: "2.0.1"
flutter_local_notifications:
dependency: "direct main"
description:
name: flutter_local_notifications
url: "https://pub.dartlang.org"
source: hosted
version: "13.0.0"
flutter_local_notifications_linux:
dependency: transitive
description:
name: flutter_local_notifications_linux
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
flutter_local_notifications_platform_interface:
dependency: transitive
description:
name: flutter_local_notifications_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.0"
flutter_plugin_android_lifecycle: flutter_plugin_android_lifecycle:
dependency: transitive dependency: transitive
description: description:
...@@ -219,6 +289,13 @@ packages: ...@@ -219,6 +289,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.3" version: "2.1.3"
petitparser:
dependency: transitive
description:
name: petitparser
url: "https://pub.dartlang.org"
source: hosted
version: "5.1.0"
platform: platform:
dependency: transitive dependency: transitive
description: description:
...@@ -357,6 +434,13 @@ packages: ...@@ -357,6 +434,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.4.12" version: "0.4.12"
timezone:
dependency: transitive
description:
name: timezone
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.0"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
...@@ -385,6 +469,13 @@ packages: ...@@ -385,6 +469,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.2.0+2" version: "0.2.0+2"
xml:
dependency: transitive
description:
name: xml
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.0"
sdks: sdks:
dart: ">=2.18.1 <3.0.0" dart: ">=2.18.1 <3.0.0"
flutter: ">=3.0.0" flutter: ">=3.0.0"
...@@ -48,6 +48,9 @@ dependencies: ...@@ -48,6 +48,9 @@ dependencies:
cupertino_icons: ^1.0.2 cupertino_icons: ^1.0.2
barcode_scan2: ^4.2.1 barcode_scan2: ^4.2.1
shared_preferences: ^2.0.15 shared_preferences: ^2.0.15
flutter_background_service: ^2.4.6
flutter_local_notifications: ^13.0.0
background_fetch: ^1.1.2
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment