Merge branch 'main' of gitlab.com:famedly/fluffychat into main

This commit is contained in:
Christian Pauly 2021-04-14 13:40:19 +02:00
commit ebbfb395df
35 changed files with 224 additions and 99 deletions

View File

@ -4,6 +4,9 @@ linter:
rules:
- camel_case_types
- avoid_print
- constant_identifier_names
- prefer_final_locals
- prefer_final_in_for_each
analyzer:
errors:

View File

@ -7,24 +7,24 @@ import 'app_config.dart';
abstract class FluffyThemes {
static const double columnWidth = 360.0;
static const fallback_text_style =
static const fallbackTextStyle =
TextStyle(fontFamily: 'NotoSans', fontFamilyFallback: ['NotoEmoji']);
static var fallback_text_theme = PlatformInfos.isDesktop
? TextTheme(
bodyText1: fallback_text_style,
bodyText2: fallback_text_style,
button: fallback_text_style,
caption: fallback_text_style,
overline: fallback_text_style,
headline1: fallback_text_style,
headline2: fallback_text_style,
headline3: fallback_text_style,
headline4: fallback_text_style,
headline5: fallback_text_style,
headline6: fallback_text_style,
subtitle1: fallback_text_style,
subtitle2: fallback_text_style)
bodyText1: fallbackTextStyle,
bodyText2: fallbackTextStyle,
button: fallbackTextStyle,
caption: fallbackTextStyle,
overline: fallbackTextStyle,
headline1: fallbackTextStyle,
headline2: fallbackTextStyle,
headline3: fallbackTextStyle,
headline4: fallbackTextStyle,
headline5: fallbackTextStyle,
headline6: fallbackTextStyle,
subtitle1: fallbackTextStyle,
subtitle2: fallbackTextStyle)
: TextTheme();
static ThemeData light = ThemeData(

View File

@ -28,16 +28,16 @@ class InvitationSelectionController extends State<InvitationSelection> {
Timer coolDown;
Future<List<User>> getContacts(BuildContext context) async {
var client = Matrix.of(context).client;
final client = Matrix.of(context).client;
final room = client.getRoomById(widget.roomId);
var participants = await room.requestParticipants();
final participants = await room.requestParticipants();
participants.removeWhere(
(u) => ![Membership.join, Membership.invite].contains(u.membership),
);
var contacts = <User>[];
var userMap = <String, bool>{};
final contacts = <User>[];
final userMap = <String, bool>{};
for (var i = 0; i < client.rooms.length; i++) {
var roomUsers = client.rooms[i].getParticipants();
final roomUsers = client.rooms[i].getParticipants();
for (var j = 0; j < roomUsers.length; j++) {
if (userMap[roomUsers[j].id] != true &&

View File

@ -20,7 +20,7 @@ class SignUpController extends State<SignUp> {
MatrixFile avatar;
void setAvatarAction() async {
var file =
final file =
await FilePickerCross.importFromStorage(type: FileTypeCross.image);
if (file != null) {
setState(
@ -35,7 +35,7 @@ class SignUpController extends State<SignUp> {
void resetAvatarAction() => setState(() => avatar = null);
void signUpAction([_]) async {
var matrix = Matrix.of(context);
final matrix = Matrix.of(context);
if (usernameController.text.isEmpty) {
setState(() => usernameError = L10n.of(context).pleaseChooseAUsername);
} else {

View File

@ -29,7 +29,7 @@ class SignUpPasswordController extends State<SignUpPassword> {
void toggleShowPassword() => setState(() => showPassword = !showPassword);
void signUpAction({AuthenticationData auth}) async {
var matrix = Matrix.of(context);
final matrix = Matrix.of(context);
if (passwordController.text.isEmpty) {
setState(() => passwordError = L10n.of(context).pleaseEnterYourPassword);
} else {
@ -42,7 +42,7 @@ class SignUpPasswordController extends State<SignUpPassword> {
try {
setState(() => loading = true);
var waitForLogin = matrix.client.onLoginStateChanged.stream.first;
final waitForLogin = matrix.client.onLoginStateChanged.stream.first;
await matrix.client.register(
username: widget.username,
password: passwordController.text,

View File

@ -2304,5 +2304,15 @@
"@chats": {
"type": "text",
"placeholders": {}
},
"goToTheNewRoom": "Ir á nova sala",
"@goToTheNewRoom": {
"type": "text",
"placeholders": {}
},
"roomVersion": "Versión da sala",
"@roomVersion": {
"type": "text",
"placeholders": {}
}
}

View File

@ -2287,5 +2287,30 @@
"@tapOnDeviceToVerify": {
"type": "text",
"placeholders": {}
},
"goToTheNewRoom": "Vai nella nuova stanza",
"@goToTheNewRoom": {
"type": "text",
"placeholders": {}
},
"roomVersion": "Versione della stanza",
"@roomVersion": {
"type": "text",
"placeholders": {}
},
"publicGroups": "Gruppi pubblici",
"@publicGroups": {
"type": "text",
"placeholders": {}
},
"people": "Persone",
"@people": {
"type": "text",
"placeholders": {}
},
"chats": "Discussioni",
"@chats": {
"type": "text",
"placeholders": {}
}
}

View File

@ -2165,7 +2165,7 @@
"type": "text",
"placeholders": {}
},
"pleaseEnterSecurityKey": "Унесите свој сигурносни кључ",
"pleaseEnterSecurityKey": "Унесите свој сигурносни кључ:",
"@pleaseEnterSecurityKey": {
"type": "text",
"placeholders": {}
@ -2215,5 +2215,90 @@
"serverVersions": {},
"supportedVersions": {}
}
},
"unlockChatBackup": "Откључај резерву ћаскања",
"@unlockChatBackup": {
"type": "text",
"placeholders": {}
},
"friends": "Пријатељи",
"@friends": {
"type": "text",
"placeholders": {}
},
"addNewFriend": "Додај новог пријатеља",
"@addNewFriend": {
"type": "text",
"placeholders": {}
},
"noEncryptionForPublicRooms": "Шифровање се може активирати након што соба престане да буде јавно доступна.",
"@noEncryptionForPublicRooms": {
"type": "text",
"placeholders": {}
},
"deviceVerifyDescription": "Шифровање је безбедно само када су сви уређаји верификовани.",
"@deviceVerifyDescription": {
"type": "text",
"placeholders": {}
},
"tapOnDeviceToVerify": "Тапните уређај да верификујете",
"@tapOnDeviceToVerify": {
"type": "text",
"placeholders": {}
},
"showPassword": "Прикажи лозинку",
"@showPassword": {
"type": "text",
"placeholders": {}
},
"addEmail": "Додај е-адресу",
"@addEmail": {
"type": "text",
"placeholders": {}
},
"zoomOut": "Умањи",
"@zoomOut": {
"type": "text",
"placeholders": {}
},
"zoomIn": "Увећај",
"@zoomIn": {
"type": "text",
"placeholders": {}
},
"blocked": "Блокиран",
"@blocked": {
"type": "text",
"placeholders": {}
},
"verified": "Верификовано",
"@verified": {
"type": "text",
"placeholders": {}
},
"goToTheNewRoom": "Иди у нову собу",
"@goToTheNewRoom": {
"type": "text",
"placeholders": {}
},
"roomVersion": "Верзија собе",
"@roomVersion": {
"type": "text",
"placeholders": {}
},
"publicGroups": "Јавне групе",
"@publicGroups": {
"type": "text",
"placeholders": {}
},
"people": "Људи",
"@people": {
"type": "text",
"placeholders": {}
},
"chats": "Ћаскања",
"@chats": {
"type": "text",
"placeholders": {}
}
}

View File

@ -300,13 +300,13 @@ class BackgroundPush {
}
// initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project
var initializationSettingsAndroid =
final initializationSettingsAndroid =
AndroidInitializationSettings('notifications_icon');
var initializationSettingsIOS =
final initializationSettingsIOS =
IOSInitializationSettings(onDidReceiveLocalNotification: (i, a, b, c) {
return null;
});
var initializationSettings = InitializationSettings(
final initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOS,
);
@ -622,7 +622,7 @@ class BackgroundPush {
);
// Show notification
var androidPlatformChannelSpecifics = _getAndroidNotificationDetails(
final androidPlatformChannelSpecifics = _getAndroidNotificationDetails(
styleInformation: MessagingStyleInformation(
person,
conversationTitle: title,
@ -636,8 +636,8 @@ class BackgroundPush {
),
ticker: l10n.newMessageInFluffyChat,
);
var iOSPlatformChannelSpecifics = IOSNotificationDetails();
var platformChannelSpecifics = NotificationDetails(
final iOSPlatformChannelSpecifics = IOSNotificationDetails();
final platformChannelSpecifics = NotificationDetails(
android: androidPlatformChannelSpecifics,
iOS: iOSPlatformChannelSpecifics,
);
@ -655,8 +655,8 @@ class BackgroundPush {
await setupLocalNotificationsPlugin();
await loadLocale();
String eventId = data['event_id'];
String roomId = data['room_id'];
final String eventId = data['event_id'];
final String roomId = data['room_id'];
final unread = ((data['counts'] is String
? json.decode(data.tryGet<String>('counts', '{}'))
: data.tryGet<Map<String, dynamic>>(
@ -668,9 +668,9 @@ class BackgroundPush {
}
// Display notification
var androidPlatformChannelSpecifics = _getAndroidNotificationDetails();
var iOSPlatformChannelSpecifics = IOSNotificationDetails();
var platformChannelSpecifics = NotificationDetails(
final androidPlatformChannelSpecifics = _getAndroidNotificationDetails();
final iOSPlatformChannelSpecifics = IOSNotificationDetails();
final platformChannelSpecifics = NotificationDetails(
android: androidPlatformChannelSpecifics,
iOS: iOSPlatformChannelSpecifics,
);
@ -692,20 +692,20 @@ class BackgroundPush {
final thumbnail = width == null && height == null ? false : true;
final tempDirectory = (await getTemporaryDirectory()).path;
final prefix = thumbnail ? 'thumbnail' : '';
var file =
final file =
File('$tempDirectory/${prefix}_${content.toString().split("/").last}');
if (!file.existsSync()) {
final url = thumbnail
? content.getThumbnail(client, width: width, height: height)
: content.getDownloadLink(client);
var request = await HttpClient().getUrl(Uri.parse(url));
var response = await request.close();
final request = await HttpClient().getUrl(Uri.parse(url));
final response = await request.close();
if (response.statusCode >= 300) {
// we are not in the 2xx range
return null;
}
var bytes = await consolidateHttpClientResponseBytes(response);
final bytes = await consolidateHttpClientResponseBytes(response);
await file.writeAsBytes(bytes);
}

View File

@ -44,13 +44,13 @@ extension DateTimeExtension on DateTime {
/// Returns [localizedTimeOfDay()] if the ChatTime is today, the name of the week
/// day if the ChatTime is this week and a date string else.
String localizedTimeShort(BuildContext context) {
var now = DateTime.now();
final now = DateTime.now();
var sameYear = now.year == year;
final sameYear = now.year == year;
var sameDay = sameYear && now.month == month && now.day == day;
final sameDay = sameYear && now.month == month && now.day == day;
var sameWeek = sameYear &&
final sameWeek = sameYear &&
!sameDay &&
now.millisecondsSinceEpoch - millisecondsSinceEpoch <
1000 * 60 * 60 * 24 * 7;
@ -86,11 +86,11 @@ extension DateTimeExtension on DateTime {
/// shows the date.
/// TODO: Add localization
String localizedTime(BuildContext context) {
var now = DateTime.now();
final now = DateTime.now();
var sameYear = now.year == year;
final sameYear = now.year == year;
var sameDay = sameYear && now.month == month && now.day == day;
final sameDay = sameYear && now.month == month && now.day == day;
if (sameDay) return localizedTimeOfDay(context);
return L10n.of(context).dateAndTimeOfDay(

View File

@ -15,7 +15,7 @@ extension MatrixFileExtension on MatrixFile {
if (kIsWeb) {
final fileName = name.split('/').last;
final mimeType = mime(fileName);
var element = html.document.createElement('a');
final element = html.document.createElement('a');
element.setAttribute(
'href', html.Url.createObjectUrlFromBlob(html.Blob([bytes])));
element.setAttribute('target', '_blank');

View File

@ -40,7 +40,7 @@ abstract class PlatformInfos {
}
static void showDialog(BuildContext context) async {
var version = await PlatformInfos.getVersion();
final version = await PlatformInfos.getVersion();
showAboutDialog(
context: context,
useRootNavigator: false,

View File

@ -35,7 +35,7 @@ extension RoomStatusExtension on Room {
String getLocalizedTypingText(BuildContext context) {
var typingText = '';
var typingUsers = this.typingUsers;
final typingUsers = this.typingUsers;
typingUsers.removeWhere((User u) => u.id == client.userID);
if (AppConfig.hideTypingUsernames) {

View File

@ -40,7 +40,7 @@ class UrlLauncher {
var roomId = room?.id;
// we make the servers a set and later on convert to a list, so that we can easily
// deduplicate servers added via alias lookup and query parameter
var servers = <String>{};
final servers = <String>{};
if (room == null && roomIdOrAlias.sigil == '#') {
// we were unable to find the room locally...so resolve it
final response = await showFutureLoadingDialog(

View File

@ -251,7 +251,7 @@ class _ChatState extends State<Chat> {
}
void openCameraAction(BuildContext context) async {
var file = await ImagePicker().getImage(source: ImageSource.camera);
final file = await ImagePicker().getImage(source: ImageSource.camera);
if (file == null) return;
final bytes = await file.readAsBytes();
await showDialog(
@ -297,7 +297,7 @@ class _ChatState extends State<Chat> {
.getDisplayEvent(timeline)
.getLocalizedBody(MatrixLocals(L10n.of(context)));
}
for (var event in selectedEvents) {
for (final event in selectedEvents) {
if (copyString.isNotEmpty) copyString += '\n\n';
copyString += event.getDisplayEvent(timeline).getLocalizedBody(
MatrixLocals(L10n.of(context)),
@ -356,7 +356,7 @@ class _ChatState extends State<Chat> {
}
void redactEventsAction(BuildContext context) async {
var confirmed = await showOkCancelAlertDialog(
final confirmed = await showOkCancelAlertDialog(
context: context,
title: L10n.of(context).messageWillBeRemovedWarning,
okLabel: L10n.of(context).remove,
@ -365,7 +365,7 @@ class _ChatState extends State<Chat> {
) ==
OkCancelResult.ok;
if (!confirmed) return;
for (var event in selectedEvents) {
for (final event in selectedEvents) {
await showFutureLoadingDialog(
context: context,
future: () => event.status > 0 ? event.redact() : event.remove());
@ -374,7 +374,7 @@ class _ChatState extends State<Chat> {
}
bool get canRedactSelectedEvents {
for (var event in selectedEvents) {
for (final event in selectedEvents) {
if (event.canRedact == false) return false;
}
return true;
@ -512,7 +512,7 @@ class _ChatState extends State<Chat> {
@override
Widget build(BuildContext context) {
matrix = Matrix.of(context);
var client = matrix.client;
final client = matrix.client;
room ??= client.getRoomById(widget.id);
if (room == null) {
return Scaffold(
@ -985,7 +985,7 @@ class _ChatState extends State<Chat> {
selectedEvents.length == 1)) {
return Container();
}
var emojis = List<String>.from(AppEmojis.emojis);
final emojis = List<String>.from(AppEmojis.emojis);
final allReactionEvents = selectedEvents.first
.aggregatedEvents(
timeline, RelationshipTypes.Reaction)

View File

@ -83,7 +83,7 @@ class _ChatDetailsState extends State<ChatDetails> {
final aliases =
aliasEvent != null ? aliasEvent.content['aliases'] ?? [] : [];
if (aliases.indexWhere((s) => s == canonicalAlias) == -1) {
var newAliases = List<String>.from(aliases);
final newAliases = List<String>.from(aliases);
newAliases.add(canonicalAlias);
final response = await showFutureLoadingDialog(
context: context,

View File

@ -116,7 +116,7 @@ class _ChatEncryptionSettingsState extends State<ChatEncryptionSettings> {
onSelected: (action) =>
onSelected(context, action, deviceKeys[i]),
itemBuilder: (c) {
var items = <PopupMenuEntry<String>>[];
final items = <PopupMenuEntry<String>>[];
if (room
.client
.userDeviceKeys[deviceKeys[i].userId]
@ -166,7 +166,7 @@ class _ChatEncryptionSettingsState extends State<ChatEncryptionSettings> {
onSelected: (action) =>
onSelected(context, action, deviceKeys[i]),
itemBuilder: (c) {
var items = <PopupMenuEntry<String>>[];
final items = <PopupMenuEntry<String>>[];
if (deviceKeys[i].blocked ||
!deviceKeys[i].verified) {
items.add(PopupMenuItem(

View File

@ -182,7 +182,7 @@ class _ChatListState extends State<ChatList> {
}
Future<void> waitForFirstSync(BuildContext context) async {
var client = Matrix.of(context).client;
final client = Matrix.of(context).client;
if (client.prevBatch?.isEmpty ?? true) {
await client.onFirstSync.stream.first;
}
@ -371,7 +371,7 @@ class _ChatListState extends State<ChatList> {
future: waitForFirstSync(context),
builder: (BuildContext context, snapshot) {
if (snapshot.hasData) {
var rooms = List<Room>.from(
final rooms = List<Room>.from(
Matrix.of(context).client.rooms);
rooms.removeWhere((room) => room.lastEvent == null);
if (rooms.isEmpty) {

View File

@ -62,7 +62,7 @@ class InvitationSelectionView extends StatelessWidget {
child: CircularProgressIndicator(),
);
}
var contacts = snapshot.data;
final contacts = snapshot.data;
return ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,

View File

@ -61,6 +61,7 @@ class _LogViewerState extends State<LogViewer> {
}
class _AnsiParser {
// ignore: constant_identifier_names
static const TEXT = 0, BRACKET = 1, CODE = 2;
final String text;
@ -73,12 +74,13 @@ class _AnsiParser {
spans = [];
var state = TEXT;
StringBuffer buffer;
var text = StringBuffer();
final text = StringBuffer();
var code = 0;
List<int> codes;
// ignore: prefer_final_locals
for (var i = 0, n = s.length; i < n; i++) {
var c = s[i];
final c = s[i];
switch (state) {
case TEXT:
@ -104,7 +106,7 @@ class _AnsiParser {
case CODE:
buffer.write(c);
var codeUnit = c.codeUnitAt(0);
final codeUnit = c.codeUnitAt(0);
if (codeUnit >= 48 && codeUnit <= 57) {
code = code * 10 + codeUnit - 48;
continue;

View File

@ -26,7 +26,7 @@ class _LoginState extends State<Login> {
bool showPassword = false;
void login(BuildContext context) async {
var matrix = Matrix.of(context);
final matrix = Matrix.of(context);
if (usernameController.text.isEmpty) {
setState(() => usernameError = L10n.of(context).pleaseEnterYourUsername);
} else {

View File

@ -121,7 +121,7 @@ class _NewPrivateChatState extends State<NewPrivateChat> {
return L10n.of(context).pleaseEnterAMatrixIdentifier;
}
final matrix = Matrix.of(context);
var mxid = '@' + controller.text.trim();
final mxid = '@' + controller.text.trim();
if (mxid == matrix.client.userID) {
return L10n.of(context).youCannotInviteYourself;
}
@ -187,7 +187,7 @@ class _NewPrivateChatState extends State<NewPrivateChat> {
child: ListView.builder(
itemCount: foundProfiles.length,
itemBuilder: (BuildContext context, int i) {
var foundProfile = foundProfiles[i];
final foundProfile = foundProfiles[i];
return ListTile(
onTap: () {
setState(() {

View File

@ -355,7 +355,7 @@ class _SearchViewState extends State<SearchView> {
? ListView.builder(
itemCount: foundProfiles.length,
itemBuilder: (BuildContext context, int i) {
var foundProfile = foundProfiles[i];
final foundProfile = foundProfiles[i];
return ListTile(
onTap: () async {
final roomID = await showFutureLoadingDialog(

View File

@ -51,7 +51,7 @@ class _SettingsState extends State<Settings> {
OkCancelResult.cancel) {
return;
}
var matrix = Matrix.of(context);
final matrix = Matrix.of(context);
await showFutureLoadingDialog(
context: context,
future: () => matrix.client.logout(),
@ -146,7 +146,7 @@ class _SettingsState extends State<Settings> {
void setJitsiInstanceAction(BuildContext context) async {
const prefix = 'https://';
var input = await showTextInputDialog(
final input = await showTextInputDialog(
context: context,
title: L10n.of(context).editJitsiInstance,
okLabel: L10n.of(context).ok,

View File

@ -38,9 +38,9 @@ class DevicesSettingsState extends State<DevicesSettings> {
useRootNavigator: false,
) ==
OkCancelResult.cancel) return;
var matrix = Matrix.of(context);
var deviceIds = <String>[];
for (var userDevice in devices) {
final matrix = Matrix.of(context);
final deviceIds = <String>[];
for (final userDevice in devices) {
deviceIds.add(userDevice.deviceId);
}
@ -150,10 +150,10 @@ class DevicesSettingsState extends State<DevicesSettings> {
if (!snapshot.hasData || this.devices == null) {
return Center(child: CircularProgressIndicator());
}
Function isOwnDevice = (Device userDevice) =>
final Function isOwnDevice = (Device userDevice) =>
userDevice.deviceId == Matrix.of(context).client.deviceID;
final devices = List<Device>.from(this.devices);
var thisDevice =
final thisDevice =
devices.firstWhere(isOwnDevice, orElse: () => null);
devices.removeWhere(isOwnDevice);
devices.sort((a, b) => b.lastSeenTs.compareTo(a.lastSeenTs));

View File

@ -137,7 +137,7 @@ class _EmotesSettingsState extends State<EmotesSettings> {
@override
Widget build(BuildContext context) {
var client = Matrix.of(context).client;
final client = Matrix.of(context).client;
if (emotes == null) {
emotes = <_EmoteEntry>[];
Map<String, dynamic> emoteSource;

View File

@ -27,10 +27,10 @@ class AudioPlayer extends StatefulWidget {
_AudioPlayerState createState() => _AudioPlayerState();
}
enum AudioPlayerStatus { NOT_DOWNLOADED, DOWNLOADING, DOWNLOADED }
enum AudioPlayerStatus { notDownloaded, downloading, downloaded }
class _AudioPlayerState extends State<AudioPlayer> {
AudioPlayerStatus status = AudioPlayerStatus.NOT_DOWNLOADED;
AudioPlayerStatus status = AudioPlayerStatus.notDownloaded;
final FlutterSoundPlayer flutterSound = FlutterSoundPlayer();
@ -70,14 +70,14 @@ class _AudioPlayerState extends State<AudioPlayer> {
}
Future<void> _downloadAction() async {
if (status != AudioPlayerStatus.NOT_DOWNLOADED) return;
setState(() => status = AudioPlayerStatus.DOWNLOADING);
if (status != AudioPlayerStatus.notDownloaded) return;
setState(() => status = AudioPlayerStatus.downloading);
try {
final matrixFile =
await widget.event.downloadAndDecryptAttachmentCached();
setState(() {
audioFile = matrixFile.bytes;
status = AudioPlayerStatus.DOWNLOADED;
status = AudioPlayerStatus.downloaded;
});
_playAction();
} catch (e, s) {
@ -126,7 +126,7 @@ class _AudioPlayerState extends State<AudioPlayer> {
});
AudioPlayer.currentId = null;
} else if (e != null) {
var txt =
final txt =
'${e.position.inMinutes.toString().padLeft(2, '0')}:${(e.position.inSeconds % 60).toString().padLeft(2, '0')}';
setState(() {
maxPosition = e.duration.inMilliseconds.toDouble();
@ -158,7 +158,7 @@ class _AudioPlayerState extends State<AudioPlayer> {
children: <Widget>[
Container(
width: 30,
child: status == AudioPlayerStatus.DOWNLOADING
child: status == AudioPlayerStatus.downloading
? CircularProgressIndicator(strokeWidth: 2)
: IconButton(
icon: Icon(
@ -171,7 +171,7 @@ class _AudioPlayerState extends State<AudioPlayer> {
? L10n.of(context).audioPlayerPause
: L10n.of(context).audioPlayerPlay,
onPressed: () {
if (status == AudioPlayerStatus.DOWNLOADED) {
if (status == AudioPlayerStatus.downloaded) {
_playAction();
} else {
_downloadAction();
@ -184,7 +184,7 @@ class _AudioPlayerState extends State<AudioPlayer> {
value: currentPosition,
onChanged: (double position) => flutterSound
.seekToPlayer(Duration(milliseconds: position.toInt())),
max: status == AudioPlayerStatus.DOWNLOADED ? maxPosition : 0,
max: status == AudioPlayerStatus.downloaded ? maxPosition : 0,
min: 0,
),
),

View File

@ -25,7 +25,7 @@ class Avatar extends StatelessWidget {
@override
Widget build(BuildContext context) {
var thumbnail = mxContent?.getThumbnail(
final thumbnail = mxContent?.getThumbnail(
client ?? Matrix.of(context).client,
width: size * MediaQuery.of(context).devicePixelRatio,
height: size * MediaQuery.of(context).devicePixelRatio,

View File

@ -38,7 +38,7 @@ class _ChatSettingsPopupMenuState extends State<ChatSettingsPopupMenu> {
.listen(
(u) => setState(() => null),
);
var items = <PopupMenuEntry<String>>[
final items = <PopupMenuEntry<String>>[
widget.room.pushRuleState == PushRuleState.notify
? PopupMenuItem<String>(
value: 'mute',
@ -66,7 +66,7 @@ class _ChatSettingsPopupMenuState extends State<ChatSettingsPopupMenu> {
onSelected: (String choice) async {
switch (choice) {
case 'leave':
var confirmed = await showOkCancelAlertDialog(
final confirmed = await showOkCancelAlertDialog(
context: context,
useRootNavigator: false,
title: L10n.of(context).areYouSure,

View File

@ -248,7 +248,7 @@ class _KeyVerificationPageState extends State<KeyVerificationDialog> {
));
break;
case KeyVerificationState.waitingSas:
var acceptText = widget.request.sasTypes.contains('emoji')
final acceptText = widget.request.sasTypes.contains('emoji')
? L10n.of(context).waitingPartnerEmoji
: L10n.of(context).waitingPartnerNumbers;
body = Column(

View File

@ -36,7 +36,7 @@ class _RecordingDialogState extends State<RecordingDialog> {
_recordedPath = '${tempDir.path}/recording${ext[codec.index]}';
// delete any existing file
var outputFile = File(_recordedPath);
final outputFile = File(_recordedPath);
if (outputFile.existsSync()) {
await outputFile.delete();
}

View File

@ -45,9 +45,9 @@ class Message extends StatelessWidget {
return StateMessage(event, unfold: unfold);
}
var client = Matrix.of(context).client;
final client = Matrix.of(context).client;
final ownMessage = event.senderId == client.userID;
var alignment = ownMessage ? Alignment.topRight : Alignment.topLeft;
final alignment = ownMessage ? Alignment.topRight : Alignment.topLeft;
var color = Theme.of(context).secondaryHeaderColor;
final sameSender = nextEvent != null &&
[EventTypes.Message, EventTypes.Sticker].contains(nextEvent.type)
@ -58,7 +58,7 @@ class Message extends StatelessWidget {
: Theme.of(context).brightness == Brightness.dark
? Colors.white
: Colors.black;
var rowMainAxisAlignment =
final rowMainAxisAlignment =
ownMessage ? MainAxisAlignment.end : MainAxisAlignment.start;
final displayEvent = event.getDisplayEvent(timeline);
@ -72,7 +72,7 @@ class Message extends StatelessWidget {
: Theme.of(context).primaryColor;
}
var rowChildren = <Widget>[
final rowChildren = <Widget>[
Expanded(
child: Container(
alignment: alignment,

View File

@ -12,7 +12,7 @@ class ParticipantListItem extends StatelessWidget {
@override
Widget build(BuildContext context) {
var membershipBatch = <Membership, String>{
final membershipBatch = <Membership, String>{
Membership.join: '',
Membership.ban: L10n.of(context).banned,
Membership.invite: L10n.of(context).invited,

View File

@ -238,7 +238,7 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
Future<void> initConfig() async {
try {
var configJsonString =
final configJsonString =
utf8.decode((await http.get('config.json')).bodyBytes);
final configJson = json.decode(configJsonString);
AppConfig.loadFromJson(configJson);

View File

@ -90,7 +90,7 @@ class UserBottomSheet extends StatelessWidget {
Widget build(BuildContext context) {
final client = user.room.client;
final presence = client.presences[user.id];
var items = <PopupMenuEntry<String>>[];
final items = <PopupMenuEntry<String>>[];
if (onMention != null) {
items.add(