Merge pull request 'Fix Debug Errors + Implement Scroll To on DM' (#481) from fix_308 into trunk

Reviewed-on: cwtch.im/cwtch-ui#481
This commit is contained in:
Dan Ballard 2022-06-20 19:10:32 +00:00
commit a83b357f0f
7 changed files with 73 additions and 35 deletions

7
.gitignore vendored
View File

@ -40,10 +40,17 @@ app.*.symbols
# Obfuscation related # Obfuscation related
app.*.map.json app.*.map.json
# Tor
data-dir*
# Compiled Libs
linux/tor linux/tor
linux/libCwtch.so linux/libCwtch.so
android/cwtch/cwtch.aar android/cwtch/cwtch.aar
android/app/src/main/jniLibs/*/libtor.so android/app/src/main/jniLibs/*/libtor.so
libCwtch.dylib
coverage coverage
test/failures test/failures
.gradle .gradle

View File

@ -21,7 +21,7 @@ class ContactListState extends ChangeNotifier {
} }
List<ContactInfoState> filteredList() { List<ContactInfoState> filteredList() {
if (!isFiltered) return contacts; if (!isFiltered) return _contacts;
return _contacts.where((ContactInfoState c) => c.onion.toLowerCase().startsWith(_filter) || (c.nickname.toLowerCase().contains(_filter))).toList(); return _contacts.where((ContactInfoState c) => c.onion.toLowerCase().startsWith(_filter) || (c.nickname.toLowerCase().contains(_filter))).toList();
} }

View File

@ -2,6 +2,7 @@ import 'dart:convert';
import 'package:cwtch/models/remoteserver.dart'; import 'package:cwtch/models/remoteserver.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
import 'contact.dart'; import 'contact.dart';
import 'contactlist.dart'; import 'contactlist.dart';
@ -20,7 +21,7 @@ class ProfileInfoState extends ChangeNotifier {
bool _online = false; bool _online = false;
Map<String, FileDownloadProgress> _downloads = Map<String, FileDownloadProgress>(); Map<String, FileDownloadProgress> _downloads = Map<String, FileDownloadProgress>();
Map<String, int> _downloadTriggers = Map<String, int>(); Map<String, int> _downloadTriggers = Map<String, int>();
ItemScrollController contactListScrollController = new ItemScrollController();
// assume profiles are encrypted...this will be set to false // assume profiles are encrypted...this will be set to false
// in the constructor if the profile is encrypted with the defacto password. // in the constructor if the profile is encrypted with the defacto password.
bool _encrypted = true; bool _encrypted = true;

View File

@ -12,6 +12,7 @@ import 'package:cwtch/widgets/profileimage.dart';
import 'package:cwtch/widgets/textfield.dart'; import 'package:cwtch/widgets/textfield.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
import '../main.dart'; import '../main.dart';
import '../settings.dart'; import '../settings.dart';
import 'addcontactview.dart'; import 'addcontactview.dart';
@ -35,6 +36,7 @@ void selectConversation(BuildContext context, int handle) {
Provider.of<ProfileInfoState>(context, listen: false).contactList.getContact(previouslySelected)!.unselected(); Provider.of<ProfileInfoState>(context, listen: false).contactList.getContact(previouslySelected)!.unselected();
} }
Provider.of<ProfileInfoState>(context, listen: false).contactList.getContact(handle)!.selected(); Provider.of<ProfileInfoState>(context, listen: false).contactList.getContact(handle)!.selected();
// triggers update in Double/TripleColumnView // triggers update in Double/TripleColumnView
Provider.of<AppState>(context, listen: false).initialScrollIndex = unread; Provider.of<AppState>(context, listen: false).initialScrollIndex = unread;
Provider.of<AppState>(context, listen: false).selectedConversation = handle; Provider.of<AppState>(context, listen: false).selectedConversation = handle;
@ -86,29 +88,35 @@ class _ContactsViewState extends State<ContactsView> {
endDrawerEnableOpenDragGesture: false, endDrawerEnableOpenDragGesture: false,
drawerEnableOpenDragGesture: false, drawerEnableOpenDragGesture: false,
appBar: AppBar( appBar: AppBar(
leading: Row(children: [ leading: Stack(children: [
IconButton( Align(
icon: Icon(Icons.arrow_back), alignment: Alignment.center,
tooltip: MaterialLocalizations.of(context).backButtonTooltip, child: IconButton(
onPressed: () { icon: Icon(Icons.arrow_back),
Provider.of<ProfileInfoState>(context, listen: false).recountUnread(); tooltip: MaterialLocalizations.of(context).backButtonTooltip,
Provider.of<AppState>(context, listen: false).selectedProfile = ""; onPressed: () {
Navigator.of(context).pop(); Provider.of<ProfileInfoState>(context, listen: false).recountUnread();
}, Provider.of<AppState>(context, listen: false).selectedProfile = "";
), Navigator.of(context).pop();
StreamBuilder<bool>( },
stream: Provider.of<AppState>(context).getUnreadProfileNotifyStream(), )),
builder: (BuildContext context, AsyncSnapshot<bool> unreadCountSnapshot) { Positioned(
int unreadCount = Provider.of<ProfileListState>(context).generateUnreadCount(Provider.of<AppState>(context).selectedProfile ?? ""); bottom: 5.0,
right: 5.0,
child: StreamBuilder<bool>(
stream: Provider.of<AppState>(context).getUnreadProfileNotifyStream(),
builder: (BuildContext context, AsyncSnapshot<bool> unreadCountSnapshot) {
int unreadCount = Provider.of<ProfileListState>(context).generateUnreadCount(Provider.of<AppState>(context).selectedProfile ?? "");
return Visibility( return Visibility(
visible: unreadCount > 0, visible: unreadCount > 0,
child: CircleAvatar( child: CircleAvatar(
radius: 10.0, radius: 10.0,
backgroundColor: Provider.of<Settings>(context).theme.portraitProfileBadgeColor, backgroundColor: Provider.of<Settings>(context).theme.portraitProfileBadgeColor,
child: Text(unreadCount > 99 ? "99+" : unreadCount.toString(), style: TextStyle(color: Provider.of<Settings>(context).theme.portraitProfileBadgeTextColor, fontSize: 8.0)), child: Text(unreadCount > 99 ? "99+" : unreadCount.toString(), style: TextStyle(color: Provider.of<Settings>(context).theme.portraitProfileBadgeTextColor, fontSize: 8.0)),
)); ));
}), }),
)
]), ]),
title: RepaintBoundary( title: RepaintBoundary(
child: Row(children: [ child: Row(children: [
@ -207,11 +215,28 @@ class _ContactsViewState extends State<ContactsView> {
); );
}); });
final divided = ListTile.divideTiles( var initialScroll =
context: context, Provider.of<ProfileInfoState>(context, listen: false).contactList.filteredList().indexWhere((element) => element.identifier == Provider.of<AppState>(context).selectedConversation);
tiles: tiles, if (initialScroll < 0) {
).toList(); initialScroll = 0;
return RepaintBoundary(child: ListView(children: divided)); }
var contactList = ScrollablePositionedList.separated(
itemScrollController: Provider.of<ProfileInfoState>(context).contactListScrollController,
itemCount: Provider.of<ContactListState>(context).num,
initialScrollIndex: initialScroll,
shrinkWrap: true,
physics: BouncingScrollPhysics(),
semanticChildCount: Provider.of<ContactListState>(context).num,
itemBuilder: (context, index) {
return tiles.elementAt(index);
},
separatorBuilder: (BuildContext context, int index) {
return Divider(height: 1);
},
);
return RepaintBoundary(child: contactList);
} }
void _pushAddContact(bool newGroup) { void _pushAddContact(bool newGroup) {

View File

@ -144,7 +144,7 @@ class _MessageViewState extends State<MessageView> {
onPressed: () { onPressed: () {
Provider.of<AppState>(context, listen: false).initialScrollIndex = 0; Provider.of<AppState>(context, listen: false).initialScrollIndex = 0;
Provider.of<AppState>(context, listen: false).unreadMessagesBelow = false; Provider.of<AppState>(context, listen: false).unreadMessagesBelow = false;
Provider.of<ContactInfoState>(context).messageScrollController.scrollTo(index: 0, duration: Duration(milliseconds: 600)); Provider.of<ContactInfoState>(context, listen: false).messageScrollController.scrollTo(index: 0, duration: Duration(milliseconds: 600));
}) })
: null, : null,
appBar: AppBar( appBar: AppBar(
@ -233,7 +233,7 @@ class _MessageViewState extends State<MessageView> {
ctrlrCompose.value = TextEditingValue(text: messageWithoutNewLine, selection: TextSelection.fromPosition(TextPosition(offset: messageWithoutNewLine.length))); ctrlrCompose.value = TextEditingValue(text: messageWithoutNewLine, selection: TextSelection.fromPosition(TextPosition(offset: messageWithoutNewLine.length)));
// Do this after we trim to preserve enter-behaviour... // Do this after we trim to preserve enter-behaviour...
bool isOffline = Provider.of<ContactInfoState>(context).isOnline() == false; bool isOffline = Provider.of<ContactInfoState>(context, listen: false).isOnline() == false;
if (isOffline) { if (isOffline) {
return; return;
} }

View File

@ -12,6 +12,7 @@ import 'package:cwtch/widgets/profileimage.dart';
import 'package:flutter/physics.dart'; import 'package:flutter/physics.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
import '../main.dart'; import '../main.dart';
import '../settings.dart'; import '../settings.dart';
@ -274,6 +275,8 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
// Can't happen // Can't happen
} else { } else {
selectConversation(context, id); selectConversation(context, id);
var contactIndex = Provider.of<ProfileInfoState>(context, listen: false).contactList.filteredList().indexWhere((element) => element.identifier == id);
Provider.of<ProfileInfoState>(context, listen: false).contactListScrollController.jumpTo(index: contactIndex);
} }
} }

View File

@ -96,17 +96,19 @@ class QuotedMessageBubbleState extends State<QuotedMessageBubble> {
margin: EdgeInsets.all(5), margin: EdgeInsets.all(5),
padding: EdgeInsets.all(5), padding: EdgeInsets.all(5),
clipBehavior: Clip.antiAlias, clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(), decoration: BoxDecoration(
color: fromMe ? Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor : Provider.of<Settings>(context).theme.messageFromMeBackgroundColor,
),
height: 75, height: 75,
color: fromMe ? Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor : Provider.of<Settings>(context).theme.messageFromMeBackgroundColor,
child: Row(mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.start, children: [ child: Row(mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.start, children: [
Padding(padding: EdgeInsets.symmetric(vertical: 5.0, horizontal: 10.0), child: Icon(Icons.reply, size: 32, color: qTextColor)), Padding(padding: EdgeInsets.symmetric(vertical: 5.0, horizontal: 10.0), child: Icon(Icons.reply, size: 32, color: qTextColor)),
DefaultTextStyle( Flexible(
child: DefaultTextStyle(
textWidthBasis: TextWidthBasis.parent, textWidthBasis: TextWidthBasis.parent,
child: qMessage.getPreviewWidget(context), child: qMessage.getPreviewWidget(context),
style: TextStyle(color: qTextColor), style: TextStyle(color: qTextColor),
overflow: TextOverflow.fade, overflow: TextOverflow.fade,
) ))
])))); ]))));
} catch (e) { } catch (e) {
print(e); print(e);