pre cache the chat list view

This commit is contained in:
otsmr 2026-06-19 17:47:49 +02:00
parent e4bc21ea10
commit f278a1dd38
4 changed files with 27 additions and 55 deletions

View file

@ -1,9 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'package:cryptography_plus/cryptography_plus.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -13,7 +10,6 @@ import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/providers/purchases.provider.dart'; import 'package:twonly/src/providers/purchases.provider.dart';
import 'package:twonly/src/services/mediafiles/mediafile.service.dart'; import 'package:twonly/src/services/mediafiles/mediafile.service.dart';
import 'package:twonly/src/services/subscription.service.dart'; import 'package:twonly/src/services/subscription.service.dart';
import 'package:twonly/src/services/user.service.dart';
import 'package:twonly/src/utils/log.dart'; import 'package:twonly/src/utils/log.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/visual/components/avatar_icon.comp.dart'; import 'package:twonly/src/visual/components/avatar_icon.comp.dart';
@ -32,7 +28,7 @@ class ChatListView extends StatefulWidget {
State<ChatListView> createState() => _ChatListViewState(); State<ChatListView> createState() => _ChatListViewState();
} }
class _ChatListViewState extends State<ChatListView> { class _ChatListViewState extends State<ChatListView> with AutomaticKeepAliveClientMixin<ChatListView> {
StreamSubscription<void>? _userSub; StreamSubscription<void>? _userSub;
StreamSubscription<List<Group>>? _contactsSub; StreamSubscription<List<Group>>? _contactsSub;
StreamSubscription<List<Contact>>? _contactsCountSub; StreamSubscription<List<Contact>>? _contactsCountSub;
@ -126,31 +122,10 @@ class _ChatListViewState extends State<ChatListView> {
} }
} }
}); });
}
WidgetsBinding.instance.addPostFrameCallback((_) async { @override
final changeLog = await rootBundle.loadString('CHANGELOG.md'); bool get wantKeepAlive => true;
final changeLogHash = (await compute(
Sha256().hash,
changeLog.codeUnits,
)).bytes;
if (!userService.currentUser.hideChangeLog &&
userService.currentUser.lastChangeLogHash.toString() !=
changeLogHash.toString()) {
await UserService.update((u) {
u.lastChangeLogHash = changeLogHash;
});
if (!mounted) return;
// only show changelog to people who already have contacts
// this prevents that this is shown directly after the user registered
if (_groupsNotPinned.isNotEmpty) {
await context.push(
Routes.settingsHelpChangelog,
extra: changeLog,
);
}
}
});
}
@override @override
void dispose() { void dispose() {
@ -165,6 +140,7 @@ class _ChatListViewState extends State<ChatListView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context);
final plan = context.watch<PurchasesProvider>().plan; final plan = context.watch<PurchasesProvider>().plan;
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(

View file

@ -3,6 +3,7 @@ import 'dart:async';
import 'package:app_links/app_links.dart'; import 'package:app_links/app_links.dart';
import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_sharing_intent/model/sharing_file.dart'; import 'package:flutter_sharing_intent/model/sharing_file.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
@ -268,6 +269,10 @@ class HomeViewState extends State<HomeView> with WidgetsBindingObserver {
setState(() { setState(() {
_offsetFromOne = 1.0 - (_homeViewPageController.page ?? 0); _offsetFromOne = 1.0 - (_homeViewPageController.page ?? 0);
_offsetRatio = _offsetFromOne.abs(); _offsetRatio = _offsetFromOne.abs();
final pageIndex = _homeViewPageController.page?.round();
if (pageIndex != null && pageIndex != _activePageIdx) {
_activePageIdx = pageIndex;
}
}); });
} }
@ -310,17 +315,19 @@ class HomeViewState extends State<HomeView> with WidgetsBindingObserver {
NotificationListener<ScrollNotification>( NotificationListener<ScrollNotification>(
onNotification: _onPageView, onNotification: _onPageView,
child: Positioned.fill( child: Positioned.fill(
child: PageView( child: CustomScrollView(
scrollDirection: Axis.horizontal,
physics: const PageScrollPhysics(),
controller: _homeViewPageController, controller: _homeViewPageController,
onPageChanged: (index) { scrollCacheExtent: const ScrollCacheExtent.viewport(1),
setState(() { slivers: [
_activePageIdx = index; SliverFillViewport(
}); delegate: SliverChildListDelegate([
},
children: [
const ChatListView(), const ChatListView(),
Container(), Container(),
const MemoriesView(), const MemoriesView(),
]),
),
], ],
), ),
), ),

View file

@ -21,7 +21,7 @@ class MemoriesView extends StatefulWidget {
State<MemoriesView> createState() => MemoriesViewState(); State<MemoriesView> createState() => MemoriesViewState();
} }
class MemoriesViewState extends State<MemoriesView> { class MemoriesViewState extends State<MemoriesView> with AutomaticKeepAliveClientMixin<MemoriesView> {
late final MemoriesService _service; late final MemoriesService _service;
final ValueNotifier<String?> _activeMediaIdNotifier = ValueNotifier(null); final ValueNotifier<String?> _activeMediaIdNotifier = ValueNotifier(null);
final ScrollController _scrollController = ScrollController(); final ScrollController _scrollController = ScrollController();
@ -38,6 +38,9 @@ class MemoriesViewState extends State<MemoriesView> {
_activeMediaIdNotifier.addListener(_onActiveMediaChanged); _activeMediaIdNotifier.addListener(_onActiveMediaChanged);
} }
@override
bool get wantKeepAlive => true;
@override @override
void dispose() { void dispose() {
_activeMediaIdNotifier.removeListener(_onActiveMediaChanged); _activeMediaIdNotifier.removeListener(_onActiveMediaChanged);
@ -369,6 +372,7 @@ class MemoriesViewState extends State<MemoriesView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context);
return Scaffold( return Scaffold(
body: Stack( body: Stack(
fit: StackFit.expand, fit: StackFit.expand,

View file

@ -3,7 +3,6 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:twonly/locator.dart'; import 'package:twonly/locator.dart';
import 'package:twonly/src/services/user.service.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
List<Widget> parseMarkdown(BuildContext context, String markdown) { List<Widget> parseMarkdown(BuildContext context, String markdown) {
@ -107,20 +106,6 @@ class _ChangeLogViewState extends State<ChangeLogView> {
), ),
), ),
), ),
bottomNavigationBar: BottomAppBar(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(context.lang.openChangeLog),
Switch.adaptive(
value: !userService.currentUser.hideChangeLog,
onChanged: (_) => UserService.update(
(u) => u.hideChangeLog = !u.hideChangeLog,
),
),
],
),
),
); );
}, },
); );