mirror of
https://gitlab.com/famedly/fluffychat.git
synced 2025-02-03 00:34:11 +01:00
Merge branch 'krille/make-utils-nullsafe' into 'main'
refactor: Make most of the utils null safe See merge request famedly/fluffychat!603
This commit is contained in:
commit
7170c9063c
@ -1,8 +1,10 @@
|
|||||||
|
//@dart=2.12
|
||||||
|
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
|
|
||||||
class AccountBundles {
|
class AccountBundles {
|
||||||
String prefix;
|
String? prefix;
|
||||||
List<AccountBundle> bundles;
|
List<AccountBundle>? bundles;
|
||||||
|
|
||||||
AccountBundles({this.prefix, this.bundles});
|
AccountBundles({this.prefix, this.bundles});
|
||||||
|
|
||||||
@ -23,13 +25,14 @@ class AccountBundles {
|
|||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
Map<String, dynamic> toJson() => {
|
||||||
if (prefix != null) 'prefix': prefix,
|
if (prefix != null) 'prefix': prefix,
|
||||||
if (bundles != null) 'bundles': bundles.map((v) => v.toJson()).toList(),
|
if (bundles != null)
|
||||||
|
'bundles': bundles!.map((v) => v.toJson()).toList(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
class AccountBundle {
|
class AccountBundle {
|
||||||
String name;
|
String? name;
|
||||||
int priority;
|
int? priority;
|
||||||
|
|
||||||
AccountBundle({this.name, this.priority});
|
AccountBundle({this.name, this.priority});
|
||||||
|
|
||||||
@ -47,9 +50,9 @@ const accountBundlesType = 'im.fluffychat.account_bundles';
|
|||||||
|
|
||||||
extension AccountBundlesExtension on Client {
|
extension AccountBundlesExtension on Client {
|
||||||
List<AccountBundle> get accountBundles {
|
List<AccountBundle> get accountBundles {
|
||||||
List<AccountBundle> ret;
|
List<AccountBundle>? ret;
|
||||||
if (accountData.containsKey(accountBundlesType)) {
|
if (accountData.containsKey(accountBundlesType)) {
|
||||||
ret = AccountBundles.fromJson(accountData[accountBundlesType].content)
|
ret = AccountBundles.fromJson(accountData[accountBundlesType]!.content)
|
||||||
.bundles;
|
.bundles;
|
||||||
}
|
}
|
||||||
ret ??= [];
|
ret ??= [];
|
||||||
@ -62,12 +65,12 @@ extension AccountBundlesExtension on Client {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> setAccountBundle(String name, [int priority]) async {
|
Future<void> setAccountBundle(String name, [int? priority]) async {
|
||||||
final data =
|
final data =
|
||||||
AccountBundles.fromJson(accountData[accountBundlesType]?.content ?? {});
|
AccountBundles.fromJson(accountData[accountBundlesType]?.content ?? {});
|
||||||
var foundBundle = false;
|
var foundBundle = false;
|
||||||
data.bundles ??= [];
|
final bundles = data.bundles ??= [];
|
||||||
for (final bundle in data.bundles) {
|
for (final bundle in bundles) {
|
||||||
if (bundle.name == name) {
|
if (bundle.name == name) {
|
||||||
bundle.priority = priority;
|
bundle.priority = priority;
|
||||||
foundBundle = true;
|
foundBundle = true;
|
||||||
@ -75,9 +78,9 @@ extension AccountBundlesExtension on Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!foundBundle) {
|
if (!foundBundle) {
|
||||||
data.bundles.add(AccountBundle(name: name, priority: priority));
|
bundles.add(AccountBundle(name: name, priority: priority));
|
||||||
}
|
}
|
||||||
await setAccountData(userID, accountBundlesType, data.toJson());
|
await setAccountData(userID!, accountBundlesType, data.toJson());
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> removeFromAccountBundle(String name) async {
|
Future<void> removeFromAccountBundle(String name) async {
|
||||||
@ -85,15 +88,15 @@ extension AccountBundlesExtension on Client {
|
|||||||
return; // nothing to do
|
return; // nothing to do
|
||||||
}
|
}
|
||||||
final data =
|
final data =
|
||||||
AccountBundles.fromJson(accountData[accountBundlesType].content);
|
AccountBundles.fromJson(accountData[accountBundlesType]!.content);
|
||||||
if (data.bundles == null) return;
|
if (data.bundles == null) return;
|
||||||
data.bundles.removeWhere((b) => b.name == name);
|
data.bundles!.removeWhere((b) => b.name == name);
|
||||||
await setAccountData(userID, accountBundlesType, data.toJson());
|
await setAccountData(userID!, accountBundlesType, data.toJson());
|
||||||
}
|
}
|
||||||
|
|
||||||
String get sendPrefix {
|
String get sendPrefix {
|
||||||
final data =
|
final data =
|
||||||
AccountBundles.fromJson(accountData[accountBundlesType]?.content ?? {});
|
AccountBundles.fromJson(accountData[accountBundlesType]?.content ?? {});
|
||||||
return data.prefix;
|
return data.prefix!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//@dart=2.12
|
||||||
|
|
||||||
extension BeautifyStringExtension on String {
|
extension BeautifyStringExtension on String {
|
||||||
String get beautified {
|
String get beautified {
|
||||||
var beautifiedStr = '';
|
var beautifiedStr = '';
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//@dart=2.12
|
||||||
|
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//@dart=2.12
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
@ -61,25 +63,25 @@ extension DateTimeExtension on DateTime {
|
|||||||
} else if (sameWeek) {
|
} else if (sameWeek) {
|
||||||
switch (weekday) {
|
switch (weekday) {
|
||||||
case 1:
|
case 1:
|
||||||
return L10n.of(context).monday;
|
return L10n.of(context)!.monday;
|
||||||
case 2:
|
case 2:
|
||||||
return L10n.of(context).tuesday;
|
return L10n.of(context)!.tuesday;
|
||||||
case 3:
|
case 3:
|
||||||
return L10n.of(context).wednesday;
|
return L10n.of(context)!.wednesday;
|
||||||
case 4:
|
case 4:
|
||||||
return L10n.of(context).thursday;
|
return L10n.of(context)!.thursday;
|
||||||
case 5:
|
case 5:
|
||||||
return L10n.of(context).friday;
|
return L10n.of(context)!.friday;
|
||||||
case 6:
|
case 6:
|
||||||
return L10n.of(context).saturday;
|
return L10n.of(context)!.saturday;
|
||||||
case 7:
|
case 7:
|
||||||
return L10n.of(context).sunday;
|
return L10n.of(context)!.sunday;
|
||||||
}
|
}
|
||||||
} else if (sameYear) {
|
} else if (sameYear) {
|
||||||
return L10n.of(context).dateWithoutYear(
|
return L10n.of(context)!.dateWithoutYear(
|
||||||
month.toString().padLeft(2, '0'), day.toString().padLeft(2, '0'));
|
month.toString().padLeft(2, '0'), day.toString().padLeft(2, '0'));
|
||||||
}
|
}
|
||||||
return L10n.of(context).dateWithYear(year.toString(),
|
return L10n.of(context)!.dateWithYear(year.toString(),
|
||||||
month.toString().padLeft(2, '0'), day.toString().padLeft(2, '0'));
|
month.toString().padLeft(2, '0'), day.toString().padLeft(2, '0'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +96,7 @@ extension DateTimeExtension on DateTime {
|
|||||||
final sameDay = sameYear && now.month == month && now.day == day;
|
final sameDay = sameYear && now.month == month && now.day == day;
|
||||||
|
|
||||||
if (sameDay) return localizedTimeOfDay(context);
|
if (sameDay) return localizedTimeOfDay(context);
|
||||||
return L10n.of(context).dateAndTimeOfDay(
|
return L10n.of(context)!.dateAndTimeOfDay(
|
||||||
localizedTimeShort(context), localizedTimeOfDay(context));
|
localizedTimeShort(context), localizedTimeOfDay(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//@dart=2.12
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
@ -15,7 +17,7 @@ abstract class FluffyShare {
|
|||||||
ClipboardData(text: text),
|
ClipboardData(text: text),
|
||||||
);
|
);
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(content: Text(L10n.of(context).copiedToClipboard)));
|
SnackBar(content: Text(L10n.of(context)!.copiedToClipboard)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//@dart=2.12
|
||||||
|
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
const _chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890';
|
const _chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890';
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//@dart=2.12
|
||||||
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -12,9 +14,9 @@ extension LocalizedExceptionExtension on Object {
|
|||||||
if (this is MatrixException) {
|
if (this is MatrixException) {
|
||||||
switch ((this as MatrixException).error) {
|
switch ((this as MatrixException).error) {
|
||||||
case MatrixError.M_FORBIDDEN:
|
case MatrixError.M_FORBIDDEN:
|
||||||
return L10n.of(context).noPermission;
|
return L10n.of(context)!.noPermission;
|
||||||
case MatrixError.M_LIMIT_EXCEEDED:
|
case MatrixError.M_LIMIT_EXCEEDED:
|
||||||
return L10n.of(context).tooManyRequestsWarning;
|
return L10n.of(context)!.tooManyRequestsWarning;
|
||||||
default:
|
default:
|
||||||
return (this as MatrixException).errorMessage;
|
return (this as MatrixException).errorMessage;
|
||||||
}
|
}
|
||||||
@ -30,7 +32,7 @@ extension LocalizedExceptionExtension on Object {
|
|||||||
.toString()
|
.toString()
|
||||||
.replaceAll('{', '"')
|
.replaceAll('{', '"')
|
||||||
.replaceAll('}', '"');
|
.replaceAll('}', '"');
|
||||||
return L10n.of(context)
|
return L10n.of(context)!
|
||||||
.badServerVersionsException(serverVersions, supportedVersions);
|
.badServerVersionsException(serverVersions, supportedVersions);
|
||||||
}
|
}
|
||||||
if (this is BadServerLoginTypesException) {
|
if (this is BadServerLoginTypesException) {
|
||||||
@ -44,15 +46,15 @@ extension LocalizedExceptionExtension on Object {
|
|||||||
.toString()
|
.toString()
|
||||||
.replaceAll('{', '"')
|
.replaceAll('{', '"')
|
||||||
.replaceAll('}', '"');
|
.replaceAll('}', '"');
|
||||||
return L10n.of(context)
|
return L10n.of(context)!
|
||||||
.badServerLoginTypesException(serverVersions, supportedVersions);
|
.badServerLoginTypesException(serverVersions, supportedVersions);
|
||||||
}
|
}
|
||||||
if (this is MatrixConnectionException || this is SocketException) {
|
if (this is MatrixConnectionException || this is SocketException) {
|
||||||
return L10n.of(context).noConnectionToTheServer;
|
return L10n.of(context)!.noConnectionToTheServer;
|
||||||
}
|
}
|
||||||
if (this is String) return toString();
|
if (this is String) return toString();
|
||||||
if (this is UiaException) return toString();
|
if (this is UiaException) return toString();
|
||||||
Logs().w('Something went wrong: ', this);
|
Logs().w('Something went wrong: ', this);
|
||||||
return L10n.of(context).oopsSomethingWentWrong;
|
return L10n.of(context)!.oopsSomethingWentWrong;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//@dart=2.12
|
||||||
|
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
|
|
||||||
extension ClientPresenceExtension on Client {
|
extension ClientPresenceExtension on Client {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//@dart=2.12
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
@ -31,14 +33,14 @@ IconData _getIconFromName(String displayname) {
|
|||||||
|
|
||||||
extension DeviceExtension on Device {
|
extension DeviceExtension on Device {
|
||||||
String get displayname =>
|
String get displayname =>
|
||||||
(displayName?.isNotEmpty ?? false) ? displayName : 'Unknown device';
|
(displayName?.isNotEmpty ?? false) ? displayName! : 'Unknown device';
|
||||||
|
|
||||||
IconData get icon => _getIconFromName(displayname);
|
IconData get icon => _getIconFromName(displayname);
|
||||||
}
|
}
|
||||||
|
|
||||||
extension DeviceKeysExtension on DeviceKeys {
|
extension DeviceKeysExtension on DeviceKeys {
|
||||||
String get displayname => (deviceDisplayName?.isNotEmpty ?? false)
|
String get displayname => (deviceDisplayName?.isNotEmpty ?? false)
|
||||||
? deviceDisplayName
|
? deviceDisplayName!
|
||||||
: 'Unknown device';
|
: 'Unknown device';
|
||||||
|
|
||||||
IconData get icon => _getIconFromName(displayname);
|
IconData get icon => _getIconFromName(displayname);
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//@dart=2.12
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
@ -19,10 +21,10 @@ extension LocalizedBody on Event {
|
|||||||
|
|
||||||
bool get isAttachmentSmallEnough =>
|
bool get isAttachmentSmallEnough =>
|
||||||
infoMap['size'] is int &&
|
infoMap['size'] is int &&
|
||||||
infoMap['size'] < room.client.database.maxFileSize;
|
infoMap['size'] < room.client.database!.maxFileSize;
|
||||||
bool get isThumbnailSmallEnough =>
|
bool get isThumbnailSmallEnough =>
|
||||||
thumbnailInfoMap['size'] is int &&
|
thumbnailInfoMap['size'] is int &&
|
||||||
thumbnailInfoMap['size'] < room.client.database.maxFileSize;
|
thumbnailInfoMap['size'] < room.client.database!.maxFileSize;
|
||||||
|
|
||||||
bool get showThumbnail =>
|
bool get showThumbnail =>
|
||||||
[MessageTypes.Image, MessageTypes.Sticker, MessageTypes.Video]
|
[MessageTypes.Image, MessageTypes.Sticker, MessageTypes.Video]
|
||||||
@ -32,7 +34,7 @@ extension LocalizedBody on Event {
|
|||||||
isThumbnailSmallEnough ||
|
isThumbnailSmallEnough ||
|
||||||
(content['url'] is String));
|
(content['url'] is String));
|
||||||
|
|
||||||
String get sizeString {
|
String? get sizeString {
|
||||||
if (content['info'] is Map<String, dynamic> &&
|
if (content['info'] is Map<String, dynamic> &&
|
||||||
content['info'].containsKey('size')) {
|
content['info'].containsKey('size')) {
|
||||||
num size = content['info']['size'];
|
num size = content['info']['size'];
|
||||||
@ -58,6 +60,7 @@ extension LocalizedBody on Event {
|
|||||||
|
|
||||||
Future<bool> isAttachmentCached({bool getThumbnail = false}) async {
|
Future<bool> isAttachmentCached({bool getThumbnail = false}) async {
|
||||||
final mxcUrl = attachmentOrThumbnailMxcUrl(getThumbnail: getThumbnail);
|
final mxcUrl = attachmentOrThumbnailMxcUrl(getThumbnail: getThumbnail);
|
||||||
|
if (mxcUrl == null) return false;
|
||||||
// check if we have it in-memory
|
// check if we have it in-memory
|
||||||
if (_downloadAndDecryptFutures.containsKey(mxcUrl)) {
|
if (_downloadAndDecryptFutures.containsKey(mxcUrl)) {
|
||||||
return true;
|
return true;
|
||||||
@ -72,7 +75,7 @@ extension LocalizedBody on Event {
|
|||||||
return file != null;
|
return file != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<MatrixFile> downloadAndDecryptAttachmentCached(
|
Future<MatrixFile?> downloadAndDecryptAttachmentCached(
|
||||||
{bool getThumbnail = false}) async {
|
{bool getThumbnail = false}) async {
|
||||||
final mxcUrl =
|
final mxcUrl =
|
||||||
attachmentOrThumbnailMxcUrl(getThumbnail: getThumbnail).toString();
|
attachmentOrThumbnailMxcUrl(getThumbnail: getThumbnail).toString();
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//@dart=2.12
|
||||||
|
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
|
|
||||||
import '../../config/app_config.dart';
|
import '../../config/app_config.dart';
|
||||||
@ -30,13 +32,14 @@ extension FilteredTimelineExtension on Timeline {
|
|||||||
filteredEvents[i - 1].isState &&
|
filteredEvents[i - 1].isState &&
|
||||||
!unfolded.contains(filteredEvents[i - 1].eventId)) {
|
!unfolded.contains(filteredEvents[i - 1].eventId)) {
|
||||||
counter++;
|
counter++;
|
||||||
filteredEvents[i].unsigned['im.fluffychat.collapsed_state_event'] =
|
filteredEvents[i].unsigned ??= {};
|
||||||
|
filteredEvents[i].unsigned!['im.fluffychat.collapsed_state_event'] =
|
||||||
true;
|
true;
|
||||||
} else {
|
} else {
|
||||||
filteredEvents[i].unsigned['im.fluffychat.collapsed_state_event'] =
|
filteredEvents[i].unsigned!['im.fluffychat.collapsed_state_event'] =
|
||||||
false;
|
false;
|
||||||
filteredEvents[i]
|
filteredEvents[i]
|
||||||
.unsigned['im.fluffychat.collapsed_state_event_count'] = counter;
|
.unsigned!['im.fluffychat.collapsed_state_event_count'] = counter;
|
||||||
counter = 0;
|
counter = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//@dart=2.12
|
||||||
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -16,14 +18,14 @@ extension MatrixFileExtension on MatrixFile {
|
|||||||
if (PlatformInfos.isMobile) {
|
if (PlatformInfos.isMobile) {
|
||||||
final tmpDirectory = PlatformInfos.isAndroid
|
final tmpDirectory = PlatformInfos.isAndroid
|
||||||
? (await getExternalStorageDirectories(
|
? (await getExternalStorageDirectories(
|
||||||
type: StorageDirectory.downloads))
|
type: StorageDirectory.downloads))!
|
||||||
.first
|
.first
|
||||||
: await getTemporaryDirectory();
|
: await getTemporaryDirectory();
|
||||||
final path = '${tmpDirectory.path}$fileName';
|
final path = '${tmpDirectory.path}$fileName';
|
||||||
await File(path).writeAsBytes(bytes);
|
await File(path).writeAsBytes(bytes);
|
||||||
await Share.shareFiles([path]);
|
await Share.shareFiles([path]);
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(content: Text(L10n.of(context).savedFileAs(path))),
|
SnackBar(content: Text(L10n.of(context)!.savedFileAs(path))),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//@dart=2.12
|
||||||
|
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//@dart=2.12
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
@ -8,25 +10,27 @@ import '../date_time_extension.dart';
|
|||||||
extension PresenceExtension on Presence {
|
extension PresenceExtension on Presence {
|
||||||
String getLocalizedLastActiveAgo(BuildContext context) {
|
String getLocalizedLastActiveAgo(BuildContext context) {
|
||||||
if (presence.lastActiveAgo != null && presence.lastActiveAgo != 0) {
|
if (presence.lastActiveAgo != null && presence.lastActiveAgo != 0) {
|
||||||
return L10n.of(context).lastActiveAgo(DateTime.fromMillisecondsSinceEpoch(
|
return L10n.of(context)!.lastActiveAgo(
|
||||||
DateTime.now().millisecondsSinceEpoch - presence.lastActiveAgo)
|
DateTime.fromMillisecondsSinceEpoch(
|
||||||
|
DateTime.now().millisecondsSinceEpoch -
|
||||||
|
presence.lastActiveAgo!)
|
||||||
.localizedTimeShort(context));
|
.localizedTimeShort(context));
|
||||||
}
|
}
|
||||||
return L10n.of(context).lastSeenLongTimeAgo;
|
return L10n.of(context)!.lastSeenLongTimeAgo;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getLocalizedStatusMessage(BuildContext context) {
|
String getLocalizedStatusMessage(BuildContext context) {
|
||||||
if (presence.statusMsg?.isNotEmpty ?? false) {
|
if (presence.statusMsg?.isNotEmpty ?? false) {
|
||||||
return presence.statusMsg;
|
return presence.statusMsg!;
|
||||||
}
|
}
|
||||||
if (presence.currentlyActive ?? false) {
|
if (presence.currentlyActive ?? false) {
|
||||||
return L10n.of(context).currentlyActive;
|
return L10n.of(context)!.currentlyActive;
|
||||||
}
|
}
|
||||||
return getLocalizedLastActiveAgo(context);
|
return getLocalizedLastActiveAgo(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color get color {
|
Color get color {
|
||||||
switch (presence?.presence ?? PresenceType.offline) {
|
switch (presence.presence) {
|
||||||
case PresenceType.online:
|
case PresenceType.online:
|
||||||
return Colors.green;
|
return Colors.green;
|
||||||
case PresenceType.offline:
|
case PresenceType.offline:
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//@dart=2.12
|
||||||
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
@ -50,7 +52,7 @@ abstract class PlatformInfos {
|
|||||||
Text('Version: $version'),
|
Text('Version: $version'),
|
||||||
OutlinedButton(
|
OutlinedButton(
|
||||||
onPressed: () => launch(AppConfig.sourceCodeUrl),
|
onPressed: () => launch(AppConfig.sourceCodeUrl),
|
||||||
child: Text(L10n.of(context).sourceCode),
|
child: Text(L10n.of(context)!.sourceCode),
|
||||||
),
|
),
|
||||||
OutlinedButton(
|
OutlinedButton(
|
||||||
onPressed: () => launch(AppConfig.emojiFontUrl),
|
onPressed: () => launch(AppConfig.emojiFontUrl),
|
||||||
@ -60,7 +62,7 @@ abstract class PlatformInfos {
|
|||||||
onPressed: () => VRouter.of(context).to('logs'),
|
onPressed: () => VRouter.of(context).to('logs'),
|
||||||
child: const Text('Logs'),
|
child: const Text('Logs'),
|
||||||
),
|
),
|
||||||
SentrySwitchListTile.adaptive(label: L10n.of(context).sendBugReports),
|
SentrySwitchListTile.adaptive(label: L10n.of(context)!.sendBugReports),
|
||||||
],
|
],
|
||||||
applicationIcon: Image.asset('assets/logo.png', width: 64, height: 64),
|
applicationIcon: Image.asset('assets/logo.png', width: 64, height: 64),
|
||||||
applicationName: AppConfig.applicationName,
|
applicationName: AppConfig.applicationName,
|
||||||
|
@ -1,20 +1,4 @@
|
|||||||
/*
|
//@dart=2.12
|
||||||
* Famedly App
|
|
||||||
* Copyright (C) 2020 Famedly GmbH
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as
|
|
||||||
* published by the Free Software Foundation, either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
|
|
||||||
@ -23,12 +7,12 @@ import 'resize_image.dart';
|
|||||||
extension RoomSendFileExtension on Room {
|
extension RoomSendFileExtension on Room {
|
||||||
Future<Uri> sendFileEventWithThumbnail(
|
Future<Uri> sendFileEventWithThumbnail(
|
||||||
MatrixFile file, {
|
MatrixFile file, {
|
||||||
String txid,
|
String? txid,
|
||||||
Event inReplyTo,
|
Event? inReplyTo,
|
||||||
String editEventId,
|
String? editEventId,
|
||||||
bool waitUntilSent,
|
bool? waitUntilSent,
|
||||||
}) async {
|
}) async {
|
||||||
MatrixFile thumbnail;
|
MatrixImageFile? thumbnail;
|
||||||
if (file is MatrixImageFile) {
|
if (file is MatrixImageFile) {
|
||||||
thumbnail = await file.resizeImage();
|
thumbnail = await file.resizeImage();
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//@dart=2.12
|
||||||
|
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
@ -8,31 +10,32 @@ import 'date_time_extension.dart';
|
|||||||
import 'matrix_sdk_extensions.dart/filtered_timeline_extension.dart';
|
import 'matrix_sdk_extensions.dart/filtered_timeline_extension.dart';
|
||||||
|
|
||||||
extension RoomStatusExtension on Room {
|
extension RoomStatusExtension on Room {
|
||||||
Presence get directChatPresence => client.presences[directChatMatrixID];
|
Presence? get directChatPresence => client.presences[directChatMatrixID];
|
||||||
|
|
||||||
String getLocalizedStatus(BuildContext context) {
|
String getLocalizedStatus(BuildContext context) {
|
||||||
if (isDirectChat) {
|
if (isDirectChat) {
|
||||||
|
final directChatPresence = this.directChatPresence;
|
||||||
if (directChatPresence != null &&
|
if (directChatPresence != null &&
|
||||||
directChatPresence.presence != null &&
|
|
||||||
(directChatPresence.presence.lastActiveAgo != null ||
|
(directChatPresence.presence.lastActiveAgo != null ||
|
||||||
directChatPresence.presence.currentlyActive != null)) {
|
directChatPresence.presence.currentlyActive != null)) {
|
||||||
if (directChatPresence.presence.statusMsg?.isNotEmpty ?? false) {
|
if (directChatPresence.presence.statusMsg?.isNotEmpty ?? false) {
|
||||||
return directChatPresence.presence.statusMsg;
|
return directChatPresence.presence.statusMsg!;
|
||||||
}
|
}
|
||||||
if (directChatPresence.presence.currentlyActive == true) {
|
if (directChatPresence.presence.currentlyActive == true) {
|
||||||
return L10n.of(context).currentlyActive;
|
return L10n.of(context)!.currentlyActive;
|
||||||
}
|
}
|
||||||
if (directChatPresence.presence.lastActiveAgo == null) {
|
if (directChatPresence.presence.lastActiveAgo == null) {
|
||||||
return L10n.of(context).lastSeenLongTimeAgo;
|
return L10n.of(context)!.lastSeenLongTimeAgo;
|
||||||
}
|
}
|
||||||
final time = DateTime.fromMillisecondsSinceEpoch(
|
final time = DateTime.fromMillisecondsSinceEpoch(
|
||||||
DateTime.now().millisecondsSinceEpoch -
|
DateTime.now().millisecondsSinceEpoch -
|
||||||
directChatPresence.presence.lastActiveAgo);
|
directChatPresence.presence.lastActiveAgo!);
|
||||||
return L10n.of(context).lastActiveAgo(time.localizedTimeShort(context));
|
return L10n.of(context)!
|
||||||
|
.lastActiveAgo(time.localizedTimeShort(context));
|
||||||
}
|
}
|
||||||
return L10n.of(context).lastSeenLongTimeAgo;
|
return L10n.of(context)!.lastSeenLongTimeAgo;
|
||||||
}
|
}
|
||||||
return L10n.of(context)
|
return L10n.of(context)!
|
||||||
.countParticipants(summary.mJoinedMemberCount.toString());
|
.countParticipants(summary.mJoinedMemberCount.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,23 +45,23 @@ extension RoomStatusExtension on Room {
|
|||||||
typingUsers.removeWhere((User u) => u.id == client.userID);
|
typingUsers.removeWhere((User u) => u.id == client.userID);
|
||||||
|
|
||||||
if (AppConfig.hideTypingUsernames) {
|
if (AppConfig.hideTypingUsernames) {
|
||||||
typingText = L10n.of(context).isTyping;
|
typingText = L10n.of(context)!.isTyping;
|
||||||
if (typingUsers.first.id != directChatMatrixID) {
|
if (typingUsers.first.id != directChatMatrixID) {
|
||||||
typingText =
|
typingText =
|
||||||
L10n.of(context).numUsersTyping(typingUsers.length.toString());
|
L10n.of(context)!.numUsersTyping(typingUsers.length.toString());
|
||||||
}
|
}
|
||||||
} else if (typingUsers.length == 1) {
|
} else if (typingUsers.length == 1) {
|
||||||
typingText = L10n.of(context).isTyping;
|
typingText = L10n.of(context)!.isTyping;
|
||||||
if (typingUsers.first.id != directChatMatrixID) {
|
if (typingUsers.first.id != directChatMatrixID) {
|
||||||
typingText =
|
typingText =
|
||||||
L10n.of(context).userIsTyping(typingUsers.first.calcDisplayname());
|
L10n.of(context)!.userIsTyping(typingUsers.first.calcDisplayname());
|
||||||
}
|
}
|
||||||
} else if (typingUsers.length == 2) {
|
} else if (typingUsers.length == 2) {
|
||||||
typingText = L10n.of(context).userAndUserAreTyping(
|
typingText = L10n.of(context)!.userAndUserAreTyping(
|
||||||
typingUsers.first.calcDisplayname(),
|
typingUsers.first.calcDisplayname(),
|
||||||
typingUsers[1].calcDisplayname());
|
typingUsers[1].calcDisplayname());
|
||||||
} else if (typingUsers.length > 2) {
|
} else if (typingUsers.length > 2) {
|
||||||
typingText = L10n.of(context).userAndOthersAreTyping(
|
typingText = L10n.of(context)!.userAndOthersAreTyping(
|
||||||
typingUsers.first.calcDisplayname(),
|
typingUsers.first.calcDisplayname(),
|
||||||
(typingUsers.length - 1).toString());
|
(typingUsers.length - 1).toString());
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//@dart=2.12
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:isolate/isolate.dart';
|
import 'package:isolate/isolate.dart';
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//@dart=2.12
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//@dart=2.12
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
extension StreamExtension on Stream {
|
extension StreamExtension on Stream {
|
||||||
@ -5,11 +7,11 @@ extension StreamExtension on Stream {
|
|||||||
/// stream, ratelimited by the Duration t
|
/// stream, ratelimited by the Duration t
|
||||||
Stream<bool> rateLimit(Duration t) {
|
Stream<bool> rateLimit(Duration t) {
|
||||||
final controller = StreamController<bool>();
|
final controller = StreamController<bool>();
|
||||||
Timer timer;
|
Timer? timer;
|
||||||
var gotMessage = false;
|
var gotMessage = false;
|
||||||
// as we call our inline-defined function recursively we need to make sure that the
|
// as we call our inline-defined function recursively we need to make sure that the
|
||||||
// variable exists prior of creating the function. Silly dart.
|
// variable exists prior of creating the function. Silly dart.
|
||||||
Function _onMessage;
|
Function? _onMessage;
|
||||||
// callback to determine if we should send out an update
|
// callback to determine if we should send out an update
|
||||||
_onMessage = () {
|
_onMessage = () {
|
||||||
// do nothing if it is already closed
|
// do nothing if it is already closed
|
||||||
@ -25,7 +27,7 @@ extension StreamExtension on Stream {
|
|||||||
// method to send out an update!
|
// method to send out an update!
|
||||||
timer = null;
|
timer = null;
|
||||||
if (gotMessage) {
|
if (gotMessage) {
|
||||||
_onMessage();
|
_onMessage?.call();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -33,7 +35,7 @@ extension StreamExtension on Stream {
|
|||||||
gotMessage = true;
|
gotMessage = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
final subscription = listen((_) => _onMessage(),
|
final subscription = listen((_) => _onMessage?.call(),
|
||||||
onDone: () => controller.close(),
|
onDone: () => controller.close(),
|
||||||
onError: (e, s) => controller.addError(e, s));
|
onError: (e, s) => controller.addError(e, s));
|
||||||
// add proper cleanup to the subscription and the controller, to not memory leak
|
// add proper cleanup to the subscription and the controller, to not memory leak
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//@dart=2.12
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
extension StringColor on String {
|
extension StringColor on String {
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
// ignore: camel_case_types
|
|
||||||
class platformViewRegistry {
|
|
||||||
static void registerViewFactory(String _, dynamic __) {}
|
|
||||||
}
|
|
@ -1,3 +1,5 @@
|
|||||||
|
//@dart=2.12
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
@ -24,9 +26,9 @@ extension UiaRequestManager on MatrixState {
|
|||||||
final input = cachedPassword ??
|
final input = cachedPassword ??
|
||||||
(await showTextInputDialog(
|
(await showTextInputDialog(
|
||||||
context: navigatorContext,
|
context: navigatorContext,
|
||||||
title: L10n.of(context).pleaseEnterYourPassword,
|
title: L10n.of(context)!.pleaseEnterYourPassword,
|
||||||
okLabel: L10n.of(context).ok,
|
okLabel: L10n.of(context)!.ok,
|
||||||
cancelLabel: L10n.of(context).cancel,
|
cancelLabel: L10n.of(context)!.cancel,
|
||||||
textFields: [
|
textFields: [
|
||||||
const DialogTextField(
|
const DialogTextField(
|
||||||
minLines: 1,
|
minLines: 1,
|
||||||
@ -37,20 +39,20 @@ extension UiaRequestManager on MatrixState {
|
|||||||
],
|
],
|
||||||
))
|
))
|
||||||
?.single;
|
?.single;
|
||||||
if (input?.isEmpty ?? true) {
|
if (input == null || input.isEmpty) {
|
||||||
return uiaRequest.cancel();
|
return uiaRequest.cancel();
|
||||||
}
|
}
|
||||||
return uiaRequest.completeStage(
|
return uiaRequest.completeStage(
|
||||||
AuthenticationPassword(
|
AuthenticationPassword(
|
||||||
session: uiaRequest.session,
|
session: uiaRequest.session,
|
||||||
password: input,
|
password: input,
|
||||||
identifier: AuthenticationUserIdentifier(user: client.userID),
|
identifier: AuthenticationUserIdentifier(user: client.userID!),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
case AuthenticationTypes.emailIdentity:
|
case AuthenticationTypes.emailIdentity:
|
||||||
if (currentThreepidCreds == null || currentClientSecret == null) {
|
if (currentThreepidCreds == null || currentClientSecret == null) {
|
||||||
return uiaRequest.cancel(
|
return uiaRequest.cancel(
|
||||||
UiaException(L10n.of(widget.context).serverRequiresEmail),
|
UiaException(L10n.of(widget.context)!.serverRequiresEmail),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
final auth = AuthenticationThreePidCreds(
|
final auth = AuthenticationThreePidCreds(
|
||||||
@ -65,10 +67,10 @@ extension UiaRequestManager on MatrixState {
|
|||||||
await showOkCancelAlertDialog(
|
await showOkCancelAlertDialog(
|
||||||
useRootNavigator: false,
|
useRootNavigator: false,
|
||||||
context: navigatorContext,
|
context: navigatorContext,
|
||||||
title: L10n.of(context).weSentYouAnEmail,
|
title: L10n.of(context)!.weSentYouAnEmail,
|
||||||
message: L10n.of(context).pleaseClickOnLink,
|
message: L10n.of(context)!.pleaseClickOnLink,
|
||||||
okLabel: L10n.of(context).iHaveClickedOnLink,
|
okLabel: L10n.of(context)!.iHaveClickedOnLink,
|
||||||
cancelLabel: L10n.of(context).cancel,
|
cancelLabel: L10n.of(context)!.cancel,
|
||||||
)) {
|
)) {
|
||||||
return uiaRequest.completeStage(auth);
|
return uiaRequest.completeStage(auth);
|
||||||
}
|
}
|
||||||
@ -90,7 +92,7 @@ extension UiaRequestManager on MatrixState {
|
|||||||
action: (_, __) {
|
action: (_, __) {
|
||||||
uiaRequest.cancel();
|
uiaRequest.cancel();
|
||||||
},
|
},
|
||||||
label: L10n.of(context).cancel,
|
label: L10n.of(context)!.cancel,
|
||||||
id: 0,
|
id: 0,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -101,10 +103,10 @@ extension UiaRequestManager on MatrixState {
|
|||||||
if (OkCancelResult.ok ==
|
if (OkCancelResult.ok ==
|
||||||
await showOkCancelAlertDialog(
|
await showOkCancelAlertDialog(
|
||||||
useRootNavigator: false,
|
useRootNavigator: false,
|
||||||
message: L10n.of(context).pleaseFollowInstructionsOnWeb,
|
message: L10n.of(context)!.pleaseFollowInstructionsOnWeb,
|
||||||
context: navigatorContext,
|
context: navigatorContext,
|
||||||
okLabel: L10n.of(context).next,
|
okLabel: L10n.of(context)!.next,
|
||||||
cancelLabel: L10n.of(context).cancel,
|
cancelLabel: L10n.of(context)!.cancel,
|
||||||
)) {
|
)) {
|
||||||
return uiaRequest.completeStage(
|
return uiaRequest.completeStage(
|
||||||
AuthenticationData(session: uiaRequest.session),
|
AuthenticationData(session: uiaRequest.session),
|
||||||
|
Loading…
Reference in New Issue
Block a user