Merge remote-tracking branch 'tzw/master'
This commit is contained in:
@@ -9,7 +9,7 @@ List<Day> dayLists = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
class Setting {
|
class Setting {
|
||||||
final int? supportBuildNum;
|
final int supportBuildNum;
|
||||||
// contact page
|
// contact page
|
||||||
String? usaAddress;
|
String? usaAddress;
|
||||||
String? mmAddress;
|
String? mmAddress;
|
||||||
@@ -27,7 +27,7 @@ class Setting {
|
|||||||
List<String> shipmentTypes;
|
List<String> shipmentTypes;
|
||||||
|
|
||||||
Setting(
|
Setting(
|
||||||
{this.supportBuildNum,
|
{this.supportBuildNum = 1,
|
||||||
this.usaAddress,
|
this.usaAddress,
|
||||||
this.mmAddress,
|
this.mmAddress,
|
||||||
this.usaContactNumber,
|
this.usaContactNumber,
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ class User {
|
|||||||
String? fcsID;
|
String? fcsID;
|
||||||
DateTime? lastMessageTime;
|
DateTime? lastMessageTime;
|
||||||
String? lastMessage;
|
String? lastMessage;
|
||||||
int? userUnseenCount;
|
int userUnseenCount;
|
||||||
int? fcsUnseenCount;
|
int fcsUnseenCount;
|
||||||
String? preferCurrency;
|
String? preferCurrency;
|
||||||
|
|
||||||
String get initial =>
|
String get initial =>
|
||||||
@@ -42,12 +42,12 @@ class User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String get getUserUnseenCount => userUnseenCount != null
|
String get getUserUnseenCount => userUnseenCount != null
|
||||||
? userUnseenCount! > 100
|
? userUnseenCount > 100
|
||||||
? "99+"
|
? "99+"
|
||||||
: userUnseenCount.toString()
|
: userUnseenCount.toString()
|
||||||
: "0";
|
: "0";
|
||||||
String get getFcsUnseenCount => fcsUnseenCount != null
|
String get getFcsUnseenCount => fcsUnseenCount != null
|
||||||
? fcsUnseenCount! > 100
|
? fcsUnseenCount > 100
|
||||||
? "99+"
|
? "99+"
|
||||||
: fcsUnseenCount.toString()
|
: fcsUnseenCount.toString()
|
||||||
: "0";
|
: "0";
|
||||||
@@ -72,8 +72,8 @@ class User {
|
|||||||
this.privileges = const [],
|
this.privileges = const [],
|
||||||
this.lastMessage,
|
this.lastMessage,
|
||||||
this.lastMessageTime,
|
this.lastMessageTime,
|
||||||
this.userUnseenCount,
|
this.userUnseenCount = 0,
|
||||||
this.fcsUnseenCount,
|
this.fcsUnseenCount = 0,
|
||||||
this.preferCurrency});
|
this.preferCurrency});
|
||||||
|
|
||||||
factory User.fromJson(Map<String, dynamic> json) {
|
factory User.fromJson(Map<String, dynamic> json) {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'package:fcs/helpers/theme.dart';
|
import 'package:fcs/helpers/theme.dart';
|
||||||
import 'package:fcs/pages/main/model/main_model.dart';
|
import 'package:fcs/pages/main/model/main_model.dart';
|
||||||
import 'package:fcs/pages/main/util.dart';
|
|
||||||
import 'package:fcs/pages/widgets/display_text.dart';
|
import 'package:fcs/pages/widgets/display_text.dart';
|
||||||
import 'package:fcs/pages/widgets/fcs_id_icon.dart';
|
import 'package:fcs/pages/widgets/fcs_id_icon.dart';
|
||||||
import 'package:fcs/pages/widgets/local_text.dart';
|
import 'package:fcs/pages/widgets/local_text.dart';
|
||||||
@@ -28,22 +27,22 @@ class _BuyingOnlinePagetate extends State<BuyingOnlinePage>
|
|||||||
MainModel mainModel = Provider.of<MainModel>(context);
|
MainModel mainModel = Provider.of<MainModel>(context);
|
||||||
|
|
||||||
final phoneNumberBox = DisplayText(
|
final phoneNumberBox = DisplayText(
|
||||||
text: mainModel.user.phone,
|
text: mainModel.user?.phone,
|
||||||
labelTextKey: "contact.phone",
|
labelTextKey: "contact.phone",
|
||||||
iconData: Icons.location_on,
|
iconData: Icons.location_on,
|
||||||
);
|
);
|
||||||
final nameBox = Center(
|
final nameBox = Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
mainModel.user.name,
|
mainModel.user?.name ?? "",
|
||||||
style: TextStyle(fontSize: 18, color: primaryColor),
|
style: TextStyle(fontSize: 18, color: primaryColor),
|
||||||
));
|
));
|
||||||
final fcsIdBox = DisplayText(
|
final fcsIdBox = DisplayText(
|
||||||
text: mainModel.user.fcsID,
|
text: mainModel.user?.fcsID,
|
||||||
labelTextKey: "customer.fcs.id",
|
labelTextKey: "customer.fcs.id",
|
||||||
icon: FcsIDIcon(),
|
icon: FcsIDIcon(),
|
||||||
);
|
);
|
||||||
final shippingAddressBox = DisplayText(
|
final shippingAddressBox = DisplayText(
|
||||||
text: mainModel.setting.usaAddress,
|
text: mainModel.setting?.usaAddress,
|
||||||
labelTextKey: "profile.usa.shipping.address",
|
labelTextKey: "profile.usa.shipping.address",
|
||||||
iconData: Icons.location_on,
|
iconData: Icons.location_on,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,9 +3,7 @@ import 'dart:async';
|
|||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
import 'package:fcs/data/services/services.dart';
|
import 'package:fcs/data/services/services.dart';
|
||||||
import 'package:fcs/domain/constants.dart';
|
import 'package:fcs/domain/constants.dart';
|
||||||
import 'package:fcs/domain/entities/cargo_type.dart';
|
|
||||||
import 'package:fcs/domain/entities/carton.dart';
|
import 'package:fcs/domain/entities/carton.dart';
|
||||||
import 'package:fcs/domain/vo/message.dart';
|
|
||||||
import 'package:fcs/domain/vo/shipment_status.dart';
|
import 'package:fcs/domain/vo/shipment_status.dart';
|
||||||
import 'package:fcs/helpers/paginator.dart';
|
import 'package:fcs/helpers/paginator.dart';
|
||||||
import 'package:fcs/pages/main/model/base_model.dart';
|
import 'package:fcs/pages/main/model/base_model.dart';
|
||||||
@@ -14,13 +12,14 @@ import 'package:logging/logging.dart';
|
|||||||
|
|
||||||
class CartonModel extends BaseModel {
|
class CartonModel extends BaseModel {
|
||||||
List<Carton> _boxes = [];
|
List<Carton> _boxes = [];
|
||||||
PaginatorListener cartonsByFilter;
|
PaginatorListener? cartonsByFilter;
|
||||||
|
|
||||||
final log = Logger('CartonModel');
|
final log = Logger('CartonModel');
|
||||||
List<Carton> get boxes =>
|
List<Carton> get boxes => _selectedIndex == 1
|
||||||
_selectedIndex == 1 ? _boxes : List<Carton>.from(_delivered.values);
|
? _boxes
|
||||||
|
: List<Carton>.from(_delivered?.values ?? []);
|
||||||
|
|
||||||
Paginator _delivered;
|
Paginator? _delivered;
|
||||||
int _selectedIndex = 1;
|
int _selectedIndex = 1;
|
||||||
int _selectedIndexFilter = 1;
|
int _selectedIndexFilter = 1;
|
||||||
bool isLoading = false;
|
bool isLoading = false;
|
||||||
@@ -87,17 +86,17 @@ class CartonModel extends BaseModel {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
get selectedIndex => _selectedIndex;
|
int get selectedIndex => _selectedIndex;
|
||||||
get selectedIndexFilter => _selectedIndexFilter;
|
int get selectedIndexFilter => _selectedIndexFilter;
|
||||||
|
|
||||||
initData() async {
|
initData() async {
|
||||||
_selectedIndex = 1;
|
_selectedIndex = 1;
|
||||||
_selectedIndexFilter = 1;
|
_selectedIndexFilter = 1;
|
||||||
_loadBoxes();
|
_loadBoxes();
|
||||||
|
|
||||||
if (_delivered != null) _delivered.close();
|
if (_delivered != null) _delivered!.close();
|
||||||
_delivered = _getDelivered();
|
_delivered = _getDelivered();
|
||||||
_delivered.load();
|
_delivered!.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ class MessageModel extends BaseModel {
|
|||||||
StreamSubscription<QuerySnapshot> listener;
|
StreamSubscription<QuerySnapshot> listener;
|
||||||
|
|
||||||
static const int rowPerLoad = 20;
|
static const int rowPerLoad = 20;
|
||||||
void initQuery(String userID) {
|
void initQuery(String? userID) {
|
||||||
|
if(userID == null)return;
|
||||||
this.messages = [];
|
this.messages = [];
|
||||||
this.userID = userID;
|
this.userID = userID;
|
||||||
this.prevSnap = null;
|
this.prevSnap = null;
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ class CustomerModel extends BaseModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<User> getUser(String id) async {
|
Future<User> getUser(String? id) async {
|
||||||
String path = "/$user_collection";
|
String path = "/$user_collection";
|
||||||
var snap = await Firestore.instance.collection(path).document(id).get();
|
var snap = await Firestore.instance.collection(path).document(id).get();
|
||||||
return User.fromMap(snap.data, snap.documentID);
|
return User.fromMap(snap.data, snap.documentID);
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ class _HomePageState extends State<HomePage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_loadStaffMode(bool isCustomer) async {
|
_loadStaffMode(bool isCustomer) async {
|
||||||
bool staffMode = await SharedPref.getStaffMode();
|
bool? staffMode = await SharedPref.getStaffMode();
|
||||||
setState(() {
|
setState(() {
|
||||||
if (isCustomer) {
|
if (isCustomer) {
|
||||||
isFcs[0] = false;
|
isFcs[0] = false;
|
||||||
@@ -117,12 +117,12 @@ class _HomePageState extends State<HomePage> {
|
|||||||
if (mainModel.isLogin()) {
|
if (mainModel.isLogin()) {
|
||||||
timer.cancel();
|
timer.cancel();
|
||||||
bool isCustomer = mainModel.isCustomer();
|
bool isCustomer = mainModel.isCustomer();
|
||||||
String receiverID = isCustomer ? mainModel.user.id : notiUserID;
|
String? receiverID = isCustomer ? mainModel.user?.id : notiUserID;
|
||||||
String receiverName = isCustomer ? mainModel.user.name : notiUserName;
|
String? receiverName = isCustomer ? mainModel.user?.name : notiUserName;
|
||||||
MessageModel messageModel =
|
MessageModel messageModel =
|
||||||
Provider.of<MessageModel>(context, listen: false);
|
Provider.of<MessageModel>(context, listen: false);
|
||||||
messageModel.initQuery(receiverID);
|
messageModel.initQuery(receiverID);
|
||||||
User user = mainModel.user;
|
User user = mainModel.user!;
|
||||||
if (!isCustomer) {
|
if (!isCustomer) {
|
||||||
CustomerModel customerModel =
|
CustomerModel customerModel =
|
||||||
Provider.of<CustomerModel>(context, listen: false);
|
Provider.of<CustomerModel>(context, listen: false);
|
||||||
@@ -133,15 +133,15 @@ class _HomePageState extends State<HomePage> {
|
|||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => MessageDetail(
|
builder: (context) => MessageDetail(
|
||||||
messageModel: messageModel,
|
messageModel: messageModel,
|
||||||
receiverID: receiverID,
|
receiverID: receiverID ?? "",
|
||||||
receiverName: receiverName,
|
receiverName: receiverName ?? "",
|
||||||
))).then((value) {
|
))).then((value) {
|
||||||
if (user.userUnseenCount > 0) {
|
if (user.userUnseenCount > 0) {
|
||||||
messageModel.seenMessages(user.id, true);
|
messageModel.seenMessages(user.id ?? "", true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (user.userUnseenCount > 0) {
|
if (user.userUnseenCount > 0) {
|
||||||
messageModel.seenMessages(user.id, true);
|
messageModel.seenMessages(user.id ?? "", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,7 +204,7 @@ class _HomePageState extends State<HomePage> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
User user = Provider.of<MainModel>(context).user;
|
User? user = Provider.of<MainModel>(context).user;
|
||||||
|
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
Future.microtask(
|
Future.microtask(
|
||||||
@@ -280,11 +280,11 @@ class _HomePageState extends State<HomePage> {
|
|||||||
))
|
))
|
||||||
.then((value) {
|
.then((value) {
|
||||||
if (user.userUnseenCount > 0) {
|
if (user.userUnseenCount > 0) {
|
||||||
messageModel.seenMessages(user.id, true);
|
messageModel.seenMessages(user.id ?? "", true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (user.userUnseenCount > 0) {
|
if (user.userUnseenCount > 0) {
|
||||||
messageModel.seenMessages(user.id, true);
|
messageModel.seenMessages(user.id ?? "", true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
final notiBtn = badgeCounter(notiBtnOrg, user.userUnseenCount);
|
final notiBtn = badgeCounter(notiBtnOrg, user.userUnseenCount);
|
||||||
|
|||||||
@@ -101,8 +101,8 @@ class _InitialLanguageSelectionPageState
|
|||||||
? BoxDecoration()
|
? BoxDecoration()
|
||||||
: BoxDecoration(
|
: BoxDecoration(
|
||||||
border: Border(
|
border: Border(
|
||||||
bottom:
|
bottom: BorderSide(
|
||||||
BorderSide(color: Colors.grey.shade300),
|
color: Colors.grey.shade300),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
@@ -177,7 +177,7 @@ class _InitialLanguageSelectionPageState
|
|||||||
setState(() {
|
setState(() {
|
||||||
selectedIndex = index;
|
selectedIndex = index;
|
||||||
selectedLanguage = lang;
|
selectedLanguage = lang;
|
||||||
Translation().onLocaleChanged!(Locale(languagesMap[lang]));
|
Translation().onLocaleChanged(Locale(languagesMap[lang]));
|
||||||
Provider.of<LanguageModel>(context, listen: false)
|
Provider.of<LanguageModel>(context, listen: false)
|
||||||
.saveLanguage(selectedLanguage);
|
.saveLanguage(selectedLanguage);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ import 'package:fcs/helpers/api_helper.dart';
|
|||||||
import 'main_model.dart';
|
import 'main_model.dart';
|
||||||
|
|
||||||
abstract class BaseModel extends ChangeNotifier {
|
abstract class BaseModel extends ChangeNotifier {
|
||||||
User user;
|
User? user;
|
||||||
Setting setting;
|
Setting? setting;
|
||||||
MainModel mainModel;
|
MainModel? mainModel;
|
||||||
|
|
||||||
void initUser(User user) async {
|
void initUser(User user) async {
|
||||||
this.user = user;
|
this.user = user;
|
||||||
@@ -16,7 +16,7 @@ abstract class BaseModel extends ChangeNotifier {
|
|||||||
|
|
||||||
void privilegeChanged() {}
|
void privilegeChanged() {}
|
||||||
|
|
||||||
void initSetting(Setting setting) async {
|
void initSetting(Setting? setting) async {
|
||||||
this.setting = setting;
|
this.setting = setting;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,8 +32,8 @@ abstract class BaseModel extends ChangeNotifier {
|
|||||||
String path,
|
String path,
|
||||||
method, {
|
method, {
|
||||||
dynamic payload,
|
dynamic payload,
|
||||||
String token,
|
required String token,
|
||||||
String url,
|
String? url,
|
||||||
}) async {
|
}) async {
|
||||||
return await requestAPI(path, method,
|
return await requestAPI(path, method,
|
||||||
payload: payload, token: token, url: url);
|
payload: payload, token: token, url: url);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import 'package:flutter/painting.dart';
|
|||||||
import 'base_model.dart';
|
import 'base_model.dart';
|
||||||
|
|
||||||
class LanguageModel extends BaseModel {
|
class LanguageModel extends BaseModel {
|
||||||
String language;
|
late String language;
|
||||||
bool get isEng => this.language == "English";
|
bool get isEng => this.language == "English";
|
||||||
List<bool> get currentState => isEng ? [true, false] : [false, true];
|
List<bool> get currentState => isEng ? [true, false] : [false, true];
|
||||||
|
|
||||||
|
|||||||
@@ -15,16 +15,16 @@ class MainModel extends ChangeNotifier {
|
|||||||
final log = Logger('MainModel');
|
final log = Logger('MainModel');
|
||||||
List<BaseModel> models = [];
|
List<BaseModel> models = [];
|
||||||
|
|
||||||
String messagingToken;
|
String? messagingToken;
|
||||||
User user;
|
User? user;
|
||||||
PackageInfo packageInfo;
|
PackageInfo? packageInfo;
|
||||||
|
|
||||||
set setMessaginToken(token) {
|
set setMessaginToken(token) {
|
||||||
this.messagingToken = token;
|
this.messagingToken = token;
|
||||||
uploadMsgToken();
|
uploadMsgToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
Setting setting;
|
Setting? setting;
|
||||||
|
|
||||||
bool isLoaded = false;
|
bool isLoaded = false;
|
||||||
bool isOnline = false;
|
bool isOnline = false;
|
||||||
@@ -42,23 +42,23 @@ class MainModel extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool faqEditable() {
|
bool faqEditable() {
|
||||||
return this.user != null && this.user.hasSupport();
|
return this.user != null && this.user!.hasSupport();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rateEditable() {
|
bool rateEditable() {
|
||||||
return this.user != null && this.user.hasSupport();
|
return this.user != null && this.user!.hasSupport();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool paymentMethodsEditable() {
|
bool paymentMethodsEditable() {
|
||||||
return this.user != null && this.user.hasSupport();
|
return this.user != null && this.user!.hasSupport();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool termEditable() {
|
bool termEditable() {
|
||||||
return this.user != null && this.user.hasSupport();
|
return this.user != null && this.user!.hasSupport();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool contactEditable() {
|
bool contactEditable() {
|
||||||
return this.user != null && this.user.hasSupport();
|
return this.user != null && this.user!.hasSupport();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isLogin() {
|
bool isLogin() {
|
||||||
@@ -66,32 +66,31 @@ class MainModel extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isCustomer() {
|
bool isCustomer() {
|
||||||
return user != null && user.isCustomer();
|
return user != null && user!.isCustomer();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSysAdmin() {
|
bool isSysAdmin() {
|
||||||
return this.user != null && this.user.hasSysAdmin();
|
return this.user != null && this.user!.hasSysAdmin();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isAdmin() {
|
bool isAdmin() {
|
||||||
return this.user != null && this.user.hasAdmin();
|
return this.user != null && this.user!.hasAdmin();
|
||||||
}
|
}
|
||||||
|
|
||||||
// userListener should never be closed
|
// userListener should never be closed
|
||||||
StreamSubscription<User> userListener;
|
StreamSubscription<User?>? userListener;
|
||||||
_init() async {
|
_init() async {
|
||||||
await _listenSetting();
|
await _listenSetting();
|
||||||
this.isFirstLaunch = await SharedPref.isFirstLaunch();
|
this.isFirstLaunch = await SharedPref.isFirstLaunch() ?? true;
|
||||||
this.isFirstLaunch = this.isFirstLaunch ?? true;
|
|
||||||
this.packageInfo = await PackageInfo.fromPlatform();
|
this.packageInfo = await PackageInfo.fromPlatform();
|
||||||
|
|
||||||
if (userListener != null) userListener.cancel();
|
if (userListener != null) userListener!.cancel();
|
||||||
userListener =
|
userListener =
|
||||||
Services.instance.authService.getUserStream().listen((_user) {
|
Services.instance.authService.getUserStream().listen((_user) {
|
||||||
if (_user != null) {
|
if (_user != null) {
|
||||||
models.forEach((m) => m.initUser(_user));
|
models.forEach((m) => m.initUser(_user));
|
||||||
// call diffPrivileges if privilege changed or first time login
|
// call diffPrivileges if privilege changed or first time login
|
||||||
if (this.user == null || _user.diffPrivileges(this.user)) {
|
if (this.user == null || _user.diffPrivileges(this.user!)) {
|
||||||
models.forEach((m) => m.privilegeChanged());
|
models.forEach((m) => m.privilegeChanged());
|
||||||
}
|
}
|
||||||
if (this.user == null) {
|
if (this.user == null) {
|
||||||
@@ -124,7 +123,7 @@ class MainModel extends ChangeNotifier {
|
|||||||
|
|
||||||
bool isSupport() {
|
bool isSupport() {
|
||||||
if (packageInfo == null || setting == null) return false;
|
if (packageInfo == null || setting == null) return false;
|
||||||
return int.parse(packageInfo.buildNumber) >= setting.supportBuildNum;
|
return int.parse(packageInfo!.buildNumber) >= setting!.supportBuildNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<AuthResult> sendSms(String phoneNumber) {
|
Future<AuthResult> sendSms(String phoneNumber) {
|
||||||
@@ -137,14 +136,14 @@ class MainModel extends ChangeNotifier {
|
|||||||
return authResult;
|
return authResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> uploadMsgToken() {
|
Future<void>? uploadMsgToken() {
|
||||||
if (messagingToken == null || user == null) return null;
|
if (messagingToken == null || user == null) return null;
|
||||||
return Services.instance.userService.uploadMsgToken(messagingToken);
|
return Services.instance.userService.uploadMsgToken(messagingToken!);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> removeMsgToken() {
|
Future<void>? removeMsgToken() {
|
||||||
if (messagingToken == null || user == null) return null;
|
if (messagingToken == null || user == null) return null;
|
||||||
return Services.instance.userService.removeMsgToken(messagingToken);
|
return Services.instance.userService.removeMsgToken(messagingToken!);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> signout() async {
|
Future<void> signout() async {
|
||||||
|
|||||||
Reference in New Issue
Block a user