Commit 447aa390 authored by Wilko Manger's avatar Wilko Manger

Use MatrixImage and FutureOrBuilder dependencies

parent f69511ab
......@@ -19,12 +19,12 @@ import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:matrix_image/matrix_image.dart';
import 'package:meta/meta.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/sentry.dart';
import 'package:pattle/src/ui/main/sync_bloc.dart';
import 'package:pattle/src/ui/util/matrix_cache_manager.dart';
import 'package:pattle/src/ui/util/room.dart';
import 'package:pattle/src/ui/util/user.dart';
import 'package:respect_24_hour/respect_24_hour.dart';
......@@ -88,7 +88,7 @@ class AppBloc {
final senderPerson = Person(
bot: false,
name: senderName,
icon: await cacheManager.getPathOf(
icon: await MatrixCacheManager(di.getHomeserver()).getPathOf(
event.sender.avatarUrl.toString(),
),
iconSource: IconSource.FilePath,
......
......@@ -18,7 +18,9 @@ import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:future_or_builder/future_or_builder.dart';
import 'package:image_picker/image_picker.dart';
import 'package:matrix_image/matrix_image.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/app.dart';
import 'package:pattle/src/ui/main/chat/chat_bloc.dart';
......@@ -32,8 +34,6 @@ import 'package:pattle/src/ui/main/widgets/title_with_sub.dart';
import 'package:pattle/src/ui/resources/localizations.dart';
import 'package:pattle/src/ui/resources/theme.dart';
import 'package:pattle/src/ui/util/color.dart';
import 'package:pattle/src/ui/util/future_or_builder.dart';
import 'package:pattle/src/ui/util/matrix_image.dart';
import 'package:pattle/src/di.dart' as di;
import 'package:pattle/src/ui/util/room.dart';
......@@ -105,6 +105,7 @@ class ChatPageState extends State<ChatPage> {
avatarUrl,
width: 64,
height: 64,
homeserver: di.getHomeserver(),
),
),
);
......
......@@ -16,12 +16,12 @@
// You should have received a copy of the GNU Affero General Public License
// along with Pattle. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:matrix_image/matrix_image.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/ui/main/chat/image/image_bloc.dart';
import 'package:pattle/src/ui/main/models/chat_item.dart';
import 'package:pattle/src/ui/util/date_format.dart';
import 'package:pattle/src/ui/util/user.dart';
import 'package:pattle/src/ui/util/matrix_image.dart';
import 'package:photo_view/photo_view.dart';
import 'package:photo_view/photo_view_gallery.dart';
......@@ -111,7 +111,10 @@ class ImagePageState extends State<ImagePage> {
reverse: true,
builder: (context, index) {
return PhotoViewGalleryPageOptions(
imageProvider: MatrixImage(events[index].content.url),
imageProvider: MatrixImage(
events[index].content.url,
homeserver: di.getHomeserver(),
),
heroTag: message.id,
minScale: PhotoViewComputedScale.contained,
);
......
......@@ -17,6 +17,8 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:future_or_builder/future_or_builder.dart';
import 'package:matrix_image/matrix_image.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/ui/main/chat/settings/chat_settings_bloc.dart';
import 'package:pattle/src/ui/main/widgets/chat_name.dart';
......@@ -26,8 +28,6 @@ import 'package:pattle/src/ui/resources/theme.dart';
import 'package:pattle/src/di.dart' as di;
import 'package:pattle/src/ui/util/color.dart';
import 'package:pattle/src/ui/util/future_or_builder.dart';
import 'package:pattle/src/ui/util/matrix_image.dart';
import 'package:pattle/src/ui/util/room.dart';
class ChatSettingsPageState extends State<ChatSettingsPage> {
......@@ -78,7 +78,10 @@ class ChatSettingsPageState extends State<ChatSettingsPage> {
),
),
background: Image(
image: MatrixImage(avatarUrlOf(room)),
image: MatrixImage(
avatarUrlOf(room),
homeserver: di.getHomeserver(),
),
fit: BoxFit.cover,
),
),
......
......@@ -16,10 +16,12 @@
// along with Pattle. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:matrix_image/matrix_image.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/app.dart';
import 'package:pattle/src/ui/main/models/chat_item.dart';
import 'package:pattle/src/ui/util/matrix_image.dart';
import 'package:pattle/src/di.dart' as di;
import 'bubble.dart';
import 'message_bubble.dart';
......@@ -145,7 +147,10 @@ class ImageBubbleState extends MessageBubbleState<ImageBubble> {
child: Hero(
tag: widget.event.id,
child: Image(
image: MatrixImage(widget.event.content.url),
image: MatrixImage(
widget.event.content.url,
homeserver: di.getHomeserver(),
),
fit: BoxFit.cover,
),
),
......
......@@ -17,10 +17,10 @@
// along with Pattle. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:future_or_builder/future_or_builder.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/ui/main/models/chat_item.dart';
import 'package:pattle/src/ui/resources/localizations.dart';
import 'package:pattle/src/ui/util/future_or_builder.dart';
import 'package:pattle/src/ui/util/user.dart';
import 'state_bubble.dart';
......
......@@ -16,10 +16,10 @@
// along with Pattle. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:future_or_builder/future_or_builder.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/ui/main/models/chat_item.dart';
import 'package:pattle/src/ui/util/color.dart';
import 'package:pattle/src/ui/util/future_or_builder.dart';
import 'package:pattle/src/ui/util/user.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:pattle/src/di.dart' as di;
......
......@@ -16,13 +16,14 @@
// along with Pattle. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:matrix_image/matrix_image.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:mdi/mdi.dart';
import 'package:pattle/src/ui/resources/theme.dart';
import 'package:pattle/src/ui/util/matrix_image.dart';
import 'package:pattle/src/ui/util/room.dart';
import 'package:pattle/src/ui/util/user.dart';
import 'package:transparent_image/transparent_image.dart';
import 'package:pattle/src/di.dart' as di;
class ChatAvatar extends StatelessWidget {
final Room room;
......@@ -42,7 +43,12 @@ class ChatAvatar extends StatelessWidget {
child: FadeInImage(
fit: BoxFit.cover,
placeholder: MemoryImage(kTransparentImage),
image: MatrixImage(avatarUrl, width: 64, height: 64),
image: MatrixImage(
avatarUrl,
width: 64,
height: 64,
homeserver: di.getHomeserver(),
),
),
),
),
......
......@@ -16,9 +16,9 @@
// along with Pattle. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:future_or_builder/future_or_builder.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:meta/meta.dart';
import 'package:pattle/src/ui/util/future_or_builder.dart';
import 'package:pattle/src/ui/util/room.dart';
class ChatName extends StatelessWidget {
......
......@@ -16,9 +16,10 @@
// along with Pattle. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:matrix_image/matrix_image.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/ui/util/matrix_image.dart';
import 'package:pattle/src/ui/util/user.dart';
import 'package:pattle/src/di.dart' as di;
class UserAvatar extends StatelessWidget {
final User user;
......@@ -36,6 +37,7 @@ class UserAvatar extends StatelessWidget {
user.avatarUrl,
width: 64,
height: 64,
homeserver: di.getHomeserver(),
),
);
} else {
......
......@@ -18,12 +18,12 @@ import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:future_or_builder/future_or_builder.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/app.dart';
import 'package:pattle/src/app_bloc.dart';
import 'package:pattle/src/ui/resources/localizations.dart';
import 'package:pattle/src/ui/start/start_bloc.dart';
import 'package:pattle/src/ui/util/future_or_builder.dart';
import '../../../request_state.dart';
......
// Copyright (C) 2019 wilko
//
// This file is part of Pattle.
//
// Pattle is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Pattle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Pattle. If not, see <https://www.gnu.org/licenses/>.
import 'dart:async';
import 'package:flutter/widgets.dart';
/// Builds immediately if the `FutureOr` is the `T`,
/// other wise build a `FutureBuilder`.
class FutureOrBuilder<T> extends StatelessWidget {
final FutureOr<T> futureOr;
final AsyncWidgetBuilder<T> builder;
const FutureOrBuilder({
Key key,
@required this.futureOr,
@required this.builder,
}) : super(key: key);
@override
Widget build(BuildContext context) {
if (futureOr is T) {
return builder(
context,
AsyncSnapshot.withData(
ConnectionState.done,
futureOr,
),
);
} else {
return FutureBuilder<T>(
future: futureOr,
builder: builder,
);
}
}
}
// Copyright (C) 2019 Wilko Manger
//
// This file is part of Pattle.
//
// Pattle is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Pattle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Pattle. If not, see <https://www.gnu.org/licenses/>.
import 'dart:typed_data';
import 'package:pattle/src/di.dart' as di;
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import 'package:url/url.dart';
final cacheManager = MatrixCacheManager();
class MatrixCacheManager extends BaseCacheManager {
static const key = 'matrix';
static final homeserver = di.getHomeserver();
MatrixCacheManager() : super(key, fileFetcher: _fetch);
Future<String> getPathOf(String url) async {
final info = await getFileFromCache(url);
return info?.file?.path;
}
@override
Future<String> getFilePath() async {
var directory = await getTemporaryDirectory();
return p.join(directory.path, key);
}
static Future<FileFetcherResponse> _fetch(
String url, {
Map<String, String> headers,
}) async {
final parsedUrl = Url.parse(url);
int width, height;
try {
width = int.parse(headers['width']);
height = int.parse(headers['height']);
} on FormatException {
width = null;
height = null;
}
Stream<List<int>> stream;
if (width != null && height != null) {
stream = await homeserver.downloadThumbnail(
parsedUrl,
width: width,
height: height,
);
} else {
stream = await homeserver.download(parsedUrl);
}
final bytes = List<int>();
await for (final part in stream) {
bytes.addAll(part);
}
return MatrixFileFetcherResponse(Uint8List.fromList(bytes));
}
}
class MatrixFileFetcherResponse implements FileFetcherResponse {
@override
final Uint8List bodyBytes;
MatrixFileFetcherResponse(this.bodyBytes);
@override
bool hasHeader(String name) => false;
@override
String header(String name) => null;
@override
get statusCode => 200;
}
// Copyright (C) 2019 Wilko Manger
//
// This file is part of Pattle.
//
// Pattle is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Pattle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Pattle. If not, see <https://www.gnu.org/licenses/>.
import 'dart:typed_data';
import 'dart:ui';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:url/url.dart';
import 'matrix_cache_manager.dart';
class MatrixImage extends ImageProvider<MatrixImage> {
/// Matrix URL pointing to the image.
final Url url;
final double scale;
final int width, height;
/// A Matrx image. If width and height are provided, downloads a thumbnail.
const MatrixImage(this.url, {this.scale = 1.0, this.width, this.height});
Future<Codec> _load(MatrixImage key) async {
final file = await cacheManager.getSingleFile(
key.url.toString(),
headers: {
'width': key.width.toString(),
'height': key.height.toString(),
},
);
if (file == null) {
return null;
}
final bytes = Uint8List.fromList(await file.readAsBytes());
return PaintingBinding.instance.instantiateImageCodec(bytes);
}
@override
ImageStreamCompleter load(MatrixImage key) {
return MultiFrameImageStreamCompleter(
codec: _load(key),
scale: key.scale,
);
}
@override
Future<MatrixImage> obtainKey(ImageConfiguration configuration) {
return SynchronousFuture<MatrixImage>(this);
}
@override
bool operator ==(dynamic other) {
if (other.runtimeType != runtimeType) return false;
final MatrixImage typedOther = other;
return url == typedOther.url && scale == typedOther.scale;
}
@override
int get hashCode => hashValues(url, scale);
}
......@@ -119,7 +119,7 @@ packages:
source: sdk
version: "0.0.0"
flutter_cache_manager:
dependency: "direct main"
dependency: transitive
description:
name: flutter_cache_manager
url: "https://pub.dartlang.org"
......@@ -165,6 +165,13 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
future_or_builder:
dependency: "direct main"
description:
name: future_or_builder
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
html:
dependency: transitive
description:
......@@ -235,13 +242,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.5"
matrix_image:
dependency: "direct main"
description:
name: matrix_image
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.5"
matrix_sdk:
dependency: "direct main"
description:
name: matrix_sdk
url: "https://pub.dartlang.org"
source: hosted
version: "0.27.0"
version: "0.27.1"
matrix_sdk_sqflite:
dependency: "direct main"
description:
......@@ -437,7 +451,7 @@ packages:
name: url
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
version: "2.0.0"
url_launcher:
dependency: "direct main"
description:
......
......@@ -15,6 +15,9 @@ dependencies:
matrix_sdk: ^0.27.0
matrix_sdk_sqflite: ^0.20.0
matrix_image: ^1.0.5
future_or_builder: ^1.0.3
sqflite: ^1.1.6
rxdart: ^0.22.0
......@@ -25,8 +28,6 @@ dependencies:
sentry:
git: https://git.pattle.im/forks/sentry.git
flutter_cache_manager: ^1.1.0
device_info: ^0.4.1+1
package_info: ^0.4.0+5
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment