1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-10-23 06:53:23 +00:00
comunicmobile/lib/ui/routes/tour_route.dart
2021-05-04 07:49:45 +02:00

231 lines
7.2 KiB
Dart

import 'package:comunic/helpers/preferences_helper.dart';
import 'package:comunic/helpers/push_notifications_helper.dart';
import 'package:comunic/helpers/server_config_helper.dart';
import 'package:comunic/helpers/users_helper.dart';
import 'package:comunic/models/config.dart';
import 'package:comunic/models/user.dart';
import 'package:comunic/ui/routes/push_notifications_route.dart';
import 'package:comunic/ui/widgets/async_screen_widget.dart';
import 'package:comunic/ui/widgets/login_routes_theme.dart';
import 'package:comunic/ui/widgets/tour/account_image_tour_pane.dart';
import 'package:comunic/ui/widgets/tour/first_pane.dart';
import 'package:comunic/ui/widgets/tour/last_pane.dart';
import 'package:comunic/ui/widgets/tour/presentation_pane.dart';
import 'package:comunic/ui/widgets/tour/tour_notifications_pane.dart';
import 'package:comunic/utils/account_utils.dart';
import 'package:comunic/utils/intl_utils.dart';
import 'package:comunic/utils/log_utils.dart';
import 'package:flutter/material.dart';
/// Tour route
///
/// The tour is shown when the client sign into the application
///
/// @author Pierre Hubert
Future<void> showTour(BuildContext context) async => await Navigator.of(context)
.push(MaterialPageRoute(builder: (c) => TourRoute()));
typedef TourEntriesBuilder = List<Widget> Function(TourRouteState);
class TourRoute extends StatefulWidget {
@override
TourRouteState createState() => TourRouteState();
}
class TourRouteState extends State<TourRoute> {
final _key = GlobalKey<AsyncScreenWidgetState>();
final pushNotificationsKey =
GlobalKey<PushNotificationsConfigurationWidgetState>();
final Map<int, GlobalKey> pubKeys = Map();
User currUser;
int _defaultIndex = 0;
bool areNotificationsConfigured = false;
Future<void> _init() async {
currUser =
await UsersHelper().getSingleWithThrow(userID(), forceDownload: true);
// Pre-configure notifications
final notificationsStatus = await PushNotificationsHelper.getLocalStatus();
if (!PushNotificationsHelper.arePushNotificationsAvailable ||
notificationsStatus != PushNotificationsStatus.UNDEFINED)
areNotificationsConfigured = true;
// Attempt to automatically register to FCM
else if (srvConfig.notificationsPolicy.hasFirebase) {
try {
await PushNotificationsHelper.configure(
context, PushNotificationsStatus.FIREBASE);
areNotificationsConfigured = true;
} catch (e, s) {
logError(e, s);
}
}
}
void rebuild() => setState(() {});
void setStateKeepCurrentIndex(BuildContext cxt) async {
_defaultIndex = DefaultTabController.of(cxt).index;
await _key.currentState.refresh();
}
List<Widget> get _list => (config().toursEntriesBuilder != null
? config().toursEntriesBuilder(this)
: [
FirstTourPane(),
// Account image
AccountImageTourPane(
user: currUser,
onUpdated: setStateKeepCurrentIndex,
),
// Notifications
TourNotificationsPane(
pushNotificationsKey: pushNotificationsKey,
onConfigured: () => setState(() {}),
onChanged: () => setState(() {}),
visible: !areNotificationsConfigured,
),
PresentationPane(
icon: Icons.group_add,
title: tr("Friends"),
text:
"${tr("You can search the people you know and ask them to become your friends!")}\n\n${tr("This will help you to reach them to exchange information!")}",
),
PresentationPane(
icon: Icons.question_answer,
title: tr("Conversations"),
text:
"${tr("With Comunic, you can have conversations with all your friends.")}\n\n${tr("It is also possible to make video calls!")}",
),
PresentationPane(
icon: Icons.group,
title: tr("Groups"),
text:
"${tr("You can join groups where people share the same interests as you!")}\n\n${tr("It is also easy to create your own groups!")}",
),
PresentationPane(
icon: Icons.lock,
title: tr("Privacy"),
text:
"${tr("Your data is YOUR DATA. We will never use it or sell it.")}\n\n${tr("If you do not trust us, you can always check out our source code to verify it!")}",
),
LastTourPane(),
])
..removeWhere((pane) {
if (pane is PresentationPane) {
PresentationPane p = pane;
return !(p.visible ?? true);
}
return false;
});
@override
Widget build(BuildContext context) => LoginRoutesTheme(
child: Scaffold(
body: SafeArea(
child: AsyncScreenWidget(
key: _key,
onReload: _init,
errorMessage: tr("Failed to load tour!"),
onBuild: () => DefaultTabController(
initialIndex: _defaultIndex,
length: _list.length,
child: _RouteBody(
panes: _list,
),
),
),
),
),
);
}
class _RouteBody extends StatefulWidget {
final List<Widget> panes;
const _RouteBody({Key key, this.panes}) : super(key: key);
@override
__RouteBodyState createState() => __RouteBodyState();
}
class __RouteBodyState extends State<_RouteBody> {
TabController _controller;
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
void didUpdateWidget(_RouteBody oldWidget) {
super.didUpdateWidget(oldWidget);
_updateController();
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
_updateController();
}
void _updateController() {
_controller = DefaultTabController.of(context);
_controller.addListener(() => setState(() {}));
}
@override
Widget build(BuildContext context) => Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
Spacer(flex: 1),
Expanded(
child: TabBarView(
children: widget.panes,
physics: NeverScrollableScrollPhysics(),
),
flex: 10),
Spacer(flex: 1),
TabPageSelector(selectedColor: Colors.white),
Spacer(flex: 1),
OutlinedButton(
onPressed: _canGoNext ? _nextOrFinish : null,
child: Text(!_isLastPane ? tr("Next") : tr("Let's go!")),
),
Spacer(flex: 1),
],
),
);
void _nextOrFinish() async {
if (_controller.indexIsChanging) return;
if (!_isLastPane) {
// Check if the next click has to be captured
if (_currPane?.onTapNext != null) {
if (!await _currPane.onTapNext(context)) return;
}
_controller.animateTo(_controller.index + 1);
} else {
(await PreferencesHelper.getInstance())
.setBool(PreferencesKeyList.IS_TOUR_SEEN, true);
Navigator.of(context).pop();
}
}
}