2024-02-18 17:36:58 +01:00
import ' package:flutter/material.dart ' ;
import ' package:infinite_scroll_pagination/infinite_scroll_pagination.dart ' ;
import ' package:provider/provider.dart ' ;
import ' package:simplecloudnotifier/api/api_client.dart ' ;
import ' package:simplecloudnotifier/models/channel.dart ' ;
2024-06-15 16:33:30 +02:00
import ' package:simplecloudnotifier/state/app_bar_state.dart ' ;
2024-05-26 00:20:25 +02:00
import ' package:simplecloudnotifier/state/application_log.dart ' ;
2024-06-02 17:09:57 +02:00
import ' package:simplecloudnotifier/state/app_auth.dart ' ;
2024-05-25 22:06:43 +02:00
import ' package:simplecloudnotifier/pages/channel_list/channel_list_item.dart ' ;
2024-02-18 17:36:58 +01:00
class ChannelRootPage extends StatefulWidget {
2024-06-15 15:56:50 +02:00
const ChannelRootPage ( { super . key , required this . isVisiblePage } ) ;
final bool isVisiblePage ;
2024-02-18 17:36:58 +01:00
@ override
State < ChannelRootPage > createState ( ) = > _ChannelRootPageState ( ) ;
}
class _ChannelRootPageState extends State < ChannelRootPage > {
2024-06-15 15:56:50 +02:00
final PagingController < int , Channel > _pagingController = PagingController . fromValue ( PagingState ( nextPageKey: null , itemList: [ ] , error: null ) , firstPageKey: 0 ) ;
bool _isInitialized = false ;
2024-02-18 17:36:58 +01:00
@ override
void initState ( ) {
super . initState ( ) ;
2024-06-15 15:56:50 +02:00
_pagingController . addPageRequestListener ( _fetchPage ) ;
2024-06-15 16:33:30 +02:00
if ( widget . isVisiblePage & & ! _isInitialized ) _realInitState ( ) ;
2024-02-18 17:36:58 +01:00
}
@ override
void dispose ( ) {
2024-06-15 16:33:30 +02:00
ApplicationLog . debug ( ' ChannelRootPage::dispose ' ) ;
2024-02-18 17:36:58 +01:00
_pagingController . dispose ( ) ;
super . dispose ( ) ;
}
2024-06-15 15:56:50 +02:00
@ override
void didUpdateWidget ( ChannelRootPage 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 ( ' ChannelRootPage::_realInitState ' ) ;
2024-06-15 15:56:50 +02:00
_pagingController . refresh ( ) ;
_isInitialized = true ;
}
2024-02-18 17:36:58 +01:00
Future < void > _fetchPage ( int pageKey ) async {
2024-06-02 17:09:57 +02:00
final acc = Provider . of < AppAuth > ( context , listen: false ) ;
2024-02-18 17:36:58 +01:00
2024-06-15 15:56:50 +02:00
ApplicationLog . debug ( ' Start ChannelList::_pagingController::_fetchPage [ ${ pageKey } ] ' ) ;
2024-06-02 17:09:57 +02:00
if ( ! acc . isAuth ( ) ) {
2024-02-18 17:36:58 +01:00
_pagingController . error = ' Not logged in ' ;
return ;
}
try {
2024-06-02 17:09:57 +02:00
final items = ( await APIClient . getChannelList ( acc , ChannelSelector . all ) ) . map ( ( p ) = > p . channel ) . toList ( ) ;
2024-02-18 17:36:58 +01:00
2024-05-26 19:24:19 +02:00
items . sort ( ( a , b ) = > - 1 * ( a . timestampLastSent ? ? ' ' ) . compareTo ( b . timestampLastSent ? ? ' ' ) ) ;
2024-06-15 16:33:30 +02:00
_pagingController . value = PagingState ( nextPageKey: null , itemList: items , error: null ) ;
2024-05-26 00:20:25 +02:00
} catch ( exc , trace ) {
_pagingController . error = exc . toString ( ) ;
ApplicationLog . error ( ' Failed to list channels: ' + exc . toString ( ) , trace: trace ) ;
2024-02-18 17:36:58 +01:00
}
}
2024-06-15 16:33:30 +02:00
Future < void > _backgroundRefresh ( ) async {
final acc = Provider . of < AppAuth > ( context , listen: false ) ;
ApplicationLog . debug ( ' Start background refresh of channel list ' ) ;
if ( ! acc . isAuth ( ) ) {
_pagingController . error = ' Not logged in ' ;
return ;
}
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 ) ;
final items = ( await APIClient . getChannelList ( acc , ChannelSelector . all ) ) . map ( ( p ) = > p . channel ) . toList ( ) ;
items . sort ( ( a , b ) = > - 1 * ( a . timestampLastSent ? ? ' ' ) . compareTo ( b . timestampLastSent ? ? ' ' ) ) ;
_pagingController . value = PagingState ( nextPageKey: null , itemList: items , error: null ) ;
} catch ( exc , trace ) {
_pagingController . error = exc . toString ( ) ;
ApplicationLog . error ( ' Failed to list channels: ' + exc . toString ( ) , trace: trace ) ;
} finally {
AppBarState ( ) . setLoadingIndeterminate ( false ) ;
}
}
2024-02-18 17:36:58 +01:00
@ override
Widget build ( BuildContext context ) {
2024-05-26 19:24:19 +02:00
return RefreshIndicator (
onRefresh: ( ) = > Future . sync (
( ) = > _pagingController . refresh ( ) ,
) ,
child: PagedListView < int , Channel > (
pagingController: _pagingController ,
builderDelegate: PagedChildBuilderDelegate < Channel > (
itemBuilder: ( context , item , index ) = > ChannelListItem (
channel: item ,
onPressed: ( ) { /*TODO*/ } ,
) ,
2024-02-18 17:36:58 +01:00
) ,
) ,
) ;
}
}