feat: reduce resume cooldown to 30s; add pull-to-refresh to News, Calendar; refresh chat on resume
This commit is contained in:
+1
-1
@@ -193,7 +193,7 @@ class _ShellState extends ConsumerState<_Shell> with WidgetsBindingObserver {
|
||||
];
|
||||
|
||||
// Minimum gap between app-resume refreshes to avoid hammering the server.
|
||||
static const _resumeCooldown = Duration(minutes: 5);
|
||||
static const _resumeCooldown = Duration(seconds: 30);
|
||||
DateTime? _lastResumeRefresh;
|
||||
int? _prevTabIndex;
|
||||
|
||||
|
||||
@@ -67,12 +67,15 @@ class CalendarScreen extends ConsumerWidget {
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Expanded(
|
||||
child: RefreshIndicator(
|
||||
onRefresh: () async => ref.invalidate(calendarProvider),
|
||||
child: _AgendaList(
|
||||
events:
|
||||
cal.eventsByDay[dateOnly(cal.selectedDay)] ?? [],
|
||||
notifier: notifier,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -106,7 +109,12 @@ class _AgendaList extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (events.isEmpty) {
|
||||
return const Center(child: Text('No events'));
|
||||
return ListView(
|
||||
children: const [
|
||||
SizedBox(height: 80),
|
||||
Center(child: Text('No events')),
|
||||
],
|
||||
);
|
||||
}
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
|
||||
@@ -16,12 +16,27 @@ class ChatScreen extends ConsumerStatefulWidget {
|
||||
ConsumerState<ChatScreen> createState() => _ChatScreenState();
|
||||
}
|
||||
|
||||
class _ChatScreenState extends ConsumerState<ChatScreen> {
|
||||
class _ChatScreenState extends ConsumerState<ChatScreen>
|
||||
with WidgetsBindingObserver {
|
||||
final _controller = TextEditingController();
|
||||
final _scrollController = ScrollController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
ref.invalidate(messagesProvider(widget.conversationId));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
_controller.dispose();
|
||||
_scrollController.dispose();
|
||||
// Exit voice mode if the user navigates away mid-session.
|
||||
|
||||
@@ -96,6 +96,8 @@ class _NewsScreenState extends ConsumerState<NewsScreen> {
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Expanded(
|
||||
child: RefreshIndicator(
|
||||
onRefresh: () async => ref.invalidate(newsProvider),
|
||||
child: ListView.builder(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 8, vertical: 8),
|
||||
@@ -129,6 +131,7 @@ class _NewsScreenState extends ConsumerState<NewsScreen> {
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user