diff --git a/android/app/build.gradle b/android/app/build.gradle index a500868..bb0c654 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -55,6 +55,9 @@ android { debug { applicationIdSuffix ".testing" } + // profile { + // applicationIdSuffix ".STOP" + // } release { signingConfig signingConfigs.release } diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml index e807f77..8606e90 100644 --- a/android/app/src/profile/AndroidManifest.xml +++ b/android/app/src/profile/AndroidManifest.xml @@ -6,4 +6,6 @@ + + diff --git a/lib/main.dart b/lib/main.dart index 61644cd..6b80c64 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,6 +21,7 @@ import 'package:twonly/src/services/api/mediafiles/upload.service.dart'; import 'package:twonly/src/services/fcm.service.dart'; import 'package:twonly/src/services/mediafiles/mediafile.service.dart'; import 'package:twonly/src/services/notifications/setup.notifications.dart'; +import 'package:twonly/src/services/twonly_safe/create_backup.twonly_safe.dart'; import 'package:twonly/src/utils/log.dart'; import 'package:twonly/src/utils/storage.dart'; @@ -63,13 +64,7 @@ void main() async { unawaited(createPushAvatars()); await twonlyDB.messagesDao.purgeMessageTable(); - // await twonlyDB.messagesDao.resetPendingDownloadState(); - // await twonlyDB.messageRetransmissionDao.purgeOldRetransmissions(); - // await twonlyDB.signalDao.purgeOutDatedPreKeys(); - - // unawaited(purgeSendMediaFiles()); - - // unawaited(performTwonlySafeBackup()); + unawaited(performTwonlySafeBackup()); runApp( MultiProvider( diff --git a/lib/src/database/daos/contacts.dao.dart b/lib/src/database/daos/contacts.dao.dart index 7435688..0d4b6a8 100644 --- a/lib/src/database/daos/contacts.dao.dart +++ b/lib/src/database/daos/contacts.dao.dart @@ -109,6 +109,7 @@ class ContactsDao extends DatabaseAccessor with _$ContactsDaoMixin { ..where( contacts.requested.equals(true) & contacts.accepted.equals(false) & + contacts.deletedByUser.equals(false) & contacts.blocked.equals(false), ) ..addColumns([count]); diff --git a/lib/src/database/daos/groups.dao.dart b/lib/src/database/daos/groups.dao.dart index 0dd04e8..85ce7ec 100644 --- a/lib/src/database/daos/groups.dao.dart +++ b/lib/src/database/daos/groups.dao.dart @@ -281,7 +281,7 @@ class GroupsDao extends DatabaseAccessor with _$GroupsDaoMixin { ..where((t) => t.groupId.equals(groupId))) .getSingle(); - final totalMediaCounter = group.totalMediaCounter + 1; + final totalMediaCounter = group.totalMediaCounter + (received ? 0 : 1); var flameCounter = group.flameCounter; var maxFlameCounter = group.maxFlameCounter; var maxFlameCounterFrom = group.maxFlameCounterFrom; @@ -321,7 +321,11 @@ class GroupsDao extends DatabaseAccessor with _$GroupsDaoMixin { if (updateFlame) { flameCounter += 1; lastFlameCounterChange = Value(timestamp); - if ((flameCounter + 1) >= maxFlameCounter) { + // Overwrite max flame counter either the current is bigger or the th max flame counter is older then 4 days + if ((flameCounter + 1) >= maxFlameCounter || + maxFlameCounterFrom == null || + maxFlameCounterFrom + .isBefore(DateTime.now().subtract(const Duration(days: 5)))) { maxFlameCounter = flameCounter + 1; maxFlameCounterFrom = DateTime.now(); } @@ -351,6 +355,15 @@ class GroupsDao extends DatabaseAccessor with _$GroupsDaoMixin { ); } + Stream watchSumTotalMediaCounter() { + final query = selectOnly(groups) + ..addColumns([groups.totalMediaCounter.sum()]); + return query.watch().map((rows) { + final expr = rows.first.read(groups.totalMediaCounter.sum()); + return expr ?? 0; + }); + } + Future increaseLastMessageExchange( String groupId, DateTime newLastMessage, diff --git a/lib/src/localization/app_de.arb b/lib/src/localization/app_de.arb index f14986a..85299bc 100644 --- a/lib/src/localization/app_de.arb +++ b/lib/src/localization/app_de.arb @@ -816,5 +816,6 @@ "deleteChatAfterADay": "einem Tag.", "deleteChatAfterAWeek": "einer Woche.", "deleteChatAfterAMonth": "einem Monat.", - "deleteChatAfterAYear": "einem Jahr." + "deleteChatAfterAYear": "einem Jahr.", + "yourTwonlyScore": "Dein twonly-Score" } \ No newline at end of file diff --git a/lib/src/localization/app_en.arb b/lib/src/localization/app_en.arb index 08f553c..4078005 100644 --- a/lib/src/localization/app_en.arb +++ b/lib/src/localization/app_en.arb @@ -594,5 +594,6 @@ "deleteChatAfterADay": "one day.", "deleteChatAfterAWeek": "one week.", "deleteChatAfterAMonth": "one month.", - "deleteChatAfterAYear": "one year." + "deleteChatAfterAYear": "one year.", + "yourTwonlyScore": "Your twonly-Score" } \ No newline at end of file diff --git a/lib/src/localization/generated/app_localizations.dart b/lib/src/localization/generated/app_localizations.dart index 140bc39..db8ac2b 100644 --- a/lib/src/localization/generated/app_localizations.dart +++ b/lib/src/localization/generated/app_localizations.dart @@ -2671,6 +2671,12 @@ abstract class AppLocalizations { /// In en, this message translates to: /// **'one year.'** String get deleteChatAfterAYear; + + /// No description provided for @yourTwonlyScore. + /// + /// In en, this message translates to: + /// **'Your twonly-Score'** + String get yourTwonlyScore; } class _AppLocalizationsDelegate diff --git a/lib/src/localization/generated/app_localizations_de.dart b/lib/src/localization/generated/app_localizations_de.dart index 2d8c516..ebe795b 100644 --- a/lib/src/localization/generated/app_localizations_de.dart +++ b/lib/src/localization/generated/app_localizations_de.dart @@ -1474,4 +1474,7 @@ class AppLocalizationsDe extends AppLocalizations { @override String get deleteChatAfterAYear => 'einem Jahr.'; + + @override + String get yourTwonlyScore => 'Dein twonly-Score'; } diff --git a/lib/src/localization/generated/app_localizations_en.dart b/lib/src/localization/generated/app_localizations_en.dart index 9834524..607bc3f 100644 --- a/lib/src/localization/generated/app_localizations_en.dart +++ b/lib/src/localization/generated/app_localizations_en.dart @@ -1464,4 +1464,7 @@ class AppLocalizationsEn extends AppLocalizations { @override String get deleteChatAfterAYear => 'one year.'; + + @override + String get yourTwonlyScore => 'Your twonly-Score'; } diff --git a/lib/src/services/api.service.dart b/lib/src/services/api.service.dart index a918d29..4cc3e23 100644 --- a/lib/src/services/api.service.dart +++ b/lib/src/services/api.service.dart @@ -51,8 +51,8 @@ final lockRetransStore = Mutex(); /// errors or network changes. class ApiService { ApiService(); - final String apiHost = kDebugMode ? '10.99.0.140:3030' : 'api.twonly.eu'; - final String apiSecure = kDebugMode ? '' : 's'; + final String apiHost = kReleaseMode ? 'api.twonly.eu' : '10.99.0.140:3030'; + final String apiSecure = kReleaseMode ? 's' : ''; bool appIsOutdated = false; bool isAuthenticated = false; diff --git a/lib/src/services/api/mediafiles/media_background.service.dart b/lib/src/services/api/mediafiles/media_background.service.dart index 8d1283e..6e513d2 100644 --- a/lib/src/services/api/mediafiles/media_background.service.dart +++ b/lib/src/services/api/mediafiles/media_background.service.dart @@ -35,15 +35,15 @@ Future initFileDownloader() async { try { var androidConfig = []; - if (kDebugMode) { - androidConfig = [(Config.bypassTLSCertificateValidation, kDebugMode)]; + if (!kReleaseMode) { + androidConfig = [(Config.bypassTLSCertificateValidation, true)]; } await FileDownloader().configure(androidConfig: androidConfig); } catch (e) { Log.error(e); } - if (kDebugMode) { + if (!kReleaseMode) { FileDownloader().configureNotification( running: const TaskNotification( 'Uploading/Downloading', diff --git a/lib/src/services/notifications/background.notifications.dart b/lib/src/services/notifications/background.notifications.dart index ac5a889..905c3ed 100644 --- a/lib/src/services/notifications/background.notifications.dart +++ b/lib/src/services/notifications/background.notifications.dart @@ -23,9 +23,10 @@ Future customLocalPushNotification(String title, String msg) async { '1', 'System', channelDescription: 'System messages.', - importance: Importance.max, - priority: Priority.max, + importance: Importance.high, + priority: Priority.high, styleInformation: BigTextStyleInformation(msg), + icon: 'ic_launcher_foreground', ); const darwinNotificationDetails = DarwinNotificationDetails(); @@ -34,8 +35,10 @@ Future customLocalPushNotification(String title, String msg) async { iOS: darwinNotificationDetails, ); + final id = Random.secure().nextInt(9999); + await flutterLocalNotificationsPlugin.show( - Random.secure().nextInt(9999), + id, title, msg, notificationDetails, @@ -95,11 +98,11 @@ Future handlePushData(String pushDataB64) async { } } } catch (e) { + Log.error(e); await customLocalPushNotification( 'Du hast eine neue Nachricht.', 'Öffne twonly um mehr zu erfahren.', ); - Log.error(e); } } @@ -161,6 +164,7 @@ Future showLocalPushNotification( priority: Priority.max, ticker: 'You got a new message.', largeIcon: styleInformation, + icon: 'ic_launcher_foreground', ); const darwinNotificationDetails = DarwinNotificationDetails(); @@ -174,7 +178,7 @@ Future showLocalPushNotification( title, body, notificationDetails, - payload: pushNotification.kind.name, + // payload: pushNotification.kind.name, ); } diff --git a/lib/src/services/notifications/pushkeys.notifications.dart b/lib/src/services/notifications/pushkeys.notifications.dart index 64509a8..b02ab0f 100644 --- a/lib/src/services/notifications/pushkeys.notifications.dart +++ b/lib/src/services/notifications/pushkeys.notifications.dart @@ -51,7 +51,7 @@ Future setupNotificationWithUsers({ final pushUser = pushUsers.firstWhereOrNull((x) => x.userId == contact.userId); - if (pushUser != null) { + if (pushUser != null && pushUser.pushKeys.isNotEmpty) { // make it harder to predict the change of the key final timeBefore = DateTime.now().subtract(Duration(days: 5 + random.nextInt(5))); diff --git a/lib/src/utils/log.dart b/lib/src/utils/log.dart index 8917f23..0344dfa 100644 --- a/lib/src/utils/log.dart +++ b/lib/src/utils/log.dart @@ -9,7 +9,7 @@ void initLogger() { Logger.root.level = Level.ALL; Logger.root.onRecord.listen((record) async { await _writeLogToFile(record); - if (kDebugMode) { + if (!kReleaseMode) { print( '${record.level.name} [twonly] ${record.loggerName} > ${record.message}', ); diff --git a/lib/src/utils/misc.dart b/lib/src/utils/misc.dart index c41c306..27b151e 100644 --- a/lib/src/utils/misc.dart +++ b/lib/src/utils/misc.dart @@ -263,7 +263,7 @@ bool isUUIDNewer(String uuid1, String uuid2) { return timestamp1 > timestamp2; } catch (e) { Log.error(e); - return true; + return false; } } diff --git a/lib/src/views/camera/camera_preview_components/zoom_selector.dart b/lib/src/views/camera/camera_preview_components/zoom_selector.dart index 3d4f944..856224e 100644 --- a/lib/src/views/camera/camera_preview_components/zoom_selector.dart +++ b/lib/src/views/camera/camera_preview_components/zoom_selector.dart @@ -3,10 +3,10 @@ import 'dart:async'; import 'dart:io'; import 'dart:math'; - import 'package:camera/camera.dart'; import 'package:flutter/material.dart'; import 'package:twonly/globals.dart'; +import 'package:twonly/src/utils/log.dart'; import 'package:twonly/src/views/camera/camera_preview_controller_view.dart'; class CameraZoomButtons extends StatefulWidget { @@ -50,6 +50,7 @@ class _CameraZoomButtonsState extends State { Future initAsync() async { showWideAngleZoom = (await widget.controller.getMinZoomLevel()) < 1; + Log.info('Found ${gCameras.length} cameras for zoom.'); if (!showWideAngleZoom && Platform.isIOS && gCameras.length == 3) { showWideAngleZoomIOS = true; } diff --git a/lib/src/views/camera/image_editor/layers/filters/location_filter.dart b/lib/src/views/camera/image_editor/layers/filters/location_filter.dart index 5b3ae64..d8ef27f 100644 --- a/lib/src/views/camera/image_editor/layers/filters/location_filter.dart +++ b/lib/src/views/camera/image_editor/layers/filters/location_filter.dart @@ -131,7 +131,7 @@ Future> getStickerIndex() async { final indexFile = File('${directory.path}/stickers.json'); var res = []; - if (indexFile.existsSync() && !kDebugMode) { + if (indexFile.existsSync() && kReleaseMode) { final lastModified = indexFile.lastModifiedSync(); final difference = DateTime.now().difference(lastModified); final content = await indexFile.readAsString(); diff --git a/lib/src/views/chats/chat_messages_components/chat_reaction_row.dart b/lib/src/views/chats/chat_messages_components/chat_reaction_row.dart index c6d4a27..1a46d10 100644 --- a/lib/src/views/chats/chat_messages_components/chat_reaction_row.dart +++ b/lib/src/views/chats/chat_messages_components/chat_reaction_row.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; @@ -45,10 +47,10 @@ class ReactionRow extends StatelessWidget { child: Center( child: Text( reaction.emoji, - style: const TextStyle(fontSize: 18), - strutStyle: const StrutStyle( + style: TextStyle(fontSize: Platform.isIOS ? 18 : 15), + strutStyle: StrutStyle( forceStrutHeight: true, - height: 1.6, + height: Platform.isIOS ? 1.6 : 1.3, ), ), ), @@ -114,7 +116,7 @@ class ReactionRow extends StatelessWidget { entry.$2.toString(), textAlign: TextAlign.center, style: TextStyle( - fontSize: 15, + fontSize: 13, color: isDarkMode(context) ? Colors.white : Colors.black, decoration: TextDecoration.none, diff --git a/lib/src/views/chats/chat_messages_components/entries/chat_media_entry.dart b/lib/src/views/chats/chat_messages_components/entries/chat_media_entry.dart index 96104b4..1f89085 100644 --- a/lib/src/views/chats/chat_messages_components/entries/chat_media_entry.dart +++ b/lib/src/views/chats/chat_messages_components/entries/chat_media_entry.dart @@ -67,9 +67,10 @@ class _ChatMediaEntryState extends State { if (widget.message.openedAt == null || widget.message.mediaStored) { return; } - if (widget.mediaService.tempPath.existsSync()) { - await sendCipherTextToGroup( - widget.message.groupId, + if (widget.mediaService.tempPath.existsSync() && + widget.message.senderId != null) { + await sendCipherText( + widget.message.senderId!, EncryptedContent( mediaUpdate: EncryptedContent_MediaUpdate( type: EncryptedContent_MediaUpdate_Type.REOPENED, diff --git a/lib/src/views/chats/chat_messages_components/entries/chat_text_entry.dart b/lib/src/views/chats/chat_messages_components/entries/chat_text_entry.dart index 89c336e..0d9f365 100644 --- a/lib/src/views/chats/chat_messages_components/entries/chat_text_entry.dart +++ b/lib/src/views/chats/chat_messages_components/entries/chat_text_entry.dart @@ -77,10 +77,10 @@ class ChatTextEntry extends StatelessWidget { children: [ if (info.expanded) Expanded( - child: BetterText(text: text, textColor: info.textColor), + child: BetterText(text: info.text, textColor: info.textColor), ) else ...[ - BetterText(text: text, textColor: info.textColor), + BetterText(text: info.text, textColor: info.textColor), SizedBox( width: info.spacerWidth, ), diff --git a/lib/src/views/chats/chat_messages_components/message_send_state_icon.dart b/lib/src/views/chats/chat_messages_components/message_send_state_icon.dart index e147dbc..9f2aefc 100644 --- a/lib/src/views/chats/chat_messages_components/message_send_state_icon.dart +++ b/lib/src/views/chats/chat_messages_components/message_send_state_icon.dart @@ -242,10 +242,10 @@ class _MessageSendStateIconState extends State { child: Center( child: Text( widget.lastReaction!.emoji, - style: const TextStyle(fontSize: 18), + style: const TextStyle(fontSize: 15), strutStyle: const StrutStyle( forceStrutHeight: true, - height: 1.6, + height: 1.4, ), ), ), diff --git a/lib/src/views/chats/chat_messages_components/test b/lib/src/views/chats/chat_messages_components/test deleted file mode 100644 index db5158b..0000000 --- a/lib/src/views/chats/chat_messages_components/test +++ /dev/null @@ -1,242 +0,0 @@ -import 'dart:io'; - -import 'package:audio_waveforms/audio_waveforms.dart'; -import 'package:audio_waveforms_example/chat_bubble.dart'; -import 'package:file_picker/file_picker.dart'; -import 'package:flutter/material.dart'; -import 'package:path_provider/path_provider.dart'; - -void main() => runApp(const MyApp()); - -class MyApp extends StatelessWidget { - const MyApp({super.key}); - - @override - Widget build(BuildContext context) { - return const MaterialApp( - title: 'Audio Waveforms', - debugShowCheckedModeBanner: false, - home: Home(), - ); - } -} - -class Home extends StatefulWidget { - const Home({super.key}); - - @override - State createState() => _HomeState(); -} - -class _HomeState extends State { - late final RecorderController recorderController; - - String? path; - String? musicFile; - bool isRecording = false; - bool isRecordingCompleted = false; - bool isLoading = true; - late Directory appDirectory; - - @override - void initState() { - super.initState(); - _getDir(); - _initialiseControllers(); - } - - void _getDir() async { - appDirectory = await getApplicationDocumentsDirectory(); - path = "${appDirectory.path}/recording.m4a"; - isLoading = false; - setState(() {}); - } - - void _initialiseControllers() { - recorderController = RecorderController() - ..androidEncoder = AndroidEncoder.aac - ..androidOutputFormat = AndroidOutputFormat.mpeg4 - ..iosEncoder = IosEncoder.kAudioFormatMPEG4AAC - ..sampleRate = 44100; - } - - void _pickFile() async { - FilePickerResult? result = await FilePicker.platform.pickFiles(); - if (result != null) { - musicFile = result.files.single.path; - setState(() {}); - } else { - debugPrint("File not picked"); - } - } - - @override - void dispose() { - recorderController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color(0xFF252331), - appBar: AppBar( - backgroundColor: const Color(0xFF252331), - elevation: 1, - centerTitle: true, - shadowColor: Colors.grey, - title: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset( - 'assets/images/logo.png', - scale: 1.5, - ), - const SizedBox(width: 10), - const Text( - 'Simform', - style: TextStyle(color: Colors.white), - ), - ], - ), - ), - body: isLoading - ? const Center( - child: CircularProgressIndicator(), - ) - : SafeArea( - child: Column( - children: [ - const SizedBox(height: 20), - Expanded( - child: ListView.builder( - itemCount: 4, - itemBuilder: (_, index) { - return WaveBubble( - index: index + 1, - isSender: index.isOdd, - width: MediaQuery.of(context).size.width / 2, - appDirectory: appDirectory, - ); - }, - ), - ), - if (isRecordingCompleted) - WaveBubble( - path: path, - isSender: true, - appDirectory: appDirectory, - ), - if (musicFile != null) - WaveBubble( - path: musicFile, - isSender: true, - appDirectory: appDirectory, - ), - SafeArea( - child: Row( - children: [ - AnimatedSwitcher( - duration: const Duration(milliseconds: 200), - child: isRecording - ? AudioWaveforms( - enableGesture: true, - size: Size( - MediaQuery.of(context).size.width / 2, - 50), - recorderController: recorderController, - waveStyle: const WaveStyle( - waveColor: Colors.white, - extendWaveform: true, - showMiddleLine: false, - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12.0), - color: const Color(0xFF1E1B26), - ), - padding: const EdgeInsets.only(left: 18), - margin: const EdgeInsets.symmetric( - horizontal: 15), - ) - : Container( - width: - MediaQuery.of(context).size.width / 1.7, - height: 50, - decoration: BoxDecoration( - color: const Color(0xFF1E1B26), - borderRadius: BorderRadius.circular(12.0), - ), - padding: const EdgeInsets.only(left: 18), - margin: const EdgeInsets.symmetric( - horizontal: 15), - child: TextField( - readOnly: true, - decoration: InputDecoration( - hintText: "Type Something...", - hintStyle: const TextStyle( - color: Colors.white54), - contentPadding: - const EdgeInsets.only(top: 16), - border: InputBorder.none, - suffixIcon: IconButton( - onPressed: _pickFile, - icon: Icon(Icons.adaptive.share), - color: Colors.white54, - ), - ), - ), - ), - ), - IconButton( - onPressed: _refreshWave, - icon: Icon( - isRecording ? Icons.refresh : Icons.send, - color: Colors.white, - ), - ), - const SizedBox(width: 16), - IconButton( - onPressed: _startOrStopRecording, - icon: Icon(isRecording ? Icons.stop : Icons.mic), - color: Colors.white, - iconSize: 28, - ), - ], - ), - ), - ], - ), - ), - ); - } - - void _startOrStopRecording() async { - try { - if (isRecording) { - recorderController.reset(); - - path = await recorderController.stop(false); - - if (path != null) { - isRecordingCompleted = true; - debugPrint(path); - debugPrint("Recorded file size: ${File(path!).lengthSync()}"); - } - } else { - await recorderController.record(path: path); // Path is optional - } - } catch (e) { - debugPrint(e.toString()); - } finally { - if (recorderController.hasPermission) { - setState(() { - isRecording = !isRecording; - }); - } - } - } - - void _refreshWave() { - if (isRecording) recorderController.refresh(); - } -} \ No newline at end of file diff --git a/lib/src/views/chats/media_viewer.view.dart b/lib/src/views/chats/media_viewer.view.dart index e81347c..9fe19f9 100644 --- a/lib/src/views/chats/media_viewer.view.dart +++ b/lib/src/views/chats/media_viewer.view.dart @@ -82,6 +82,7 @@ class _MediaViewerViewState extends State { _subscription.cancel(); downloadStateListener?.cancel(); videoController?.dispose(); + videoController = null; super.dispose(); } @@ -141,7 +142,9 @@ class _MediaViewerViewState extends State { Future loadCurrentMediaFile({bool showTwonly = false}) async { if (!mounted || !context.mounted) return; - if (allMediaFiles.isEmpty) return nextMediaOrExit(); + if (allMediaFiles.isEmpty || allMediaFiles.first.mediaId == null) { + return nextMediaOrExit(); + } await _noScreenshot.screenshotOff(); setState(() { @@ -175,7 +178,8 @@ class _MediaViewerViewState extends State { downloadTriggered = true; final mediaFile = await twonlyDB.mediaFilesDao .getMediaFileById(allMediaFiles.first.mediaId!); - await startDownloadMedia(mediaFile!, true); + if (mediaFile == null) return; + await startDownloadMedia(mediaFile, true); unawaited(tryDownloadAllMediaFiles(force: true)); } return; @@ -269,6 +273,10 @@ class _MediaViewerViewState extends State { } }); progressTimer = Timer.periodic(const Duration(milliseconds: 10), (timer) { + if (currentMedia!.mediaFile.displayLimitInMilliseconds == null || + canBeSeenUntil == null) { + return; + } final difference = canBeSeenUntil!.difference(DateTime.now()); // Calculate the progress as a value between 0.0 and 1.0 progress = difference.inMilliseconds / @@ -312,10 +320,12 @@ class _MediaViewerViewState extends State { void displayShortReactions() { final renderBox = - mediaWidgetKey.currentContext!.findRenderObject()! as RenderBox; + mediaWidgetKey.currentContext!.findRenderObject() as RenderBox?; setState(() { showShortReactions = true; - mediaViewerDistanceFromBottom = renderBox.size.height; + if (renderBox != null) { + mediaViewerDistanceFromBottom = renderBox.size.height; + } }); } diff --git a/lib/src/views/components/max_flame_list_title.dart b/lib/src/views/components/max_flame_list_title.dart index ee193e7..efe80ba 100644 --- a/lib/src/views/components/max_flame_list_title.dart +++ b/lib/src/views/components/max_flame_list_title.dart @@ -85,7 +85,7 @@ class _MaxFlameListTitleState extends State { if (_directChat == null || _directChat!.maxFlameCounter == 0 || _flameCounter >= (_directChat!.maxFlameCounter + 1) || - _directChat!.lastFlameCounterChange! + _directChat!.maxFlameCounterFrom! .isBefore(DateTime.now().subtract(const Duration(days: 4)))) { return Container(); } diff --git a/lib/src/views/settings/account.view.dart b/lib/src/views/settings/account.view.dart index 37af702..d56e734 100644 --- a/lib/src/views/settings/account.view.dart +++ b/lib/src/views/settings/account.view.dart @@ -37,7 +37,7 @@ class _AccountViewState extends State { .where( (x) => x.transactionType != Response_TransactionTypes.ThanksForTesting || - kDebugMode, + !kReleaseMode, ) .map((a) => a.depositCents.toInt()) .sum; @@ -101,7 +101,7 @@ class _AccountViewState extends State { ), ) : Text(context.lang.settingsAccountDeleteAccountNoBallance), - onLongPress: kDebugMode + onLongPress: !kReleaseMode ? () async { await deleteLocalUserData(); await Restart.restartApp( diff --git a/lib/src/views/settings/backup/twonly_safe_backup.view.dart b/lib/src/views/settings/backup/twonly_safe_backup.view.dart index 64f7ba1..c5255d1 100644 --- a/lib/src/views/settings/backup/twonly_safe_backup.view.dart +++ b/lib/src/views/settings/backup/twonly_safe_backup.view.dart @@ -204,7 +204,7 @@ class _TwonlyIdentityBackupViewState extends State { onPressed: (!isLoading && (passwordCtrl.text == repeatedPasswordCtrl.text && passwordCtrl.text.length >= 8 || - kDebugMode)) + !kReleaseMode)) ? onPressedEnableTwonlySafe : null, icon: isLoading diff --git a/lib/src/views/settings/developer/automated_testing.view.dart b/lib/src/views/settings/developer/automated_testing.view.dart index 89f3774..02a7b9d 100644 --- a/lib/src/views/settings/developer/automated_testing.view.dart +++ b/lib/src/views/settings/developer/automated_testing.view.dart @@ -32,7 +32,7 @@ class _AutomatedTestingViewState extends State { ), body: ListView( children: [ - if (kDebugMode) + if (!kReleaseMode) ListTile( title: const Text('Sending a lot of messages.'), subtitle: Text(lotsOfMessagesStatus), diff --git a/lib/src/views/settings/developer/developer.view.dart b/lib/src/views/settings/developer/developer.view.dart index efa8812..42e4aa3 100644 --- a/lib/src/views/settings/developer/developer.view.dart +++ b/lib/src/views/settings/developer/developer.view.dart @@ -66,7 +66,7 @@ class _DeveloperSettingsViewState extends State { ); }, ), - // if (kDebugMode) + // if (!kReleaseMode) // ListTile( // title: const Text('FlameSync Test'), // onTap: () async { @@ -74,7 +74,7 @@ class _DeveloperSettingsViewState extends State { // await syncFlameCounters(); // }, // ), - if (kDebugMode) + if (!kReleaseMode) ListTile( title: const Text('Automated Testing'), onTap: () async { diff --git a/lib/src/views/settings/profile/profile.view.dart b/lib/src/views/settings/profile/profile.view.dart index 02aa643..5d24f45 100644 --- a/lib/src/views/settings/profile/profile.view.dart +++ b/lib/src/views/settings/profile/profile.view.dart @@ -25,11 +25,26 @@ class _ProfileViewState extends State { final AvatarMakerController _avatarMakerController = PersistentAvatarMakerController(customizedPropertyCategories: []); + int twonlyScore = 0; + late StreamSubscription twonlyScoreSub; + @override void initState() { + twonlyScoreSub = + twonlyDB.groupsDao.watchSumTotalMediaCounter().listen((update) { + setState(() { + twonlyScore = update; + }); + }); super.initState(); } + @override + void dispose() { + twonlyScoreSub.cancel(); + super.dispose(); + } + Future updateUserDisplayName(String displayName) async { await updateUserdata((user) { user @@ -156,6 +171,17 @@ class _ProfileViewState extends State { } }, ), + BetterListTile( + text: context.lang.yourTwonlyScore, + icon: FontAwesomeIcons.trophy, + trailing: Text( + twonlyScore.toString(), + style: TextStyle( + color: context.color.primary, + fontSize: 18, + ), + ), + ), ], ), ); diff --git a/lib/src/views/settings/subscription/checkout.view.dart b/lib/src/views/settings/subscription/checkout.view.dart index 83804a5..3d6797c 100644 --- a/lib/src/views/settings/subscription/checkout.view.dart +++ b/lib/src/views/settings/subscription/checkout.view.dart @@ -102,6 +102,7 @@ class _CheckoutViewState extends State { Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Card( + color: context.color.surfaceContainer, child: Padding( padding: const EdgeInsets.all(16), child: Row( diff --git a/lib/src/views/settings/subscription/select_payment.view.dart b/lib/src/views/settings/subscription/select_payment.view.dart index 4ae1ae2..f9d3b8f 100644 --- a/lib/src/views/settings/subscription/select_payment.view.dart +++ b/lib/src/views/settings/subscription/select_payment.view.dart @@ -111,6 +111,7 @@ class _SelectPaymentViewState extends State { Padding( padding: const EdgeInsets.all(16), child: Card( + color: context.color.surfaceContainer, child: Padding( padding: const EdgeInsets.all(16), child: Row( @@ -193,6 +194,7 @@ class _SelectPaymentViewState extends State { Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Card( + color: context.color.surfaceContainer, child: Padding( padding: const EdgeInsets.all(16), child: Row( @@ -215,6 +217,7 @@ class _SelectPaymentViewState extends State { Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Card( + color: context.color.surfaceContainer, child: Padding( padding: const EdgeInsets.all(16), child: Row( diff --git a/lib/src/views/settings/subscription/subscription.view.dart b/lib/src/views/settings/subscription/subscription.view.dart index 6d1ccbf..d87434a 100644 --- a/lib/src/views/settings/subscription/subscription.view.dart +++ b/lib/src/views/settings/subscription/subscription.view.dart @@ -444,6 +444,7 @@ class PlanCard extends StatelessWidget { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), + color: context.color.surfaceContainer, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), child: Column(