This commit is contained in:
2021-09-11 08:27:27 +06:30
parent 7e9ea1b867
commit a4d3777e8a
55 changed files with 929 additions and 382 deletions

View File

@@ -1,57 +1,53 @@
import 'dart:io';
import 'package:fcs/data/services/messaging_service.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:logging/logging.dart';
final msgLog = Logger('backgroundMessageHandler');
Future<dynamic> backgroundMessageHandler(Map<String, dynamic> message) async {
if (message.containsKey('data')) {
// Handle data message
final dynamic data = message['data'];
msgLog.info("background onMessage: $message");
}
if (message.containsKey('notification')) {
// Handle notification message
final dynamic notification = message['notification'];
}
Future<void> backgroundMessageHandler(RemoteMessage message) async {
await Firebase.initializeApp();
msgLog.info("background onMessage: $message");
}
class MessagingFCM {
final log = Logger('MessagingFCM');
FirebaseMessaging _firebaseMessaging;
late FirebaseMessaging _firebaseMessaging;
MessagingFCM(OnNotify onMessage,
{OnNotify onLaunch, OnNotify onResume, OnSetupComplete onSetupComplete}) {
_firebaseMessaging = FirebaseMessaging();
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
log.info("onMessage: $message");
if (onMessage != null) _onNotify(message, onMessage);
},
onBackgroundMessage: Platform.isIOS ? null : backgroundMessageHandler,
onLaunch: (Map<String, dynamic> message) async {
log.info("onLaunch: $message");
if (onLaunch != null) _onNotify(message, onLaunch);
},
onResume: (Map<String, dynamic> message) async {
log.info("onResume: $message");
if (onResume != null) _onNotify(message, onResume);
},
{OnNotify? onLaunch,
OnNotify? onResume,
OnSetupComplete? onSetupComplete}) {
_firebaseMessaging = FirebaseMessaging.instance;
init(onMessage: onMessage, onSetupComplete: onSetupComplete);
}
init({OnNotify? onMessage, OnSetupComplete? onSetupComplete}) async {
NotificationSettings settings = await _firebaseMessaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
_firebaseMessaging
.requestNotificationPermissions(const IosNotificationSettings());
_firebaseMessaging.onIosSettingsRegistered
.listen((IosNotificationSettings settings) {
log.info("Settings registered: $settings");
});
_firebaseMessaging.getToken().then((String token) {
if (onSetupComplete != null) onSetupComplete(token);
log.info("Messaging Token:$token");
print('User granted permission: ${settings.authorizationStatus}');
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
log.info("onMessage: $message");
if (onMessage != null) _onNotify(message.data, onMessage);
if (message.notification != null) {
print('Message also contained a notification: ${message.notification}');
}
});
String? token = await _firebaseMessaging.getToken();
if (onSetupComplete != null && token != null) onSetupComplete(token);
log.info("Messaging Token:$token");
}
Future<void> subscribeToTopic(String topic) {

View File

@@ -5,11 +5,13 @@ import 'messaging_service.dart';
class MessagingServiceImp implements MessagingService {
MessagingServiceImp();
static MessagingFCM messagingFCM;
late MessagingFCM messagingFCM;
@override
void init(onMessage,
{OnNotify onLaunch, OnNotify onResume, OnSetupComplete onSetupComplete}) {
{OnNotify? onLaunch,
OnNotify? onResume,
OnSetupComplete? onSetupComplete}) {
messagingFCM = MessagingFCM(onMessage,
onLaunch: onLaunch,
onResume: onResume,

View File

@@ -1,11 +1,15 @@
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'app.dart';
import 'config.dart';
import 'data/provider/messaging_fcm.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler);
Config(
flavor: Flavor.DEV,
color: Colors.blue,

113
lib/main.dart Normal file
View File

@@ -0,0 +1,113 @@
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
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,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({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;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
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(widget.title),
),
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: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}

View File

@@ -180,7 +180,7 @@ class MessageDetail extends StatelessWidget {
message.messageID != "") {
PackageModel packageModel =
Provider.of<PackageModel>(context, listen: false);
Package p = await packageModel.getPackage(message.messageID!);
Package? p = await packageModel.getPackage(message.messageID!);
if (p == null) return;
Navigator.push<bool>(context,
CupertinoPageRoute(builder: (context) => PackageInfo(package: p)));
@@ -206,7 +206,7 @@ class MessageDetail extends StatelessWidget {
message.messageID != "") {
ShipmentModel shipmentModel =
Provider.of<ShipmentModel>(context, listen: false);
Shipment s = await shipmentModel.getShipment(message.messageID!);
Shipment? s = await shipmentModel.getShipment(message.messageID!);
if (s == null) return;
await Navigator.push<bool>(
context,

View File

@@ -8,27 +8,28 @@ import 'package:fcs/pages/widgets/local_text.dart';
import 'package:fcs/pages/widgets/progress.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_icons_null_safety/flutter_icons_null_safety.dart';
import 'package:provider/provider.dart';
import 'package:zefyr/zefyr.dart';
// import 'package:zefyr/zefyr.dart';
typedef void ProfileCallback();
class TermEdit extends StatefulWidget {
final Term term;
TermEdit({this.term});
TermEdit({required this.term});
@override
_TermEditState createState() => _TermEditState();
}
class _TermEditState extends State<TermEdit> {
/// Allows to control the editor and the document.
ZefyrController _controllerEng;
ZefyrController _controllerMm;
// ZefyrController _controllerEng;
// ZefyrController _controllerMm;
/// Zefyr editor like any other input field requires a focus node.
FocusNode _focusNodeEng;
FocusNode _focusNodeMm;
bool _isLoading;
// FocusNode _focusNodeEng;
// FocusNode _focusNodeMm;
bool _isLoading = false;
@override
void initState() {
@@ -36,23 +37,23 @@ class _TermEditState extends State<TermEdit> {
_isLoading = false;
// Here we must load the document and pass it to Zefyr controller.
_controllerEng = ZefyrController(_loadDocument(widget.term.termEng));
_controllerMm = ZefyrController(_loadDocument(widget.term.termMm));
_focusNodeEng = FocusNode();
_focusNodeMm = FocusNode();
// _controllerEng = ZefyrController(_loadDocument(widget.term.termEng));
// _controllerMm = ZefyrController(_loadDocument(widget.term.termMm));
// _focusNodeEng = FocusNode();
// _focusNodeMm = FocusNode();
}
/// Loads the document to be edited in Zefyr.
NotusDocument _loadDocument(String data) {
NotusDocument doc;
try {
doc = NotusDocument.fromJson(jsonDecode(data));
} catch (e) {}
if (doc == null) {
doc = NotusDocument();
}
return doc;
}
// NotusDocument _loadDocument(String data) {
// NotusDocument doc;
// try {
// doc = NotusDocument.fromJson(jsonDecode(data));
// } catch (e) {}
// if (doc == null) {
// doc = NotusDocument();
// }
// return doc;
// }
@override
Widget build(BuildContext context) {
@@ -115,8 +116,8 @@ class _TermEditState extends State<TermEdit> {
height: MediaQuery.of(context).size.height - 200,
child: TabBarView(
children: [
textEditor(_controllerEng, _focusNodeEng),
textEditor(_controllerMm, _focusNodeMm),
// textEditor(_controllerEng, _focusNodeEng),
// textEditor(_controllerMm, _focusNodeMm),
],
),
),
@@ -128,35 +129,35 @@ class _TermEditState extends State<TermEdit> {
);
}
Widget textEditor(ZefyrController controller, FocusNode focusNode) {
return ListView(
children: [
Container(
height: MediaQuery.of(context).size.height - 200,
child: ZefyrScaffold(
child: ZefyrTheme(
data: ZefyrThemeData().copyWith(
defaultLineTheme: LineTheme(
padding: EdgeInsets.all(0),
textStyle: TextStyle(fontFamily: "Myanmar3"),
),
),
child: ZefyrEditor(
autofocus: false,
padding: EdgeInsets.all(16),
controller: controller,
focusNode: focusNode,
),
),
),
),
// savebtn,
SizedBox(
height: 10,
)
],
);
}
// Widget textEditor(ZefyrController controller, FocusNode focusNode) {
// return ListView(
// children: [
// Container(
// height: MediaQuery.of(context).size.height - 200,
// child: ZefyrScaffold(
// child: ZefyrTheme(
// data: ZefyrThemeData().copyWith(
// defaultLineTheme: LineTheme(
// padding: EdgeInsets.all(0),
// textStyle: TextStyle(fontFamily: "Myanmar3"),
// ),
// ),
// child: ZefyrEditor(
// autofocus: false,
// padding: EdgeInsets.all(16),
// controller: controller,
// focusNode: focusNode,
// ),
// ),
// ),
// ),
// // savebtn,
// SizedBox(
// height: 10,
// )
// ],
// );
// }
_unfocus() {
FocusScope.of(context).unfocus();
@@ -167,11 +168,11 @@ class _TermEditState extends State<TermEdit> {
_isLoading = true;
});
try {
final contentsEng = jsonEncode(_controllerEng.document);
final contentsMm = jsonEncode(_controllerMm.document);
print('contents => $contentsEng');
TermModel termModel = Provider.of<TermModel>(context, listen: false);
await termModel.saveTerm(Term(termEng: contentsEng, termMm: contentsMm));
// final contentsEng = jsonEncode(_controllerEng.document);
// final contentsMm = jsonEncode(_controllerMm.document);
// print('contents => $contentsEng');
// TermModel termModel = Provider.of<TermModel>(context, listen: false);
// await termModel.saveTerm(Term(termEng: contentsEng, termMm: contentsMm));
} catch (e) {
showMsgDialog(context, "Error", e.toString());
} finally {

View File

@@ -10,46 +10,46 @@ import 'package:fcs/pages/widgets/local_text.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:zefyr/zefyr.dart';
// import 'package:zefyr/zefyr.dart';
typedef void ProfileCallback();
class TermPage extends StatefulWidget {
const TermPage({
Key key,
Key? key,
}) : super(key: key);
@override
_TermPageState createState() => _TermPageState();
}
class _TermPageState extends State<TermPage> {
ZefyrController _controller;
FocusNode _focusNode;
NotusDocument document = new NotusDocument();
// ZefyrController _controller;
// FocusNode _focusNode;
// NotusDocument document = new NotusDocument();
bool isLoading = false;
@override
void initState() {
super.initState();
_focusNode = FocusNode();
// _focusNode = FocusNode();
}
NotusDocument _loadDocument(Setting setting) {
bool isEng = Provider.of<LanguageModel>(context).isEng;
String term = isEng ? setting.termsEng : setting.termsMm;
NotusDocument doc;
try {
doc = NotusDocument.fromJson(jsonDecode(term));
} catch (e) {}
if (doc == null) {
doc = NotusDocument();
}
return doc;
}
// NotusDocument _loadDocument(Setting setting) {
// bool isEng = Provider.of<LanguageModel>(context).isEng;
// String term = isEng ? setting.termsEng : setting.termsMm;
// NotusDocument doc;
// try {
// doc = NotusDocument.fromJson(jsonDecode(term));
// } catch (e) {}
// if (doc == null) {
// doc = NotusDocument();
// }
// return doc;
// }
@override
Widget build(BuildContext context) {
Setting setting = Provider.of<MainModel>(context).setting;
Setting? setting = Provider.of<MainModel>(context).setting;
bool isEditable = context.select((MainModel m) => m.termEditable());
return Scaffold(
@@ -76,7 +76,7 @@ class _TermPageState extends State<TermPage> {
onPressed: () =>
Navigator.of(context).push<void>(CupertinoPageRoute(
builder: (context) =>
TermEdit(term: Term.fromSetting(setting)),
TermEdit(term: Term.fromSetting(setting!)),
)),
icon: Icon(
CupertinoIcons.pen,
@@ -85,25 +85,25 @@ class _TermPageState extends State<TermPage> {
]
: [],
),
body: ZefyrTheme(
data: ZefyrThemeData().copyWith(
defaultLineTheme: LineTheme(
padding: EdgeInsets.all(0),
textStyle: TextStyle(fontFamily: "Myanmar3"),
),
),
// data: ZefyrThemeData().copyWith(
// defaultLineTheme: LineTheme(
// textStyle: TextStyle(color: Colors.black),
// padding: EdgeInsets.all(0))),
child: ZefyrScaffold(
child: ZefyrEditor(
mode: ZefyrMode.view,
padding: EdgeInsets.all(16),
controller: ZefyrController(_loadDocument(setting)),
focusNode: _focusNode,
),
)),
// body: ZefyrTheme(
// data: ZefyrThemeData().copyWith(
// defaultLineTheme: LineTheme(
// padding: EdgeInsets.all(0),
// textStyle: TextStyle(fontFamily: "Myanmar3"),
// ),
// ),
// // data: ZefyrThemeData().copyWith(
// // defaultLineTheme: LineTheme(
// // textStyle: TextStyle(color: Colors.black),
// // padding: EdgeInsets.all(0))),
// child: ZefyrScaffold(
// child: ZefyrEditor(
// mode: ZefyrMode.view,
// padding: EdgeInsets.all(16),
// controller: ZefyrController(_loadDocument(setting)),
// focusNode: _focusNode,
// ),
// )),
);
}
}