Commit 2b238698 authored by Wilko Manger's avatar Wilko Manger

Merge branch 'swipe_images' into 'master'

Swipe images

Closes #47

See merge request pattle/app!11
parents b3905c4e fce777d2
// Copyright (C) 2019 Nathan van Beelen (CLA signed)
//
// 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 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/ui/main/models/chat_item.dart';
import 'package:pattle/src/ui/main/sync_bloc.dart';
import 'package:pattle/src/ui/util/room.dart';
import 'package:rxdart/rxdart.dart';
class ImageBloc {
Room room;
ImageMessageEvent event;
ImageBloc(this.event);
PublishSubject<bool> _isLoadingEventsSubj = PublishSubject<bool>();
Stream<bool> get isLoadingEvents => _isLoadingEventsSubj.stream.distinct();
bool _isLoading = false;
bool get isLoading => _isLoading;
set isLoading(bool value) {
_isLoading = value;
if (!isLoading) {
_isLoadingEventsSubj.add(false);
} else {
// If still loading after 2 seconds, notify the UI
Future.delayed(const Duration(seconds: 2), () {
if (isLoading) {
_isLoadingEventsSubj.add(true);
}
});
}
}
PublishSubject<List<ImageMessageEvent>> _eventSubj
= PublishSubject<List<ImageMessageEvent>>();
Stream<List<ImageMessageEvent>> get events => _eventSubj.stream;
Future<void> startLoadingEvents() async {
await loadEvents();
syncBloc.stream.listen((success) async => await loadEvents());
}
Future<void> loadEvents() async {
final imageMessageEvents = List<ImageMessageEvent>();
RoomEvent event;
await for (event in room.timeline.get(allowRemote: false)) {
if (event is ImageMessageEvent) {
imageMessageEvents.add(event);
}
}
_eventSubj.add(List.of(imageMessageEvents));
}
}
// Copyright (C) 2019 Wilko Manger
// Copyright (C) 2019 Nathan van Beelen (CLA signed)
//
// This file is part of Pattle.
//
......@@ -18,39 +19,49 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/ui/main/chat/image/image_bloc.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';
import 'package:pattle/src/di.dart' as di;
class ImagePageState extends State<ImagePage> {
final me = di.getLocalUser();
ImageBloc bloc;
final ImageMessageEvent message;
ImagePageState(this.message);
var _messageSender;
var _date;
ImagePageState(this.message) {
bloc = ImageBloc(message);
bloc.room = message.room;
}
@override
void initState() {
super.initState();
bloc.startLoadingEvents();
_messageSender = message.sender;
}
@override
Widget build(BuildContext context) {
final date =
void didChangeDependencies() {
_date =
'${formatAsDate(context, message.time)}, ${formatAsTime(message.time)}';
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: Stack(
children: <Widget>[
PhotoView(
imageProvider: MatrixImage(message.content.url),
heroTag: message.id,
minScale: PhotoViewComputedScale.contained,
),
_buildPhotoViewList(),
Positioned(
top: 0,
left: 0,
......@@ -60,10 +71,10 @@ class ImagePageState extends State<ImagePage> {
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(displayNameOf(message.sender)),
Text(displayNameOf(_messageSender)),
SizedBox(height: 2),
Text(
date,
_date,
style: Theme.of(context).textTheme.body1.copyWith(
color: Colors.white,
)
......@@ -77,6 +88,41 @@ class ImagePageState extends State<ImagePage> {
)
);
}
Widget _buildPhotoViewList() {
return StreamBuilder<List<ImageMessageEvent>>(
stream: bloc.events,
builder: (BuildContext context, AsyncSnapshot<List<ImageMessageEvent>> snapshot) {
switch(snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
case ConnectionState.active:
case ConnectionState.done:
final events = snapshot.data;
return PhotoViewGallery.builder(
itemCount: events.length,
builder: (context, index) {
return PhotoViewGalleryPageOptions(
imageProvider: MatrixImage(events[index].content.url),
heroTag: message.id,
minScale: PhotoViewComputedScale.contained
);
},
onPageChanged: (index) {
setState(() {
_messageSender = events[index].sender;
_date =
'${formatAsDate(context, events[index].time)}, ${formatAsTime(events[index].time)}';
});
},
pageController:
PageController(initialPage: events.indexOf(message))
);
}
}
);
}
}
class ImagePage extends StatefulWidget {
......@@ -87,4 +133,4 @@ class ImagePage extends StatefulWidget {
@override
State<StatefulWidget> createState() => ImagePageState(message);
}
\ No newline at end of file
}
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