1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-11-25 14:29:22 +00:00
comunicmobile/lib/ui/routes/tour_route.dart

201 lines
6.1 KiB
Dart

import 'package:comunic/helpers/preferences_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: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;
Future<void> _init() async {
currUser =
await UsersHelper().getSingleWithThrow(userID(), forceDownload: true);
}
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(() {}),
),
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\nThis 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\nIt 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\nIt 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\nIf you do not trust us, you can always check out our source code to verify it!"),
),
LastTourPane(),
];
@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();
}
}
}