2021-04-17 16:05:33 +00:00
import ' package:comunic/helpers/preferences_helper.dart ' ;
2021-04-26 08:49:33 +00:00
import ' package:comunic/helpers/push_notifications_helper.dart ' ;
import ' package:comunic/helpers/server_config_helper.dart ' ;
2021-04-17 16:33:08 +00:00
import ' package:comunic/helpers/users_helper.dart ' ;
2021-04-23 16:11:17 +00:00
import ' package:comunic/models/config.dart ' ;
2021-04-17 16:33:08 +00:00
import ' package:comunic/models/user.dart ' ;
2021-04-17 17:19:55 +00:00
import ' package:comunic/ui/routes/push_notifications_route.dart ' ;
2021-04-17 16:33:08 +00:00
import ' package:comunic/ui/widgets/async_screen_widget.dart ' ;
2021-04-17 16:05:33 +00:00
import ' package:comunic/ui/widgets/login_routes_theme.dart ' ;
2021-04-23 11:43:24 +00:00
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 ' ;
2021-04-23 12:05:06 +00:00
import ' package:comunic/ui/widgets/tour/tour_notifications_pane.dart ' ;
2021-04-17 16:33:08 +00:00
import ' package:comunic/utils/account_utils.dart ' ;
2021-04-17 16:05:33 +00:00
import ' package:comunic/utils/intl_utils.dart ' ;
2021-04-26 08:49:33 +00:00
import ' package:comunic/utils/log_utils.dart ' ;
2021-04-17 16:05:33 +00:00
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 ( ) ) ) ;
2021-04-23 16:11:17 +00:00
typedef TourEntriesBuilder = List < Widget > Function ( TourRouteState ) ;
2021-04-17 16:05:33 +00:00
class TourRoute extends StatefulWidget {
@ override
2021-04-23 16:11:17 +00:00
TourRouteState createState ( ) = > TourRouteState ( ) ;
2021-04-17 16:05:33 +00:00
}
2021-04-23 16:11:17 +00:00
class TourRouteState extends State < TourRoute > {
final _key = GlobalKey < AsyncScreenWidgetState > ( ) ;
final pushNotificationsKey =
2021-04-17 17:19:55 +00:00
GlobalKey < PushNotificationsConfigurationWidgetState > ( ) ;
2021-04-17 16:33:08 +00:00
2021-04-23 16:46:35 +00:00
final Map < int , GlobalKey > pubKeys = Map ( ) ;
2021-04-17 16:33:08 +00:00
User currUser ;
int _defaultIndex = 0 ;
2021-04-26 08:49:33 +00:00
bool areNotificationsConfigured = false ;
2021-04-17 16:33:08 +00:00
Future < void > _init ( ) async {
currUser =
await UsersHelper ( ) . getSingleWithThrow ( userID ( ) , forceDownload: true ) ;
2021-04-26 08:49:33 +00:00
// 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 ) ;
2021-05-04 05:49:45 +00:00
areNotificationsConfigured = true ;
2021-04-26 08:49:33 +00:00
} catch ( e , s ) {
logError ( e , s ) ;
}
}
2021-04-17 16:33:08 +00:00
}
2021-04-23 16:46:35 +00:00
void rebuild ( ) = > setState ( ( ) { } ) ;
2021-04-23 11:48:33 +00:00
void setStateKeepCurrentIndex ( BuildContext cxt ) async {
_defaultIndex = DefaultTabController . of ( cxt ) . index ;
2021-04-23 16:11:17 +00:00
await _key . currentState . refresh ( ) ;
2021-04-23 11:48:33 +00:00
}
2021-04-26 08:49:33 +00:00
List < Widget > get _list = > ( config ( ) . toursEntriesBuilder ! = null
2021-04-23 16:11:17 +00:00
? config ( ) . toursEntriesBuilder ( this )
: [
FirstTourPane ( ) ,
2021-04-17 17:19:55 +00:00
2021-04-23 16:11:17 +00:00
// Account image
AccountImageTourPane (
user: currUser ,
onUpdated: setStateKeepCurrentIndex ,
) ,
2021-04-17 17:19:55 +00:00
2021-04-23 16:11:17 +00:00
// Notifications
TourNotificationsPane (
pushNotificationsKey: pushNotificationsKey ,
onConfigured: ( ) = > setState ( ( ) { } ) ,
onChanged: ( ) = > setState ( ( ) { } ) ,
2021-04-26 08:49:33 +00:00
visible: ! areNotificationsConfigured ,
2021-04-23 16:11:17 +00:00
) ,
2021-04-17 17:19:55 +00:00
2021-04-23 16:11:17 +00:00
PresentationPane (
icon: Icons . group_add ,
title: tr ( " Friends " ) ,
2021-04-26 08:19:48 +00:00
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! " ) } " ,
2021-04-23 16:11:17 +00:00
) ,
PresentationPane (
icon: Icons . question_answer ,
title: tr ( " Conversations " ) ,
2021-04-26 08:19:48 +00:00
text:
" ${ tr ( " With Comunic, you can have conversations with all your friends. " ) } \n \n ${ tr ( " It is also possible to make video calls! " ) } " ,
2021-04-23 16:11:17 +00:00
) ,
PresentationPane (
icon: Icons . group ,
title: tr ( " Groups " ) ,
2021-04-26 08:19:48 +00:00
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! " ) } " ,
2021-04-23 16:11:17 +00:00
) ,
PresentationPane (
icon: Icons . lock ,
title: tr ( " Privacy " ) ,
2021-04-26 08:19:48 +00:00
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! " ) } " ,
2021-04-23 16:11:17 +00:00
) ,
LastTourPane ( ) ,
2021-04-26 08:49:33 +00:00
] )
. . removeWhere ( ( pane ) {
if ( pane is PresentationPane ) {
PresentationPane p = pane ;
return ! ( p . visible ? ? true ) ;
}
return false ;
} ) ;
2021-04-17 16:05:33 +00:00
@ override
Widget build ( BuildContext context ) = > LoginRoutesTheme (
child: Scaffold (
body: SafeArea (
2021-04-17 16:33:08 +00:00
child: AsyncScreenWidget (
2021-04-23 16:11:17 +00:00
key: _key ,
2021-04-17 16:33:08 +00:00
onReload: _init ,
errorMessage: tr ( " Failed to load tour! " ) ,
onBuild: ( ) = > DefaultTabController (
initialIndex: _defaultIndex ,
2021-04-17 16:05:33 +00:00
length: _list . length ,
2021-04-17 16:33:08 +00:00
child: _RouteBody (
panes: _list ,
) ,
2021-04-17 16:05:33 +00:00
) ,
) ,
) ,
) ,
) ;
}
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 ;
2021-04-23 11:43:24 +00:00
PresentationPane get _currPane = >
widget . panes [ _controller . index ] is PresentationPane
2021-04-17 17:19:55 +00:00
? widget . panes [ _controller . index ]
: null ;
bool get _canGoNext = > _currPane ? . canGoNext ? ? true ;
2021-04-17 16:05:33 +00:00
@ 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 ) ,
2021-04-17 17:19:55 +00:00
Expanded (
child: TabBarView (
children: widget . panes ,
physics: NeverScrollableScrollPhysics ( ) ,
) ,
flex: 10 ) ,
2021-04-17 16:05:33 +00:00
Spacer ( flex: 1 ) ,
TabPageSelector ( selectedColor: Colors . white ) ,
Spacer ( flex: 1 ) ,
OutlinedButton (
2021-04-17 17:19:55 +00:00
onPressed: _canGoNext ? _nextOrFinish : null ,
2021-04-17 16:05:33 +00:00
child: Text ( ! _isLastPane ? tr ( " Next " ) : tr ( " Let's go! " ) ) ,
) ,
Spacer ( flex: 1 ) ,
] ,
) ,
) ;
void _nextOrFinish ( ) async {
2021-04-17 17:19:55 +00:00
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 ;
2021-04-17 16:05:33 +00:00
}
2021-04-17 17:19:55 +00:00
_controller . animateTo ( _controller . index + 1 ) ;
} else {
( await PreferencesHelper . getInstance ( ) )
. setBool ( PreferencesKeyList . IS_TOUR_SEEN , true ) ;
Navigator . of ( context ) . pop ( ) ;
2021-04-17 16:05:33 +00:00
}
}
}