refactor: Update to Dart 3.10 with . shorthands

This commit is contained in:
Christian Kußowski 2025-11-30 12:54:06 +01:00
commit 1ea649f01e
No known key found for this signature in database
GPG key ID: E067ECD60F1A0652
167 changed files with 3351 additions and 3912 deletions

View file

@ -46,11 +46,7 @@ class _ImportEmoteArchiveDialogState extends State<ImportEmoteArchiveDialog> {
return AlertDialog(
title: Text(L10n.of(context).importEmojis),
content: _loading
? Center(
child: CircularProgressIndicator(
value: _progress,
),
)
? Center(child: CircularProgressIndicator(value: _progress))
: SingleChildScrollView(
child: Wrap(
alignment: WrapAlignment.spaceEvenly,
@ -79,8 +75,8 @@ class _ImportEmoteArchiveDialogState extends State<ImportEmoteArchiveDialog> {
onPressed: _loading
? null
: _importMap.isNotEmpty
? _addEmotePack
: null,
? _addEmotePack
: null,
child: Text(L10n.of(context).importNow),
),
],
@ -91,12 +87,8 @@ class _ImportEmoteArchiveDialogState extends State<ImportEmoteArchiveDialog> {
_importMap = Map.fromEntries(
widget.archive.files
.where((e) => e.isFile)
.map(
(e) => MapEntry(e, e.name.emoteNameFromPath),
)
.sorted(
(a, b) => a.value.compareTo(b.value),
),
.map((e) => MapEntry(e, e.name.emoteNameFromPath))
.sorted((a, b) => a.value.compareTo(b.value)),
);
}
@ -148,10 +140,7 @@ class _ImportEmoteArchiveDialogState extends State<ImportEmoteArchiveDialog> {
final imageCode = entry.value;
try {
var mxcFile = MatrixImageFile(
bytes: file.content,
name: file.name,
);
var mxcFile = MatrixImageFile(bytes: file.content, name: file.name);
final thumbnail = (await mxcFile.generateThumbnail(
nativeImplementations: ClientManager.nativeImplementations,
@ -162,14 +151,12 @@ class _ImportEmoteArchiveDialogState extends State<ImportEmoteArchiveDialog> {
mxcFile = thumbnail;
}
final uri = await Matrix.of(context).client.uploadContent(
mxcFile.bytes,
filename: mxcFile.name,
contentType: mxcFile.mimeType,
);
mxcFile.bytes,
filename: mxcFile.name,
contentType: mxcFile.mimeType,
);
final info = <String, dynamic>{
...mxcFile.info,
};
final info = <String, dynamic>{...mxcFile.info};
// normalize width / height to 256, required for stickers
if (info['w'] is int && info['h'] is int) {
@ -184,9 +171,9 @@ class _ImportEmoteArchiveDialogState extends State<ImportEmoteArchiveDialog> {
}
widget.controller.pack!.images[imageCode] =
ImagePackImageContent.fromJson(<String, dynamic>{
'url': uri.toString(),
'info': info,
});
'url': uri.toString(),
'info': info,
});
successfulUploads.add(file.name);
} catch (e) {
Logs().d('Could not upload emote $imageCode');
@ -204,8 +191,9 @@ class _ImportEmoteArchiveDialogState extends State<ImportEmoteArchiveDialog> {
// in case we have unhandled / duplicated emotes left, don't pop
if (mounted) setState(() {});
if (_importMap.isEmpty) {
WidgetsBinding.instance
.addPostFrameCallback((_) => Navigator.of(context).pop());
WidgetsBinding.instance.addPostFrameCallback(
(_) => Navigator.of(context).pop(),
);
}
}
}
@ -250,21 +238,20 @@ class _EmojiImportPreviewState extends State<_EmojiImportPreview> {
if (hasError) return _ImageFileError(name: widget.entry.key.name);
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: .min,
mainAxisAlignment: .center,
crossAxisAlignment: .center,
children: [
Image.memory(
widget.entry.key.content,
height: 64,
width: 64,
errorBuilder: (context, e, s) {
WidgetsBinding.instance
.addPostFrameCallback((_) => _setRenderError());
return _ImageFileError(
name: widget.entry.key.name,
WidgetsBinding.instance.addPostFrameCallback(
(_) => _setRenderError(),
);
return _ImageFileError(name: widget.entry.key.name);
},
),
SizedBox(
@ -323,9 +310,9 @@ class _ImageFileError extends StatelessWidget {
child: Tooltip(
message: name,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: .start,
mainAxisSize: .min,
crossAxisAlignment: .center,
children: [
const Icon(Icons.error),
Text(
@ -347,8 +334,7 @@ extension on String {
/// Used to compute emote name proposal based on file name
String get emoteNameFromPath {
// ... removing leading path
return split(RegExp(r'[/\\]'))
.last
return split(RegExp(r'[/\\]')).last
// ... removing file extension
.split('.')
.first

View file

@ -55,10 +55,7 @@ class EmotesSettingsController extends State<EmotesSettings> {
final event = key == null
? null
: room?.getState(
'im.ponies.room_emotes',
key,
);
: room?.getState('im.ponies.room_emotes', key);
final eventPack = event?.content.tryGetMap<String, Object?>('pack');
packDisplayNameController.text =
eventPack?.tryGet<String>('display_name') ?? '';
@ -71,13 +68,11 @@ class EmotesSettingsController extends State<EmotesSettings> {
ImagePackContent _getPack() {
final client = Matrix.of(context).client;
final event = (room != null
final event =
(room != null
? room!.getState('im.ponies.room_emotes', stateKey ?? '')
: client.accountData['im.ponies.user_emotes']) ??
BasicEvent(
type: 'm.dummy',
content: {},
);
BasicEvent(type: 'm.dummy', content: {});
// make sure we work on a *copy* of the event
return BasicEvent.fromJson(event.toJson()).parsedImagePackContent;
}
@ -124,7 +119,8 @@ class EmotesSettingsController extends State<EmotesSettings> {
return;
}
final client = Matrix.of(context).client;
final content = client.accountData['im.ponies.emote_rooms']?.content ??
final content =
client.accountData['im.ponies.emote_rooms']?.content ??
<String, dynamic>{};
if (active) {
if (content['rooms'] is! Map) {
@ -158,14 +154,15 @@ class EmotesSettingsController extends State<EmotesSettings> {
TextEditingController();
void removeImageAction(String oldImageCode) => setState(() {
pack!.images.remove(oldImageCode);
showSave = true;
});
pack!.images.remove(oldImageCode);
showSave = true;
});
void toggleUsage(String imageCode, ImagePackUsage usage) {
setState(() {
final usages =
pack!.images[imageCode]!.usage ??= List.from(ImagePackUsage.values);
final usages = pack!.images[imageCode]!.usage ??= List.from(
ImagePackUsage.values,
);
if (!usages.remove(usage)) usages.add(usage);
showSave = true;
});
@ -265,9 +262,7 @@ class EmotesSettingsController extends State<EmotesSettings> {
if (packKeys?.contains(name) ?? false) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(L10n.of(context).stickerPackNameAlreadyExists),
),
SnackBar(content: Text(L10n.of(context).stickerPackNameAlreadyExists)),
);
return;
}
@ -316,20 +311,19 @@ class EmotesSettingsController extends State<EmotesSettings> {
bytes: await pickedFile.readAsBytes(),
name: pickedFile.name,
);
file = await file.generateThumbnail(
file =
await file.generateThumbnail(
nativeImplementations: ClientManager.nativeImplementations,
) ??
file;
final uri = await Matrix.of(context).client.uploadContent(
file.bytes,
filename: file.name,
contentType: file.mimeType,
);
file.bytes,
filename: file.name,
contentType: file.mimeType,
);
setState(() {
final info = <String, dynamic>{
...file.info,
};
final info = <String, dynamic>{...file.info};
// normalize width / height to 256, required for stickers
if (info['w'] is int && info['h'] is int) {
final ratio = info['w'] / info['h'];
@ -342,11 +336,9 @@ class EmotesSettingsController extends State<EmotesSettings> {
}
}
final imageCode = pickedFile.name.split('.').first;
pack!.images[imageCode] =
ImagePackImageContent.fromJson(<String, dynamic>{
'url': uri.toString(),
'info': info,
});
pack!.images[imageCode] = ImagePackImageContent.fromJson(
<String, dynamic>{'url': uri.toString(), 'info': info},
);
});
}
},
@ -363,10 +355,7 @@ class EmotesSettingsController extends State<EmotesSettings> {
}
Future<void> importEmojiZip() async {
final result = await selectFiles(
context,
type: FileSelectorType.zip,
);
final result = await selectFiles(context, type: FileSelectorType.zip);
if (result.isEmpty) return;
@ -378,10 +367,8 @@ class EmotesSettingsController extends State<EmotesSettings> {
context: context,
// breaks [Matrix.of] calls otherwise
useRootNavigator: false,
builder: (context) => ImportEmoteArchiveDialog(
controller: this,
archive: archive,
),
builder: (context) =>
ImportEmoteArchiveDialog(controller: this, archive: archive),
);
setState(() {});
}
@ -404,11 +391,7 @@ class EmotesSettingsController extends State<EmotesSettings> {
);
archive.addFile(
ArchiveFile(
name,
response.bodyBytes.length,
response.bodyBytes,
),
ArchiveFile(name, response.bodyBytes.length, response.bodyBytes),
);
}
final fileName =

View file

@ -23,9 +23,7 @@ class EmotesSettingsView extends StatelessWidget {
Widget build(BuildContext context) {
if (controller.widget.roomId != null && controller.room == null) {
return Scaffold(
appBar: AppBar(
title: Text(L10n.of(context).oopsSomethingWentWrong),
),
appBar: AppBar(title: Text(L10n.of(context).oopsSomethingWentWrong)),
body: Center(
child: Text(L10n.of(context).youAreNoLongerParticipatingInThisChat),
),
@ -110,10 +108,7 @@ class EmotesSettingsView extends StatelessWidget {
horizontal: 4.0,
),
child: FilterChip(
label: const Icon(
Icons.add_outlined,
size: 20,
),
label: const Icon(Icons.add_outlined, size: 20),
onSelected: controller.showSave
? null
: (_) => controller.createImagePack(),
@ -122,23 +117,24 @@ class EmotesSettingsView extends StatelessWidget {
}
i--;
final key = packKeys[i];
final event = controller.room
?.getState('im.ponies.room_emotes', packKeys[i]);
final event = controller.room?.getState(
'im.ponies.room_emotes',
packKeys[i],
);
final eventPack =
event?.content.tryGetMap<String, Object?>('pack');
final eventPack = event?.content
.tryGetMap<String, Object?>('pack');
final packName =
eventPack?.tryGet<String>('display_name') ??
eventPack?.tryGet<String>('name') ??
(key.isNotEmpty ? key : 'Default');
eventPack?.tryGet<String>('name') ??
(key.isNotEmpty ? key : 'Default');
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 4.0,
),
padding: const EdgeInsets.symmetric(horizontal: 4.0),
child: FilterChip(
label: Text(packName),
selected: controller.stateKey == key ||
selected:
controller.stateKey == key ||
(controller.stateKey == null && key.isEmpty),
onSelected: controller.showSave
? null
@ -153,8 +149,8 @@ class EmotesSettingsView extends StatelessWidget {
),
body: MaxWidthBody(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: .min,
crossAxisAlignment: .stretch,
children: <Widget>[
if (controller.room != null) ...[
const SizedBox(height: 16),
@ -188,9 +184,10 @@ class EmotesSettingsView extends StatelessWidget {
? null
: IconButton(
icon: const Icon(Icons.link_outlined),
onPressed: () =>
UrlLauncher(context, attributionUrl.toString())
.launchUrl(),
onPressed: () => UrlLauncher(
context,
attributionUrl.toString(),
).launchUrl(),
),
),
),
@ -283,25 +280,23 @@ class EmotesSettingsView extends StatelessWidget {
),
onSubmitted: (s) =>
controller.submitImageAction(
imageCode,
image,
textEditingController,
),
imageCode,
image,
textEditingController,
),
),
),
),
),
if (!controller.readonly)
PopupMenuButton<ImagePackUsage>(
onSelected: (usage) => controller.toggleUsage(
imageCode,
usage,
),
onSelected: (usage) =>
controller.toggleUsage(imageCode, usage),
itemBuilder: (context) => [
PopupMenuItem(
value: ImagePackUsage.sticker,
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisSize: .min,
children: [
if (image.usage?.contains(
ImagePackUsage.sticker,
@ -316,7 +311,7 @@ class EmotesSettingsView extends StatelessWidget {
PopupMenuItem(
value: ImagePackUsage.emoticon,
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisSize: .min,
children: [
if (image.usage?.contains(
ImagePackUsage.emoticon,
@ -363,10 +358,8 @@ class _EmoteImage extends StatelessWidget {
final key = 'sticker_preview_$mxc';
return InkWell(
borderRadius: BorderRadius.circular(4),
onTap: () => showDialog(
context: context,
builder: (_) => MxcImageViewer(mxc),
),
onTap: () =>
showDialog(context: context, builder: (_) => MxcImageViewer(mxc)),
child: MxcImage(
key: ValueKey(key),
cacheKey: key,