refactor: Migrate to null safety
This commit is contained in:
parent
5269f04a99
commit
55f0300f9f
163 changed files with 1759 additions and 1903 deletions
|
|
@ -34,25 +34,28 @@ enum PopupMenuAction {
|
|||
}
|
||||
|
||||
class ChatList extends StatefulWidget {
|
||||
const ChatList({Key key}) : super(key: key);
|
||||
const ChatList({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
ChatListController createState() => ChatListController();
|
||||
}
|
||||
|
||||
class ChatListController extends State<ChatList> {
|
||||
StreamSubscription _intentDataStreamSubscription;
|
||||
StreamSubscription? _intentDataStreamSubscription;
|
||||
|
||||
StreamSubscription _intentFileStreamSubscription;
|
||||
StreamSubscription? _intentFileStreamSubscription;
|
||||
|
||||
StreamSubscription _intentUriStreamSubscription;
|
||||
StreamSubscription? _intentUriStreamSubscription;
|
||||
|
||||
String _activeSpaceId;
|
||||
String? _activeSpaceId;
|
||||
|
||||
String? get activeSpaceId {
|
||||
final id = _activeSpaceId;
|
||||
return id != null && Matrix.of(context).client.getRoomById(id) == null
|
||||
? null
|
||||
: _activeSpaceId;
|
||||
}
|
||||
|
||||
String get activeSpaceId =>
|
||||
Matrix.of(context).client.getRoomById(_activeSpaceId) == null
|
||||
? null
|
||||
: _activeSpaceId;
|
||||
final ScrollController scrollController = ScrollController();
|
||||
bool scrolledToTop = true;
|
||||
|
||||
|
|
@ -69,12 +72,12 @@ class ChatListController extends State<ChatList> {
|
|||
}
|
||||
}
|
||||
|
||||
void setActiveSpaceId(BuildContext context, String spaceId) {
|
||||
void setActiveSpaceId(BuildContext context, String? spaceId) {
|
||||
setState(() => _activeSpaceId = spaceId);
|
||||
}
|
||||
|
||||
void editSpace(BuildContext context, String spaceId) async {
|
||||
await Matrix.of(context).client.getRoomById(spaceId).postLoad();
|
||||
await Matrix.of(context).client.getRoomById(spaceId)!.postLoad();
|
||||
VRouter.of(context).toSegments(['spaces', spaceId]);
|
||||
}
|
||||
|
||||
|
|
@ -82,7 +85,7 @@ class ChatListController extends State<ChatList> {
|
|||
Matrix.of(context).client.rooms.where((r) => r.isSpace).toList();
|
||||
|
||||
final selectedRoomIds = <String>{};
|
||||
bool crossSigningCached;
|
||||
bool? crossSigningCached;
|
||||
bool showChatBackupBanner = false;
|
||||
|
||||
void firstRunBootstrapAction() async {
|
||||
|
|
@ -96,7 +99,7 @@ class ChatListController extends State<ChatList> {
|
|||
VRouter.of(context).to('/rooms');
|
||||
}
|
||||
|
||||
String get activeChat => VRouter.of(context).pathParameters['roomid'];
|
||||
String? get activeChat => VRouter.of(context).pathParameters['roomid'];
|
||||
|
||||
SelectMode get selectMode => Matrix.of(context).shareContent != null
|
||||
? SelectMode.share
|
||||
|
|
@ -105,7 +108,7 @@ class ChatListController extends State<ChatList> {
|
|||
: SelectMode.select;
|
||||
|
||||
void _processIncomingSharedFiles(List<SharedMediaFile> files) {
|
||||
if (files?.isEmpty ?? true) return;
|
||||
if (files.isEmpty) return;
|
||||
VRouter.of(context).to('/rooms');
|
||||
final file = File(files.first.path);
|
||||
|
||||
|
|
@ -118,7 +121,7 @@ class ChatListController extends State<ChatList> {
|
|||
};
|
||||
}
|
||||
|
||||
void _processIncomingSharedText(String text) {
|
||||
void _processIncomingSharedText(String? text) {
|
||||
if (text == null) return;
|
||||
VRouter.of(context).to('/rooms');
|
||||
if (text.toLowerCase().startsWith(AppConfig.deepLinkPrefix) ||
|
||||
|
|
@ -133,10 +136,10 @@ class ChatListController extends State<ChatList> {
|
|||
};
|
||||
}
|
||||
|
||||
void _processIncomingUris(String text) async {
|
||||
void _processIncomingUris(String? text) async {
|
||||
if (text == null) return;
|
||||
VRouter.of(context).to('/rooms');
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
WidgetsBinding.instance!.addPostFrameCallback((_) {
|
||||
UrlLauncher(context, text).openMatrixToUrl();
|
||||
});
|
||||
}
|
||||
|
|
@ -180,10 +183,10 @@ class ChatListController extends State<ChatList> {
|
|||
await Matrix.of(context).client.accountDataLoading;
|
||||
await Matrix.of(context).client.userDeviceKeysLoading;
|
||||
final crossSigning =
|
||||
await Matrix.of(context).client.encryption?.crossSigning?.isCached() ??
|
||||
await Matrix.of(context).client.encryption?.crossSigning.isCached() ??
|
||||
false;
|
||||
final needsBootstrap =
|
||||
Matrix.of(context).client.encryption?.crossSigning?.enabled == false ||
|
||||
Matrix.of(context).client.encryption?.crossSigning.enabled == false ||
|
||||
crossSigning == false;
|
||||
final isUnknownSession = Matrix.of(context).client.isUnknownSession;
|
||||
if (needsBootstrap || isUnknownSession) {
|
||||
|
|
@ -206,23 +209,21 @@ class ChatListController extends State<ChatList> {
|
|||
if (room.isSpace && room.membership == Membership.join && !room.isUnread) {
|
||||
return false;
|
||||
}
|
||||
if (room.getState(EventTypes.RoomCreate)?.content?.tryGet<String>('type') ==
|
||||
if (room.getState(EventTypes.RoomCreate)?.content.tryGet<String>('type') ==
|
||||
ClientStoriesExtension.storiesRoomType) {
|
||||
return false;
|
||||
}
|
||||
if (activeSpaceId != null) {
|
||||
final space = Matrix.of(context).client.getRoomById(activeSpaceId);
|
||||
if (space.spaceChildren?.any((child) => child.roomId == room.id) ??
|
||||
false) {
|
||||
final space = Matrix.of(context).client.getRoomById(activeSpaceId!)!;
|
||||
if (space.spaceChildren.any((child) => child.roomId == room.id)) {
|
||||
return true;
|
||||
}
|
||||
if (room.spaceParents?.any((parent) => parent.roomId == activeSpaceId) ??
|
||||
false) {
|
||||
if (room.spaceParents.any((parent) => parent.roomId == activeSpaceId)) {
|
||||
return true;
|
||||
}
|
||||
if (room.isDirectChat &&
|
||||
room.summary?.mHeroes != null &&
|
||||
room.summary.mHeroes.any((userId) {
|
||||
room.summary.mHeroes != null &&
|
||||
room.summary.mHeroes!.any((userId) {
|
||||
final user = space.getState(EventTypes.RoomMember, userId)?.asUser;
|
||||
return user != null && user.membership == Membership.join;
|
||||
})) {
|
||||
|
|
@ -246,9 +247,9 @@ class ChatListController extends State<ChatList> {
|
|||
final markUnread = anySelectedRoomNotMarkedUnread;
|
||||
final client = Matrix.of(context).client;
|
||||
for (final roomId in selectedRoomIds) {
|
||||
final room = client.getRoomById(roomId);
|
||||
final room = client.getRoomById(roomId)!;
|
||||
if (room.markedUnread == markUnread) continue;
|
||||
await client.getRoomById(roomId).markUnread(markUnread);
|
||||
await client.getRoomById(roomId)!.markUnread(markUnread);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
@ -262,9 +263,9 @@ class ChatListController extends State<ChatList> {
|
|||
final makeFavorite = anySelectedRoomNotFavorite;
|
||||
final client = Matrix.of(context).client;
|
||||
for (final roomId in selectedRoomIds) {
|
||||
final room = client.getRoomById(roomId);
|
||||
final room = client.getRoomById(roomId)!;
|
||||
if (room.isFavourite == makeFavorite) continue;
|
||||
await client.getRoomById(roomId).setFavourite(makeFavorite);
|
||||
await client.getRoomById(roomId)!.setFavourite(makeFavorite);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
@ -280,9 +281,9 @@ class ChatListController extends State<ChatList> {
|
|||
: PushRuleState.notify;
|
||||
final client = Matrix.of(context).client;
|
||||
for (final roomId in selectedRoomIds) {
|
||||
final room = client.getRoomById(roomId);
|
||||
final room = client.getRoomById(roomId)!;
|
||||
if (room.pushRuleState == newState) continue;
|
||||
await client.getRoomById(roomId).setPushRuleState(newState);
|
||||
await client.getRoomById(roomId)!.setPushRuleState(newState);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
@ -293,9 +294,9 @@ class ChatListController extends State<ChatList> {
|
|||
final confirmed = await showOkCancelAlertDialog(
|
||||
useRootNavigator: false,
|
||||
context: context,
|
||||
title: L10n.of(context).areYouSure,
|
||||
okLabel: L10n.of(context).yes,
|
||||
cancelLabel: L10n.of(context).cancel,
|
||||
title: L10n.of(context)!.areYouSure,
|
||||
okLabel: L10n.of(context)!.yes,
|
||||
cancelLabel: L10n.of(context)!.cancel,
|
||||
) ==
|
||||
OkCancelResult.ok;
|
||||
if (!confirmed) return;
|
||||
|
|
@ -303,26 +304,26 @@ class ChatListController extends State<ChatList> {
|
|||
context: context,
|
||||
future: () => _archiveSelectedRooms(),
|
||||
);
|
||||
setState(() => null);
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
void setStatus() async {
|
||||
final input = await showTextInputDialog(
|
||||
useRootNavigator: false,
|
||||
context: context,
|
||||
title: L10n.of(context).setStatus,
|
||||
okLabel: L10n.of(context).ok,
|
||||
cancelLabel: L10n.of(context).cancel,
|
||||
title: L10n.of(context)!.setStatus,
|
||||
okLabel: L10n.of(context)!.ok,
|
||||
cancelLabel: L10n.of(context)!.cancel,
|
||||
textFields: [
|
||||
DialogTextField(
|
||||
hintText: L10n.of(context).statusExampleMessage,
|
||||
hintText: L10n.of(context)!.statusExampleMessage,
|
||||
),
|
||||
]);
|
||||
if (input == null) return;
|
||||
await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => Matrix.of(context).client.setPresence(
|
||||
Matrix.of(context).client.userID,
|
||||
Matrix.of(context).client.userID!,
|
||||
PresenceType.online,
|
||||
statusMsg: input.single,
|
||||
),
|
||||
|
|
@ -339,7 +340,7 @@ class ChatListController extends State<ChatList> {
|
|||
break;
|
||||
case PopupMenuAction.invite:
|
||||
FluffyShare.share(
|
||||
L10n.of(context).inviteText(Matrix.of(context).client.userID,
|
||||
L10n.of(context)!.inviteText(Matrix.of(context).client.userID!,
|
||||
'https://matrix.to/#/${Matrix.of(context).client.userID}?client=im.fluffychat'),
|
||||
context);
|
||||
break;
|
||||
|
|
@ -360,7 +361,7 @@ class ChatListController extends State<ChatList> {
|
|||
while (selectedRoomIds.isNotEmpty) {
|
||||
final roomId = selectedRoomIds.first;
|
||||
try {
|
||||
await client.getRoomById(roomId).leave();
|
||||
await client.getRoomById(roomId)!.leave();
|
||||
} finally {
|
||||
toggleSelection(roomId);
|
||||
}
|
||||
|
|
@ -371,36 +372,36 @@ class ChatListController extends State<ChatList> {
|
|||
if (activeSpaceId != null) {
|
||||
final consent = await showOkCancelAlertDialog(
|
||||
context: context,
|
||||
title: L10n.of(context).removeFromSpace,
|
||||
message: L10n.of(context).removeFromSpaceDescription,
|
||||
okLabel: L10n.of(context).remove,
|
||||
cancelLabel: L10n.of(context).cancel,
|
||||
title: L10n.of(context)!.removeFromSpace,
|
||||
message: L10n.of(context)!.removeFromSpaceDescription,
|
||||
okLabel: L10n.of(context)!.remove,
|
||||
cancelLabel: L10n.of(context)!.cancel,
|
||||
isDestructiveAction: true,
|
||||
fullyCapitalizedForMaterial: false,
|
||||
);
|
||||
if (consent != OkCancelResult.ok) return;
|
||||
|
||||
final space = Matrix.of(context).client.getRoomById(activeSpaceId);
|
||||
final space = Matrix.of(context).client.getRoomById(activeSpaceId!);
|
||||
final result = await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () async {
|
||||
for (final roomId in selectedRoomIds) {
|
||||
await space.removeSpaceChild(roomId);
|
||||
await space!.removeSpaceChild(roomId);
|
||||
}
|
||||
},
|
||||
);
|
||||
if (result.error == null) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(L10n.of(context).chatHasBeenRemovedFromThisSpace),
|
||||
content: Text(L10n.of(context)!.chatHasBeenRemovedFromThisSpace),
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
final selectedSpace = await showConfirmationDialog<String>(
|
||||
context: context,
|
||||
title: L10n.of(context).addToSpace,
|
||||
message: L10n.of(context).addToSpaceDescription,
|
||||
title: L10n.of(context)!.addToSpace,
|
||||
message: L10n.of(context)!.addToSpaceDescription,
|
||||
fullyCapitalizedForMaterial: false,
|
||||
actions: Matrix.of(context)
|
||||
.client
|
||||
|
|
@ -417,7 +418,7 @@ class ChatListController extends State<ChatList> {
|
|||
final result = await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () async {
|
||||
final space = Matrix.of(context).client.getRoomById(selectedSpace);
|
||||
final space = Matrix.of(context).client.getRoomById(selectedSpace)!;
|
||||
if (space.canSendDefaultStates) {
|
||||
for (final roomId in selectedRoomIds) {
|
||||
await space.setSpaceChild(roomId);
|
||||
|
|
@ -428,7 +429,7 @@ class ChatListController extends State<ChatList> {
|
|||
if (result.error == null) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(L10n.of(context).chatHasBeenAddedToThisSpace),
|
||||
content: Text(L10n.of(context)!.chatHasBeenAddedToThisSpace),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -437,13 +438,13 @@ class ChatListController extends State<ChatList> {
|
|||
}
|
||||
|
||||
bool get anySelectedRoomNotMarkedUnread => selectedRoomIds.any(
|
||||
(roomId) => !Matrix.of(context).client.getRoomById(roomId).markedUnread);
|
||||
(roomId) => !Matrix.of(context).client.getRoomById(roomId)!.markedUnread);
|
||||
|
||||
bool get anySelectedRoomNotFavorite => selectedRoomIds.any(
|
||||
(roomId) => !Matrix.of(context).client.getRoomById(roomId).isFavourite);
|
||||
(roomId) => !Matrix.of(context).client.getRoomById(roomId)!.isFavourite);
|
||||
|
||||
bool get anySelectedRoomNotMuted => selectedRoomIds.any((roomId) =>
|
||||
Matrix.of(context).client.getRoomById(roomId).pushRuleState ==
|
||||
Matrix.of(context).client.getRoomById(roomId)!.pushRuleState ==
|
||||
PushRuleState.notify);
|
||||
|
||||
bool waitForFirstSync = false;
|
||||
|
|
@ -457,10 +458,10 @@ class ChatListController extends State<ChatList> {
|
|||
}
|
||||
// Load space members to display DM rooms
|
||||
if (activeSpaceId != null) {
|
||||
final space = client.getRoomById(activeSpaceId);
|
||||
final space = client.getRoomById(activeSpaceId!)!;
|
||||
final localMembers = space.getParticipants().length;
|
||||
final actualMembersCount = (space.summary?.mInvitedMemberCount ?? 0) +
|
||||
(space.summary?.mJoinedMemberCount ?? 0);
|
||||
final actualMembersCount = (space.summary.mInvitedMemberCount ?? 0) +
|
||||
(space.summary.mJoinedMemberCount ?? 0);
|
||||
if (localMembers < actualMembersCount) {
|
||||
await space.requestParticipants();
|
||||
}
|
||||
|
|
@ -468,7 +469,7 @@ class ChatListController extends State<ChatList> {
|
|||
setState(() {
|
||||
waitForFirstSync = true;
|
||||
});
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => checkBootstrap());
|
||||
WidgetsBinding.instance!.addPostFrameCallback((_) => checkBootstrap());
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -481,7 +482,6 @@ class ChatListController extends State<ChatList> {
|
|||
}
|
||||
|
||||
void setActiveClient(Client client) {
|
||||
if (client == null) return;
|
||||
VRouter.of(context).to('/rooms');
|
||||
setState(() {
|
||||
_activeSpaceId = null;
|
||||
|
|
@ -498,30 +498,30 @@ class ChatListController extends State<ChatList> {
|
|||
selectedRoomIds.clear();
|
||||
Matrix.of(context).activeBundle = bundle;
|
||||
if (!Matrix.of(context)
|
||||
.currentBundle
|
||||
.currentBundle!
|
||||
.any((client) => client == Matrix.of(context).client)) {
|
||||
Matrix.of(context)
|
||||
.setActiveClient(Matrix.of(context).currentBundle.first);
|
||||
.setActiveClient(Matrix.of(context).currentBundle!.first);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void editBundlesForAccount(String userId, String activeBundle) async {
|
||||
void editBundlesForAccount(String? userId, String? activeBundle) async {
|
||||
final client = Matrix.of(context)
|
||||
.widget
|
||||
.clients[Matrix.of(context).getClientIndexByMatrixId(userId)];
|
||||
.clients[Matrix.of(context).getClientIndexByMatrixId(userId!)];
|
||||
final action = await showConfirmationDialog<EditBundleAction>(
|
||||
context: context,
|
||||
title: L10n.of(context).editBundlesForAccount,
|
||||
title: L10n.of(context)!.editBundlesForAccount,
|
||||
actions: [
|
||||
AlertDialogAction(
|
||||
key: EditBundleAction.addToBundle,
|
||||
label: L10n.of(context).addToBundle,
|
||||
label: L10n.of(context)!.addToBundle,
|
||||
),
|
||||
if (activeBundle != client.userID)
|
||||
AlertDialogAction(
|
||||
key: EditBundleAction.removeFromBundle,
|
||||
label: L10n.of(context).removeFromBundle,
|
||||
label: L10n.of(context)!.removeFromBundle,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
|
@ -530,9 +530,9 @@ class ChatListController extends State<ChatList> {
|
|||
case EditBundleAction.addToBundle:
|
||||
final bundle = await showTextInputDialog(
|
||||
context: context,
|
||||
title: L10n.of(context).bundleName,
|
||||
title: L10n.of(context)!.bundleName,
|
||||
textFields: [
|
||||
DialogTextField(hintText: L10n.of(context).bundleName)
|
||||
DialogTextField(hintText: L10n.of(context)!.bundleName)
|
||||
]);
|
||||
if (bundle == null || bundle.isEmpty || bundle.single.isEmpty) return;
|
||||
await showFutureLoadingDialog(
|
||||
|
|
@ -543,7 +543,7 @@ class ChatListController extends State<ChatList> {
|
|||
case EditBundleAction.removeFromBundle:
|
||||
await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => client.removeFromAccountBundle(activeBundle),
|
||||
future: () => client.removeFromAccountBundle(activeBundle!),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -552,7 +552,7 @@ class ChatListController extends State<ChatList> {
|
|||
Matrix.of(context).hasComplexBundles &&
|
||||
Matrix.of(context).accountBundles.keys.length > 1;
|
||||
|
||||
String get secureActiveBundle {
|
||||
String? get secureActiveBundle {
|
||||
if (Matrix.of(context).activeBundle == null ||
|
||||
!Matrix.of(context)
|
||||
.accountBundles
|
||||
|
|
@ -564,7 +564,7 @@ class ChatListController extends State<ChatList> {
|
|||
}
|
||||
|
||||
void resetActiveBundle() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
|
||||
setState(() {
|
||||
Matrix.of(context).activeBundle = null;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@ class ChatListItem extends StatelessWidget {
|
|||
final Room room;
|
||||
final bool activeChat;
|
||||
final bool selected;
|
||||
final Function onForget;
|
||||
final Function onTap;
|
||||
final Function onLongPress;
|
||||
final Function? onForget;
|
||||
final Function? onTap;
|
||||
final Function? onLongPress;
|
||||
|
||||
const ChatListItem(
|
||||
this.room, {
|
||||
|
|
@ -32,11 +32,11 @@ class ChatListItem extends StatelessWidget {
|
|||
this.onTap,
|
||||
this.onLongPress,
|
||||
this.onForget,
|
||||
Key key,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
dynamic clickAction(BuildContext context) async {
|
||||
if (onTap != null) return onTap();
|
||||
if (onTap != null) return onTap!();
|
||||
if (!activeChat) {
|
||||
if (room.membership == Membership.invite &&
|
||||
(await showFutureLoadingDialog(
|
||||
|
|
@ -57,7 +57,7 @@ class ChatListItem extends StatelessWidget {
|
|||
if (room.membership == Membership.ban) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(L10n.of(context).youHaveBeenBannedFromThisChat),
|
||||
content: Text(L10n.of(context)!.youHaveBeenBannedFromThisChat),
|
||||
),
|
||||
);
|
||||
return;
|
||||
|
|
@ -66,15 +66,15 @@ class ChatListItem extends StatelessWidget {
|
|||
if (room.membership == Membership.leave) {
|
||||
final action = await showModalActionSheet<ArchivedRoomAction>(
|
||||
context: context,
|
||||
title: L10n.of(context).archivedRoom,
|
||||
message: L10n.of(context).thisRoomHasBeenArchived,
|
||||
title: L10n.of(context)!.archivedRoom,
|
||||
message: L10n.of(context)!.thisRoomHasBeenArchived,
|
||||
actions: [
|
||||
SheetAction(
|
||||
label: L10n.of(context).rejoin,
|
||||
label: L10n.of(context)!.rejoin,
|
||||
key: ArchivedRoomAction.rejoin,
|
||||
),
|
||||
SheetAction(
|
||||
label: L10n.of(context).delete,
|
||||
label: L10n.of(context)!.delete,
|
||||
key: ArchivedRoomAction.delete,
|
||||
isDestructiveAction: true,
|
||||
),
|
||||
|
|
@ -97,18 +97,18 @@ class ChatListItem extends StatelessWidget {
|
|||
|
||||
if (room.membership == Membership.join) {
|
||||
if (Matrix.of(context).shareContent != null) {
|
||||
if (Matrix.of(context).shareContent['msgtype'] ==
|
||||
if (Matrix.of(context).shareContent!['msgtype'] ==
|
||||
'chat.fluffy.shared_file') {
|
||||
await showDialog(
|
||||
context: context,
|
||||
useRootNavigator: false,
|
||||
builder: (c) => SendFileDialog(
|
||||
file: Matrix.of(context).shareContent['file'],
|
||||
file: Matrix.of(context).shareContent!['file'],
|
||||
room: room,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
unawaited(room.sendEvent(Matrix.of(context).shareContent));
|
||||
unawaited(room.sendEvent(Matrix.of(context).shareContent!));
|
||||
}
|
||||
Matrix.of(context).shareContent = null;
|
||||
}
|
||||
|
|
@ -125,16 +125,16 @@ class ChatListItem extends StatelessWidget {
|
|||
future: () => room.forget(),
|
||||
);
|
||||
if (success.error == null) {
|
||||
if (onForget != null) onForget();
|
||||
if (onForget != null) onForget!();
|
||||
}
|
||||
return success;
|
||||
return;
|
||||
}
|
||||
final confirmed = await showOkCancelAlertDialog(
|
||||
useRootNavigator: false,
|
||||
context: context,
|
||||
title: L10n.of(context).areYouSure,
|
||||
okLabel: L10n.of(context).yes,
|
||||
cancelLabel: L10n.of(context).no,
|
||||
title: L10n.of(context)!.areYouSure,
|
||||
okLabel: L10n.of(context)!.yes,
|
||||
cancelLabel: L10n.of(context)!.no,
|
||||
);
|
||||
if (confirmed == OkCancelResult.cancel) return;
|
||||
await showFutureLoadingDialog(
|
||||
|
|
@ -160,7 +160,7 @@ class ChatListItem extends StatelessWidget {
|
|||
selectedTileColor: selected
|
||||
? Theme.of(context).primaryColor.withAlpha(100)
|
||||
: Theme.of(context).secondaryHeaderColor,
|
||||
onLongPress: onLongPress,
|
||||
onLongPress: onLongPress as void Function()?,
|
||||
leading: selected
|
||||
? SizedBox(
|
||||
width: Avatar.defaultSize,
|
||||
|
|
@ -174,13 +174,13 @@ class ChatListItem extends StatelessWidget {
|
|||
: Avatar(
|
||||
mxContent: room.avatar,
|
||||
name: room.displayname,
|
||||
onTap: onLongPress,
|
||||
onTap: onLongPress as void Function()?,
|
||||
),
|
||||
title: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Text(
|
||||
room.getLocalizedDisplayname(MatrixLocals(L10n.of(context))),
|
||||
room.getLocalizedDisplayname(MatrixLocals(L10n.of(context)!)),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: false,
|
||||
|
|
@ -188,7 +188,7 @@ class ChatListItem extends StatelessWidget {
|
|||
fontWeight: FontWeight.bold,
|
||||
color: unread
|
||||
? Theme.of(context).colorScheme.secondary
|
||||
: Theme.of(context).textTheme.bodyText1.color,
|
||||
: Theme.of(context).textTheme.bodyText1!.color,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -218,7 +218,7 @@ class ChatListItem extends StatelessWidget {
|
|||
fontSize: 13,
|
||||
color: unread
|
||||
? Theme.of(context).colorScheme.secondary
|
||||
: Theme.of(context).textTheme.bodyText2.color,
|
||||
: Theme.of(context).textTheme.bodyText2!.color,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -229,7 +229,7 @@ class ChatListItem extends StatelessWidget {
|
|||
children: <Widget>[
|
||||
if (typingText.isEmpty &&
|
||||
ownMessage &&
|
||||
room.lastEvent.status.isSending) ...[
|
||||
room.lastEvent!.status.isSending) ...[
|
||||
const SizedBox(
|
||||
width: 16,
|
||||
height: 16,
|
||||
|
|
@ -261,9 +261,9 @@ class ChatListItem extends StatelessWidget {
|
|||
)
|
||||
: Text(
|
||||
room.membership == Membership.invite
|
||||
? L10n.of(context).youAreInvitedToThisChat
|
||||
? L10n.of(context)!.youAreInvitedToThisChat
|
||||
: room.lastEvent?.getLocalizedBody(
|
||||
MatrixLocals(L10n.of(context)),
|
||||
MatrixLocals(L10n.of(context)!),
|
||||
hideReply: true,
|
||||
hideEdit: true,
|
||||
plaintextBody: true,
|
||||
|
|
@ -271,14 +271,14 @@ class ChatListItem extends StatelessWidget {
|
|||
room.directChatMatrixID !=
|
||||
room.lastEvent?.senderId,
|
||||
) ??
|
||||
L10n.of(context).emptyChat,
|
||||
L10n.of(context)!.emptyChat,
|
||||
softWrap: false,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
color: unread
|
||||
? Theme.of(context).colorScheme.secondary
|
||||
: Theme.of(context).textTheme.bodyText2.color,
|
||||
: Theme.of(context).textTheme.bodyText2!.color,
|
||||
decoration: room.lastEvent?.redacted == true
|
||||
? TextDecoration.lineThrough
|
||||
: null,
|
||||
|
|
|
|||
|
|
@ -21,11 +21,11 @@ import '../../widgets/matrix.dart';
|
|||
class ChatListView extends StatelessWidget {
|
||||
final ChatListController controller;
|
||||
|
||||
const ChatListView(this.controller, {Key key}) : super(key: key);
|
||||
const ChatListView(this.controller, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StreamBuilder<Object>(
|
||||
return StreamBuilder<Object?>(
|
||||
stream: Matrix.of(context).onShareContentChanged.stream,
|
||||
builder: (_, __) {
|
||||
final selectMode = controller.selectMode;
|
||||
|
|
@ -48,7 +48,7 @@ class ChatListView extends StatelessWidget {
|
|||
? ClientChooserButton(controller)
|
||||
: null
|
||||
: IconButton(
|
||||
tooltip: L10n.of(context).cancel,
|
||||
tooltip: L10n.of(context)!.cancel,
|
||||
icon: const Icon(Icons.close_outlined),
|
||||
onPressed: controller.cancelAction,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
|
|
@ -60,12 +60,12 @@ class ChatListView extends StatelessWidget {
|
|||
? [
|
||||
if (controller.spaces.isNotEmpty)
|
||||
IconButton(
|
||||
tooltip: L10n.of(context).addToSpace,
|
||||
tooltip: L10n.of(context)!.addToSpace,
|
||||
icon: const Icon(Icons.group_work_outlined),
|
||||
onPressed: controller.addOrRemoveToSpace,
|
||||
),
|
||||
IconButton(
|
||||
tooltip: L10n.of(context).toggleUnread,
|
||||
tooltip: L10n.of(context)!.toggleUnread,
|
||||
icon: Icon(
|
||||
controller.anySelectedRoomNotMarkedUnread
|
||||
? Icons.mark_chat_read_outlined
|
||||
|
|
@ -73,7 +73,7 @@ class ChatListView extends StatelessWidget {
|
|||
onPressed: controller.toggleUnread,
|
||||
),
|
||||
IconButton(
|
||||
tooltip: L10n.of(context).toggleFavorite,
|
||||
tooltip: L10n.of(context)!.toggleFavorite,
|
||||
icon: Icon(controller.anySelectedRoomNotFavorite
|
||||
? Icons.push_pin_outlined
|
||||
: Icons.push_pin),
|
||||
|
|
@ -83,19 +83,19 @@ class ChatListView extends StatelessWidget {
|
|||
icon: Icon(controller.anySelectedRoomNotMuted
|
||||
? Icons.notifications_off_outlined
|
||||
: Icons.notifications_outlined),
|
||||
tooltip: L10n.of(context).toggleMuted,
|
||||
tooltip: L10n.of(context)!.toggleMuted,
|
||||
onPressed: controller.toggleMuted,
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.delete_outlined),
|
||||
tooltip: L10n.of(context).archive,
|
||||
tooltip: L10n.of(context)!.archive,
|
||||
onPressed: controller.archiveAction,
|
||||
),
|
||||
]
|
||||
: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.search_outlined),
|
||||
tooltip: L10n.of(context).search,
|
||||
tooltip: L10n.of(context)!.search,
|
||||
onPressed: () =>
|
||||
VRouter.of(context).to('/search'),
|
||||
),
|
||||
|
|
@ -109,7 +109,7 @@ class ChatListView extends StatelessWidget {
|
|||
children: [
|
||||
const Icon(Icons.edit_outlined),
|
||||
const SizedBox(width: 12),
|
||||
Text(L10n.of(context).setStatus),
|
||||
Text(L10n.of(context)!.setStatus),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
@ -120,7 +120,7 @@ class ChatListView extends StatelessWidget {
|
|||
children: [
|
||||
const Icon(Icons.group_add_outlined),
|
||||
const SizedBox(width: 12),
|
||||
Text(L10n.of(context).createNewGroup),
|
||||
Text(L10n.of(context)!.createNewGroup),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
@ -131,7 +131,7 @@ class ChatListView extends StatelessWidget {
|
|||
children: [
|
||||
const Icon(Icons.group_work_outlined),
|
||||
const SizedBox(width: 12),
|
||||
Text(L10n.of(context).createNewSpace),
|
||||
Text(L10n.of(context)!.createNewSpace),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
@ -142,7 +142,7 @@ class ChatListView extends StatelessWidget {
|
|||
children: [
|
||||
const Icon(Icons.share_outlined),
|
||||
const SizedBox(width: 12),
|
||||
Text(L10n.of(context).inviteContact),
|
||||
Text(L10n.of(context)!.inviteContact),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
@ -153,7 +153,7 @@ class ChatListView extends StatelessWidget {
|
|||
children: [
|
||||
const Icon(Icons.archive_outlined),
|
||||
const SizedBox(width: 12),
|
||||
Text(L10n.of(context).archive),
|
||||
Text(L10n.of(context)!.archive),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
@ -164,7 +164,7 @@ class ChatListView extends StatelessWidget {
|
|||
children: [
|
||||
const Icon(Icons.settings_outlined),
|
||||
const SizedBox(width: 12),
|
||||
Text(L10n.of(context).settings),
|
||||
Text(L10n.of(context)!.settings),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
@ -172,14 +172,14 @@ class ChatListView extends StatelessWidget {
|
|||
),
|
||||
],
|
||||
title: Text(selectMode == SelectMode.share
|
||||
? L10n.of(context).share
|
||||
? L10n.of(context)!.share
|
||||
: selectMode == SelectMode.select
|
||||
? controller.selectedRoomIds.length.toString()
|
||||
: controller.activeSpaceId == null
|
||||
? AppConfig.applicationName
|
||||
: Matrix.of(context)
|
||||
.client
|
||||
.getRoomById(controller.activeSpaceId)
|
||||
.getRoomById(controller.activeSpaceId!)!
|
||||
.displayname),
|
||||
),
|
||||
body: Column(children: [
|
||||
|
|
@ -197,7 +197,7 @@ class ChatListView extends StatelessWidget {
|
|||
fit: BoxFit.contain,
|
||||
width: 44,
|
||||
),
|
||||
title: Text(L10n.of(context).setupChatBackupNow),
|
||||
title: Text(L10n.of(context)!.setupChatBackupNow),
|
||||
trailing: const Icon(Icons.chevron_right_outlined),
|
||||
onTap: controller.firstRunBootstrapAction,
|
||||
),
|
||||
|
|
@ -211,7 +211,7 @@ class ChatListView extends StatelessWidget {
|
|||
onPressed: () =>
|
||||
VRouter.of(context).to('/newprivatechat'),
|
||||
icon: const Icon(CupertinoIcons.chat_bubble),
|
||||
label: Text(L10n.of(context).newChat),
|
||||
label: Text(L10n.of(context)!.newChat),
|
||||
)
|
||||
: null,
|
||||
bottomNavigationBar: Column(
|
||||
|
|
@ -232,7 +232,7 @@ class ChatListView extends StatelessWidget {
|
|||
class _ChatListViewBody extends StatefulWidget {
|
||||
final ChatListController controller;
|
||||
|
||||
const _ChatListViewBody(this.controller, {Key key}) : super(key: key);
|
||||
const _ChatListViewBody(this.controller, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<_ChatListViewBody> createState() => _ChatListViewBodyState();
|
||||
|
|
@ -240,12 +240,12 @@ class _ChatListViewBody extends StatefulWidget {
|
|||
|
||||
class _ChatListViewBodyState extends State<_ChatListViewBody> {
|
||||
// the matrix sync stream
|
||||
StreamSubscription _subscription;
|
||||
StreamSubscription _clientSubscription;
|
||||
late StreamSubscription _subscription;
|
||||
late StreamSubscription _clientSubscription;
|
||||
|
||||
// used to check the animation direction
|
||||
String _lastUserId;
|
||||
String _lastSpaceId;
|
||||
String? _lastUserId;
|
||||
String? _lastSpaceId;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
|
@ -285,7 +285,7 @@ class _ChatListViewBodyState extends State<_ChatListViewBody> {
|
|||
),
|
||||
Center(
|
||||
child: Text(
|
||||
L10n.of(context).startYourFirstChat,
|
||||
L10n.of(context)!.startYourFirstChat,
|
||||
textAlign: TextAlign.start,
|
||||
style: const TextStyle(
|
||||
color: Colors.grey,
|
||||
|
|
@ -324,9 +324,9 @@ class _ChatListViewBodyState extends State<_ChatListViewBody> {
|
|||
} else {
|
||||
const dummyChatCount = 8;
|
||||
final titleColor =
|
||||
Theme.of(context).textTheme.bodyText1.color.withAlpha(100);
|
||||
Theme.of(context).textTheme.bodyText1!.color!.withAlpha(100);
|
||||
final subtitleColor =
|
||||
Theme.of(context).textTheme.bodyText1.color.withAlpha(50);
|
||||
Theme.of(context).textTheme.bodyText1!.color!.withAlpha(50);
|
||||
child = ListView.builder(
|
||||
itemCount: dummyChatCount,
|
||||
itemBuilder: (context, i) => Opacity(
|
||||
|
|
@ -336,7 +336,7 @@ class _ChatListViewBodyState extends State<_ChatListViewBody> {
|
|||
backgroundColor: titleColor,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 1,
|
||||
color: Theme.of(context).textTheme.bodyText1.color,
|
||||
color: Theme.of(context).textTheme.bodyText1!.color,
|
||||
),
|
||||
),
|
||||
title: Row(
|
||||
|
|
@ -417,11 +417,11 @@ class _ChatListViewBodyState extends State<_ChatListViewBody> {
|
|||
final newClient = Matrix.of(context).client;
|
||||
if (_lastUserId != newClient.userID) {
|
||||
reversed = Matrix.of(context)
|
||||
.currentBundle
|
||||
.indexWhere((element) => element.userID == _lastUserId) <
|
||||
.currentBundle!
|
||||
.indexWhere((element) => element!.userID == _lastUserId) <
|
||||
Matrix.of(context)
|
||||
.currentBundle
|
||||
.indexWhere((element) => element.userID == newClient.userID);
|
||||
.currentBundle!
|
||||
.indexWhere((element) => element!.userID == newClient.userID);
|
||||
}
|
||||
// otherwise, the space changed...
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -8,20 +8,20 @@ import 'chat_list.dart';
|
|||
|
||||
class ClientChooserButton extends StatelessWidget {
|
||||
final ChatListController controller;
|
||||
const ClientChooserButton(this.controller, {Key key}) : super(key: key);
|
||||
const ClientChooserButton(this.controller, {Key? key}) : super(key: key);
|
||||
|
||||
List<PopupMenuEntry<Object>> _bundleMenuItems(BuildContext context) {
|
||||
final matrix = Matrix.of(context);
|
||||
final bundles = matrix.accountBundles.keys.toList()
|
||||
..sort((a, b) => a.isValidMatrixId == b.isValidMatrixId
|
||||
..sort((a, b) => a!.isValidMatrixId == b!.isValidMatrixId
|
||||
? 0
|
||||
: a.isValidMatrixId && !b.isValidMatrixId
|
||||
? -1
|
||||
: 1);
|
||||
return <PopupMenuEntry<Object>>[
|
||||
for (final bundle in bundles) ...[
|
||||
if (matrix.accountBundles[bundle].length != 1 ||
|
||||
matrix.accountBundles[bundle].single.userID != bundle)
|
||||
if (matrix.accountBundles[bundle]!.length != 1 ||
|
||||
matrix.accountBundles[bundle]!.single!.userID != bundle)
|
||||
PopupMenuItem(
|
||||
value: null,
|
||||
child: Column(
|
||||
|
|
@ -29,9 +29,9 @@ class ClientChooserButton extends StatelessWidget {
|
|||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
bundle,
|
||||
bundle!,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).textTheme.subtitle1.color,
|
||||
color: Theme.of(context).textTheme.subtitle1!.color,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
|
|
@ -39,25 +39,26 @@ class ClientChooserButton extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
),
|
||||
...matrix.accountBundles[bundle]
|
||||
...matrix.accountBundles[bundle]!
|
||||
.map(
|
||||
(client) => PopupMenuItem(
|
||||
value: client,
|
||||
child: FutureBuilder<Profile>(
|
||||
future: client.ownProfile,
|
||||
future: client!.ownProfile,
|
||||
builder: (context, snapshot) => Row(
|
||||
children: [
|
||||
Avatar(
|
||||
mxContent: snapshot.data?.avatarUrl,
|
||||
name: snapshot.data?.displayName ??
|
||||
client.userID.localpart,
|
||||
client.userID!.localpart,
|
||||
size: 28,
|
||||
fontSize: 12,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(
|
||||
snapshot.data?.displayName ?? client.userID.localpart,
|
||||
snapshot.data?.displayName ??
|
||||
client.userID!.localpart!,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
|
|
@ -86,7 +87,7 @@ class ClientChooserButton extends StatelessWidget {
|
|||
builder: (context, snapshot) => PopupMenuButton<Object>(
|
||||
child: Avatar(
|
||||
mxContent: snapshot.data?.avatarUrl,
|
||||
name: snapshot.data?.displayName ?? matrix.client.userID.localpart,
|
||||
name: snapshot.data?.displayName ?? matrix.client.userID!.localpart,
|
||||
size: 28,
|
||||
fontSize: 12,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import 'package:fluffychat/widgets/matrix.dart';
|
|||
|
||||
class SpacesBottomBar extends StatelessWidget {
|
||||
final ChatListController controller;
|
||||
const SpacesBottomBar(this.controller, {Key key}) : super(key: key);
|
||||
const SpacesBottomBar(this.controller, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -25,8 +25,9 @@ class SpacesBottomBar extends StatelessWidget {
|
|||
child: SafeArea(
|
||||
child: StreamBuilder<Object>(
|
||||
stream: Matrix.of(context).client.onSync.stream.where((sync) =>
|
||||
(sync.rooms?.join?.values?.any((r) =>
|
||||
r.state?.any((s) => s.type.startsWith('m.space'))) ??
|
||||
(sync.rooms?.join?.values.any((r) =>
|
||||
r.state?.any((s) => s.type.startsWith('m.space')) ??
|
||||
false) ??
|
||||
false) ||
|
||||
(sync.rooms?.leave?.isNotEmpty ?? false)),
|
||||
builder: (context, snapshot) {
|
||||
|
|
@ -48,7 +49,7 @@ class SpacesBottomBar extends StatelessWidget {
|
|||
icon: const Icon(CupertinoIcons.chat_bubble_2),
|
||||
activeIcon:
|
||||
const Icon(CupertinoIcons.chat_bubble_2_fill),
|
||||
title: Text(L10n.of(context).allChats),
|
||||
title: Text(L10n.of(context)!.allChats),
|
||||
),
|
||||
...controller.spaces
|
||||
.map((space) => SalomonBottomBarItem(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
//@dart=2.12
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue