Compare commits

..

3 Commits

10 changed files with 57 additions and 48 deletions

View File

@ -3,7 +3,6 @@ import 'dart:io';
import 'package:cryptography/cryptography.dart'; import 'package:cryptography/cryptography.dart';
import 'package:get_it/get_it.dart'; import 'package:get_it/get_it.dart';
import 'package:hex/hex.dart'; import 'package:hex/hex.dart';
import 'package:image_size_getter/image_size_getter.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:moxlib/moxlib.dart'; import 'package:moxlib/moxlib.dart';
import 'package:moxxmpp/moxxmpp.dart'; import 'package:moxxmpp/moxxmpp.dart';
@ -14,6 +13,7 @@ import 'package:moxxyv2/service/service.dart';
import 'package:moxxyv2/service/xmpp.dart'; import 'package:moxxyv2/service/xmpp.dart';
import 'package:moxxyv2/shared/avatar.dart'; import 'package:moxxyv2/shared/avatar.dart';
import 'package:moxxyv2/shared/events.dart'; import 'package:moxxyv2/shared/events.dart';
import 'package:moxxyv2/shared/helpers.dart';
/// Removes line breaks and spaces from [original]. This might happen when we request the /// Removes line breaks and spaces from [original]. This might happen when we request the
/// avatar data. Returns the cleaned version. /// avatar data. Returns the cleaned version.
@ -158,7 +158,7 @@ class AvatarService {
final public = prefs.isAvatarPublic; final public = prefs.isAvatarPublic;
// Read the image metadata // Read the image metadata
final imageSize = ImageSizeGetter.getSize(MemoryInput(bytes)); final imageSize = (await getImageSizeFromData(bytes))!;
// Publish data and metadata // Publish data and metadata
final manager = _getUserAvatarManager(); final manager = _getUserAvatarManager();
@ -171,8 +171,8 @@ class AvatarService {
UserAvatarMetadata( UserAvatarMetadata(
hash, hash,
bytes.length, bytes.length,
imageSize.width, imageSize.width.toInt(),
imageSize.height, imageSize.height.toInt(),
// TODO(PapaTutuWawa): Maybe do a check here // TODO(PapaTutuWawa): Maybe do a check here
'image/png', 'image/png',
), ),

View File

@ -6,8 +6,6 @@ import 'dart:math';
import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:dio/dio.dart' as dio; import 'package:dio/dio.dart' as dio;
import 'package:get_it/get_it.dart'; import 'package:get_it/get_it.dart';
import 'package:image_size_getter/file_input.dart';
import 'package:image_size_getter/image_size_getter.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:mime/mime.dart'; import 'package:mime/mime.dart';
import 'package:moxplatform/moxplatform.dart'; import 'package:moxplatform/moxplatform.dart';
@ -24,6 +22,7 @@ import 'package:moxxyv2/service/notifications.dart';
import 'package:moxxyv2/service/service.dart'; import 'package:moxxyv2/service/service.dart';
import 'package:moxxyv2/shared/error_types.dart'; import 'package:moxxyv2/shared/error_types.dart';
import 'package:moxxyv2/shared/events.dart'; import 'package:moxxyv2/shared/events.dart';
import 'package:moxxyv2/shared/helpers.dart';
import 'package:moxxyv2/shared/warning_types.dart'; import 'package:moxxyv2/shared/warning_types.dart';
import 'package:path/path.dart' as pathlib; import 'package:path/path.dart' as pathlib;
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
@ -438,16 +437,13 @@ class HttpFileTransferService {
MoxplatformPlugin.media.scanFile(downloadedPath); MoxplatformPlugin.media.scanFile(downloadedPath);
// Find out the dimensions // Find out the dimensions
// TODO(Unknown): Restrict to the library's supported file types final imageSize = await getImageSizeFromPath(downloadedPath);
Size? size; if (imageSize == null) {
try { _log.warning('Failed to get image size for $downloadedPath');
size = ImageSizeGetter.getSize(FileInput(File(downloadedPath)));
} catch (ex) {
_log.warning('Failed to get image size for $downloadedPath: $ex');
} }
mediaWidth = size?.width; mediaWidth = imageSize?.width.toInt();
mediaHeight = size?.height; mediaHeight = imageSize?.height.toInt();
} else if (mime.startsWith('video/')) { } else if (mime.startsWith('video/')) {
// TODO(Unknown): Also figure out the thumbnail size here // TODO(Unknown): Also figure out the thumbnail size here
MoxplatformPlugin.media.scanFile(downloadedPath); MoxplatformPlugin.media.scanFile(downloadedPath);

View File

@ -3,8 +3,6 @@ import 'dart:io';
import 'dart:ui'; import 'dart:ui';
import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:get_it/get_it.dart'; import 'package:get_it/get_it.dart';
import 'package:image_size_getter/file_input.dart';
import 'package:image_size_getter/image_size_getter.dart' as image_size;
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:mime/mime.dart'; import 'package:mime/mime.dart';
import 'package:moxlib/moxlib.dart'; import 'package:moxlib/moxlib.dart';
@ -375,13 +373,13 @@ class XmppService {
// TODO(Unknown): Do the same for videos // TODO(Unknown): Do the same for videos
if (pathMime != null && pathMime.startsWith('image/')) { if (pathMime != null && pathMime.startsWith('image/')) {
try { final imageSize = await getImageSizeFromPath(path);
final imageSize = image_size.ImageSizeGetter.getSize(FileInput(File(path))); if (imageSize != null) {
dimensions[path] = Size( dimensions[path] = Size(
imageSize.width.toDouble(), imageSize.width,
imageSize.height.toDouble(), imageSize.height,
); );
} catch (ex) { } else {
_log.warning('Failed to get image dimensions for $path'); _log.warning('Failed to get image dimensions for $path');
} }
} }

View File

@ -1,4 +1,7 @@
import 'dart:core'; import 'dart:core';
import 'dart:io';
import 'dart:typed_data';
import 'dart:ui';
import 'package:moxxyv2/i18n/strings.g.dart'; import 'package:moxxyv2/i18n/strings.g.dart';
import 'package:moxxyv2/shared/models/message.dart'; import 'package:moxxyv2/shared/models/message.dart';
import 'package:synchronized/synchronized.dart'; import 'package:synchronized/synchronized.dart';
@ -317,3 +320,31 @@ String fileSizeToString(int size) {
return '$size B'; return '$size B';
} }
} }
/// Load [path] into memory and determine its width and height. Returns null in case
/// of an error.
Future<Size?> getImageSizeFromPath(String path) async {
final bytes = await File(path).readAsBytes();
return getImageSizeFromData(bytes);
}
/// Like getImageSizeFromPath but taking the image's bytes directly.
Future<Size?> getImageSizeFromData(Uint8List bytes) async {
try {
final dartCodec = await instantiateImageCodec(bytes);
final dartFrame = await dartCodec.getNextFrame();
final size = Size(
dartFrame.image.width.toDouble(),
dartFrame.image.height.toDouble(),
);
dartFrame.image.dispose();
dartCodec.dispose();
return size;
} catch (_) {
// TODO(PapaTutuWawa): Log error
return null;
}
}

View File

@ -99,6 +99,9 @@ class Conversation with _$Conversation {
'lastMessage': lastMessage?.id, 'lastMessage': lastMessage?.id,
}; };
} }
/// True, when the chat state of the conversation indicates typing. False, if not.
bool get isTyping => chatState == ChatState.composing;
} }
/// Sorts conversations in descending order by their last change timestamp. /// Sorts conversations in descending order by their last change timestamp.

View File

@ -5,7 +5,7 @@ import 'package:bloc/bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:get_it/get_it.dart'; import 'package:get_it/get_it.dart';
import 'package:image/image.dart'; import 'package:image/image.dart';
import 'package:image_size_getter/image_size_getter.dart'; import 'package:moxxyv2/shared/helpers.dart';
import 'package:moxxyv2/ui/bloc/navigation_bloc.dart'; import 'package:moxxyv2/ui/bloc/navigation_bloc.dart';
import 'package:moxxyv2/ui/bloc/preferences_bloc.dart'; import 'package:moxxyv2/ui/bloc/preferences_bloc.dart';
import 'package:moxxyv2/ui/constants.dart'; import 'package:moxxyv2/ui/constants.dart';
@ -81,13 +81,13 @@ class CropBackgroundBloc extends Bloc<CropBackgroundEvent, CropBackgroundState>
); );
final data = await File(event.path).readAsBytes(); final data = await File(event.path).readAsBytes();
final imageSize = ImageSizeGetter.getSize(MemoryInput(data)); final imageSize = (await getImageSizeFromData(data))!;
emit( emit(
state.copyWith( state.copyWith(
image: data, image: data,
imagePath: event.path, imagePath: event.path,
imageWidth: imageSize.width, imageWidth: imageSize.width.toInt(),
imageHeight: imageSize.height, imageHeight: imageSize.height.toInt(),
), ),
); );
} }

View File

@ -5,6 +5,7 @@ import 'package:moxxyv2/i18n/strings.g.dart';
import 'package:moxxyv2/ui/bloc/crop_bloc.dart'; import 'package:moxxyv2/ui/bloc/crop_bloc.dart';
import 'package:moxxyv2/ui/constants.dart'; import 'package:moxxyv2/ui/constants.dart';
import 'package:moxxyv2/ui/widgets/button.dart'; import 'package:moxxyv2/ui/widgets/button.dart';
import 'package:moxxyv2/ui/widgets/cancel_button.dart';
class CropPage extends StatelessWidget { class CropPage extends StatelessWidget {
CropPage({ super.key }) : _controller = CropController(); CropPage({ super.key }) : _controller = CropController();
@ -42,11 +43,7 @@ class CropPage extends StatelessWidget {
top: 10, top: 10,
child: Material( child: Material(
color: const Color.fromRGBO(0, 0, 0, 0), color: const Color.fromRGBO(0, 0, 0, 0),
child: IconButton( child: CancelButton(
icon: const Icon(
Icons.arrow_back,
size: 32,
),
onPressed: () => Navigator.of(context).pop(), onPressed: () => Navigator.of(context).pop(),
), ),
), ),

View File

@ -2,7 +2,6 @@ import 'dart:async';
import 'package:badges/badges.dart'; import 'package:badges/badges.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart'; import 'package:get_it/get_it.dart';
import 'package:moxxmpp/moxxmpp.dart';
import 'package:moxxyv2/i18n/strings.g.dart'; import 'package:moxxyv2/i18n/strings.g.dart';
import 'package:moxxyv2/shared/constants.dart'; import 'package:moxxyv2/shared/constants.dart';
import 'package:moxxyv2/shared/helpers.dart'; import 'package:moxxyv2/shared/helpers.dart';
@ -82,7 +81,7 @@ class ConversationsListRowState extends State<ConversationsListRow> {
} }
Widget _buildLastMessageBody() { Widget _buildLastMessageBody() {
if (widget.conversation.chatState == ChatState.composing) { if (widget.conversation.isTyping) {
return const TypingIndicatorWidget(Colors.black, Colors.white); return const TypingIndicatorWidget(Colors.black, Colors.white);
} }
@ -198,7 +197,7 @@ class ConversationsListRowState extends State<ConversationsListRow> {
child: Row( child: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
...widget.conversation.lastMessage?.isThumbnailable == true ? [ ...widget.conversation.lastMessage?.isThumbnailable == true && !widget.conversation.isTyping ? [
Padding( Padding(
padding: const EdgeInsets.only(right: 5), padding: const EdgeInsets.only(right: 5),
child: SharedImageWidget( child: SharedImageWidget(

View File

@ -523,13 +523,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.0" version: "2.1.0"
hashcodes:
dependency: transitive
description:
name: hashcodes
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
hex: hex:
dependency: "direct main" dependency: "direct main"
description: description:
@ -558,13 +551,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.2.0" version: "3.2.0"
image_size_getter:
dependency: "direct main"
description:
name: image_size_getter
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
integration_test: integration_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter

View File

@ -41,7 +41,6 @@ dependencies:
get_it: 7.2.0 get_it: 7.2.0
hex: 0.2.0 hex: 0.2.0
image: 3.2.0 image: 3.2.0
image_size_getter: 2.1.2
json_annotation: 4.6.0 json_annotation: 4.6.0
logging: 1.0.2 logging: 1.0.2
mime: 1.0.2 mime: 1.0.2