2024-06-04 08:20:28 +02:00
import ' dart:io ' ;
2024-06-01 03:06:02 +02:00
import ' package:firebase_messaging/firebase_messaging.dart ' ;
2024-05-27 17:21:29 +02:00
import ' package:flutter/material.dart ' ;
import ' package:font_awesome_flutter/font_awesome_flutter.dart ' ;
import ' package:provider/provider.dart ' ;
import ' package:simplecloudnotifier/api/api_client.dart ' ;
import ' package:simplecloudnotifier/models/user.dart ' ;
2024-06-01 03:06:02 +02:00
import ' package:simplecloudnotifier/pages/account/login.dart ' ;
2024-06-15 16:33:30 +02:00
import ' package:simplecloudnotifier/state/app_bar_state.dart ' ;
2024-06-01 03:06:02 +02:00
import ' package:simplecloudnotifier/state/application_log.dart ' ;
import ' package:simplecloudnotifier/state/globals.dart ' ;
2024-06-02 17:09:57 +02:00
import ' package:simplecloudnotifier/state/app_auth.dart ' ;
2024-06-15 16:33:30 +02:00
import ' package:simplecloudnotifier/types/immediate_future.dart ' ;
2024-06-13 15:42:39 +02:00
import ' package:simplecloudnotifier/utils/navi.dart ' ;
2024-06-01 03:06:02 +02:00
import ' package:simplecloudnotifier/utils/toaster.dart ' ;
2024-06-08 12:55:58 +02:00
import ' package:simplecloudnotifier/utils/ui.dart ' ;
2024-06-04 08:20:28 +02:00
import ' package:uuid/uuid.dart ' ;
2024-05-27 17:21:29 +02:00
class AccountRootPage extends StatefulWidget {
2024-06-15 15:56:50 +02:00
const AccountRootPage ( { super . key , required this . isVisiblePage } ) ;
final bool isVisiblePage ;
2024-05-27 17:21:29 +02:00
@ override
State < AccountRootPage > createState ( ) = > _AccountRootPageState ( ) ;
}
class _AccountRootPageState extends State < AccountRootPage > {
2024-06-15 16:33:30 +02:00
late ImmediateFuture < int > ? futureSubscriptionCount ;
late ImmediateFuture < int > ? futureClientCount ;
late ImmediateFuture < int > ? futureKeyCount ;
late ImmediateFuture < int > ? futureChannelAllCount ;
late ImmediateFuture < int > ? futureChannelSubscribedCount ;
late ImmediateFuture < User > ? futureUser ;
2024-05-27 17:21:29 +02:00
2024-06-02 17:09:57 +02:00
late AppAuth userAcc ;
2024-05-27 17:21:29 +02:00
2024-06-01 03:06:02 +02:00
bool loading = false ;
2024-06-15 15:56:50 +02:00
bool _isInitialized = false ;
2024-05-27 17:21:29 +02:00
@ override
void initState ( ) {
super . initState ( ) ;
2024-06-02 17:09:57 +02:00
userAcc = Provider . of < AppAuth > ( context , listen: false ) ;
2024-05-27 17:21:29 +02:00
userAcc . addListener ( _onAuthStateChanged ) ;
2024-06-15 15:56:50 +02:00
2024-06-15 16:33:30 +02:00
if ( widget . isVisiblePage & & ! _isInitialized ) _realInitState ( ) ;
2024-06-15 15:56:50 +02:00
}
@ override
void didUpdateWidget ( AccountRootPage oldWidget ) {
super . didUpdateWidget ( oldWidget ) ;
if ( oldWidget . isVisiblePage ! = widget . isVisiblePage & & widget . isVisiblePage ) {
if ( ! _isInitialized ) {
2024-06-15 16:33:30 +02:00
_realInitState ( ) ;
2024-06-15 15:56:50 +02:00
} else {
2024-06-15 16:33:30 +02:00
_backgroundRefresh ( ) ;
2024-06-15 15:56:50 +02:00
}
}
}
2024-06-15 16:33:30 +02:00
void _realInitState ( ) {
ApplicationLog . debug ( ' AccountRootPage::_realInitState ' ) ;
2024-05-27 17:21:29 +02:00
_onAuthStateChanged ( ) ;
2024-06-15 15:56:50 +02:00
_isInitialized = true ;
2024-05-27 17:21:29 +02:00
}
@ override
void dispose ( ) {
2024-06-15 16:33:30 +02:00
ApplicationLog . debug ( ' AccountRootPage::dispose ' ) ;
2024-05-27 17:21:29 +02:00
userAcc . removeListener ( _onAuthStateChanged ) ;
super . dispose ( ) ;
}
void _onAuthStateChanged ( ) {
2024-06-15 16:33:30 +02:00
ApplicationLog . debug ( ' AccountRootPage::_onAuthStateChanged ' ) ;
_createFutures ( ) ;
}
void _createFutures ( ) {
2024-05-27 17:21:29 +02:00
futureSubscriptionCount = null ;
futureClientCount = null ;
futureKeyCount = null ;
futureChannelAllCount = null ;
futureChannelSubscribedCount = null ;
2024-06-02 17:09:57 +02:00
if ( userAcc . isAuth ( ) ) {
2024-06-15 16:33:30 +02:00
futureChannelAllCount = ImmediateFuture . ofFuture ( ( ) async {
2024-06-02 17:09:57 +02:00
if ( ! userAcc . isAuth ( ) ) throw new Exception ( ' not logged in ' ) ;
final channels = await APIClient . getChannelList ( userAcc , ChannelSelector . all ) ;
2024-05-31 23:21:24 +02:00
return channels . length ;
2024-06-15 16:33:30 +02:00
} ( ) ) ;
2024-05-27 17:21:29 +02:00
2024-06-15 16:33:30 +02:00
futureChannelSubscribedCount = ImmediateFuture . ofFuture ( ( ) async {
2024-06-02 17:09:57 +02:00
if ( ! userAcc . isAuth ( ) ) throw new Exception ( ' not logged in ' ) ;
final channels = await APIClient . getChannelList ( userAcc , ChannelSelector . subscribed ) ;
2024-05-31 23:21:24 +02:00
return channels . length ;
2024-06-15 16:33:30 +02:00
} ( ) ) ;
2024-05-27 17:21:29 +02:00
2024-06-15 16:33:30 +02:00
futureSubscriptionCount = ImmediateFuture . ofFuture ( ( ) async {
2024-06-02 17:09:57 +02:00
if ( ! userAcc . isAuth ( ) ) throw new Exception ( ' not logged in ' ) ;
final subs = await APIClient . getSubscriptionList ( userAcc ) ;
2024-05-31 23:21:24 +02:00
return subs . length ;
2024-06-15 16:33:30 +02:00
} ( ) ) ;
2024-05-27 17:21:29 +02:00
2024-06-15 16:33:30 +02:00
futureClientCount = ImmediateFuture . ofFuture ( ( ) async {
2024-06-02 17:09:57 +02:00
if ( ! userAcc . isAuth ( ) ) throw new Exception ( ' not logged in ' ) ;
final clients = await APIClient . getClientList ( userAcc ) ;
2024-05-31 23:21:24 +02:00
return clients . length ;
2024-06-15 16:33:30 +02:00
} ( ) ) ;
2024-05-27 17:21:29 +02:00
2024-06-15 16:33:30 +02:00
futureKeyCount = ImmediateFuture . ofFuture ( ( ) async {
2024-06-02 17:09:57 +02:00
if ( ! userAcc . isAuth ( ) ) throw new Exception ( ' not logged in ' ) ;
final keys = await APIClient . getKeyTokenList ( userAcc ) ;
2024-05-31 23:21:24 +02:00
return keys . length ;
2024-06-15 16:33:30 +02:00
} ( ) ) ;
futureUser = ImmediateFuture . ofFuture ( userAcc . loadUser ( force: false ) ) ;
}
}
Future < void > _backgroundRefresh ( ) async {
if ( userAcc . isAuth ( ) ) {
try {
await Future . delayed ( const Duration ( seconds: 0 ) , ( ) { } ) ; // this is annoyingly important - otherwise we call setLoadingIndeterminate directly in initStat() and get an exception....
AppBarState ( ) . setLoadingIndeterminate ( true ) ;
// refresh all data and then replace teh futures used in build()
final channelsAll = await APIClient . getChannelList ( userAcc , ChannelSelector . all ) ;
final channelsSubscribed = await APIClient . getChannelList ( userAcc , ChannelSelector . subscribed ) ;
final subs = await APIClient . getSubscriptionList ( userAcc ) ;
final clients = await APIClient . getClientList ( userAcc ) ;
final keys = await APIClient . getKeyTokenList ( userAcc ) ;
final user = await userAcc . loadUser ( force: true ) ;
setState ( ( ) {
futureChannelAllCount = ImmediateFuture . ofValue ( channelsAll . length ) ;
futureChannelSubscribedCount = ImmediateFuture . ofValue ( channelsSubscribed . length ) ;
futureSubscriptionCount = ImmediateFuture . ofValue ( subs . length ) ;
futureClientCount = ImmediateFuture . ofValue ( clients . length ) ;
futureKeyCount = ImmediateFuture . ofValue ( keys . length ) ;
futureUser = ImmediateFuture . ofValue ( user ) ;
} ) ;
} catch ( exc , trace ) {
ApplicationLog . error ( ' Failed to refresh account data: ' + exc . toString ( ) , trace: trace ) ;
Toaster . error ( " Error " , ' Failed to refresh account data ' ) ;
} finally {
AppBarState ( ) . setLoadingIndeterminate ( false ) ;
}
2024-05-31 23:21:24 +02:00
}
2024-05-27 17:21:29 +02:00
}
@ override
Widget build ( BuildContext context ) {
2024-06-02 17:09:57 +02:00
return Consumer < AppAuth > (
2024-05-27 17:21:29 +02:00
builder: ( context , acc , child ) {
2024-06-15 15:56:50 +02:00
if ( ! _isInitialized ) return SizedBox ( ) ;
2024-06-02 17:09:57 +02:00
if ( ! userAcc . isAuth ( ) ) {
2024-06-01 14:00:16 +02:00
return _buildNoAuth ( context ) ;
2024-05-27 17:21:29 +02:00
} else {
return FutureBuilder (
2024-06-15 16:33:30 +02:00
future: futureUser ! . future ,
2024-05-27 17:21:29 +02:00
builder: ( ( context , snapshot ) {
2024-06-15 16:33:30 +02:00
if ( futureUser ? . value ! = null ) {
return _buildShowAccount ( context , acc , futureUser ! . value ! ) ;
} else if ( snapshot . connectionState = = ConnectionState . done & & snapshot . hasError ) {
return Text ( ' Error: ${ snapshot . error } ' ) ; //TODO better error display
} else if ( snapshot . connectionState = = ConnectionState . done ) {
2024-06-01 14:00:16 +02:00
return _buildShowAccount ( context , acc , snapshot . data ! ) ;
2024-06-15 16:33:30 +02:00
} else {
return Center ( child: CircularProgressIndicator ( ) ) ;
2024-05-27 17:21:29 +02:00
}
} ) ,
) ;
}
} ,
) ;
}
2024-06-01 14:00:16 +02:00
Widget _buildNoAuth ( BuildContext context ) {
return SingleChildScrollView (
child: Padding (
padding: const EdgeInsets . fromLTRB ( 24 , 32 , 24 , 16 ) ,
child: Column (
mainAxisAlignment: MainAxisAlignment . start ,
crossAxisAlignment: CrossAxisAlignment . stretch ,
children: [
if ( ! loading )
Center (
child: Container (
width: 200 ,
height: 200 ,
decoration: BoxDecoration (
color: Theme . of ( context ) . colorScheme . secondary ,
borderRadius: BorderRadius . circular ( 100 ) ,
) ,
child: Center ( child: FaIcon ( FontAwesomeIcons . userSecret , size: 96 , color: Theme . of ( context ) . colorScheme . onSecondary ) ) ,
2024-06-01 03:06:02 +02:00
) ,
) ,
2024-06-01 14:00:16 +02:00
if ( loading )
Center (
child: Container (
width: 200 ,
height: 200 ,
decoration: BoxDecoration (
color: Theme . of ( context ) . colorScheme . secondary ,
borderRadius: BorderRadius . circular ( 100 ) ,
) ,
child: Center ( child: CircularProgressIndicator ( color: Theme . of ( context ) . colorScheme . onSecondary ) ) ,
2024-06-01 03:06:02 +02:00
) ,
) ,
2024-06-01 14:00:16 +02:00
const SizedBox ( height: 32 ) ,
2024-06-08 12:55:58 +02:00
UI . button (
text: ' Create new account ' ,
2024-06-01 14:00:16 +02:00
onPressed: ( ) {
if ( loading ) return ;
_createNewAccount ( ) ;
} ,
2024-06-08 12:55:58 +02:00
big: true ,
2024-06-01 03:06:02 +02:00
) ,
2024-06-01 14:00:16 +02:00
const SizedBox ( height: 16 ) ,
2024-06-08 12:55:58 +02:00
UI . button (
text: ' Use existing account ' ,
2024-06-01 14:00:16 +02:00
onPressed: ( ) {
if ( loading ) return ;
2024-06-13 15:42:39 +02:00
Navi . push ( context , ( ) = > AccountLoginPage ( ) ) ;
2024-06-01 14:00:16 +02:00
} ,
2024-06-08 12:55:58 +02:00
tonal: true ,
big: true ,
2024-06-01 14:00:16 +02:00
) ,
] ,
) ,
2024-05-27 17:21:29 +02:00
) ,
) ;
}
2024-06-02 17:09:57 +02:00
Widget _buildShowAccount ( BuildContext context , AppAuth acc , User user ) {
2024-06-08 12:55:58 +02:00
return SingleChildScrollView (
child: Padding (
padding: const EdgeInsets . fromLTRB ( 8.0 , 24.0 , 8.0 , 8.0 ) ,
child: Column (
children: [
_buildHeader ( context , user ) ,
const SizedBox ( height: 16 ) ,
Text ( user . username ? ? user . userID , overflow: TextOverflow . ellipsis , style: TextStyle ( fontWeight: FontWeight . bold , fontSize: 20 ) ) ,
const SizedBox ( height: 16 ) ,
. . . _buildCards ( context , user ) ,
SizedBox ( height: 16 ) ,
_buildFooter ( context , user ) ,
SizedBox ( height: 40 ) ,
] ,
2024-05-27 17:21:29 +02:00
) ,
2024-06-08 12:55:58 +02:00
) ,
2024-05-27 17:21:29 +02:00
) ;
}
2024-06-01 14:00:16 +02:00
Row _buildHeader ( BuildContext context , User user ) {
2024-05-27 17:21:29 +02:00
return Row (
crossAxisAlignment: CrossAxisAlignment . start ,
children: [
SizedBox (
width: 80 ,
height: 80 ,
child: Stack (
children: [
Container (
width: 80 ,
height: 80 ,
decoration: BoxDecoration (
color: Colors . grey ,
borderRadius: BorderRadius . circular ( 8 ) ,
) ,
child: Center ( child: FaIcon ( FontAwesomeIcons . addressCard , size: 55 , color: Colors . white ) ) ) ,
if ( user . isPro )
Align (
alignment: Alignment . bottomRight ,
child: Container (
child: Text ( ' PRO ' , style: TextStyle ( fontSize: 14 , color: Colors . white , fontWeight: FontWeight . bold ) ) ,
padding: const EdgeInsets . fromLTRB ( 4 , 1 , 4 , 1 ) ,
decoration: BoxDecoration (
color: Colors . blue ,
2024-06-01 15:37:59 +02:00
borderRadius: BorderRadius . only ( topLeft: Radius . circular ( 4 ) ) ,
2024-05-27 17:21:29 +02:00
) ,
) ,
) ,
if ( ! user . isPro )
Align (
alignment: Alignment . bottomRight ,
child: Container (
child: Text ( ' FREE ' , style: TextStyle ( fontSize: 14 , color: Colors . white , fontWeight: FontWeight . bold ) ) ,
padding: const EdgeInsets . fromLTRB ( 4 , 1 , 4 , 1 ) ,
decoration: BoxDecoration (
color: Colors . purple ,
2024-06-01 15:37:59 +02:00
borderRadius: BorderRadius . only ( topLeft: Radius . circular ( 4 ) ) ,
2024-05-27 17:21:29 +02:00
) ,
) ,
) ,
] ,
) ,
) ,
const SizedBox ( width: 16 ) ,
Expanded (
child: Column (
crossAxisAlignment: CrossAxisAlignment . start ,
children: [
2024-06-01 15:37:59 +02:00
Text ( user . username ? ? user . userID , overflow: TextOverflow . ellipsis ) ,
2024-05-27 17:21:29 +02:00
const SizedBox ( height: 4 ) ,
Row (
children: [
SizedBox ( width: 80 , child: Text ( " Quota " , style: TextStyle ( color: Theme . of ( context ) . textTheme . bodyLarge ? . color ? . withAlpha ( 160 ) ) ) ) ,
Expanded ( child: Text ( ' ${ user . quotaUsed } / ${ user . quotaPerDay } ' ) ) ,
] ,
) ,
Row (
children: [
SizedBox ( width: 80 , child: Text ( " Messages " , style: TextStyle ( color: Theme . of ( context ) . textTheme . bodyLarge ? . color ? . withAlpha ( 160 ) ) ) ) ,
Expanded ( child: Text ( ' ${ user . messagesSent } ' ) ) ,
] ,
) ,
Row (
children: [
SizedBox ( width: 80 , child: Text ( " Channels " , style: TextStyle ( color: Theme . of ( context ) . textTheme . bodyLarge ? . color ? . withAlpha ( 160 ) ) ) ) ,
FutureBuilder (
2024-06-15 16:33:30 +02:00
future: futureChannelAllCount ! . future ,
2024-05-27 17:21:29 +02:00
builder: ( context , snapshot ) {
2024-06-15 16:33:30 +02:00
if ( futureChannelAllCount ? . value ! = null ) {
return Text ( ' ${ futureChannelAllCount ! . value } ' ) ;
} else if ( snapshot . connectionState = = ConnectionState . done ) {
2024-05-27 17:21:29 +02:00
return Text ( ' ${ snapshot . data } ' ) ;
2024-06-15 16:33:30 +02:00
} else {
return const SizedBox ( width: 8 , height: 8 , child: Center ( child: CircularProgressIndicator ( ) ) ) ;
2024-05-27 17:21:29 +02:00
}
} ,
)
] ,
) ,
] ,
) ,
) ,
2024-06-01 15:37:59 +02:00
Column (
mainAxisAlignment: MainAxisAlignment . start ,
children: [
2024-06-08 12:55:58 +02:00
UI . buttonIconOnly (
2024-06-01 15:37:59 +02:00
onPressed: ( ) { /*TODO*/ } ,
2024-06-08 12:55:58 +02:00
icon: FontAwesomeIcons . pen ,
2024-06-01 15:37:59 +02:00
) ,
const SizedBox ( height: 4 ) ,
if ( ! user . isPro )
2024-06-08 12:55:58 +02:00
UI . buttonIconOnly (
2024-06-01 15:37:59 +02:00
onPressed: ( ) { /*TODO*/ } ,
2024-06-08 12:55:58 +02:00
icon: FontAwesomeIcons . cartCircleArrowUp ,
2024-06-01 15:37:59 +02:00
) ,
] ,
) ,
2024-05-27 17:21:29 +02:00
] ,
) ;
}
2024-06-01 14:00:16 +02:00
List < Widget > _buildCards ( BuildContext context , User user ) {
2024-05-27 17:21:29 +02:00
return [
2024-06-15 16:33:30 +02:00
_buildNumberCard ( context , ' Subscriptions ' , futureSubscriptionCount , ( ) { /*TODO*/ } ) ,
_buildNumberCard ( context , ' Clients ' , futureClientCount , ( ) { /*TODO*/ } ) ,
_buildNumberCard ( context , ' Keys ' , futureKeyCount , ( ) { /*TODO*/ } ) ,
_buildNumberCard ( context , ' Channels ' , futureChannelSubscribedCount , ( ) { /*TODO*/ } ) ,
2024-06-08 12:55:58 +02:00
UI . buttonCard (
context: context ,
2024-05-27 17:21:29 +02:00
margin: EdgeInsets . fromLTRB ( 0 , 4 , 0 , 4 ) ,
2024-06-08 12:55:58 +02:00
child: Row (
children: [
Text ( ' ${ user . messagesSent } ' , style: TextStyle ( fontWeight: FontWeight . bold , fontSize: 20 ) ) ,
const SizedBox ( width: 12 ) ,
Text ( ' Messages ' , style: TextStyle ( fontWeight: FontWeight . bold , fontSize: 20 ) ) ,
] ,
2024-05-27 17:21:29 +02:00
) ,
2024-06-08 12:55:58 +02:00
onTap: ( ) { /*TODO*/ } ,
2024-05-27 17:21:29 +02:00
) ,
] ;
}
2024-06-15 16:33:30 +02:00
Widget _buildNumberCard ( BuildContext context , String txt , ImmediateFuture < int > ? future , void Function ( ) action ) {
return UI . buttonCard (
context: context ,
margin: EdgeInsets . fromLTRB ( 0 , 4 , 0 , 4 ) ,
child: Row (
children: [
FutureBuilder (
future: future ? . future ,
builder: ( context , snapshot ) {
if ( future ? . value ! = null ) {
return Text ( ' ${ future ? . value } ' , style: TextStyle ( fontWeight: FontWeight . bold , fontSize: 20 ) ) ;
} else if ( snapshot . connectionState = = ConnectionState . done ) {
return Text ( ' ${ snapshot . data } ' , style: TextStyle ( fontWeight: FontWeight . bold , fontSize: 20 ) ) ;
} else {
return const SizedBox ( width: 12 , height: 12 , child: Center ( child: CircularProgressIndicator ( ) ) ) ;
}
} ,
) ,
const SizedBox ( width: 12 ) ,
Text ( txt , style: TextStyle ( fontWeight: FontWeight . bold , fontSize: 20 ) ) ,
] ,
) ,
onTap: action ,
) ;
}
2024-06-01 14:00:16 +02:00
Widget _buildFooter ( BuildContext context , User user ) {
2024-05-27 17:21:29 +02:00
return Padding (
padding: const EdgeInsets . fromLTRB ( 8 , 0 , 8 , 0 ) ,
child: Row (
children: [
2024-06-08 12:55:58 +02:00
Expanded (
child: UI . button (
text: ' Logout ' ,
onPressed: _logout ,
color: Colors . orange ,
) ) ,
2024-05-27 17:21:29 +02:00
const SizedBox ( width: 8 ) ,
2024-06-08 12:55:58 +02:00
Expanded (
child: UI . button (
text: ' Delete Account ' ,
onPressed: _deleteAccount ,
color: Colors . red ,
) ) ,
2024-05-27 17:21:29 +02:00
] ,
) ,
) ;
}
2024-06-01 03:06:02 +02:00
2024-06-01 14:00:16 +02:00
void _createNewAccount ( ) async {
2024-06-01 03:06:02 +02:00
setState ( ( ) = > loading = true ) ;
2024-06-02 17:09:57 +02:00
final acc = Provider . of < AppAuth > ( context , listen: false ) ;
2024-06-01 03:06:02 +02:00
try {
2024-06-04 08:20:28 +02:00
final String ? fcmToken ;
if ( Platform . isLinux ) {
Toaster . warn ( " Unsupported Platform " , ' Your platform is not supported by FCM - notifications will not work ' ) ;
fcmToken = ' (linux- ' + Uuid ( ) . v4 ( ) + ' ) ' ;
} else {
final notificationSettings = await FirebaseMessaging . instance . requestPermission ( provisional: true ) ;
2024-06-01 03:06:02 +02:00
2024-06-04 08:20:28 +02:00
if ( notificationSettings . authorizationStatus = = AuthorizationStatus . denied ) {
Toaster . error ( " Missing Permission " , ' Please allow notifications to create an account ' ) ;
return ;
}
2024-06-01 03:06:02 +02:00
2024-06-04 08:20:28 +02:00
fcmToken = await FirebaseMessaging . instance . getToken ( ) ;
}
2024-06-01 03:06:02 +02:00
if ( fcmToken = = null ) {
Toaster . warn ( " Missing Token " , ' No FCM Token found, please allow notifications, ensure you have a network connection and restart the app ' ) ;
return ;
}
await Globals ( ) . setPrefFCMToken ( fcmToken ) ;
final user = await APIClient . createUserWithClient ( null , fcmToken , Globals ( ) . platform , Globals ( ) . version , Globals ( ) . hostname , Globals ( ) . clientType ) ;
2024-06-02 17:09:57 +02:00
acc . set ( user . user , user . clients [ 0 ] , user . adminKey , user . sendKey ) ;
2024-06-01 14:00:16 +02:00
2024-06-01 03:06:02 +02:00
await acc . save ( ) ;
2024-06-01 15:37:59 +02:00
Toaster . success ( " Success " , ' Successfully Created a new account ' ) ;
2024-06-01 03:06:02 +02:00
} catch ( exc , trace ) {
ApplicationLog . error ( ' Failed to create user account: ' + exc . toString ( ) , trace: trace ) ;
Toaster . error ( " Error " , ' Failed to create user account ' ) ;
} finally {
setState ( ( ) = > loading = false ) ;
}
}
2024-06-01 14:00:16 +02:00
void _logout ( ) async {
2024-06-02 17:09:57 +02:00
final acc = Provider . of < AppAuth > ( context , listen: false ) ;
2024-06-01 14:00:16 +02:00
2024-06-01 15:37:59 +02:00
//TODO clear messages/channels/etc in open views
2024-06-01 14:00:16 +02:00
acc . clear ( ) ;
await acc . save ( ) ;
Toaster . info ( ' Logout ' , ' Successfully logged out ' ) ;
}
void _deleteAccount ( ) async {
//TODO
}
2024-05-27 17:21:29 +02:00
}