mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-06-25 08:44:08 +00:00
implement a precacheImage for faster image loading
Some checks are pending
Flutter analyze & test / flutter_analyze_and_test (push) Waiting to run
Some checks are pending
Flutter analyze & test / flutter_analyze_and_test (push) Waiting to run
This commit is contained in:
parent
e7301020f6
commit
f22e9086ed
3 changed files with 43 additions and 0 deletions
|
|
@ -66,6 +66,25 @@ class MessagesDao extends DatabaseAccessor<TwonlyDB> with _$MessagesDaoMixin {
|
||||||
return query.map((row) => row.readTable(messages)).watch();
|
return query.map((row) => row.readTable(messages)).watch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Stream<List<MediaFile>> watchUnopenedMediaFiles() {
|
||||||
|
final query =
|
||||||
|
select(messages).join([
|
||||||
|
leftOuterJoin(
|
||||||
|
mediaFiles,
|
||||||
|
mediaFiles.mediaId.equalsExp(messages.mediaId),
|
||||||
|
),
|
||||||
|
])
|
||||||
|
..where(
|
||||||
|
messages.openedAt.isNull() &
|
||||||
|
messages.mediaId.isNotNull() &
|
||||||
|
messages.type.equals(MessageType.media.name) &
|
||||||
|
mediaFiles.downloadState.equals(DownloadState.ready.name) &
|
||||||
|
(mediaFiles.type.equals(MediaType.image.name) |
|
||||||
|
mediaFiles.type.equals(MediaType.gif.name)),
|
||||||
|
);
|
||||||
|
return query.map((row) => row.readTable(mediaFiles)).watch();
|
||||||
|
}
|
||||||
|
|
||||||
Future<Stream<Message?>> watchLastMessage(String groupId) async {
|
Future<Stream<Message?>> watchLastMessage(String groupId) async {
|
||||||
final group = await twonlyDB.groupsDao.getGroup(groupId);
|
final group = await twonlyDB.groupsDao.getGroup(groupId);
|
||||||
final deletionTime = clock.now().subtract(
|
final deletionTime = clock.now().subtract(
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,10 @@ import 'package:twonly/locator.dart';
|
||||||
import 'package:twonly/src/constants/routes.keys.dart';
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
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/subscription.service.dart';
|
import 'package:twonly/src/services/subscription.service.dart';
|
||||||
import 'package:twonly/src/services/user.service.dart';
|
import 'package:twonly/src/services/user.service.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';
|
||||||
import 'package:twonly/src/visual/components/connection_status.comp.dart';
|
import 'package:twonly/src/visual/components/connection_status.comp.dart';
|
||||||
|
|
@ -34,6 +36,8 @@ class _ChatListViewState extends State<ChatListView> {
|
||||||
StreamSubscription<void>? _userSub;
|
StreamSubscription<void>? _userSub;
|
||||||
StreamSubscription<List<Group>>? _contactsSub;
|
StreamSubscription<List<Group>>? _contactsSub;
|
||||||
StreamSubscription<List<Contact>>? _contactsCountSub;
|
StreamSubscription<List<Contact>>? _contactsCountSub;
|
||||||
|
StreamSubscription<List<MediaFile>>? _precacheSub;
|
||||||
|
final Set<String> _precachedMediaIds = {};
|
||||||
List<Group> _groupsNotPinned = [];
|
List<Group> _groupsNotPinned = [];
|
||||||
List<Group> _groupsPinned = [];
|
List<Group> _groupsPinned = [];
|
||||||
List<Group> _groupsArchived = [];
|
List<Group> _groupsArchived = [];
|
||||||
|
|
@ -105,6 +109,24 @@ class _ChatListViewState extends State<ChatListView> {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_precacheSub = twonlyDB.messagesDao.watchUnopenedMediaFiles().listen((mediaFiles) {
|
||||||
|
if (!mounted) return;
|
||||||
|
for (final media in mediaFiles) {
|
||||||
|
if (!_precachedMediaIds.contains(media.mediaId)) {
|
||||||
|
_precachedMediaIds.add(media.mediaId);
|
||||||
|
final fileService = MediaFileService(media);
|
||||||
|
if (fileService.tempPath.existsSync()) {
|
||||||
|
precacheImage(
|
||||||
|
FileImage(fileService.tempPath),
|
||||||
|
context,
|
||||||
|
).catchError((Object e, StackTrace st) {
|
||||||
|
Log.error('Failed to precache image in ChatListView: $e\n$st');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||||
final changeLog = await rootBundle.loadString('CHANGELOG.md');
|
final changeLog = await rootBundle.loadString('CHANGELOG.md');
|
||||||
final changeLogHash = (await compute(
|
final changeLogHash = (await compute(
|
||||||
|
|
@ -137,6 +159,7 @@ class _ChatListViewState extends State<ChatListView> {
|
||||||
_countContactRequestStream.cancel();
|
_countContactRequestStream.cancel();
|
||||||
_countAnnouncedStream.cancel();
|
_countAnnouncedStream.cancel();
|
||||||
_userSub?.cancel();
|
_userSub?.cancel();
|
||||||
|
_precacheSub?.cancel();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -721,6 +721,7 @@ class _MediaViewerViewState extends State<MediaViewerView> {
|
||||||
imageProvider: FileImage(
|
imageProvider: FileImage(
|
||||||
currentMedia!.tempPath,
|
currentMedia!.tempPath,
|
||||||
),
|
),
|
||||||
|
loadingBuilder: (context, event) => _loader(),
|
||||||
initialScale: PhotoViewComputedScale.contained,
|
initialScale: PhotoViewComputedScale.contained,
|
||||||
minScale: PhotoViewComputedScale.contained,
|
minScale: PhotoViewComputedScale.contained,
|
||||||
errorBuilder: (context, error, stackTrace) {
|
errorBuilder: (context, error, stackTrace) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue