mirror of
https://gitlab.com/comunic/comunicmobile
synced 2024-11-25 14:29:22 +00:00
Can configure push notifications from tour
This commit is contained in:
parent
899270961a
commit
116e6ce66d
@ -1,6 +1,7 @@
|
|||||||
import 'package:comunic/helpers/preferences_helper.dart';
|
import 'package:comunic/helpers/preferences_helper.dart';
|
||||||
import 'package:comunic/helpers/users_helper.dart';
|
import 'package:comunic/helpers/users_helper.dart';
|
||||||
import 'package:comunic/models/user.dart';
|
import 'package:comunic/models/user.dart';
|
||||||
|
import 'package:comunic/ui/routes/push_notifications_route.dart';
|
||||||
import 'package:comunic/ui/routes/settings/account_image_settings.dart';
|
import 'package:comunic/ui/routes/settings/account_image_settings.dart';
|
||||||
import 'package:comunic/ui/widgets/account_image_widget.dart';
|
import 'package:comunic/ui/widgets/account_image_widget.dart';
|
||||||
import 'package:comunic/ui/widgets/async_screen_widget.dart';
|
import 'package:comunic/ui/widgets/async_screen_widget.dart';
|
||||||
@ -25,6 +26,8 @@ class TourRoute extends StatefulWidget {
|
|||||||
|
|
||||||
class _TourRouteState extends State<TourRoute> {
|
class _TourRouteState extends State<TourRoute> {
|
||||||
final key = GlobalKey<AsyncScreenWidgetState>();
|
final key = GlobalKey<AsyncScreenWidgetState>();
|
||||||
|
final _pushNotificationsKey =
|
||||||
|
GlobalKey<PushNotificationsConfigurationWidgetState>();
|
||||||
|
|
||||||
User currUser;
|
User currUser;
|
||||||
|
|
||||||
@ -37,6 +40,8 @@ class _TourRouteState extends State<TourRoute> {
|
|||||||
|
|
||||||
List<Widget> get _list => [
|
List<Widget> get _list => [
|
||||||
_FirstPane(),
|
_FirstPane(),
|
||||||
|
|
||||||
|
// Account image
|
||||||
_PresentationPane(
|
_PresentationPane(
|
||||||
iconWidget: AccountImageWidget(user: currUser, width: 50),
|
iconWidget: AccountImageWidget(user: currUser, width: 50),
|
||||||
title: tr("Account image"),
|
title: tr("Account image"),
|
||||||
@ -49,6 +54,20 @@ class _TourRouteState extends State<TourRoute> {
|
|||||||
await key.currentState.refresh();
|
await key.currentState.refresh();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// Notifications
|
||||||
|
_PresentationPane(
|
||||||
|
icon: Icons.notifications,
|
||||||
|
title: tr("Push notifications"),
|
||||||
|
child: (c) => PushNotificationsConfigurationWidget(
|
||||||
|
key: _pushNotificationsKey,
|
||||||
|
onConfigured: () => setState(() {}),
|
||||||
|
onChanged: () => setState(() {}),
|
||||||
|
),
|
||||||
|
canGoNext: _pushNotificationsKey?.currentState?.canSubmit ?? false,
|
||||||
|
onTapNext: (c) => _pushNotificationsKey.currentState.submit(),
|
||||||
|
),
|
||||||
|
|
||||||
_PresentationPane(
|
_PresentationPane(
|
||||||
icon: Icons.group_add,
|
icon: Icons.group_add,
|
||||||
title: tr("Friends"),
|
title: tr("Friends"),
|
||||||
@ -111,6 +130,13 @@ class __RouteBodyState extends State<_RouteBody> {
|
|||||||
|
|
||||||
bool get _isLastPane => _controller.index >= widget.panes.length - 1;
|
bool get _isLastPane => _controller.index >= widget.panes.length - 1;
|
||||||
|
|
||||||
|
_PresentationPane get _currPane =>
|
||||||
|
widget.panes[_controller.index] is _PresentationPane
|
||||||
|
? widget.panes[_controller.index]
|
||||||
|
: null;
|
||||||
|
|
||||||
|
bool get _canGoNext => _currPane?.canGoNext ?? true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didUpdateWidget(_RouteBody oldWidget) {
|
void didUpdateWidget(_RouteBody oldWidget) {
|
||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
@ -134,12 +160,17 @@ class __RouteBodyState extends State<_RouteBody> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Spacer(flex: 1),
|
Spacer(flex: 1),
|
||||||
Expanded(child: TabBarView(children: widget.panes), flex: 5),
|
Expanded(
|
||||||
|
child: TabBarView(
|
||||||
|
children: widget.panes,
|
||||||
|
physics: NeverScrollableScrollPhysics(),
|
||||||
|
),
|
||||||
|
flex: 10),
|
||||||
Spacer(flex: 1),
|
Spacer(flex: 1),
|
||||||
TabPageSelector(selectedColor: Colors.white),
|
TabPageSelector(selectedColor: Colors.white),
|
||||||
Spacer(flex: 1),
|
Spacer(flex: 1),
|
||||||
OutlinedButton(
|
OutlinedButton(
|
||||||
onPressed: _nextOrFinish,
|
onPressed: _canGoNext ? _nextOrFinish : null,
|
||||||
child: Text(!_isLastPane ? tr("Next") : tr("Let's go!")),
|
child: Text(!_isLastPane ? tr("Next") : tr("Let's go!")),
|
||||||
),
|
),
|
||||||
Spacer(flex: 1),
|
Spacer(flex: 1),
|
||||||
@ -148,14 +179,19 @@ class __RouteBodyState extends State<_RouteBody> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
void _nextOrFinish() async {
|
void _nextOrFinish() async {
|
||||||
if (!_controller.indexIsChanging) {
|
if (_controller.indexIsChanging) return;
|
||||||
if (!_isLastPane) {
|
|
||||||
_controller.animateTo(_controller.index + 1);
|
if (!_isLastPane) {
|
||||||
} else {
|
// Check if the next click has to be captured
|
||||||
(await PreferencesHelper.getInstance())
|
if (_currPane?.onTapNext != null) {
|
||||||
.setBool(PreferencesKeyList.IS_TOUR_SEEN, true);
|
if (!await _currPane.onTapNext(context)) return;
|
||||||
Navigator.of(context).pop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_controller.animateTo(_controller.index + 1);
|
||||||
|
} else {
|
||||||
|
(await PreferencesHelper.getInstance())
|
||||||
|
.setBool(PreferencesKeyList.IS_TOUR_SEEN, true);
|
||||||
|
Navigator.of(context).pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -165,26 +201,34 @@ class _PresentationPane extends StatelessWidget {
|
|||||||
final Widget iconWidget;
|
final Widget iconWidget;
|
||||||
final String title;
|
final String title;
|
||||||
final String text;
|
final String text;
|
||||||
|
final Function(BuildContext) child;
|
||||||
final String actionTitle;
|
final String actionTitle;
|
||||||
final Function(BuildContext) onActionTap;
|
final Function(BuildContext) onActionTap;
|
||||||
|
final bool canGoNext;
|
||||||
|
final Future<bool> Function(BuildContext) onTapNext;
|
||||||
|
|
||||||
const _PresentationPane({
|
const _PresentationPane({
|
||||||
Key key,
|
Key key,
|
||||||
this.icon,
|
this.icon,
|
||||||
this.iconWidget,
|
this.iconWidget,
|
||||||
@required this.title,
|
@required this.title,
|
||||||
@required this.text,
|
this.text,
|
||||||
|
this.child,
|
||||||
this.actionTitle,
|
this.actionTitle,
|
||||||
this.onActionTap,
|
this.onActionTap,
|
||||||
|
this.canGoNext = true,
|
||||||
|
this.onTapNext,
|
||||||
}) : assert(icon != null || iconWidget != null),
|
}) : assert(icon != null || iconWidget != null),
|
||||||
assert(title != null),
|
assert(title != null),
|
||||||
assert(text != null),
|
assert(text != null || child != null),
|
||||||
super(key: key);
|
super(key: key);
|
||||||
|
|
||||||
bool get _hasAction => actionTitle != null && onActionTap != null;
|
bool get _hasAction => actionTitle != null && onActionTap != null;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => Column(
|
Widget build(BuildContext context) {
|
||||||
|
if (text != null)
|
||||||
|
return Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Spacer(flex: 3),
|
Spacer(flex: 3),
|
||||||
icon != null ? Icon(icon, color: Colors.white, size: 50) : iconWidget,
|
icon != null ? Icon(icon, color: Colors.white, size: 50) : iconWidget,
|
||||||
@ -214,6 +258,38 @@ class _PresentationPane extends StatelessWidget {
|
|||||||
Spacer(flex: 3),
|
Spacer(flex: 3),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
children: <Widget>[
|
||||||
|
Spacer(flex: 1),
|
||||||
|
icon != null ? Icon(icon, color: Colors.white, size: 50) : iconWidget,
|
||||||
|
Spacer(flex: 1),
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style: TextStyle(fontSize: 20),
|
||||||
|
),
|
||||||
|
Spacer(flex: 1),
|
||||||
|
child(context),
|
||||||
|
Spacer(flex: 1),
|
||||||
|
_hasAction
|
||||||
|
? OutlinedButton(
|
||||||
|
onPressed: () => onActionTap(context),
|
||||||
|
child: Text(
|
||||||
|
actionTitle,
|
||||||
|
style: TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Opacity(
|
||||||
|
opacity: 0,
|
||||||
|
child: OutlinedButton(
|
||||||
|
onPressed: null,
|
||||||
|
child: Text(""),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Spacer(flex: 1),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _FirstPane extends StatelessWidget {
|
class _FirstPane extends StatelessWidget {
|
||||||
|
@ -31,6 +31,63 @@ class PushNotificationsConfigurationRoute extends StatefulWidget {
|
|||||||
|
|
||||||
class _PushNotificationsConfigurationRouteState
|
class _PushNotificationsConfigurationRouteState
|
||||||
extends State<PushNotificationsConfigurationRoute> {
|
extends State<PushNotificationsConfigurationRoute> {
|
||||||
|
final _key = GlobalKey<PushNotificationsConfigurationWidgetState>();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => Material(
|
||||||
|
textStyle: TextStyle(color: Colors.white),
|
||||||
|
color: config().splashBackgroundColor,
|
||||||
|
child: Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Spacer(),
|
||||||
|
Icon(Icons.notifications_none, color: Colors.white),
|
||||||
|
Spacer(),
|
||||||
|
Text(
|
||||||
|
tr("Comunic can send you notifications to your device when the application is closed if you want."),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
Spacer(),
|
||||||
|
PushNotificationsConfigurationWidget(
|
||||||
|
key: _key,
|
||||||
|
onConfigured: () => (Navigator.of(context).pop()),
|
||||||
|
onChanged: () => setState(() {}),
|
||||||
|
),
|
||||||
|
Spacer(),
|
||||||
|
OutlinedButton(
|
||||||
|
onPressed: _key?.currentState?.canSubmit ?? false
|
||||||
|
? _key.currentState.submit
|
||||||
|
: null,
|
||||||
|
child: Text(tr("Configure").toUpperCase()),
|
||||||
|
style: OutlinedButton.styleFrom(primary: Colors.white)),
|
||||||
|
Spacer(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class PushNotificationsConfigurationWidget extends StatefulWidget {
|
||||||
|
final Function() onConfigured;
|
||||||
|
final Function() onChanged;
|
||||||
|
|
||||||
|
const PushNotificationsConfigurationWidget({
|
||||||
|
Key key,
|
||||||
|
@required this.onConfigured,
|
||||||
|
this.onChanged,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
PushNotificationsConfigurationWidgetState createState() =>
|
||||||
|
PushNotificationsConfigurationWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class PushNotificationsConfigurationWidgetState
|
||||||
|
extends State<PushNotificationsConfigurationWidget> {
|
||||||
PushNotificationsStatus currStatus;
|
PushNotificationsStatus currStatus;
|
||||||
|
|
||||||
bool get canSubmit =>
|
bool get canSubmit =>
|
||||||
@ -40,46 +97,36 @@ class _PushNotificationsConfigurationRouteState
|
|||||||
Future<void> _refresh() async {
|
Future<void> _refresh() async {
|
||||||
await PushNotificationsHelper.refreshLocalStatus();
|
await PushNotificationsHelper.refreshLocalStatus();
|
||||||
currStatus = await PushNotificationsHelper.getLocalStatus();
|
currStatus = await PushNotificationsHelper.getLocalStatus();
|
||||||
|
|
||||||
|
if (currStatus == PushNotificationsStatus.UNDEFINED &&
|
||||||
|
srvConfig.notificationsPolicy.hasFirebase)
|
||||||
|
currStatus = PushNotificationsStatus.FIREBASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Material(
|
return AsyncScreenWidget(
|
||||||
textStyle: TextStyle(color: Colors.white),
|
onReload: _refresh,
|
||||||
color: config().splashBackgroundColor,
|
onBuild: _buildForm,
|
||||||
child: Center(
|
errorMessage: tr("Failed to load push notifications settings!"),
|
||||||
child: Padding(
|
);
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: AsyncScreenWidget(
|
|
||||||
onReload: _refresh,
|
|
||||||
onBuild: _buildForm,
|
|
||||||
errorMessage: tr("Failed to load push notifications settings!"),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildForm() => ConstrainedBox(
|
Widget _buildForm() => ConstrainedBox(
|
||||||
constraints: BoxConstraints(maxWidth: 300),
|
constraints: BoxConstraints(maxWidth: 300),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
children: [
|
||||||
Spacer(),
|
|
||||||
Icon(Icons.notifications_none, color: Colors.white),
|
|
||||||
Spacer(),
|
|
||||||
Text(
|
|
||||||
tr("Comunic can now send you notifications to your device when the application is closed if you want."),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
Spacer(),
|
|
||||||
_NotificationOption(
|
_NotificationOption(
|
||||||
title: tr("Use Google services"),
|
title: tr("Use Google services (recommended)"),
|
||||||
description: tr(
|
description: tr(
|
||||||
"Use the Google Play services to send you notifications. This option is less privacy-friendly, but it will work on most phones and will save your battery life."),
|
"Use the Google Play services to send you notifications. This option is less privacy-friendly, but it will work on most phones and will save your battery life."),
|
||||||
option: PushNotificationsStatus.FIREBASE,
|
option: PushNotificationsStatus.FIREBASE,
|
||||||
current: currStatus,
|
current: currStatus,
|
||||||
available: srvConfig.notificationsPolicy.hasFirebase,
|
available: srvConfig.notificationsPolicy.hasFirebase,
|
||||||
onChanged: (s) => setState(() => currStatus = s),
|
onChanged: (s) {
|
||||||
|
setState(() => currStatus = s);
|
||||||
|
if (widget.onChanged != null) widget.onChanged();
|
||||||
|
},
|
||||||
),
|
),
|
||||||
_NotificationOption(
|
_NotificationOption(
|
||||||
title: tr("Use independent notifications service"),
|
title: tr("Use independent notifications service"),
|
||||||
@ -89,7 +136,10 @@ class _PushNotificationsConfigurationRouteState
|
|||||||
current: currStatus,
|
current: currStatus,
|
||||||
available:
|
available:
|
||||||
srvConfig.notificationsPolicy.hasIndependent && isAndroid,
|
srvConfig.notificationsPolicy.hasIndependent && isAndroid,
|
||||||
onChanged: (s) => setState(() => currStatus = s),
|
onChanged: (s) {
|
||||||
|
setState(() => currStatus = s);
|
||||||
|
if (widget.onChanged != null) widget.onChanged();
|
||||||
|
},
|
||||||
),
|
),
|
||||||
_NotificationOption(
|
_NotificationOption(
|
||||||
title: tr("Do not send notification"),
|
title: tr("Do not send notification"),
|
||||||
@ -98,25 +148,22 @@ class _PushNotificationsConfigurationRouteState
|
|||||||
option: PushNotificationsStatus.DISABLED,
|
option: PushNotificationsStatus.DISABLED,
|
||||||
current: currStatus,
|
current: currStatus,
|
||||||
available: true,
|
available: true,
|
||||||
onChanged: (s) => setState(() => currStatus = s),
|
onChanged: (s) {
|
||||||
|
setState(() => currStatus = s);
|
||||||
|
if (widget.onChanged != null) widget.onChanged();
|
||||||
|
},
|
||||||
),
|
),
|
||||||
Spacer(),
|
|
||||||
OutlinedButton(
|
|
||||||
onPressed: canSubmit ? _submit : null,
|
|
||||||
child: Text(tr("Configure").toUpperCase()),
|
|
||||||
style: OutlinedButton.styleFrom(primary: Colors.white)),
|
|
||||||
Spacer(),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
Future<void> _submit() async {
|
Future<bool> submit() async {
|
||||||
try {
|
try {
|
||||||
String firebaseToken = "";
|
String firebaseToken = "";
|
||||||
|
|
||||||
if (currStatus == await PushNotificationsHelper.getLocalStatus()) {
|
if (currStatus == await PushNotificationsHelper.getLocalStatus()) {
|
||||||
Navigator.of(context).pop();
|
widget.onConfigured();
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (currStatus) {
|
switch (currStatus) {
|
||||||
@ -142,13 +189,15 @@ class _PushNotificationsConfigurationRouteState
|
|||||||
firebaseToken: firebaseToken);
|
firebaseToken: firebaseToken);
|
||||||
await PushNotificationsHelper.refreshLocalStatus();
|
await PushNotificationsHelper.refreshLocalStatus();
|
||||||
|
|
||||||
Navigator.of(context).pop();
|
widget.onConfigured();
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
logError(e, s);
|
logError(e, s);
|
||||||
showAlert(
|
showAlert(
|
||||||
context: context,
|
context: context,
|
||||||
message: tr("Failed to configure push notifications!"));
|
message: tr("Failed to configure push notifications!"));
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user