mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-06-25 10:54:08 +00:00
fix svg performance issue
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
83fd99ea70
commit
9daf275310
3 changed files with 73 additions and 29 deletions
|
|
@ -60,10 +60,26 @@ File avatarPNGFile(int contactId) {
|
||||||
return File('${avatarsDirectory.path}/$contactId.png');
|
return File('${avatarsDirectory.path}/$contactId.png');
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Uint8List> getUserAvatar() async {
|
File currentUserAvatarFile(int avatarCounter) {
|
||||||
|
final avatarsDirectory = Directory(
|
||||||
|
'${AppEnvironment.cacheDir}/avatars',
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!avatarsDirectory.existsSync()) {
|
||||||
|
avatarsDirectory.createSync(recursive: true);
|
||||||
|
}
|
||||||
|
return File('${avatarsDirectory.path}/user_$avatarCounter.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String?> getUserAvatar() async {
|
||||||
if (userService.currentUser.avatarSvg == null) {
|
if (userService.currentUser.avatarSvg == null) {
|
||||||
final data = await rootBundle.load('assets/images/default_avatar.png');
|
return null;
|
||||||
return data.buffer.asUint8List();
|
}
|
||||||
|
|
||||||
|
final avatarCounter = userService.currentUser.avatarCounter;
|
||||||
|
final file = currentUserAvatarFile(avatarCounter);
|
||||||
|
if (file.existsSync()) {
|
||||||
|
return file.path;
|
||||||
}
|
}
|
||||||
|
|
||||||
final pictureInfo = await vg.loadPicture(
|
final pictureInfo = await vg.loadPicture(
|
||||||
|
|
@ -76,9 +92,8 @@ Future<Uint8List> getUserAvatar() async {
|
||||||
final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
|
final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
|
||||||
final pngBytes = byteData!.buffer.asUint8List();
|
final pngBytes = byteData!.buffer.asUint8List();
|
||||||
|
|
||||||
final file = avatarPNGFile(userService.currentUser.userId)
|
await file.writeAsBytes(pngBytes);
|
||||||
..writeAsBytesSync(pngBytes);
|
|
||||||
pictureInfo.picture.dispose();
|
pictureInfo.picture.dispose();
|
||||||
|
|
||||||
return file.readAsBytesSync();
|
return file.path;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
|
@ -29,7 +30,7 @@ class AvatarIcon extends StatefulWidget {
|
||||||
|
|
||||||
class _AvatarIconState extends State<AvatarIcon> {
|
class _AvatarIconState extends State<AvatarIcon> {
|
||||||
List<Contact> _avatarContacts = [];
|
List<Contact> _avatarContacts = [];
|
||||||
String? _avatarSvg;
|
String? _myAvatarPath;
|
||||||
|
|
||||||
StreamSubscription<List<Contact>>? groupStream;
|
StreamSubscription<List<Contact>>? groupStream;
|
||||||
StreamSubscription<List<Contact>>? contactsStream;
|
StreamSubscription<List<Contact>>? contactsStream;
|
||||||
|
|
@ -101,19 +102,9 @@ class _AvatarIconState extends State<AvatarIcon> {
|
||||||
});
|
});
|
||||||
} else if (widget.myAvatar) {
|
} else if (widget.myAvatar) {
|
||||||
_userSub = userService.onUserUpdated.listen((_) {
|
_userSub = userService.onUserUpdated.listen((_) {
|
||||||
if (mounted) {
|
unawaited(_updateMyAvatar());
|
||||||
setState(() {
|
|
||||||
if (userService.currentUser.avatarSvg != null) {
|
|
||||||
_avatarSvg = userService.currentUser.avatarSvg;
|
|
||||||
} else {
|
|
||||||
_avatarContacts = [];
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
unawaited(_updateMyAvatar());
|
||||||
});
|
|
||||||
if (userService.currentUser.avatarSvg != null) {
|
|
||||||
_avatarSvg = userService.currentUser.avatarSvg;
|
|
||||||
}
|
|
||||||
} else if (widget.contactId != null) {
|
} else if (widget.contactId != null) {
|
||||||
contactStream = twonlyDB.contactsDao
|
contactStream = twonlyDB.contactsDao
|
||||||
.watchContact(widget.contactId!)
|
.watchContact(widget.contactId!)
|
||||||
|
|
@ -127,17 +118,44 @@ class _AvatarIconState extends State<AvatarIcon> {
|
||||||
if (mounted) setState(() {});
|
if (mounted) setState(() {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _updateMyAvatar() async {
|
||||||
|
final avatarSvg = userService.currentUser.avatarSvg;
|
||||||
|
if (avatarSvg == null) {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_myAvatarPath = null;
|
||||||
|
_avatarContacts = [];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final path = await getUserAvatar();
|
||||||
|
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_myAvatarPath = path;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final proSize = (widget.fontSize == null) ? 40 : (widget.fontSize! * 2);
|
final proSize = (widget.fontSize == null) ? 40 : (widget.fontSize! * 2);
|
||||||
|
|
||||||
Widget avatars = Container();
|
Widget avatars = Container();
|
||||||
|
|
||||||
if (_avatarSvg != null) {
|
if (widget.myAvatar) {
|
||||||
avatars = SvgPicture.string(
|
if (_myAvatarPath != null) {
|
||||||
_avatarSvg!,
|
avatars = Image.file(
|
||||||
|
File(_myAvatarPath!),
|
||||||
errorBuilder: errorBuilder,
|
errorBuilder: errorBuilder,
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
avatars = const SvgPicture(
|
||||||
|
AssetBytesLoader('assets/images/default_avatar.svg.vec'),
|
||||||
|
);
|
||||||
|
}
|
||||||
} else if (_avatarContacts.length == 1) {
|
} else if (_avatarContacts.length == 1) {
|
||||||
avatars = getAvatarForContact(_avatarContacts.first);
|
avatars = getAvatarForContact(_avatarContacts.first);
|
||||||
} else if (_avatarContacts.length >= 2) {
|
} else if (_avatarContacts.length >= 2) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:typed_data';
|
import 'dart:io';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:qr_flutter/qr_flutter.dart';
|
import 'package:qr_flutter/qr_flutter.dart';
|
||||||
import 'package:twonly/src/utils/avatars.dart';
|
import 'package:twonly/src/utils/avatars.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
|
@ -32,11 +33,20 @@ class _ProfileQrCodeCompState extends State<ProfileQrCodeComp> {
|
||||||
|
|
||||||
Future<void> _loadData() async {
|
Future<void> _loadData() async {
|
||||||
final qr = await QrCodeUtils.publicProfileLink();
|
final qr = await QrCodeUtils.publicProfileLink();
|
||||||
final avatar = widget.showAvatar ? await getUserAvatar() : null;
|
Uint8List? avatarBytes;
|
||||||
|
if (widget.showAvatar) {
|
||||||
|
final avatarPath = await getUserAvatar();
|
||||||
|
if (avatarPath != null) {
|
||||||
|
avatarBytes = await File(avatarPath).readAsBytes();
|
||||||
|
} else {
|
||||||
|
final data = await rootBundle.load('assets/images/default_avatar.png');
|
||||||
|
avatarBytes = data.buffer.asUint8List();
|
||||||
|
}
|
||||||
|
}
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_qrCode = qr;
|
_qrCode = qr;
|
||||||
_userAvatar = avatar;
|
_userAvatar = avatarBytes;
|
||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -53,7 +63,6 @@ class _ProfileQrCodeCompState extends State<ProfileQrCodeComp> {
|
||||||
child: loaded
|
child: loaded
|
||||||
? Container(
|
? Container(
|
||||||
key: const ValueKey('qr_code_container'),
|
key: const ValueKey('qr_code_container'),
|
||||||
// padding: const EdgeInsets.all(3),
|
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: context.color.primary,
|
color: context.color.primary,
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
|
@ -79,7 +88,9 @@ class _ProfileQrCodeCompState extends State<ProfileQrCodeComp> {
|
||||||
borderRadius: 2,
|
borderRadius: 2,
|
||||||
),
|
),
|
||||||
gapless: false,
|
gapless: false,
|
||||||
embeddedImage: (widget.showAvatar && _userAvatar != null) ? MemoryImage(_userAvatar!) : null,
|
embeddedImage: (widget.showAvatar && _userAvatar != null)
|
||||||
|
? MemoryImage(_userAvatar!)
|
||||||
|
: null,
|
||||||
embeddedImageStyle: QrEmbeddedImageStyle(
|
embeddedImageStyle: QrEmbeddedImageStyle(
|
||||||
size: const Size(60, 66),
|
size: const Size(60, 66),
|
||||||
embeddedImageShape: EmbeddedImageShape.square,
|
embeddedImageShape: EmbeddedImageShape.square,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue