From 2c95ec7600f7c51076d6d7b1db107b05740eb6d6 Mon Sep 17 00:00:00 2001 From: phyothandar Date: Fri, 10 Sep 2021 17:14:59 +0630 Subject: [PATCH 1/4] null safety --- lib/domain/entities/invoice.dart | 10 ++++----- lib/domain/entities/package.dart | 2 +- lib/helpers/firebase_helper.dart | 15 ++++++++----- lib/pages/carton/cargo_type_editor.dart | 2 +- lib/pages/carton_search/carton_search.dart | 2 +- lib/pages/invoice/editor/invoice_editor.dart | 16 +++++++------- .../editor/invoice_handling_fee_list.dart | 4 ++-- lib/pages/invoice/invoice_info.dart | 4 ++-- lib/pages/invoice/invoice_table.dart | 4 ++-- lib/pages/package/model/package_model.dart | 22 +++++++++---------- lib/pages/package/tracking_id_page.dart | 2 +- lib/pages/package_search/package_serach.dart | 2 +- lib/pages/profile/profile_page.dart | 2 +- lib/pages/rates/custom_editor.dart | 2 +- lib/pages/rates/custom_list.dart | 2 +- lib/pages/rates/shipment_rates_calculate.dart | 4 ++-- lib/pages/receiving/receiving_editor.dart | 2 +- lib/pages/shipment/shipment_assign.dart | 2 +- lib/pages/shipment/shipment_confirm.dart | 2 +- lib/pages/shipment/shipment_info.dart | 2 +- lib/pages/widgets/multi_img_controller.dart | 2 +- 21 files changed, 54 insertions(+), 51 deletions(-) diff --git a/lib/domain/entities/invoice.dart b/lib/domain/entities/invoice.dart index 3ac1c9e..a15e905 100644 --- a/lib/domain/entities/invoice.dart +++ b/lib/domain/entities/invoice.dart @@ -28,7 +28,7 @@ class Invoice { List customDuties; List cartons; List cargoTypes; - List shipments; + List? shipments; List payments; Discount? discount; PaymentMethod? paymentMethod; @@ -85,9 +85,9 @@ class Invoice { } double getHandlingFee() { - return shipments - .where((sh) => sh.isSelected) - .fold(0, (p, s) => p + (s.handlingFee - s.paidHandlingFee)); + return shipments! + .where((sh) => sh!.isSelected) + .fold(0, (p, s) => p + (s!.handlingFee - s.paidHandlingFee)); } double getTotalBalance(Rate rate) { @@ -176,7 +176,7 @@ class Invoice { List _cargoTypes = cargoTypes.map((c) => c.toMap()).toList(); List _customDuties = customDuties.map((c) => c.toMap()).toList(); List _cartons = cartons.map((c) => c.toMap()).toList(); - List _shipments = shipments.map((s) => s.toMap()).toList(); + List _shipments = shipments!.map((s) => s!.toMap()).toList(); return { "id": id, "invoice_date": invoiceDate?.toUtc().toIso8601String(), diff --git a/lib/domain/entities/package.dart b/lib/domain/entities/package.dart index c583de1..2df0c7d 100644 --- a/lib/domain/entities/package.dart +++ b/lib/domain/entities/package.dart @@ -36,7 +36,7 @@ class Package { DeliveryAddress? deliveryAddress; //for packages in processing - List photoFiles; + List photoFiles; int get amount => rate != null && weight != null ? rate * weight : 0; diff --git a/lib/helpers/firebase_helper.dart b/lib/helpers/firebase_helper.dart index 0fd5b84..4014aa8 100644 --- a/lib/helpers/firebase_helper.dart +++ b/lib/helpers/firebase_helper.dart @@ -24,20 +24,24 @@ Future getClaims({bool refreshIdToken = false}) async { } // returns list of url -Future> uploadFiles(String path, List files, +Future> uploadFiles(String path, List files, {String? fileName}) async { List> fu = []; - for (File f in files) { + for (File? f in files) { Future u = uploadStorage(path, f); fu.add(u); } return Future.wait(fu); } -Future uploadStorage(String path, File file, {String? fileName}) async { +Future uploadStorage(String path, File? file, + {String? fileName}) async { if (fileName == null) { fileName = Uuid().v4(); } + if (file == null) { + return Future.value(''); + } Reference ref = FirebaseStorage.instance.ref().child('$path/$fileName'); UploadTask uploadTask = ref.putFile(file); await uploadTask.resume(); @@ -57,10 +61,11 @@ Future uploadStorage(String path, File file, {String? fileName}) async { // return downloadUrl; } -Future deleteStorageFromUrls(List urls) async { +Future deleteStorageFromUrls(List urls) async { if (urls == null) return; for (int i = 0; i < urls.length; i++) { - await deleteStorageFromUrl(urls[i]); + if (urls[i] == null) return; + await deleteStorageFromUrl(urls[i]!); } } diff --git a/lib/pages/carton/cargo_type_editor.dart b/lib/pages/carton/cargo_type_editor.dart index 7c8553a..1d6572c 100644 --- a/lib/pages/carton/cargo_type_editor.dart +++ b/lib/pages/carton/cargo_type_editor.dart @@ -39,7 +39,7 @@ class _CargoTypeEditorState extends State { _loadDefalut() { ShipmentRateModel shipmentRateModel = Provider.of(context, listen: false); - _cargo = shipmentRateModel.rate.defaultCargoType?.clone(); + _cargo = shipmentRateModel.rate.defaultCargoType.clone(); } @override diff --git a/lib/pages/carton_search/carton_search.dart b/lib/pages/carton_search/carton_search.dart index 5442616..07c2215 100644 --- a/lib/pages/carton_search/carton_search.dart +++ b/lib/pages/carton_search/carton_search.dart @@ -171,7 +171,7 @@ class PartSearchDelegate extends SearchDelegate { // } try { - String barcode = await scanBarcode(); + String? barcode = await scanBarcode(); if (barcode != null) { query = barcode; showResults(context); diff --git a/lib/pages/invoice/editor/invoice_editor.dart b/lib/pages/invoice/editor/invoice_editor.dart index c8b9efa..99b5143 100644 --- a/lib/pages/invoice/editor/invoice_editor.dart +++ b/lib/pages/invoice/editor/invoice_editor.dart @@ -103,10 +103,10 @@ class _InvoiceEditorState extends State { _loadShipments() async { ShipmentModel shipmentModel = Provider.of(context, listen: false); - List shipments = await shipmentModel.getShipmentWithHandlingFee( + List? shipments = await shipmentModel.getShipmentWithHandlingFee( widget.fcsShipment!.id!, widget.customer!.id!); - shipments.forEach((s) { - s.isSelected = true; + shipments!.forEach((s) { + s!.isSelected = true; }); setState(() { _invoice!.shipments = shipments; @@ -380,8 +380,8 @@ class _InvoiceEditorState extends State { if (shipment == null) return; shipment.isSelected = true; setState(() { - _invoice!.shipments.remove(shipment); - _invoice!.shipments.add(shipment); + _invoice!.shipments!.remove(shipment); + _invoice!.shipments!.add(shipment); }); } @@ -389,8 +389,8 @@ class _InvoiceEditorState extends State { if (shipment == null) return; shipment.isSelected = false; setState(() { - _invoice!.shipments.remove(shipment); - _invoice!.shipments.add(shipment); + _invoice!.shipments!.remove(shipment); + _invoice!.shipments!.add(shipment); }); } @@ -431,7 +431,7 @@ class _InvoiceEditorState extends State { invoice.handlingFee = _invoice!.getHandlingFee(); invoice.cartons = _invoice!.cartons.where((c) => c.isChecked!).toList(); invoice.shipments = - _invoice!.shipments.where((s) => s.isSelected).toList(); + _invoice!.shipments!.where((s) => s!.isSelected).toList(); invoice.discount = _invoice!.discount; invoice.deliveryFee = _invoice!.deliveryFee; diff --git a/lib/pages/invoice/editor/invoice_handling_fee_list.dart b/lib/pages/invoice/editor/invoice_handling_fee_list.dart index 5ee937d..75d6462 100644 --- a/lib/pages/invoice/editor/invoice_handling_fee_list.dart +++ b/lib/pages/invoice/editor/invoice_handling_fee_list.dart @@ -9,7 +9,7 @@ typedef OnAdd(Shipment shipment); typedef OnRemove(Shipment shipment); class InvoiceHandlingFeeList extends StatelessWidget { - final List? shipments; + final List? shipments; final OnAdd? onAdd; final OnRemove? onRemove; @@ -72,7 +72,7 @@ class InvoiceHandlingFeeList extends StatelessWidget { onSelectChanged: (value) => Navigator.pop(context, c), cells: [ MyDataCell(new Text( - c.shipmentNumber!, + c!.shipmentNumber!, style: textStyle, )), MyDataCell( diff --git a/lib/pages/invoice/invoice_info.dart b/lib/pages/invoice/invoice_info.dart index ba3adbc..d9980ec 100644 --- a/lib/pages/invoice/invoice_info.dart +++ b/lib/pages/invoice/invoice_info.dart @@ -39,8 +39,8 @@ class _InvoiceInfoState extends State { void initState() { super.initState(); _invoice = widget.invoice!; - _invoice!.shipments.forEach((s) { - s.isSelected = true; + _invoice!.shipments!.forEach((s) { + s!.isSelected = true; }); _loadCartons(); } diff --git a/lib/pages/invoice/invoice_table.dart b/lib/pages/invoice/invoice_table.dart index 46ed34b..77812dd 100644 --- a/lib/pages/invoice/invoice_table.dart +++ b/lib/pages/invoice/invoice_table.dart @@ -70,11 +70,11 @@ class InvoiceTable extends StatelessWidget { "${c.calWeight.toStringAsFixed(2)} x ${c.calRate.toStringAsFixed(2)}", amount: "${c.calAmount.toStringAsFixed(2)}")); }); - invoice!.shipments.where((ss) => (ss.isSelected )).forEach((s) { + invoice!.shipments!.where((ss) => (ss!.isSelected )).forEach((s) { tableRows.add(InvoiceTableRow( data: s, invoiceDataType: InvoiceDataType.HandlingFeeType, - desc: "Handling fee\n${s.shipmentNumber}", + desc: "Handling fee\n${s!.shipmentNumber}", rate: "", amount: "${s.handlingFee.toStringAsFixed(2)}")); }); diff --git a/lib/pages/package/model/package_model.dart b/lib/pages/package/model/package_model.dart index 9e979e1..380f9b7 100644 --- a/lib/pages/package/model/package_model.dart +++ b/lib/pages/package/model/package_model.dart @@ -260,7 +260,7 @@ class PackageModel extends BaseModel { } Future createReceiving( - User user, Package package, List files) async { + User user, Package package, List files) async { if (user != null) { package.fcsID = user.fcsID; } @@ -288,22 +288,21 @@ class PackageModel extends BaseModel { } } - Future updateReceiving(User user, Package package, List files, - List deletedUrls) async { + Future updateReceiving(User user, Package package, List files, + List deletedUrls) async { if (user != null) { package.fcsID = user.fcsID; } if (deletedUrls != null) { - for (String url in deletedUrls) { + for (String? url in deletedUrls) { package.photoUrls.remove(url); } } List uploadedURL = []; if (files != null) { - var count = (package.photoUrls?.length ?? 0) + - files.length - - (deletedUrls?.length ?? 0); + var count = + (package.photoUrls.length) + files.length - (deletedUrls.length); if (count > uploadPhotoLimit) throw Exception("Exceed number of file upload"); @@ -333,18 +332,17 @@ class PackageModel extends BaseModel { } Future updateProcessing( - Package package, List files, List deletedUrls) async { + Package package, List files, List deletedUrls) async { if (deletedUrls != null) { - for (String url in deletedUrls) { + for (String? url in deletedUrls) { package.photoUrls.remove(url); } } List uploadedURL = []; if (files != null) { - var count = (package.photoUrls?.length ?? 0) + - files.length - - (deletedUrls?.length ?? 0); + var count = + (package.photoUrls.length) + files.length - (deletedUrls.length); if (count > uploadPhotoLimit) throw Exception("Exceed number of file upload"); diff --git a/lib/pages/package/tracking_id_page.dart b/lib/pages/package/tracking_id_page.dart index 1856f7a..6cdd773 100644 --- a/lib/pages/package/tracking_id_page.dart +++ b/lib/pages/package/tracking_id_page.dart @@ -164,7 +164,7 @@ class _TrackingIDPageState extends State { // } try { - String barcode = await scanBarcode(); + String? barcode = await scanBarcode(); if (barcode != null) { setState(() { _transcationIDCtl.text = barcode; diff --git a/lib/pages/package_search/package_serach.dart b/lib/pages/package_search/package_serach.dart index 18b57ef..566b46c 100644 --- a/lib/pages/package_search/package_serach.dart +++ b/lib/pages/package_search/package_serach.dart @@ -147,7 +147,7 @@ class PackageSearchDelegate extends SearchDelegate { // Barcode bc = barcodes.firstWhere((element) => true); // String barcode; // if (bc != null) barcode = bc.rawValue; - String barcode = await scanBarcode(); + String? barcode = await scanBarcode(); if (barcode != null) { query = barcode; showResults(context); diff --git a/lib/pages/profile/profile_page.dart b/lib/pages/profile/profile_page.dart index a618c3a..3732104 100644 --- a/lib/pages/profile/profile_page.dart +++ b/lib/pages/profile/profile_page.dart @@ -80,7 +80,7 @@ class _ProfileState extends State { ); final phonenumberbox = DisplayText( - text: mainModel.user!.phone ?? "", + text: mainModel.user!.phone, labelTextKey: "profile.phone", iconData: Icons.phone, ); diff --git a/lib/pages/rates/custom_editor.dart b/lib/pages/rates/custom_editor.dart index 4e7f2b1..bec5ddb 100644 --- a/lib/pages/rates/custom_editor.dart +++ b/lib/pages/rates/custom_editor.dart @@ -36,7 +36,7 @@ class _CustomEditorState extends State { _productController.text = _custom.name??""; _feeController.text = _custom.customDutyFee.toStringAsFixed(2); _shipmentRateController.text = - _custom.rate == null ? "" : _custom.rate?.toStringAsFixed(2) ?? ''; + _custom.rate == null ? "" : _custom.rate.toStringAsFixed(2); } else { _isNew = true; } diff --git a/lib/pages/rates/custom_list.dart b/lib/pages/rates/custom_list.dart index 898c8a3..f5a1dc9 100644 --- a/lib/pages/rates/custom_list.dart +++ b/lib/pages/rates/custom_list.dart @@ -86,7 +86,7 @@ class _CustomListState extends State { custom.rate == null ? "" : "Shipment rate \$ " + - custom.rate!.toStringAsFixed(2)), + custom.rate.toStringAsFixed(2)), ), ); }), diff --git a/lib/pages/rates/shipment_rates_calculate.dart b/lib/pages/rates/shipment_rates_calculate.dart index d956a55..c722c86 100644 --- a/lib/pages/rates/shipment_rates_calculate.dart +++ b/lib/pages/rates/shipment_rates_calculate.dart @@ -62,11 +62,11 @@ class _ShipmentRatesCalState extends State { var amount = box.calAmount(rate); var shipmentWeight = box.getShipmentWeight(rate.volumetricRatio); var effectiveWeight = - _cargoType.weight! > shipmentWeight ? _cargoType.weight : shipmentWeight; + _cargoType.weight > shipmentWeight ? _cargoType.weight : shipmentWeight; setState(() { _deliveryFee = - effectiveWeight! > rate.freeDeliveryWeight ? 0 : rate.deliveryFee; + effectiveWeight > rate.freeDeliveryWeight ? 0 : rate.deliveryFee; _amount = amount == null ? 0 : amount + _deliveryFee; _shipmentWeight = shipmentWeight.toDouble(); }); diff --git a/lib/pages/receiving/receiving_editor.dart b/lib/pages/receiving/receiving_editor.dart index e8ec46c..a120ee0 100644 --- a/lib/pages/receiving/receiving_editor.dart +++ b/lib/pages/receiving/receiving_editor.dart @@ -212,7 +212,7 @@ class _ReceivingEditorState extends State { // } try { - String barcode = await scanBarcode(); + String? barcode = await scanBarcode(); if (barcode != null) { setState(() { _trackingIDCtl.text = barcode; diff --git a/lib/pages/shipment/shipment_assign.dart b/lib/pages/shipment/shipment_assign.dart index 7c37695..ad2e808 100644 --- a/lib/pages/shipment/shipment_assign.dart +++ b/lib/pages/shipment/shipment_assign.dart @@ -56,7 +56,7 @@ class _ShipmentAssignState extends State { _selectedShipmentType = _shipment!.shipmentType; _fromTimeEditingController.text = _shipment!.pickupTimeStart!; _toTimeEditingController.text = _shipment!.pickupTimeEnd!; - _pickupDate.text = dateFormatter.format(_shipment!.pickupDate! ?? now); + _pickupDate.text = dateFormatter.format(_shipment!.pickupDate ?? now); _handlingFee.text = _shipment!.handlingFee != null ? _shipment!.handlingFee.toString() : "0"; diff --git a/lib/pages/shipment/shipment_confirm.dart b/lib/pages/shipment/shipment_confirm.dart index 68daf42..05ed394 100644 --- a/lib/pages/shipment/shipment_confirm.dart +++ b/lib/pages/shipment/shipment_confirm.dart @@ -37,7 +37,7 @@ class _ShipmentConfirmState extends State { super.initState(); _shipment = widget.shipment; - _handlingFee.text = _shipment!.handlingFee?.toString() ?? "0"; + _handlingFee.text = _shipment!.handlingFee.toString(); } @override diff --git a/lib/pages/shipment/shipment_info.dart b/lib/pages/shipment/shipment_info.dart index 382d2af..ee29ad5 100644 --- a/lib/pages/shipment/shipment_info.dart +++ b/lib/pages/shipment/shipment_info.dart @@ -223,7 +223,7 @@ class _ShipmentInfoState extends State { iconData: MaterialCommunityIcons.worker); var handlingFeeBox = DisplayText( labelTextKey: "shipment.handling.fee", - text: (_shipment!.handlingFee ?? 0).toString(), + text: (_shipment!.handlingFee).toString(), iconData: FontAwesome.truck); final assignCompleteBtn = LocalButton( diff --git a/lib/pages/widgets/multi_img_controller.dart b/lib/pages/widgets/multi_img_controller.dart index 26191ed..ad0be39 100644 --- a/lib/pages/widgets/multi_img_controller.dart +++ b/lib/pages/widgets/multi_img_controller.dart @@ -80,7 +80,7 @@ class MultiImgController { List get getUpdatedFile { List _addfiles = getAddedFile; - this.imageFiles!.addAll(_addfiles); + this.imageFiles.addAll(_addfiles); return this.imageFiles; } From 93fcd473bbe1481b52ca6be7eb6db2e0592e2b40 Mon Sep 17 00:00:00 2001 From: phyothandar Date: Fri, 10 Sep 2021 17:42:40 +0630 Subject: [PATCH 2/4] null safety --- lib/pages/widgets/my_data_table.dart | 255 ++++++++++++++------------- 1 file changed, 132 insertions(+), 123 deletions(-) diff --git a/lib/pages/widgets/my_data_table.dart b/lib/pages/widgets/my_data_table.dart index 3015c50..f86925f 100644 --- a/lib/pages/widgets/my_data_table.dart +++ b/lib/pages/widgets/my_data_table.dart @@ -75,7 +75,7 @@ class MyDataRow { this.key, this.selected = false, this.onSelectChanged, - @required this.cells, + required this.cells, }) : assert(cells != null); /// Creates the configuration for a row of a [MyDataTable], deriving @@ -83,12 +83,12 @@ class MyDataRow { /// /// The [cells] argument must not be null. MyDataRow.byIndex({ - int index, + int? index, this.selected = false, this.onSelectChanged, - @required this.cells, + required this.cells, }) : assert(cells != null), - key = ValueKey(index); + key = ValueKey(index!); /// A [Key] that uniquely identifies this row. This is used to /// ensure that if a row is added or removed, any stateful widgets @@ -96,7 +96,7 @@ class MyDataRow { /// remain on the right row visually. /// /// If the table never changes once created, no key is necessary. - final LocalKey key; + final LocalKey? key; /// Called when the user selects or unselects a selectable row. /// @@ -111,7 +111,7 @@ class MyDataRow { /// A row whose [onSelectChanged] callback is null is ignored for /// the purposes of determining the state of the "all" checkbox, /// and its checkbox is disabled. - final ValueChanged onSelectChanged; + final ValueChanged? onSelectChanged; /// Whether the row is selected. /// @@ -193,7 +193,7 @@ class MyDataCell { /// If non-null, tapping the cell will call this callback. If /// null, tapping the cell will attempt to select the row (if /// [MyDataRow.onSelectChanged] is provided). - final VoidCallback onTap; + final VoidCallback? onTap; bool get _debugInteractive => onTap != null; } @@ -309,8 +309,8 @@ class MyDataTable extends StatelessWidget { /// the sort order is ascending, this should be true (the default), /// otherwise it should be false. MyDataTable({ - Key key, - @required this.columns, + Key? key, + required this.columns, this.sortColumnIndex, this.sortAscending = true, this.onSelectAll, @@ -320,7 +320,7 @@ class MyDataTable extends StatelessWidget { this.columnSpacing = 56.0, this.oddLine, this.evenLine, - @required this.rows, + required this.rows, }) : assert(columns != null), assert(columns.isNotEmpty), assert(sortColumnIndex == null || @@ -339,8 +339,8 @@ class MyDataTable extends StatelessWidget { /// The configuration and labels for the columns in the table. final List columns; - final Decoration oddLine; - final Decoration evenLine; + final Decoration? oddLine; + final Decoration? evenLine; /// The current primary sort key's column. /// @@ -353,7 +353,7 @@ class MyDataTable extends StatelessWidget { /// /// When this is null, it implies that the table's sort order does /// not correspond to any of the columns. - final int sortColumnIndex; + final int? sortColumnIndex; /// Whether the column mentioned in [sortColumnIndex], if any, is sorted /// in ascending order. @@ -376,7 +376,7 @@ class MyDataTable extends StatelessWidget { /// To control whether a particular row is selectable or not, see /// [MyDataRow.onSelectChanged]. This callback is only relevant if any /// row is selectable. - final ValueSetter onSelectAll; + final ValueSetter? onSelectAll; /// The height of each row (excluding the row that contains column headings). /// @@ -413,11 +413,10 @@ class MyDataTable extends StatelessWidget { // non-numeric, if there is exactly one, otherwise null. final int _onlyTextColumn; static int _initOnlyTextColumn(List columns) { - int result; + int result = 0; for (int index = 0; index < columns.length; index += 1) { final MyDataColumn column = columns[index]; if (!column.numeric) { - if (result != null) return null; result = index; } } @@ -433,11 +432,11 @@ class MyDataTable extends StatelessWidget { void _handleSelectAll(bool checked) { if (onSelectAll != null) { - onSelectAll(checked); + onSelectAll!(checked); } else { for (MyDataRow row in rows) { if ((row.onSelectChanged != null) && (row.selected != checked)) - row.onSelectChanged(checked); + row.onSelectChanged!(checked); } } } @@ -452,10 +451,10 @@ class MyDataTable extends StatelessWidget { Color(0x1E000000); // Dark theme variant is just a guess. Widget _buildCheckbox({ - Color color, - bool checked, - VoidCallback onRowTap, - ValueChanged onCheckboxChanged, + Color? color, + bool? checked, + VoidCallback? onRowTap, + ValueChanged? onCheckboxChanged, }) { Widget contents = Semantics( container: true, @@ -466,7 +465,9 @@ class MyDataTable extends StatelessWidget { child: Checkbox( activeColor: color, value: checked, - onChanged: onCheckboxChanged, + onChanged: (bool? value) { + onCheckboxChanged!(value ?? false); + }, ), ), ), @@ -484,32 +485,33 @@ class MyDataTable extends StatelessWidget { } Widget _buildHeadingCell({ - BuildContext context, - EdgeInsetsGeometry padding, - Widget label, - String tooltip, - bool numeric, - VoidCallback onSort, - bool sorted, - bool ascending, + required BuildContext context, + EdgeInsetsGeometry? padding, + Widget? label, + String? tooltip, + bool? numeric, + VoidCallback? onSort, + bool? sorted, + bool? ascending, }) { if (onSort != null) { final Widget arrow = _SortArrow( - visible: sorted, + visible: sorted!, down: sorted ? ascending : null, duration: _sortArrowAnimationDuration, ); const Widget arrowPadding = SizedBox(width: _sortArrowPadding); label = Row( - textDirection: numeric ? TextDirection.rtl : null, - children: [label, arrowPadding, arrow], + textDirection: (numeric ?? false) ? TextDirection.rtl : null, + children: [label ?? Container(), arrowPadding, arrow], ); } label = Container( padding: padding, height: headingRowHeight, - alignment: - numeric ? Alignment.centerRight : AlignmentDirectional.centerStart, + alignment: (numeric ?? false) + ? Alignment.centerRight + : AlignmentDirectional.centerStart, child: AnimatedDefaultTextStyle( style: TextStyle( // TODO(ianh): font family should match Theme; see https://github.com/flutter/flutter/issues/3116 @@ -517,12 +519,16 @@ class MyDataTable extends StatelessWidget { fontSize: _headingFontSize, height: math.min(1.0, headingRowHeight / _headingFontSize), color: (Theme.of(context).brightness == Brightness.light) - ? ((onSort != null && sorted) ? Colors.black87 : Colors.black54) - : ((onSort != null && sorted) ? Colors.white : Colors.white70), + ? ((onSort != null && (sorted ?? false)) + ? Colors.black87 + : Colors.black54) + : ((onSort != null && (sorted ?? false)) + ? Colors.white + : Colors.white70), ), softWrap: false, duration: _sortArrowAnimationDuration, - child: label, + child: label ?? Container(), ), ); if (tooltip != null) { @@ -541,42 +547,43 @@ class MyDataTable extends StatelessWidget { } Widget _buildMyDataCell({ - BuildContext context, - EdgeInsetsGeometry padding, - Widget label, - bool numeric, - bool placeholder, - bool showEditIcon, - VoidCallback onTap, - VoidCallback onSelectChanged, + required BuildContext context, + EdgeInsetsGeometry? padding, + Widget? label, + bool? numeric, + bool? placeholder, + bool? showEditIcon, + VoidCallback? onTap, + VoidCallback? onSelectChanged, }) { final bool isLightTheme = Theme.of(context).brightness == Brightness.light; - if (showEditIcon) { + if (showEditIcon ?? false) { const Widget icon = Icon(Icons.edit, size: 18.0); - label = Expanded(child: label); + label = Expanded(child: label ?? Container()); label = Row( - textDirection: numeric ? TextDirection.rtl : null, + textDirection: (numeric ?? false) ? TextDirection.rtl : null, children: [label, icon], ); } label = Container( padding: padding, height: MyDataRowHeight, - alignment: - numeric ? Alignment.centerRight : AlignmentDirectional.centerStart, + alignment: (numeric ?? false) + ? Alignment.centerRight + : AlignmentDirectional.centerStart, child: DefaultTextStyle( style: TextStyle( // TODO(ianh): font family should be Roboto; see https://github.com/flutter/flutter/issues/3116 fontSize: 13.0, color: isLightTheme - ? (placeholder ? Colors.black38 : Colors.black87) - : (placeholder ? Colors.white38 : Colors.white70), + ? ((placeholder ?? false) ? Colors.black38 : Colors.black87) + : ((placeholder ?? false) ? Colors.white38 : Colors.white70), ), child: IconTheme.merge( data: IconThemeData( color: isLightTheme ? Colors.black54 : Colors.white70, ), - child: DropdownButtonHideUnderline(child: label), + child: DropdownButtonHideUnderline(child: label ?? Container()), ), ), ); @@ -613,8 +620,9 @@ class MyDataTable extends StatelessWidget { final bool showCheckboxColumn = false; final bool allChecked = false; - final List tableColumns = - List(columns.length + (showCheckboxColumn ? 1 : 0)); + final List tableColumns = (columns.length + + (showCheckboxColumn ? 1 : 0)) as List; + final List tableRows = List.generate( rows.length + 1, // the +1 is for the header row (int index) { @@ -627,36 +635,36 @@ class MyDataTable extends StatelessWidget { : index.isEven && evenLine != null ? evenLine : _kUnselectedDecoration, - children: List(tableColumns.length), + children: tableColumns.map((e) => Container()).toList(), ); }, ); int rowIndex; - int displayColumnIndex = 0; - if (showCheckboxColumn) { - tableColumns[0] = FixedColumnWidth( - horizontalMargin + Checkbox.width + horizontalMargin / 2.0); - tableRows[0].children[0] = _buildCheckbox( - color: theme.accentColor, - checked: allChecked, - onCheckboxChanged: _handleSelectAll, - ); - rowIndex = 1; - for (MyDataRow row in rows) { - tableRows[rowIndex].children[0] = _buildCheckbox( - color: theme.accentColor, - checked: row.selected, - onRowTap: () => row.onSelectChanged != null - ? row.onSelectChanged(!row.selected) - : null, - onCheckboxChanged: row.onSelectChanged, - ); - rowIndex += 1; - } - displayColumnIndex += 1; - } + int displayColumnIndex = 0; + // if (showCheckboxColumn) { + // tableColumns[0] = FixedColumnWidth( + // horizontalMargin + Checkbox.width + horizontalMargin / 2.0); + // tableRows[0].children![0] = _buildCheckbox( + // color: theme.accentColor, + // checked: allChecked, + // onCheckboxChanged: _handleSelectAll, + // ); + // rowIndex = 1; + // for (MyDataRow row in rows) { + // tableRows[rowIndex].children[0] = _buildCheckbox( + // color: theme.accentColor, + // checked: row.selected, + // onRowTap: () => row.onSelectChanged != null + // ? row.onSelectChanged(!row.selected) + // : null, + // onCheckboxChanged: row.onSelectChanged, + // ); + // rowIndex += 1; + // } + // displayColumnIndex += 1; + // } for (int MyDataColumnIndex = 0; MyDataColumnIndex < columns.length; @@ -689,14 +697,14 @@ class MyDataTable extends StatelessWidget { } else { tableColumns[displayColumnIndex] = const IntrinsicColumnWidth(); } - tableRows[0].children[displayColumnIndex] = _buildHeadingCell( + tableRows[0].children![displayColumnIndex] = _buildHeadingCell( context: context, padding: padding, label: column.label, tooltip: column.tooltip, numeric: column.numeric, onSort: () => column.onSort != null - ? column.onSort(MyDataColumnIndex, + ? column.onSort!(MyDataColumnIndex, sortColumnIndex != MyDataColumnIndex || !sortAscending) : null, sorted: MyDataColumnIndex == sortColumnIndex, @@ -705,7 +713,7 @@ class MyDataTable extends StatelessWidget { rowIndex = 1; for (MyDataRow row in rows) { final MyDataCell cell = row.cells[MyDataColumnIndex]; - tableRows[rowIndex].children[displayColumnIndex] = _buildMyDataCell( + tableRows[rowIndex].children?[displayColumnIndex] = _buildMyDataCell( context: context, padding: padding, label: cell.child, @@ -714,7 +722,7 @@ class MyDataTable extends StatelessWidget { showEditIcon: cell.showEditIcon, onTap: cell.onTap, onSelectChanged: () => row.onSelectChanged != null - ? row.onSelectChanged(!row.selected) + ? row.onSelectChanged!(!row.selected) : null, ); rowIndex += 1; @@ -745,12 +753,12 @@ class MyDataTable extends StatelessWidget { class TableRowInkWell extends InkResponse { /// Creates an ink well for a table row. const TableRowInkWell({ - Key key, - Widget child, - GestureTapCallback onTap, - GestureTapCallback onDoubleTap, - GestureLongPressCallback onLongPress, - ValueChanged onHighlightChanged, + Key? key, + Widget? child, + GestureTapCallback? onTap, + GestureTapCallback? onDoubleTap, + GestureLongPressCallback? onLongPress, + ValueChanged? onHighlightChanged, }) : super( key: key, child: child, @@ -766,7 +774,7 @@ class TableRowInkWell extends InkResponse { RectCallback getRectCallback(RenderBox referenceBox) { return () { RenderObject cell = referenceBox; - AbstractNode table = cell.parent; + AbstractNode? table = cell.parent; final Matrix4 transform = Matrix4.identity(); while (table is RenderObject && table is! RenderTable) { final RenderObject parentBox = table as RenderObject; @@ -779,11 +787,11 @@ class TableRowInkWell extends InkResponse { final TableCellParentData cellParentData = cell.parentData as TableCellParentData; assert(cellParentData.y != null); - final Rect rect = table.getRowBox(cellParentData.y); + final Rect rect = table.getRowBox(cellParentData.y!); // The rect is in the table's coordinate space. We need to change it to the // TableRowInkWell's coordinate space. table.applyPaintTransform(cell, transform); - final Offset offset = MatrixUtils.getAsTranslation(transform); + final Offset? offset = MatrixUtils.getAsTranslation(transform); if (offset != null) return rect.shift(-offset); } return Rect.zero; @@ -799,31 +807,31 @@ class TableRowInkWell extends InkResponse { class _SortArrow extends StatefulWidget { const _SortArrow({ - Key key, + Key? key, this.visible, this.down, this.duration, }) : super(key: key); - final bool visible; + final bool? visible; - final bool down; + final bool? down; - final Duration duration; + final Duration? duration; @override _SortArrowState createState() => _SortArrowState(); } class _SortArrowState extends State<_SortArrow> with TickerProviderStateMixin { - AnimationController _opacityController; - Animation _opacityAnimation; + AnimationController? _opacityController; + Animation? _opacityAnimation; - AnimationController _orientationController; - Animation _orientationAnimation; + AnimationController? _orientationController; + Animation? _orientationAnimation; double _orientationOffset = 0.0; - bool _down; + bool? _down; static final Animatable _turnTween = Tween(begin: 0.0, end: math.pi) @@ -839,15 +847,16 @@ class _SortArrowState extends State<_SortArrow> with TickerProviderStateMixin { ), curve: Curves.fastOutSlowIn, )..addListener(_rebuild); - _opacityController.value = widget.visible ? 1.0 : 0.0; + _opacityController!.value = (widget.visible ?? false) ? 1.0 : 0.0; _orientationController = AnimationController( duration: widget.duration, vsync: this, ); - _orientationAnimation = _orientationController.drive(_turnTween) + _orientationAnimation = _orientationController!.drive(_turnTween) ..addListener(_rebuild) ..addStatusListener(_resetOrientationAnimation); - if (widget.visible) _orientationOffset = widget.down ? 0.0 : math.pi; + if (widget.visible ?? false) + _orientationOffset = (widget.down ?? false) ? 0.0 : math.pi; } void _rebuild() { @@ -858,9 +867,9 @@ class _SortArrowState extends State<_SortArrow> with TickerProviderStateMixin { void _resetOrientationAnimation(AnimationStatus status) { if (status == AnimationStatus.completed) { - assert(_orientationAnimation.value == math.pi); + assert(_orientationAnimation!.value == math.pi); _orientationOffset += math.pi; - _orientationController.value = + _orientationController!.value = 0.0; // TODO(ianh): This triggers a pointless rebuild. } } @@ -869,26 +878,26 @@ class _SortArrowState extends State<_SortArrow> with TickerProviderStateMixin { void didUpdateWidget(_SortArrow oldWidget) { super.didUpdateWidget(oldWidget); bool skipArrow = false; - final bool newDown = widget.down ?? _down; + final bool newDown = widget.down ?? _down!; if (oldWidget.visible != widget.visible) { - if (widget.visible && - (_opacityController.status == AnimationStatus.dismissed)) { - _orientationController.stop(); - _orientationController.value = 0.0; + if (widget.visible! && + (_opacityController!.status == AnimationStatus.dismissed)) { + _orientationController!.stop(); + _orientationController!.value = 0.0; _orientationOffset = newDown ? 0.0 : math.pi; skipArrow = true; } - if (widget.visible) { - _opacityController.forward(); + if ((widget.visible ?? false)) { + _opacityController!.forward(); } else { - _opacityController.reverse(); + _opacityController!.reverse(); } } if ((_down != newDown) && !skipArrow) { - if (_orientationController.status == AnimationStatus.dismissed) { - _orientationController.forward(); + if (_orientationController!.status == AnimationStatus.dismissed) { + _orientationController?.forward(); } else { - _orientationController.reverse(); + _orientationController?.reverse(); } } _down = newDown; @@ -896,8 +905,8 @@ class _SortArrowState extends State<_SortArrow> with TickerProviderStateMixin { @override void dispose() { - _opacityController.dispose(); - _orientationController.dispose(); + _opacityController?.dispose(); + _orientationController?.dispose(); super.dispose(); } @@ -907,10 +916,10 @@ class _SortArrowState extends State<_SortArrow> with TickerProviderStateMixin { @override Widget build(BuildContext context) { return Opacity( - opacity: _opacityAnimation.value, + opacity: _opacityAnimation!.value, child: Transform( transform: - Matrix4.rotationZ(_orientationOffset + _orientationAnimation.value) + Matrix4.rotationZ(_orientationOffset + _orientationAnimation!.value) ..setTranslationRaw(0.0, _arrowIconBaselineOffset, 0.0), alignment: Alignment.center, child: Icon( From 60160ba62ce04b30db28598504f973c2b7ba3d06 Mon Sep 17 00:00:00 2001 From: phyothandar Date: Fri, 10 Sep 2021 17:43:22 +0630 Subject: [PATCH 3/4] null safety --- lib/pages/main/home_page.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/main/home_page.dart b/lib/pages/main/home_page.dart index 1f81ac0..1e1b88d 100644 --- a/lib/pages/main/home_page.dart +++ b/lib/pages/main/home_page.dart @@ -533,7 +533,7 @@ class _HomePageState extends State { String term = _searchCtl.text; if (term == null || term.trim() == "") return; var packageModel = Provider.of(context, listen: false); - Package package = await packageModel.lookupPackage(term); + Package? package = await packageModel.lookupPackage(term); if (package == null) { showMsgDialog(context, "Not found", "Tracking ID - '$term' not found!"); return; From a4d3777e8a7cff38cad564358bc96f1f8c53782d Mon Sep 17 00:00:00 2001 From: sainw Date: Sat, 11 Sep 2021 08:27:27 +0630 Subject: [PATCH 4/4] fix msg --- .metadata | 2 +- README.md | 14 +++ android/.gitignore | 4 + android/.project | 17 --- .../org.eclipse.buildship.core.prefs | 13 -- android/app/.classpath | 6 - android/app/.project | 23 ---- .../org.eclipse.buildship.core.prefs | 2 - android/app/build.gradle | 28 +---- android/app/src/debug/AndroidManifest.xml | 2 +- android/app/src/main/AndroidManifest.xml | 54 ++++---- .../java/com/mokkon/fcs/fcs/MainActivity.java | 6 + .../com/mokkon/fcs_dev/fcs/Application.java | 20 --- .../com/mokkon/fcs_dev/fcs/MainActivity.java | 13 -- .../res/drawable-v21/launch_background.xml | 12 ++ .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 8760 -> 544 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 4526 -> 442 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 12725 -> 721 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 24893 -> 1031 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 37342 -> 1443 bytes .../app/src/main/res/values-night/styles.xml | 18 +++ android/app/src/main/res/values/strings.xml | 4 - android/app/src/main/res/values/styles.xml | 8 +- android/app/src/profile/AndroidManifest.xml | 2 +- android/build.gradle | 9 +- android/gradle.properties | 1 - .../gradle/wrapper/gradle-wrapper.properties | 2 +- android/proguard-rules.pro | 7 -- android/settings.gradle | 18 ++- android/settings_aar.gradle | 1 - lib/data/provider/messaging_fcm.dart | 74 ++++++----- lib/data/services/messaging_imp.dart | 6 +- lib/main-dev.dart | 4 + lib/main.dart | 113 +++++++++++++++++ lib/pages/chat/message_detail.dart | 4 +- lib/pages/term/term_edit.dart | 115 ++++++++--------- lib/pages/term/term_page.dart | 78 ++++++------ linux/.gitignore | 1 + linux/CMakeLists.txt | 116 ++++++++++++++++++ linux/flutter/CMakeLists.txt | 87 +++++++++++++ linux/flutter/generated_plugin_registrant.cc | 13 ++ linux/flutter/generated_plugin_registrant.h | 13 ++ linux/flutter/generated_plugins.cmake | 16 +++ linux/main.cc | 6 + linux/my_application.cc | 105 ++++++++++++++++ linux/my_application.h | 18 +++ pubspec.lock | 61 ++++++--- pubspec.yaml | 11 +- test/rate_test.dart | 33 ----- test/widget_test.dart | 30 +++++ web/favicon.png | Bin 0 -> 917 bytes web/icons/Icon-192.png | Bin 0 -> 5292 bytes web/icons/Icon-512.png | Bin 0 -> 8252 bytes web/index.html | 98 +++++++++++++++ web/manifest.json | 23 ++++ 55 files changed, 929 insertions(+), 382 deletions(-) delete mode 100644 android/.project delete mode 100644 android/.settings/org.eclipse.buildship.core.prefs delete mode 100644 android/app/.classpath delete mode 100644 android/app/.project delete mode 100644 android/app/.settings/org.eclipse.buildship.core.prefs create mode 100644 android/app/src/main/java/com/mokkon/fcs/fcs/MainActivity.java delete mode 100644 android/app/src/main/java/com/mokkon/fcs_dev/fcs/Application.java delete mode 100644 android/app/src/main/java/com/mokkon/fcs_dev/fcs/MainActivity.java create mode 100644 android/app/src/main/res/drawable-v21/launch_background.xml create mode 100644 android/app/src/main/res/values-night/styles.xml delete mode 100644 android/app/src/main/res/values/strings.xml delete mode 100644 android/proguard-rules.pro delete mode 100644 android/settings_aar.gradle create mode 100644 lib/main.dart create mode 100644 linux/.gitignore create mode 100644 linux/CMakeLists.txt create mode 100644 linux/flutter/CMakeLists.txt create mode 100644 linux/flutter/generated_plugin_registrant.cc create mode 100644 linux/flutter/generated_plugin_registrant.h create mode 100644 linux/flutter/generated_plugins.cmake create mode 100644 linux/main.cc create mode 100644 linux/my_application.cc create mode 100644 linux/my_application.h delete mode 100644 test/rate_test.dart create mode 100644 test/widget_test.dart create mode 100644 web/favicon.png create mode 100644 web/icons/Icon-192.png create mode 100644 web/icons/Icon-512.png create mode 100644 web/index.html create mode 100644 web/manifest.json diff --git a/.metadata b/.metadata index 6ac2303..56bfc2c 100644 --- a/.metadata +++ b/.metadata @@ -4,7 +4,7 @@ # This file should be version controlled and should not be manually edited. version: - revision: f7a6a7906be96d2288f5d63a5a54c515a6e987fe + revision: f4abaa0735eba4dfd8f33f73363911d63931fe03 channel: stable project_type: app diff --git a/README.md b/README.md index 8d57857..cc8b706 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,16 @@ # fcs +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/android/.gitignore b/android/.gitignore index bc2100d..0a741cb 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -5,3 +5,7 @@ gradle-wrapper.jar /gradlew.bat /local.properties GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties diff --git a/android/.project b/android/.project deleted file mode 100644 index 3964dd3..0000000 --- a/android/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - android - Project android created by Buildship. - - - - - org.eclipse.buildship.core.gradleprojectbuilder - - - - - - org.eclipse.buildship.core.gradleprojectnature - - diff --git a/android/.settings/org.eclipse.buildship.core.prefs b/android/.settings/org.eclipse.buildship.core.prefs deleted file mode 100644 index d19d611..0000000 --- a/android/.settings/org.eclipse.buildship.core.prefs +++ /dev/null @@ -1,13 +0,0 @@ -arguments= -auto.sync=false -build.scans.enabled=false -connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER) -connection.project.dir= -eclipse.preferences.version=1 -gradle.user.home= -java.home=/usr/lib/jvm/java-8-openjdk-amd64 -jvm.arguments= -offline.mode=false -override.workspace.settings=true -show.console.view=true -show.executions.view=true diff --git a/android/app/.classpath b/android/app/.classpath deleted file mode 100644 index eb19361..0000000 --- a/android/app/.classpath +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/android/app/.project b/android/app/.project deleted file mode 100644 index ac485d7..0000000 --- a/android/app/.project +++ /dev/null @@ -1,23 +0,0 @@ - - - app - Project app created by Buildship. - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.buildship.core.gradleprojectbuilder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.buildship.core.gradleprojectnature - - diff --git a/android/app/.settings/org.eclipse.buildship.core.prefs b/android/app/.settings/org.eclipse.buildship.core.prefs deleted file mode 100644 index b1886ad..0000000 --- a/android/app/.settings/org.eclipse.buildship.core.prefs +++ /dev/null @@ -1,2 +0,0 @@ -connection.project.dir=.. -eclipse.preferences.version=1 diff --git a/android/app/build.gradle b/android/app/build.gradle index 5492e81..0e9c8c7 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -24,26 +24,17 @@ if (flutterVersionName == null) { apply plugin: 'com.android.application' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" -def keystoreProperties = new Properties() -def keystorePropertiesFile = rootProject.file('key.properties') -if (keystorePropertiesFile.exists()) { - keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) -} - android { - compileSdkVersion 28 - - lintOptions { - disable 'InvalidPackage' - } + compileSdkVersion 30 defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.mokkon.fcs.fcs" minSdkVersion 21 - targetSdkVersion 28 + targetSdkVersion 30 versionCode flutterVersionCode.toInteger() versionName flutterVersionName multiDexEnabled true - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } @@ -92,17 +83,8 @@ flutter { source '../..' } -apply plugin: 'kotlin-android' - dependencies { - testImplementation 'junit:junit:4.12' - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' - implementation 'com.android.support:multidex:1.0.3' - implementation 'com.google.firebase:firebase-analytics:17.5.0' - implementation 'com.google.firebase:firebase-auth:19.0.0' - implementation 'com.google.firebase:firebase-messaging:20.1.0' - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'com.android.support:multidex:1.0.3' } apply plugin: 'com.google.gms.google-services' diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml index 64c388e..e5bd26c 100644 --- a/android/app/src/debug/AndroidManifest.xml +++ b/android/app/src/debug/AndroidManifest.xml @@ -1,5 +1,5 @@ + package="com.mokkon.fcs.fcs"> diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index e32dd3b..890efd6 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,43 +1,41 @@ - - - - - - - - + package="com.mokkon.fcs.fcs"> + - + + android:name="io.flutter.embedding.android.NormalTheme" + android:resource="@style/NormalTheme" + /> + + - - - - + + diff --git a/android/app/src/main/java/com/mokkon/fcs/fcs/MainActivity.java b/android/app/src/main/java/com/mokkon/fcs/fcs/MainActivity.java new file mode 100644 index 0000000..2069e10 --- /dev/null +++ b/android/app/src/main/java/com/mokkon/fcs/fcs/MainActivity.java @@ -0,0 +1,6 @@ +package com.mokkon.fcs.fcs; + +import io.flutter.embedding.android.FlutterActivity; + +public class MainActivity extends FlutterActivity { +} diff --git a/android/app/src/main/java/com/mokkon/fcs_dev/fcs/Application.java b/android/app/src/main/java/com/mokkon/fcs_dev/fcs/Application.java deleted file mode 100644 index 1fe18f1..0000000 --- a/android/app/src/main/java/com/mokkon/fcs_dev/fcs/Application.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.mokkon.fcs_dev.fcs; - - import io.flutter.app.FlutterApplication; - import io.flutter.plugin.common.PluginRegistry; - import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback; - import io.flutter.plugins.GeneratedPluginRegistrant; - import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService; - - public class Application extends FlutterApplication implements PluginRegistrantCallback { - @Override - public void onCreate() { - super.onCreate(); - FlutterFirebaseMessagingService.setPluginRegistrant(this); - } - - @Override - public void registerWith(PluginRegistry registry) { - GeneratedPluginRegistrant.registerWith(registry); - } - } diff --git a/android/app/src/main/java/com/mokkon/fcs_dev/fcs/MainActivity.java b/android/app/src/main/java/com/mokkon/fcs_dev/fcs/MainActivity.java deleted file mode 100644 index 4a8f859..0000000 --- a/android/app/src/main/java/com/mokkon/fcs_dev/fcs/MainActivity.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.mokkon.fcs_dev.fcs; - -import android.os.Bundle; -import io.flutter.app.FlutterActivity; -import io.flutter.plugins.GeneratedPluginRegistrant; - -public class MainActivity extends FlutterActivity { - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - GeneratedPluginRegistrant.registerWith(this); - } -} diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index b1da307024d4284d35e3338baa7cc1e53478783f..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 100644 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ literal 8760 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 i|E2T(<)D;a{Qm=D62>s#@Z*gD0000i*pfB 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 diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index a8316e64426d91b1b272cf6395da897fa814adca..09d4391482be68e9e4a07fab769b5de337d16eb1 100644 GIT binary patch literal 721 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD3?#3*wSy!iOI#yLg7ec#$`gxH85~pclTsBt za}(23gHjVyDhp4h+5i=O3-AeX1=1l$e`s#|#^}+&7(N@w0CIr{$Oe+Uk^K-ZP~83C zcc@hG6rikF&NPT(23>y!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ literal 12725 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 diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index 2b859873f7466adf291ec381116ed3c0418d1e4a..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c 100644 GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof literal 24893 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 A-v9sr diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 7e0c4477905b9e7186f85a265f234a8454bee76c..4d6372eebdb28e45604e46eeda8dd24651419bc0 100644 GIT binary patch literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` literal 37342 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 aYyAJ7hUq3hT)cY#0000 + + + + + + diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml deleted file mode 100644 index 0a46b50..0000000 --- a/android/app/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - FCS - diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index 1f83a33..d74aa35 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -1,7 +1,7 @@ - - diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml index 64c388e..e5bd26c 100644 --- a/android/app/src/profile/AndroidManifest.xml +++ b/android/app/src/profile/AndroidManifest.xml @@ -1,5 +1,5 @@ + package="com.mokkon.fcs.fcs"> diff --git a/android/build.gradle b/android/build.gradle index b2c3f03..9070705 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,15 +1,12 @@ buildscript { - ext.kotlin_version = '1.3.61' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.3' - classpath 'com.google.gms:google-services:4.3.3' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.12' //add this line + classpath 'com.android.tools.build:gradle:4.1.0' + classpath 'com.google.gms:google-services:4.3.8' } } @@ -23,8 +20,6 @@ allprojects { rootProject.buildDir = '../build' subprojects { project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { project.evaluationDependsOn(':app') } diff --git a/android/gradle.properties b/android/gradle.properties index 38c8d45..94adc3a 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,4 +1,3 @@ org.gradle.jvmargs=-Xmx1536M -android.enableR8=true android.useAndroidX=true android.enableJetifier=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 296b146..bc6a58a 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip diff --git a/android/proguard-rules.pro b/android/proguard-rules.pro deleted file mode 100644 index 70885bd..0000000 --- a/android/proguard-rules.pro +++ /dev/null @@ -1,7 +0,0 @@ -## Flutter wrapper --keep class io.flutter.app.** { *; } --keep class io.flutter.plugin.** { *; } --keep class io.flutter.util.** { *; } --keep class io.flutter.view.** { *; } --keep class io.flutter.** { *; } --keep class io.flutter.plugins.** { *; } \ No newline at end of file diff --git a/android/settings.gradle b/android/settings.gradle index 5a2f14f..44e62bc 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,15 +1,11 @@ include ':app' -def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() -def plugins = new Properties() -def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') -if (pluginsFile.exists()) { - pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } -} +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } -plugins.each { name, path -> - def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() - include ":$name" - project(":$name").projectDir = pluginDirectory -} +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/android/settings_aar.gradle b/android/settings_aar.gradle deleted file mode 100644 index e7b4def..0000000 --- a/android/settings_aar.gradle +++ /dev/null @@ -1 +0,0 @@ -include ':app' diff --git a/lib/data/provider/messaging_fcm.dart b/lib/data/provider/messaging_fcm.dart index a184004..c008ecd 100644 --- a/lib/data/provider/messaging_fcm.dart +++ b/lib/data/provider/messaging_fcm.dart @@ -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 backgroundMessageHandler(Map 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 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 message) async { - log.info("onMessage: $message"); - if (onMessage != null) _onNotify(message, onMessage); - }, - onBackgroundMessage: Platform.isIOS ? null : backgroundMessageHandler, - onLaunch: (Map message) async { - log.info("onLaunch: $message"); - if (onLaunch != null) _onNotify(message, onLaunch); - }, - onResume: (Map 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 subscribeToTopic(String topic) { diff --git a/lib/data/services/messaging_imp.dart b/lib/data/services/messaging_imp.dart index ceb6e57..9b41260 100644 --- a/lib/data/services/messaging_imp.dart +++ b/lib/data/services/messaging_imp.dart @@ -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, diff --git a/lib/main-dev.dart b/lib/main-dev.dart index 7ad6513..8964b01 100644 --- a/lib/main-dev.dart +++ b/lib/main-dev.dart @@ -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, diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..b9bfc38 --- /dev/null +++ b/lib/main.dart @@ -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 { + 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: [ + 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. + ); + } +} diff --git a/lib/pages/chat/message_detail.dart b/lib/pages/chat/message_detail.dart index d1b7144..74d352d 100644 --- a/lib/pages/chat/message_detail.dart +++ b/lib/pages/chat/message_detail.dart @@ -180,7 +180,7 @@ class MessageDetail extends StatelessWidget { message.messageID != "") { PackageModel packageModel = Provider.of(context, listen: false); - Package p = await packageModel.getPackage(message.messageID!); + Package? p = await packageModel.getPackage(message.messageID!); if (p == null) return; Navigator.push(context, CupertinoPageRoute(builder: (context) => PackageInfo(package: p))); @@ -206,7 +206,7 @@ class MessageDetail extends StatelessWidget { message.messageID != "") { ShipmentModel shipmentModel = Provider.of(context, listen: false); - Shipment s = await shipmentModel.getShipment(message.messageID!); + Shipment? s = await shipmentModel.getShipment(message.messageID!); if (s == null) return; await Navigator.push( context, diff --git a/lib/pages/term/term_edit.dart b/lib/pages/term/term_edit.dart index 2a5c188..48d11e7 100644 --- a/lib/pages/term/term_edit.dart +++ b/lib/pages/term/term_edit.dart @@ -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 { /// 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 { _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 { 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 { ); } - 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 { _isLoading = true; }); try { - final contentsEng = jsonEncode(_controllerEng.document); - final contentsMm = jsonEncode(_controllerMm.document); - print('contents => $contentsEng'); - TermModel termModel = Provider.of(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(context, listen: false); + // await termModel.saveTerm(Term(termEng: contentsEng, termMm: contentsMm)); } catch (e) { showMsgDialog(context, "Error", e.toString()); } finally { diff --git a/lib/pages/term/term_page.dart b/lib/pages/term/term_page.dart index b8913b3..ee765c8 100644 --- a/lib/pages/term/term_page.dart +++ b/lib/pages/term/term_page.dart @@ -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 { - 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(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(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(context).setting; + Setting? setting = Provider.of(context).setting; bool isEditable = context.select((MainModel m) => m.termEditable()); return Scaffold( @@ -76,7 +76,7 @@ class _TermPageState extends State { onPressed: () => Navigator.of(context).push(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 { ] : [], ), - 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, + // ), + // )), ); } } diff --git a/linux/.gitignore b/linux/.gitignore new file mode 100644 index 0000000..d3896c9 --- /dev/null +++ b/linux/.gitignore @@ -0,0 +1 @@ +flutter/ephemeral diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt new file mode 100644 index 0000000..b2eaaba --- /dev/null +++ b/linux/CMakeLists.txt @@ -0,0 +1,116 @@ +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +set(BINARY_NAME "fcs") +set(APPLICATION_ID "com.mokkon.fcs.fcs") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Root filesystem for cross-building. +if(FLUTTER_TARGET_PLATFORM_SYSROOT) + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endif() + +# Configure build options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Application build +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) +apply_standard_settings(${BINARY_NAME}) +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) +add_dependencies(${BINARY_NAME} flutter_assemble) +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/linux/flutter/CMakeLists.txt b/linux/flutter/CMakeLists.txt new file mode 100644 index 0000000..33fd580 --- /dev/null +++ b/linux/flutter/CMakeLists.txt @@ -0,0 +1,87 @@ +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000..026851f --- /dev/null +++ b/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,13 @@ +// +// Generated file. Do not edit. +// + +#include "generated_plugin_registrant.h" + +#include + +void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); +} diff --git a/linux/flutter/generated_plugin_registrant.h b/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..9bf7478 --- /dev/null +++ b/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,13 @@ +// +// Generated file. Do not edit. +// + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake new file mode 100644 index 0000000..1fc8ed3 --- /dev/null +++ b/linux/flutter/generated_plugins.cmake @@ -0,0 +1,16 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + url_launcher_linux +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) diff --git a/linux/main.cc b/linux/main.cc new file mode 100644 index 0000000..e7c5c54 --- /dev/null +++ b/linux/main.cc @@ -0,0 +1,6 @@ +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/linux/my_application.cc b/linux/my_application.cc new file mode 100644 index 0000000..a2cc618 --- /dev/null +++ b/linux/my_application.cc @@ -0,0 +1,105 @@ +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen *screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "fcs"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } + else { + gtk_window_set_title(window, "fcs"); + } + + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, gchar ***arguments, int *exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject *object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, + "flags", G_APPLICATION_NON_UNIQUE, + nullptr)); +} diff --git a/linux/my_application.h b/linux/my_application.h new file mode 100644 index 0000000..72271d5 --- /dev/null +++ b/linux/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/pubspec.lock b/pubspec.lock index 2901b05..c317df9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -70,7 +70,7 @@ packages: name: camera url: "https://pub.dartlang.org" source: hosted - version: "0.9.0" + version: "0.9.2+2" camera_platform_interface: dependency: transitive description: @@ -196,7 +196,7 @@ packages: name: cross_file url: "https://pub.dartlang.org" source: hosted - version: "0.3.1+4" + version: "0.3.1+5" crypto: dependency: transitive description: @@ -259,21 +259,21 @@ packages: name: firebase_auth url: "https://pub.dartlang.org" source: hosted - version: "3.0.2" + version: "3.1.1" firebase_auth_platform_interface: dependency: transitive description: name: firebase_auth_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "6.0.1" + version: "6.1.0" firebase_auth_web: dependency: transitive description: name: firebase_auth_web url: "https://pub.dartlang.org" source: hosted - version: "3.0.1" + version: "3.1.0" firebase_core: dependency: "direct main" description: @@ -295,27 +295,48 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.0" + firebase_messaging: + dependency: "direct main" + description: + name: firebase_messaging + url: "https://pub.dartlang.org" + source: hosted + version: "10.0.7" + firebase_messaging_platform_interface: + dependency: transitive + description: + name: firebase_messaging_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.5" + firebase_messaging_web: + dependency: transitive + description: + name: firebase_messaging_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.5" firebase_storage: dependency: "direct main" description: name: firebase_storage url: "https://pub.dartlang.org" source: hosted - version: "10.0.2" + version: "10.0.3" firebase_storage_platform_interface: dependency: transitive description: name: firebase_storage_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "4.0.1" + version: "4.0.2" firebase_storage_web: dependency: transitive description: name: firebase_storage_web url: "https://pub.dartlang.org" source: hosted - version: "3.0.1" + version: "3.0.2" fixnum: dependency: transitive description: @@ -388,7 +409,7 @@ packages: name: flutter_plugin_android_lifecycle url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "2.0.3" flutter_test: dependency: "direct dev" description: flutter @@ -454,7 +475,7 @@ packages: name: image_picker url: "https://pub.dartlang.org" source: hosted - version: "0.8.3+3" + version: "0.8.4" image_picker_for_web: dependency: transitive description: @@ -468,7 +489,7 @@ packages: name: image_picker_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.3.0" + version: "2.4.1" intl: dependency: "direct main" description: @@ -573,7 +594,7 @@ packages: name: path_provider url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "2.0.3" path_provider_linux: dependency: transitive description: @@ -615,7 +636,7 @@ packages: name: permission_handler url: "https://pub.dartlang.org" source: hosted - version: "8.1.4+2" + version: "8.1.6" permission_handler_platform_interface: dependency: transitive description: @@ -706,7 +727,7 @@ packages: name: rxdart url: "https://pub.dartlang.org" source: hosted - version: "0.27.1" + version: "0.27.2" share: dependency: "direct main" description: @@ -823,7 +844,7 @@ packages: name: sqflite_common url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "2.0.1+1" stack_trace: dependency: transitive description: @@ -893,7 +914,7 @@ packages: name: timeline_list url: "https://pub.dartlang.org" source: hosted - version: "0.0.5" + version: "0.0.6" timezone: dependency: transitive description: @@ -921,21 +942,21 @@ packages: name: url_launcher url: "https://pub.dartlang.org" source: hosted - version: "6.0.9" + version: "6.0.10" url_launcher_linux: dependency: transitive description: name: url_launcher_linux url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "2.0.2" url_launcher_macos: dependency: transitive description: name: url_launcher_macos url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "2.0.2" url_launcher_platform_interface: dependency: transitive description: @@ -1005,7 +1026,7 @@ packages: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "2.2.6" + version: "2.2.9" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index e60aa6c..260c466 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,11 +13,11 @@ dependencies: sdk: flutter cupertino_icons: ^1.0.3 - firebase_core: ^1.5.0 + firebase_core: ^1.6.0 cloud_firestore: ^2.5.2 - firebase_storage: ^10.0.2 - firebase_auth: "^3.0.2" - # firebase_messaging: ^6.0.15 + firebase_storage: ^10.0.3 + firebase_auth: ^3.1.1 + firebase_messaging: ^10.0.7 provider: ^6.0.0 image_picker: ^0.8.3+3 @@ -72,5 +72,4 @@ flutter: - family: Myanmar3 fonts: - - asset: assets/fonts/Myanmar3_2018.ttf - + - asset: assets/fonts/Myanmar3_2018.ttf \ No newline at end of file diff --git a/test/rate_test.dart b/test/rate_test.dart deleted file mode 100644 index a373e2c..0000000 --- a/test/rate_test.dart +++ /dev/null @@ -1,33 +0,0 @@ -import 'package:fcs/domain/entities/cargo_type.dart'; -import 'package:fcs/domain/entities/carton.dart'; -import 'package:fcs/domain/entities/discount_by_weight.dart'; -import 'package:fcs/domain/entities/rate.dart'; -import 'package:test/test.dart'; - -@TestOn('vm') -void main() { - var rate = Rate(); - rate.discountByWeights = [ - DiscountByWeight(weight: 25, discount: 0.25), - DiscountByWeight(weight: 50, discount: 0.5), - ]; - rate.volumetricRatio = 166.36; - rate.diffDiscountWeight = 5; - rate.diffWeightRate = 1.5; - - test('Calculate carton price 1', () { - var ct = CargoType(name: "General", weight: 10, rate: 6); - var carton = Carton(cargoTypes: [ct], length: 15, width: 15, height: 15); - expect(carton.calAmount(rate), equals(67.50)); - }); - test('Calculate carton price 2', () { - var ct = CargoType(name: "General", weight: 10, rate: 6); - var carton = Carton(cargoTypes: [ct], length: 10, width: 10, height: 10); - expect(carton.calAmount(rate), equals(60)); - }); - test('Calculate carton price 3', () { - var ct = CargoType(name: "General", weight: 10, rate: 6); - var carton = Carton(cargoTypes: [ct], length: 15, width: 15, height: 10); - expect(carton.calAmount(rate), equals(60)); - }); -} diff --git a/test/widget_test.dart b/test/widget_test.dart new file mode 100644 index 0000000..6eea97d --- /dev/null +++ b/test/widget_test.dart @@ -0,0 +1,30 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:fcs/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(MyApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +} diff --git a/web/favicon.png b/web/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..8aaa46ac1ae21512746f852a42ba87e4165dfdd1 GIT binary patch literal 917 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|I14-?iy0X7 zltGxWVyS%@P(fs7NJL45ua8x7ey(0(N`6wRUPW#JP&EUCO@$SZnVVXYs8ErclUHn2 zVXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO|i&7O#^-S~(l1AfjnEK zjFOT9D}DX)@^Za$W4-*MbbUihOG|wNBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o z3raHc^AtelCMM;Vme?vOfh>Xph&xL%(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjo zGZknv$b36P8?Z_gF{nK@`XI}Z90TzwSQO}0J1!f2c(B=V`5aP@1P1a|PZ!4!3&Gl8 zTYqUsf!gYFyJnXpu0!n&N*SYAX-%d(5gVjrHJWqXQshj@!Zm{!01WsQrH~9=kTxW#6SvuapgMqt>$=j#%eyGrQzr zP{L-3gsMA^$I1&gsBAEL+vxi1*Igl=8#8`5?A-T5=z-sk46WA1IUT)AIZHx1rdUrf zVJrJn<74DDw`j)Ki#gt}mIT-Q`XRa2-jQXQoI%w`nb|XblvzK${ZzlV)m-XcwC(od z71_OEC5Bt9GEXosOXaPTYOia#R4ID2TiU~`zVMl08TV_C%DnU4^+HE>9(CE4D6?Fz oujB08i7adh9xk7*FX66dWH6F5TM;?E2b5PlUHx3vIVCg!0Dx9vYXATM literal 0 HcmV?d00001 diff --git a/web/icons/Icon-192.png b/web/icons/Icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..b749bfef07473333cf1dd31e9eed89862a5d52aa GIT binary patch literal 5292 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 literal 0 HcmV?d00001 diff --git a/web/icons/Icon-512.png b/web/icons/Icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..88cfd48dff1169879ba46840804b412fe02fefd6 GIT binary patch literal 8252 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 literal 0 HcmV?d00001 diff --git a/web/index.html b/web/index.html new file mode 100644 index 0000000..8387474 --- /dev/null +++ b/web/index.html @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + fcs + + + + + + + diff --git a/web/manifest.json b/web/manifest.json new file mode 100644 index 0000000..9f0d80b --- /dev/null +++ b/web/manifest.json @@ -0,0 +1,23 @@ +{ + "name": "fcs", + "short_name": "fcs", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +}