Merge branch 'back-clears-selection' into 'main'
Android: back button clears selection in room list and chat (fixes #399) Closes #399 See merge request famedly/fluffychat!419
This commit is contained in:
commit
dfda3a6938
|
@ -26,7 +26,14 @@ class ChatListView extends StatelessWidget {
|
|||
: controller.selectedRoomIds.isEmpty
|
||||
? SelectMode.normal
|
||||
: SelectMode.select;
|
||||
return Scaffold(
|
||||
return VWidgetGuard(
|
||||
onSystemPop: (redirector) async {
|
||||
if (controller.selectedRoomIds.isNotEmpty) {
|
||||
controller.cancelAction();
|
||||
redirector.stopRedirection();
|
||||
}
|
||||
},
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
elevation: MediaQuery.of(context).size.width >
|
||||
FluffyThemes.columnWidth * 2
|
||||
|
@ -66,8 +73,8 @@ class ChatListView extends StatelessWidget {
|
|||
IconButton(
|
||||
icon: Icon(Matrix.of(context)
|
||||
.client
|
||||
.getRoomById(
|
||||
controller.selectedRoomIds.single)
|
||||
.getRoomById(controller
|
||||
.selectedRoomIds.single)
|
||||
.pushRuleState ==
|
||||
PushRuleState.notify
|
||||
? Icons.notifications_off_outlined
|
||||
|
@ -172,7 +179,8 @@ class ChatListView extends StatelessWidget {
|
|||
if (snapshot.hasData) {
|
||||
final rooms = List<Room>.from(
|
||||
Matrix.of(context).client.rooms);
|
||||
rooms.removeWhere((room) => room.lastEvent == null);
|
||||
rooms.removeWhere(
|
||||
(room) => room.lastEvent == null);
|
||||
if (rooms.isEmpty) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
|
@ -205,8 +213,8 @@ class ChatListView extends StatelessWidget {
|
|||
selected: controller.selectedRoomIds
|
||||
.contains(rooms[i].id),
|
||||
onTap: selectMode == SelectMode.select
|
||||
? () =>
|
||||
controller.toggleSelection(rooms[i].id)
|
||||
? () => controller
|
||||
.toggleSelection(rooms[i].id)
|
||||
: null,
|
||||
onLongPress: () =>
|
||||
controller.toggleSelection(rooms[i].id),
|
||||
|
@ -231,7 +239,7 @@ class ChatListView extends StatelessWidget {
|
|||
child: Icon(CupertinoIcons.chat_bubble),
|
||||
)
|
||||
: null,
|
||||
);
|
||||
));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,14 @@ class ChatView extends StatelessWidget {
|
|||
context: context, future: () => controller.room.join());
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
return VWidgetGuard(
|
||||
onSystemPop: (redirector) async {
|
||||
if (controller.selectedEvents.isNotEmpty) {
|
||||
controller.clearSelectedEvents();
|
||||
redirector.stopRedirection();
|
||||
}
|
||||
},
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: controller.selectMode
|
||||
? IconButton(
|
||||
|
@ -68,8 +75,8 @@ class ChatView extends StatelessWidget {
|
|||
? StreamBuilder(
|
||||
stream: controller.room.onUpdate.stream,
|
||||
builder: (context, snapshot) => ListTile(
|
||||
leading: Avatar(
|
||||
controller.room.avatar, controller.room.displayname),
|
||||
leading: Avatar(controller.room.avatar,
|
||||
controller.room.displayname),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
onTap: controller.room.isDirectChat
|
||||
? () => showModalBottomSheet(
|
||||
|
@ -101,15 +108,17 @@ class ChatView extends StatelessWidget {
|
|||
p.senderId ==
|
||||
controller.room.directChatMatrixID),
|
||||
builder: (context, snapshot) => Text(
|
||||
controller.room.getLocalizedStatus(context),
|
||||
controller.room
|
||||
.getLocalizedStatus(context),
|
||||
maxLines: 1,
|
||||
//overflow: TextOverflow.ellipsis,
|
||||
))
|
||||
: Row(
|
||||
children: <Widget>[
|
||||
Icon(Icons.edit_outlined,
|
||||
color:
|
||||
Theme.of(context).colorScheme.secondary,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondary,
|
||||
size: 13),
|
||||
SizedBox(width: 4),
|
||||
Expanded(
|
||||
|
@ -128,13 +137,14 @@ class ChatView extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
))
|
||||
: Text(L10n.of(context)
|
||||
.numberSelected(controller.selectedEvents.length.toString())),
|
||||
: Text(L10n.of(context).numberSelected(
|
||||
controller.selectedEvents.length.toString())),
|
||||
actions: controller.selectMode
|
||||
? <Widget>[
|
||||
if (controller.selectedEvents.length == 1 &&
|
||||
controller.selectedEvents.first.status > 0 &&
|
||||
controller.selectedEvents.first.senderId == client.userID)
|
||||
controller.selectedEvents.first.senderId ==
|
||||
client.userID)
|
||||
IconButton(
|
||||
icon: Icon(Icons.edit_outlined),
|
||||
tooltip: L10n.of(context).edit,
|
||||
|
@ -182,7 +192,8 @@ class ChatView extends StatelessWidget {
|
|||
padding: const EdgeInsets.only(bottom: 56.0),
|
||||
child: FloatingActionButton(
|
||||
onPressed: controller.scrollDown,
|
||||
foregroundColor: Theme.of(context).textTheme.bodyText2.color,
|
||||
foregroundColor:
|
||||
Theme.of(context).textTheme.bodyText2.color,
|
||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
mini: true,
|
||||
child: Icon(Icons.arrow_downward_outlined,
|
||||
|
@ -203,7 +214,8 @@ class ChatView extends StatelessWidget {
|
|||
child: Column(
|
||||
children: <Widget>[
|
||||
ConnectionStatusHeader(),
|
||||
if (controller.room.getState(EventTypes.RoomTombstone) != null)
|
||||
if (controller.room.getState(EventTypes.RoomTombstone) !=
|
||||
null)
|
||||
Container(
|
||||
height: 72,
|
||||
child: Material(
|
||||
|
@ -212,7 +224,8 @@ class ChatView extends StatelessWidget {
|
|||
leading: CircleAvatar(
|
||||
foregroundColor:
|
||||
Theme.of(context).colorScheme.secondary,
|
||||
backgroundColor: Theme.of(context).backgroundColor,
|
||||
backgroundColor:
|
||||
Theme.of(context).backgroundColor,
|
||||
child: Icon(Icons.upgrade_outlined),
|
||||
),
|
||||
title: Text(
|
||||
|
@ -244,8 +257,8 @@ class ChatView extends StatelessWidget {
|
|||
for (var i = 0;
|
||||
i < controller.filteredEvents.length;
|
||||
i++) {
|
||||
thisEventsKeyMap[controller.filteredEvents[i].eventId] =
|
||||
i;
|
||||
thisEventsKeyMap[
|
||||
controller.filteredEvents[i].eventId] = i;
|
||||
}
|
||||
|
||||
return ListView.custom(
|
||||
|
@ -275,15 +288,16 @@ class ChatView extends StatelessWidget {
|
|||
color: Theme.of(context)
|
||||
.primaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
decoration:
|
||||
TextDecoration.underline,
|
||||
decoration: TextDecoration
|
||||
.underline,
|
||||
),
|
||||
),
|
||||
)
|
||||
: Container()
|
||||
: i == 0
|
||||
? StreamBuilder(
|
||||
stream: controller.room.onUpdate.stream,
|
||||
stream:
|
||||
controller.room.onUpdate.stream,
|
||||
builder: (_, __) {
|
||||
final seenByText = controller.room
|
||||
.getLocalizedSeenByText(
|
||||
|
@ -293,12 +307,16 @@ class ChatView extends StatelessWidget {
|
|||
controller.unfolded,
|
||||
);
|
||||
return AnimatedContainer(
|
||||
height: seenByText.isEmpty ? 0 : 24,
|
||||
height:
|
||||
seenByText.isEmpty ? 0 : 24,
|
||||
duration: seenByText.isEmpty
|
||||
? Duration(milliseconds: 0)
|
||||
: Duration(milliseconds: 300),
|
||||
alignment: controller.filteredEvents
|
||||
.first.senderId ==
|
||||
: Duration(
|
||||
milliseconds: 300),
|
||||
alignment: controller
|
||||
.filteredEvents
|
||||
.first
|
||||
.senderId ==
|
||||
client.userID
|
||||
? Alignment.topRight
|
||||
: Alignment.topLeft,
|
||||
|
@ -315,12 +333,14 @@ class ChatView extends StatelessWidget {
|
|||
.scaffoldBackgroundColor
|
||||
.withOpacity(0.8),
|
||||
borderRadius:
|
||||
BorderRadius.circular(4),
|
||||
BorderRadius.circular(
|
||||
4),
|
||||
),
|
||||
child: Text(
|
||||
seenByText,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
overflow:
|
||||
TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
|
@ -335,24 +355,30 @@ class ChatView extends StatelessWidget {
|
|||
key: ValueKey(controller
|
||||
.filteredEvents[i - 1].eventId),
|
||||
index: i - 1,
|
||||
controller: controller.scrollController,
|
||||
controller:
|
||||
controller.scrollController,
|
||||
child: Swipeable(
|
||||
key: ValueKey(controller
|
||||
.filteredEvents[i - 1].eventId),
|
||||
.filteredEvents[i - 1]
|
||||
.eventId),
|
||||
background: Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 12.0),
|
||||
child: Center(
|
||||
child: Icon(Icons.reply_outlined),
|
||||
child: Icon(
|
||||
Icons.reply_outlined),
|
||||
),
|
||||
),
|
||||
direction: SwipeDirection.endToStart,
|
||||
direction:
|
||||
SwipeDirection.endToStart,
|
||||
onSwipe: (direction) =>
|
||||
controller.replyAction(
|
||||
replyTo: controller
|
||||
.filteredEvents[i - 1]),
|
||||
.filteredEvents[
|
||||
i - 1]),
|
||||
child: Message(
|
||||
controller.filteredEvents[i - 1],
|
||||
controller
|
||||
.filteredEvents[i - 1],
|
||||
onAvatarTab: (Event event) =>
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
|
@ -367,28 +393,29 @@ class ChatView extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
unfold: controller.unfold,
|
||||
onSelect:
|
||||
controller.onSelectMessage,
|
||||
scrollToEventId:
|
||||
(String eventId) => controller
|
||||
.scrollToEventId(eventId),
|
||||
onSelect: controller
|
||||
.onSelectMessage,
|
||||
scrollToEventId: (String eventId) =>
|
||||
controller.scrollToEventId(
|
||||
eventId),
|
||||
longPressSelect: controller
|
||||
.selectedEvents.isEmpty,
|
||||
selected: controller
|
||||
.selectedEvents
|
||||
.contains(controller
|
||||
.filteredEvents[i - 1]),
|
||||
.contains(
|
||||
controller.filteredEvents[
|
||||
i - 1]),
|
||||
timeline: controller.timeline,
|
||||
nextEvent: i >= 2
|
||||
? controller
|
||||
.filteredEvents[i - 2]
|
||||
? controller.filteredEvents[i - 2]
|
||||
: null),
|
||||
),
|
||||
);
|
||||
},
|
||||
childCount: controller.filteredEvents.length + 2,
|
||||
findChildIndexCallback: (key) => controller
|
||||
.findChildIndexCallback(key, thisEventsKeyMap),
|
||||
findChildIndexCallback: (key) =>
|
||||
controller.findChildIndexCallback(
|
||||
key, thisEventsKeyMap),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
@ -414,15 +441,17 @@ class ChatView extends StatelessWidget {
|
|||
final emojis = List<String>.from(AppEmojis.emojis);
|
||||
final allReactionEvents = controller
|
||||
.selectedEvents.first
|
||||
.aggregatedEvents(
|
||||
controller.timeline, RelationshipTypes.reaction)
|
||||
.aggregatedEvents(controller.timeline,
|
||||
RelationshipTypes.reaction)
|
||||
?.where((event) =>
|
||||
event.senderId == event.room.client.userID &&
|
||||
event.senderId ==
|
||||
event.room.client.userID &&
|
||||
event.type == 'm.reaction');
|
||||
|
||||
allReactionEvents.forEach((event) {
|
||||
try {
|
||||
emojis.remove(event.content['m.relates_to']['key']);
|
||||
emojis.remove(
|
||||
event.content['m.relates_to']['key']);
|
||||
} catch (_) {}
|
||||
});
|
||||
return ListView.builder(
|
||||
|
@ -506,7 +535,8 @@ class ChatView extends StatelessWidget {
|
|||
onPressed: controller.forwardEventsAction,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Icon(Icons.keyboard_arrow_left_outlined),
|
||||
Icon(Icons
|
||||
.keyboard_arrow_left_outlined),
|
||||
Text(L10n.of(context).forward),
|
||||
],
|
||||
),
|
||||
|
@ -521,12 +551,14 @@ class ChatView extends StatelessWidget {
|
|||
? Container(
|
||||
height: 56,
|
||||
child: TextButton(
|
||||
onPressed: controller.replyAction,
|
||||
onPressed:
|
||||
controller.replyAction,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Text(L10n.of(context).reply),
|
||||
Icon(
|
||||
Icons.keyboard_arrow_right),
|
||||
Text(
|
||||
L10n.of(context).reply),
|
||||
Icon(Icons
|
||||
.keyboard_arrow_right),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -553,14 +585,15 @@ class ChatView extends StatelessWidget {
|
|||
AnimatedContainer(
|
||||
duration: Duration(milliseconds: 200),
|
||||
height: 56,
|
||||
width: controller.inputText.isEmpty ? 56 : 0,
|
||||
width:
|
||||
controller.inputText.isEmpty ? 56 : 0,
|
||||
alignment: Alignment.center,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
decoration: BoxDecoration(),
|
||||
child: PopupMenuButton<String>(
|
||||
icon: Icon(Icons.add_outlined),
|
||||
onSelected:
|
||||
controller.onAddPopupMenuButtonSelected,
|
||||
onSelected: controller
|
||||
.onAddPopupMenuButtonSelected,
|
||||
itemBuilder: (BuildContext context) =>
|
||||
<PopupMenuEntry<String>>[
|
||||
PopupMenuItem<String>(
|
||||
|
@ -569,10 +602,11 @@ class ChatView extends StatelessWidget {
|
|||
leading: CircleAvatar(
|
||||
backgroundColor: Colors.green,
|
||||
foregroundColor: Colors.white,
|
||||
child:
|
||||
Icon(Icons.attachment_outlined),
|
||||
child: Icon(
|
||||
Icons.attachment_outlined),
|
||||
),
|
||||
title: Text(L10n.of(context).sendFile),
|
||||
title:
|
||||
Text(L10n.of(context).sendFile),
|
||||
contentPadding: EdgeInsets.all(0),
|
||||
),
|
||||
),
|
||||
|
@ -584,7 +618,8 @@ class ChatView extends StatelessWidget {
|
|||
foregroundColor: Colors.white,
|
||||
child: Icon(Icons.image_outlined),
|
||||
),
|
||||
title: Text(L10n.of(context).sendImage),
|
||||
title: Text(
|
||||
L10n.of(context).sendImage),
|
||||
contentPadding: EdgeInsets.all(0),
|
||||
),
|
||||
),
|
||||
|
@ -595,11 +630,11 @@ class ChatView extends StatelessWidget {
|
|||
leading: CircleAvatar(
|
||||
backgroundColor: Colors.purple,
|
||||
foregroundColor: Colors.white,
|
||||
child:
|
||||
Icon(Icons.camera_alt_outlined),
|
||||
child: Icon(
|
||||
Icons.camera_alt_outlined),
|
||||
),
|
||||
title:
|
||||
Text(L10n.of(context).openCamera),
|
||||
title: Text(
|
||||
L10n.of(context).openCamera),
|
||||
contentPadding: EdgeInsets.all(0),
|
||||
),
|
||||
),
|
||||
|
@ -610,11 +645,11 @@ class ChatView extends StatelessWidget {
|
|||
leading: CircleAvatar(
|
||||
backgroundColor: Colors.red,
|
||||
foregroundColor: Colors.white,
|
||||
child:
|
||||
Icon(Icons.mic_none_outlined),
|
||||
child: Icon(
|
||||
Icons.mic_none_outlined),
|
||||
),
|
||||
title: Text(
|
||||
L10n.of(context).voiceMessage),
|
||||
title: Text(L10n.of(context)
|
||||
.voiceMessage),
|
||||
contentPadding: EdgeInsets.all(0),
|
||||
),
|
||||
),
|
||||
|
@ -628,8 +663,8 @@ class ChatView extends StatelessWidget {
|
|||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 4.0),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 4.0),
|
||||
child: InputBar(
|
||||
room: controller.room,
|
||||
minLines: 1,
|
||||
|
@ -638,11 +673,13 @@ class ChatView extends StatelessWidget {
|
|||
keyboardType: !PlatformInfos.isMobile
|
||||
? TextInputType.text
|
||||
: TextInputType.multiline,
|
||||
onSubmitted: controller.onInputBarSubmitted,
|
||||
onSubmitted:
|
||||
controller.onInputBarSubmitted,
|
||||
focusNode: controller.inputFocus,
|
||||
controller: controller.sendController,
|
||||
decoration: InputDecoration(
|
||||
hintText: L10n.of(context).writeAMessage,
|
||||
hintText:
|
||||
L10n.of(context).writeAMessage,
|
||||
hintMaxLines: 1,
|
||||
border: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
|
@ -660,7 +697,8 @@ class ChatView extends StatelessWidget {
|
|||
child: IconButton(
|
||||
tooltip: L10n.of(context).voiceMessage,
|
||||
icon: Icon(Icons.mic_none_outlined),
|
||||
onPressed: controller.voiceMessageAction,
|
||||
onPressed:
|
||||
controller.voiceMessageAction,
|
||||
),
|
||||
),
|
||||
if (!PlatformInfos.isMobile ||
|
||||
|
@ -694,7 +732,7 @@ class ChatView extends StatelessWidget {
|
|||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue