From bac8e1d11f5dccbce70c2632230bec567b4159ef Mon Sep 17 00:00:00 2001 From: Ed Geraghty Date: Wed, 5 Jan 2022 19:54:31 +0000 Subject: [PATCH 01/10] chore: i18n / internationalisation across the app (first round) (#490) * chore: add alerts to Strings * chore: i18n support for user details * chore: i18n support for image options modal * chore: i18n support for lock overlay screen * fix: typo * chore: i18n support in context switcher * chore: i18n support in messages * chore: i18n support for local images * chore: i18n support on the colo(u)r picker * chore: i18n support on password dialog * fix: add missing imports * fix: replace optional parameters with positional ones * chore: i18n support in Chat Input widget * chore: i18n support for the home screen * chore: i18n support on Advanced Settings commit 1 of 2 * fix: can't use i18n Strings in Dialog const Require them to be passed in, instead. This was happening anyway. * chore: i18n support in Encryption dialog * chore: add missing i18n on chat input widget * chore: i18n support for chat invite dialog * chore: add missing i18n for all users detail screen * chore: i18n support in message detail screen * chore: i18n support in chat details screen * chore: add missing i18n on media preview screen * chore: cleanup * chore: typos --- assets/translations/en.json | 82 +++++++++++++++- lib/global/strings.dart | 94 ++++++++++++++++++- lib/store/auth/homeserver/actions.dart | 1 - .../chat/chat-detail-all-users-screen.dart | 2 +- .../home/chat/chat-detail-message-screen.dart | 13 +-- lib/views/home/chat/chat-detail-screen.dart | 32 +++---- lib/views/home/chat/media-preview-screen.dart | 6 +- lib/views/home/chat/widgets/chat-input.dart | 12 +-- .../home/chat/widgets/dialog-encryption.dart | 2 +- .../home/chat/widgets/dialog-invite.dart | 8 +- lib/views/home/home-screen.dart | 12 +-- .../settings/advanced-settings-screen.dart | 20 ++-- lib/views/syphon.dart | 9 +- .../widgets/dialogs/dialog-color-picker.dart | 2 +- .../dialogs/dialog-confirm-password.dart | 6 +- .../widgets/lists/list-local-images.dart | 3 +- lib/views/widgets/messages/message.dart | 4 +- .../modals/modal-context-switcher.dart | 7 +- .../widgets/modals/modal-image-options.dart | 9 +- .../modal-lock-overlay/lock-overlay.dart | 5 +- .../widgets/modals/modal-user-details.dart | 14 +-- 21 files changed, 252 insertions(+), 91 deletions(-) diff --git a/assets/translations/en.json b/assets/translations/en.json index 54f276f13..ac5a3141c 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -23,6 +23,12 @@ "title-proxy-use-proxy": "Use a Proxy", "title-proxy-host": "Modify Proxy Host", "title-proxy-port": "Modify Proxy Port", + "title-lock-overlay": "Please enter passcode.", + "title-search-unencrypted": "Search Unencrypted", + "title-confirm-lock-overlay": "Please confirm passcode.", + "title-message-details": "Message Details", + "title-send-media-message": "Send Media Message", + "title-send-media-message-unencrypted": "Send Media Message (Unencrypted)", "title-dialog-delete-keys": "Confirm Deleting Keys", "title-dialog-confirm-linkout": "Confirm Opening Link", "title-dialog-encryption": "Encrypt Chat?", @@ -31,11 +37,16 @@ "title-dialog-terms-alpha": "Confirm Open Alpha Terms Of Service", "title-dialog-email-requirement": "Email requirement", "title-dialog-email-requirement-verified": "Email verification", + "title-dialog-accept-invite": "Accept Invite?", + "title-dialog-chat-color": "Select Chat Color", + "title-dialog-draft-preview": "Draft Preview", "title-user-verification": "User verification", "title-confirm-password": "Confirm Password", "title-confirm-email": "Confirm Email", "title-device-rename": "Rename a device", "subtitle-proxy-use-proxy": "This will force all traffic leaving Syphon to do so via a proxy", + "subtitle-settings-sync-interval": "Amount of time in seconds the app wait\nbetween syncing", + "subtitle-settings-sync-toggle": "Toggle syncing with the matrix server", "label-searching": "Searching…", "label-search-homeservers": "Search for homeservers…", "label-search-user": "Search for a user…", @@ -63,6 +74,11 @@ "label-message-matrix-unencrypted": "Matrix message (unencrypted)", "label-deleted-message": "This message was deleted", "label-terms-of-service": "Terms of Service", + "label-search-unencrypted": "Search Unencrypted", + "label-about": "About", + "label-chat-settings": "Chat Settings", + "label-color": "Color", + "label-default-room-notification": "Default (Argon)", "button-login": "log in", "button-login-sso": "single sign on", "button-save": "save", @@ -87,6 +103,7 @@ "button-confirm-verification": "confirm verification", "button-deactivate": "deactivate", "button-reset-password": "reset password", + "button-dismiss": "Dismiss", "button-text-agreement": "I Agree", "button-text-see-users": "See All Users", "button-text-login-question": "Already have a username?", @@ -100,6 +117,21 @@ "button-text-invite": "Invite Friends", "button-text-settings": "Settings", "button-text-support": "Help", + "button-text-go-back": "go back", + "button-text-reject": "reject", + "button-text-accept": "accept", + "button-text-lets-encrypt": "let's encrypt", + "button-save-message-edit": "Save Message Edit", + "button-gallery": "Gallery", + "button-file": "File", + "button-contact": "Contact", + "button-location": "Location", + "list-item-chat-detail-toggle-direct-chat": "Toggle Direct Chat", + "list-item-chat-detail-notification-setting": "Notification Settings", + "list-item-chat-detail-notifications": "Notifications", + "list-item-chat-detail-notification-sound": "Notification Sound", + "list-item-chat-detail-privacy-status": "Privacy and Status", + "list-item-chat-detail-view-key": "View Encryption Key", "list-item-settings-notification": "Notifications", "list-item-settings-privacy": "Privacy", "list-item-settings-sms": "SMS and MMS", @@ -107,12 +139,42 @@ "list-item-settings-proxy": "Proxy Settings", "list-item-settings-proxy-host": "Host", "list-item-settings-proxy-port": "Port", + "list-item-settings-sync-interval": "Sync Interval", + "list-item-settings-sync-toggle": "Toggle Syncing", + "list-item-user-details-invite-to-room": "Invite to Room", + "list-item-user-details-confirm-start-chat": "Chat with {}", + "list-item-user-details-send-message": "Send A Message", + "list-item-user-details-view-profile": "View Profile", + "list-item-user-details-unblock-user": "Unblock User", + "list-item-user-details-block-user": "Block User", + "list-item-image-options-photo-select-method": "Photo Select Method", + "list-item-image-options-take-photo": "Take Photo", + "list-item-image-options-pick-from-gallery": "Pick from Gallery", + "list-item-image-options-remove-photo": "Remove Photo", + "list-item-context-switcher-user-display-name": "{} (Encrypted User)", + "list-item-context-switcher-accounts": "Accounts", + "list-item-context-switcher-add-account": "Add Account", + "list-item-advanced-settings-licenses": "Open Source Licenses", + "list-item-advanced-settings-start-background": "Start Background Service", + "list-item-advanced-settings-stop-background": "Stop All Services", + "list-item-advanced-settings-test-notifications": "Test Notifications", + "list-item-advanced-settings-test-sync-loop": "Test Background Sync Loop", + "list-item-advanced-settings-force-function": "Force Function", + "list-item-sent": "Sent", + "list-item-received": "Received", + "list-item-via": "Via", + "list-item-from": "From", + "list-item-read-by": "Read By", "alert-restart-app-effect": "You'll need to close and restart the app for this to take effect", "alert-invite-user-unknown": "This user doesn't appear to exist within matrix, but you can attempt to invite them anyway.\n\nMake sure you have the correct name before trying.", "alert-feature-in-progress": "🛠 This feature is coming soon", "alert-message-failed": "Message Failed To Send", "alert-homeserver-invalid": "This server failed the 'well-known' check. Make sure the server is configured correctly.", "alert-hidden-read-receipts": "Hidden Read Receipts must be supported by your homeserver, or this will have the same effect as switching Read Receipts 'On'", + "alert-offline": "Looks like you may be offline. Check your connection and try again.", + "alert-unknown": "Unknown Error Occurred", + "alert-could-not-launch-url": "Could not launch {}", + "alert-no-images-found": "No Images Found.", "prompt-homeserver-select": "Select your username and homeserver", "prompt-confirm-deactivate": "Enter your password below to confirm deactivation", "placeholder-topic": "No Topic Description", @@ -138,6 +200,8 @@ "content-sync-interval": "Syncing works by submitting a long poll request to a matrix server. The sync interval is not how frequently it will sync, but how frequently it will attempt a new long poll request.", "content-proxy-host": "The host for your proxy", "content-proxy-port": "The port your proxy is listening on", + "content-dialog-confirm-password": "Please confirm your password (Default)", + "message-edited-append": " (Edited)", "confirm-linkout": "Are you sure you want to open the following link?\n\n{}", "confirm-delete-keys": "Are you sure you want to delete your encryption keys for this device? This is very destructive and will probably render all your encrypted messages undecryptable.", "confirm-invite": "Are you sure you want to invite the following user to the following chat?", @@ -168,14 +232,22 @@ "warning-deactivate-account-final": "There is no way to recover this account after it's deleted. You will immediately be logged out of your account and it will become unavailable.\n\nThis is your final warning regarding deactivation. If you are sure, press deactivate below.", "label-send-unencrypted": "Send unencrypted message", "label-send-encrypted": "Send encrypted message", - "semnatics-image-intro": "Relaxed, lounging User", - "semnatics-image-private-message": "A person holding up a private message bubble", - "semnatics-image-intro-section-third": "People lounging around and messaging each other", - "semnatics-image-intro-section-four": "Two different people feeling confident and lookin' good", + "label-default": "Default", + "semantics-image-intro": "Relaxed, lounging User", + "semantics-image-private-message": "A person holding up a private message bubble", + "semantics-image-intro-section-third": "People lounging around and messaging each other", + "semantics-image-intro-section-four": "Two different people feeling confident and lookin' good", "semantics-image-empty-chat-list": "Several tiny, cute monsters peering out behind foliage.", "semantics-image-terms-of-service": "Hand holding a phone with a terms of service checkbox checked", "semantics-image-signup-username": "Person resting elbow on I.D. card", "semantics-image-password-reset": "Person resting arm ontop a letter with a checkbox inside", + "semantics-create-public-room": "Create A Public Room", "label-proxy-host": "Hostname", - "label-proxy-port": "Port" + "label-proxy-port": "Port", + "label-password": "password", + "tooltip-search-users": "Search users", + "tooltip-profile-settings": "Profile and Settings", + "tooltip-search-chats": "Search Chats", + "tooltip-search-unencrypted": "Search Unencrypted", + "tooltip-cancel-reply": "Cancel Reply" } diff --git a/lib/global/strings.dart b/lib/global/strings.dart index 6474a5ba4..f90674e12 100644 --- a/lib/global/strings.dart +++ b/lib/global/strings.dart @@ -38,6 +38,12 @@ class Strings { static final titleUseProxyServer = tr('title-proxy-use-proxy'); static final titleProxyHost = tr('title-proxy-host'); static final titleProxyPort = tr('title-proxy-port'); + static final titleLockOverlay = tr('title-lock-overlay'); + static final titleConfirmLockOverlay = tr('title-confirm-lock-overlay'); + static final titleSearchUnencrypted = tr('title-search-unencrypted'); + static final titleMessageDetails = tr('title-message-details'); + static final titleSendMediaMessage = tr('title-send-media-message'); + static final titleSendMediaMessageUnencrypted = tr('title-send-media-message-unencrypted'); // Titles (Dialogs) static final titleDialogConfirmLinkout = tr('title-dialog-confirm-linkout'); @@ -50,9 +56,15 @@ class Strings { static final titleRenameDevice = tr('title-device-rename'); static final titleConfirmDeleteKeys = tr('title-dialog-delete-keys'); static final titleConfirmEmail = tr('title-confirm-email'); + static final titleDialogColorPicker = tr('title-dialog-color-picker'); + static final titleDialogAcceptInvite = tr('title-dialog-accept-invite'); + static final titleDialogChatColor = tr('title-dialog-chat-color'); + static final titleDialogDraftPreview = tr('title-dialog-draft-preview'); // Subtitles static final subtitleUseProxyServer = tr('subtitle-proxy-use-proxy'); + static final subtitleSettingsSyncInterval = tr('subtitle-settings-sync-interval'); + static final subtitleSettingsSyncToggle = tr('subtitle-settings-sync-toggle'); // Headers static final headerIntro = tr('header-intro'); @@ -86,6 +98,10 @@ class Strings { static final labelOn = tr('label-on'); // 'On'; static final labelOff = tr('label-off'); // 'Off'; static final labelTermsOfService = tr('label-terms-of-service'); + static final labelSearchUnencrypted = tr('label-search-unencrypted'); + static final labelAbout = tr('label-about'); + static final labelChatSettings = tr('label-chat-settings'); + static final labelColor = tr('label-color'); // List Items static final listItemSettingsSms = tr('list-item-settings-sms'); @@ -95,6 +111,45 @@ class Strings { static final listItemSettingsProxy = tr('list-item-settings-proxy'); static final listItemSettingsProxyHost = tr('list-item-settings-proxy-host'); static final listItemSettingsProxyPort = tr('list-item-settings-proxy-port'); + static final listItemSettingsSyncInterval = tr('list-item-settings-sync-interval'); + static final listItemSettingsSyncToggle = tr('list-item-settings-sync-toggle'); + + static String listItemUserDetailsStartChat(String? name) => tr('list-item-user-details-start-chat', args: ['$name']); + static final listItemUserDetailsRoomInvite = tr('list-item-user-details-room-invite'); + static final listItemUserDetailsSendMessage = tr('list-item-user-details-send-message'); + static final listItemUserDetailsViewProfile = tr('list-item-user-details-view-profile'); + static final listItemUserDetailsUnblockUser = tr('list-item-user-details-unblock-user'); + static final listItemUserDetailsBlockUser = tr('list-item-user-details-block-user'); + + static final listItemImageOptionsPhotoSelectMethod = tr('list-item-image-options-photo-select-method'); + static final listItemImageOptionsTakePhoto = tr('list-item-image-options-take-photo'); + static final listItemImageOptionsPickFromGallery = tr('list-item-image-options-pick-from-gallery'); + static final listItemImageOptionsRemovePhoto = tr('list-item-image-options-remove-photo'); + + static String listItemContextSwitcherUserDisplayName(String? username) => tr('list-item-context-switcher-user-display-name', args: ['$username']); + static final listItemContextSwitcherAccounts = tr('list-item-context-switcher-accounts'); + static final listItemContextSwitcherAddAccount = tr('list-item-context-switcher-add-account'); + + static final listItemAdvancedSettingsLicenses = tr('list-item-advanced-settings-licenses'); + static final listItemAdvancedSettingsStartBackground = tr('list-item-advanced-settings-start-background'); + static final listItemAdvancedSettingsStopBackground = tr('list-item-advanced-settings-stop-background'); + static final listItemAdvancedSettingsTestNotifications = tr('list-item-advanced-settings-test-notifications'); + static final listItemAdvancedSettingsTestSyncLoop = tr('list-item-advanced-settings-test-sync-loop'); + static final listItemAdvancedSettingsForceFunction = tr('list-item-advanced-settings-force-function'); + + static final listItemSent = tr('list-item-sent'); + static final listItemReceived = tr('list-item-received'); + static final listItemVia = tr('list-item-via'); + static final listItemFrom = tr('list-item-from'); + static final listItemReadBy = tr('list-item-read-by'); + + static final listItemChatDetailToggleDirectChat = tr('list-item-chat-detail-toggle-direct-chat'); + static final listItemChatDetailNotificationSetting = tr('list-item-chat-detail-notification-setting'); + static final listItemChatDetailNotifications = tr('list-item-chat-detail-notifications'); + static final listItemChatDetailVibrate = tr('list-item-chat-detail-vibrate'); + static final listItemChatDetailNotificationSound = tr('list-item-chat-detail-notification-sound'); + static final listItemChatDetailPrivacyStatus = tr('list-item-chat-detail-privacy-status'); + static final listItemChatDetailViewKey = tr('list-item-chat-detail-view-key'); // Buttons static final buttonLogin = tr('button-login'); @@ -120,6 +175,8 @@ class Strings { static final buttonSelectAll = tr('button-select-all'); static final buttonRoomDetails = tr('button-chat-details'); static final buttonResetPassword = tr('button-reset-password'); // 'reset password'; + static final buttonDismiss = tr('button-dismiss'); + static final buttonSaveMessageEdit = tr('button-save-message-edit'); // Buttons (Text) static final buttonTextLogin = tr('button-text-login'); // 'Login'; @@ -131,6 +188,10 @@ class Strings { static final buttonTextLoadCaptcha = tr('button-text-load-captcha'); static final buttonTextConfirmed = tr('button-text-confirmed'); static final buttonTextDeleteKeys = tr('button-delete-keys'); // 'delete keys'; + static final buttonTextLetsEncrypt = tr('button-text-lets-encrypt'); + static final buttonTextGoBack = tr('button-text-go-back'); + static final buttonTextReject = tr('button-text-reject'); + static final buttonTextAccept = tr('button-text-accept'); // Buttons (Options) static final buttonTextCreateGroup = tr('button-text-create-group'); @@ -139,10 +200,17 @@ class Strings { static final buttonTextSettings = tr('button-text-settings'); static final buttonTextSupport = tr('button-text-support'); + // Buttons (Media Cards) + static final buttonGallery = tr('button-gallery'); + static final buttonFile = tr('button-file'); + static final buttonContact = tr('button-contact'); + static final buttonLocation = tr('button-location'); + // Placeholders static final placeholderTopic = tr('placeholder-topic'); static final placeholderMatrixEncrypted = tr('label-message-matrix'); static final placeholderMatrixUnencrypted = tr('label-message-matrix-unencrypted'); + static final placeholderDefaultRoomNotification = tr('label-default-room-notification'); // Warnings static final warningDeactivateAccount = tr('warning-deactivate-account'); @@ -155,6 +223,10 @@ class Strings { static final alertCheckHomeserver = tr('alert-homeserver-invalid'); // 'Message Failed To Send'; static final alertFeatureInProgress = tr('alert-feature-in-progress'); static final alertHiddenReadReceipts = tr('alert-hidden-read-receipts'); + static final alertOffline = tr('alert-offline'); + static final alertUnknown = tr('alert-unknown'); + static String alertCouldNotLaunchURL(String? url) => tr('alert-could-not-launch-url', args: ['$url']); + static final alertNoImagesFound = tr('alert-no-images-found'); // Alert (Non-Flutter / Background Thread w/o i18n) static const alertBackgroundService = 'Background connection enabled'; @@ -182,6 +254,8 @@ class Strings { static final contentProxyHost = tr('content-proxy-host'); static final contentProxyPort = tr('content-proxy-port'); + static final messageEditedAppend = tr('message-edited-append'); + // Confirmations (use confirm*) static final confirmInvite = tr('confirm-invite'); @@ -231,18 +305,28 @@ class Strings { return s; } - static String confirmBlockUser({String? name}) => tr('confirm-block-user', args: ['$name']); + static String confirmBlockUser(String? name) => tr('confirm-block-user', args: ['$name']); // Accessibility - static final semanticsImageIntro = tr('semnatics-image-intro'); - static final semanticsPrivateMessage = tr('semnatics-image-private-message'); - static final semanticsIntroFinal = tr('semnatics-image-intro-section-four'); - static final semanticsIntroThird = tr('semnatics-image-intro-section-third'); + static final semanticsImageIntro = tr('semantics-image-intro'); + static final semanticsPrivateMessage = tr('semantics-image-private-message'); + static final semanticsIntroFinal = tr('semantics-image-intro-section-four'); + static final semanticsIntroThird = tr('semantics-image-intro-section-third'); static final semanticsHomeDefault = tr('semantics-image-empty-chat-list'); static final semanticsImageSignupUsername = tr('semantics-image-signup-username'); static final semanticsImagePasswordReset = tr('semantics-image-password-reset'); + static final semanticsCreatePublicRoom = tr('semantics-create-public-room'); // Labels static final labelProxyHost = tr('label-proxy-host'); static final labelProxyPort = tr('label-proxy-port'); + static final labelPassword = tr('label-password'); + static final labelDefault = tr('label-default'); + + // Tooltips + static final tooltipProfileAndSettings = tr('tooltip-profile-settings'); + static final tooltipSearchChats = tr('tooltip-search-chats'); + static final tooltipSearchUnencrypted = tr('tooltip-search-unencrypted'); + static final tooltipCancelReply = tr('tooltip-cancel-reply'); + static final tooltipSearchUsers = tr('tooltip-search-users'); } diff --git a/lib/store/auth/homeserver/actions.dart b/lib/store/auth/homeserver/actions.dart index 2ddace7cf..bd10ce124 100644 --- a/lib/store/auth/homeserver/actions.dart +++ b/lib/store/auth/homeserver/actions.dart @@ -8,7 +8,6 @@ import 'package:syphon/global/assets.dart'; import 'package:syphon/global/https.dart'; import 'package:syphon/global/libs/matrix/index.dart'; import 'package:syphon/global/print.dart'; -import 'package:syphon/global/strings.dart'; import 'package:syphon/store/alerts/actions.dart'; import 'package:syphon/store/auth/actions.dart'; import 'package:syphon/store/auth/homeserver/model.dart'; diff --git a/lib/views/home/chat/chat-detail-all-users-screen.dart b/lib/views/home/chat/chat-detail-all-users-screen.dart index c0d7ffbaa..2f38e4e3d 100644 --- a/lib/views/home/chat/chat-detail-all-users-screen.dart +++ b/lib/views/home/chat/chat-detail-all-users-screen.dart @@ -129,7 +129,7 @@ class ChatUsersDetailState extends State appBar: AppBarSearch( title: Strings.titleChatUsers, label: Strings.labelSearchUser, - tooltip: 'Search users', + tooltip: Strings.tooltipSearchUsers, focusNode: searchInputFocusNode, onChange: (text) { props.onSearch(text); diff --git a/lib/views/home/chat/chat-detail-message-screen.dart b/lib/views/home/chat/chat-detail-message-screen.dart index 7903955a7..46d619138 100644 --- a/lib/views/home/chat/chat-detail-message-screen.dart +++ b/lib/views/home/chat/chat-detail-message-screen.dart @@ -5,6 +5,7 @@ import 'package:flutter_redux/flutter_redux.dart'; import 'package:intl/intl.dart'; import 'package:redux/redux.dart'; import 'package:syphon/global/dimensions.dart'; +import 'package:syphon/global/strings.dart'; import 'package:syphon/store/events/messages/model.dart'; import 'package:syphon/store/events/receipts/model.dart'; import 'package:syphon/store/index.dart'; @@ -66,7 +67,7 @@ class MessageDetailsScreen extends StatelessWidget { onPressed: () => Navigator.pop(context, false), ), title: Text( - 'Message Details', + Strings.titleMessageDetails, style: TextStyle( color: Colors.white, fontWeight: FontWeight.w100, @@ -103,7 +104,7 @@ class MessageDetailsScreen extends StatelessWidget { dense: true, contentPadding: Dimensions.listPadding, title: Text( - 'Sent', + Strings.listItemSent, style: TextStyle( fontSize: 14.0, fontWeight: FontWeight.w600, @@ -121,7 +122,7 @@ class MessageDetailsScreen extends StatelessWidget { dense: true, contentPadding: Dimensions.listPadding, title: Text( - 'Received', + Strings.listItemReceived, style: TextStyle( fontSize: 14.0, fontWeight: FontWeight.w600, @@ -139,7 +140,7 @@ class MessageDetailsScreen extends StatelessWidget { dense: true, contentPadding: Dimensions.listPadding, title: Text( - 'Via', + Strings.listItemVia, style: TextStyle( fontSize: 14.0, fontWeight: FontWeight.w600, @@ -157,7 +158,7 @@ class MessageDetailsScreen extends StatelessWidget { dense: true, contentPadding: Dimensions.listPadding, title: Text( - 'From', + Strings.listItemFrom, style: TextStyle( fontSize: 14.0, fontWeight: FontWeight.w600, @@ -175,7 +176,7 @@ class MessageDetailsScreen extends StatelessWidget { ListTile( contentPadding: Dimensions.listPadding, title: Text( - 'Read By', + Strings.listItemReadBy, style: TextStyle( fontSize: 14.0, fontWeight: FontWeight.w600, diff --git a/lib/views/home/chat/chat-detail-screen.dart b/lib/views/home/chat/chat-detail-screen.dart index 888053af8..e7e8f86e9 100644 --- a/lib/views/home/chat/chat-detail-screen.dart +++ b/lib/views/home/chat/chat-detail-screen.dart @@ -117,7 +117,7 @@ class ChatDetailsState extends State with Lifecycle DialogConfirm( title: Strings.buttonBlockUser, - content: Strings.confirmBlockUser(name: user?.displayName), + content: Strings.confirmBlockUser(user?.displayName), onConfirm: () async { await props.onBlockUser(user); Navigator.popUntil(context, (route) => route.isFirst); @@ -135,7 +135,7 @@ class ChatDetailsState extends State with Lifecycle DialogColorPicker( - title: 'Select Chat Color', + title: Strings.titleDialogChatColor, currentColor: originalColor, onSelectColor: onSelectColor, ), @@ -321,7 +321,7 @@ class ChatDetailsState extends State with Lifecycle with Lifecycle with Lifecycle with Lifecycle with Lifecycle with Lifecycle props.onToggleRoomNotifications(), contentPadding: contentPadding, title: Text( - 'Notifications', + Strings.listItemChatDetailNotifications, ), trailing: Switch( value: notificationsEnabled, @@ -443,12 +443,12 @@ class ChatDetailsState extends State with Lifecycle with Lifecycle with Lifecycle with Lifecycle with Lifecycle with Lifecycle onLeaveChat(props), contentPadding: contentPadding, title: Text( - 'Leave Chat', + Strings.buttonLeaveChat, style: Theme.of(context).textTheme.subtitle1!.copyWith( color: Colors.redAccent, ), diff --git a/lib/views/home/chat/media-preview-screen.dart b/lib/views/home/chat/media-preview-screen.dart index aa6fae361..672408a6c 100644 --- a/lib/views/home/chat/media-preview-screen.dart +++ b/lib/views/home/chat/media-preview-screen.dart @@ -81,7 +81,7 @@ class MediaPreviewState extends State with Lifecycle with Lifecycle { Icons.close, size: Dimensions.iconSize, ), - tooltip: 'Cancel Reply', + tooltip: Strings.tooltipCancelReply, ), ), ], @@ -450,7 +450,7 @@ class ChatInputState extends State { crossAxisAlignment: CrossAxisAlignment.center, children: [ ButtonText( - text: 'Save Message Edit', + text: Strings.buttonSaveMessageEdit, size: 18.0, disabled: widget.sending || !isSendable, onPressed: () => onSubmit(), @@ -559,7 +559,7 @@ class ChatInputState extends State { Padding( padding: EdgeInsets.only(right: 2), child: MediaCard( - text: 'Gallery', + text: Strings.buttonGallery, icon: Icons.photo, onPress: () => onAddPhoto(), ), @@ -567,7 +567,7 @@ class ChatInputState extends State { Padding( padding: EdgeInsets.symmetric(horizontal: 2), child: MediaCard( - text: 'File', + text: Strings.buttonFile, icon: Icons.note_add, onPress: () => onAddInProgress(), ), @@ -575,7 +575,7 @@ class ChatInputState extends State { Padding( padding: EdgeInsets.symmetric(horizontal: 2), child: MediaCard( - text: 'Contact', + text: Strings.buttonContact, icon: Icons.person, onPress: () => onAddInProgress(), ), @@ -583,7 +583,7 @@ class ChatInputState extends State { Padding( padding: EdgeInsets.symmetric(horizontal: 2), child: MediaCard( - text: 'Location', + text: Strings.buttonLocation, icon: Icons.near_me_rounded, onPress: () => onAddInProgress(), ), diff --git a/lib/views/home/chat/widgets/dialog-encryption.dart b/lib/views/home/chat/widgets/dialog-encryption.dart index f33c4c31e..b5519a03b 100644 --- a/lib/views/home/chat/widgets/dialog-encryption.dart +++ b/lib/views/home/chat/widgets/dialog-encryption.dart @@ -55,7 +55,7 @@ class DialogEncryption extends StatelessWidget { Navigator.pop(context); }, child: Text( - 'let\'s encrypt', + Strings.buttonTextLetsEncrypt, style: Theme.of(context).textTheme.subtitle1, ), ), diff --git a/lib/views/home/chat/widgets/dialog-invite.dart b/lib/views/home/chat/widgets/dialog-invite.dart index af61ece62..e7f33f4ba 100644 --- a/lib/views/home/chat/widgets/dialog-invite.dart +++ b/lib/views/home/chat/widgets/dialog-invite.dart @@ -20,7 +20,7 @@ class DialogInvite extends StatelessWidget { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), - title: const Text('Accept Invite?'), + title: Text(Strings.titleDialogAcceptInvite), contentPadding: Dimensions.dialogPadding, children: [ Container( @@ -44,7 +44,7 @@ class DialogInvite extends StatelessWidget { } }, child: Text( - 'go back', + Strings.buttonTextGoBack, style: Theme.of(context).textTheme.subtitle1, ), ), @@ -63,7 +63,7 @@ class DialogInvite extends StatelessWidget { } }, child: Text( - 'reject', + Strings.buttonTextReject, style: Theme.of(context).textTheme.subtitle1, ), ), @@ -80,7 +80,7 @@ class DialogInvite extends StatelessWidget { Navigator.pop(context); }, child: Text( - 'accept', + Strings.buttonTextAccept, style: Theme.of(context).textTheme.subtitle1, ), ), diff --git a/lib/views/home/home-screen.dart b/lib/views/home/home-screen.dart index 5f77cf585..42cb3cfd4 100644 --- a/lib/views/home/home-screen.dart +++ b/lib/views/home/home-screen.dart @@ -307,7 +307,7 @@ class HomeState extends State { offline: props.offline, syncing: props.syncing, unauthed: props.unauthed, - tooltip: 'Profile and Settings', + tooltip: Strings.tooltipProfileAndSettings, onPressed: () { Navigator.pushNamed(context, Routes.settingsProfile); }, @@ -325,7 +325,7 @@ class HomeState extends State { IconButton( color: assetColor, icon: Icon(Icons.search), - tooltip: 'Search Chats', + tooltip: Strings.tooltipSearchChats, onPressed: () => onToggleSearch(), ), RoundedPopupMenu( @@ -690,9 +690,9 @@ class HomeState extends State { if (searching) { currentAppBar = AppBarSearch( - title: 'Search Unencrypted', - label: 'Search Unencrypted', - tooltip: 'Search Unencrypted', + title: Strings.titleSearchUnencrypted, + label: Strings.labelSearchUnencrypted, + tooltip: Strings.tooltipSearchUnencrypted, forceFocus: true, navigate: false, startFocused: true, @@ -848,7 +848,7 @@ class _Props extends Equatable { if (await canLaunch(Values.openHelpUrl)) { await launch(Values.openHelpUrl); } else { - throw 'Could not launch ${Values.openHelpUrl}'; + throw Strings.alertCouldNotLaunchURL(Values.openHelpUrl); } } catch (error) {} }, diff --git a/lib/views/home/settings/advanced-settings-screen.dart b/lib/views/home/settings/advanced-settings-screen.dart index 4db6cc85d..458f5f18e 100644 --- a/lib/views/home/settings/advanced-settings-screen.dart +++ b/lib/views/home/settings/advanced-settings-screen.dart @@ -71,7 +71,7 @@ class AdvancedSettingsScreenState extends State { onTap: () => props.onStartBackgroundSync(), contentPadding: Dimensions.listPadding, title: Text( - 'Start Background Service', + Strings.listItemAdvancedSettingsStartBackground, style: Theme.of(context).textTheme.subtitle1, ), ), @@ -88,7 +88,7 @@ class AdvancedSettingsScreenState extends State { }, contentPadding: Dimensions.listPadding, title: Text( - 'Stop All Services', + Strings.listItemAdvancedSettingsStopBackground, style: Theme.of(context).textTheme.subtitle1, ), ), @@ -103,7 +103,7 @@ class AdvancedSettingsScreenState extends State { ); }, contentPadding: Dimensions.listPadding, - title: Text('Test Notifications', style: Theme.of(context).textTheme.subtitle1), + title: Text(Strings.listItemAdvancedSettingsTestNotifications, style: Theme.of(context).textTheme.subtitle1), ), ), Visibility( @@ -114,7 +114,7 @@ class AdvancedSettingsScreenState extends State { await notificationSyncTEST(); }, contentPadding: Dimensions.listPadding, - title: Text('Test Background Sync Loop', + title: Text(Strings.listItemAdvancedSettingsTestSyncLoop, style: Theme.of(context).textTheme.subtitle1), ), ), @@ -126,7 +126,7 @@ class AdvancedSettingsScreenState extends State { onTap: () { props.onForceFunction(); }, - title: Text('Force Function', style: Theme.of(context).textTheme.subtitle1), + title: Text(Strings.listItemAdvancedSettingsForceFunction, style: Theme.of(context).textTheme.subtitle1), ), ), ListTile( @@ -136,7 +136,7 @@ class AdvancedSettingsScreenState extends State { }, contentPadding: Dimensions.listPadding, title: Text( - 'Open Source Licenses', + Strings.listItemAdvancedSettingsLicenses, style: Theme.of(context).textTheme.subtitle1, ), ), @@ -156,11 +156,11 @@ class AdvancedSettingsScreenState extends State { onTap: () => props.onEditSyncInterval(context), contentPadding: Dimensions.listPadding, title: Text( - 'Sync Interval', + Strings.listItemSettingsSyncInterval, style: Theme.of(context).textTheme.subtitle1, ), subtitle: Text( - 'Amount of time in seconds the app wait\nbetween syncing', + Strings.subtitleSettingsSyncInterval, ), trailing: Container( padding: EdgeInsets.symmetric(horizontal: 8), @@ -175,11 +175,11 @@ class AdvancedSettingsScreenState extends State { onTap: props.onToggleSyncing as void Function()?, contentPadding: Dimensions.listPadding, title: Text( - 'Toggle Syncing', + Strings.listItemSettingsSyncToggle, style: Theme.of(context).textTheme.subtitle1, ), subtitle: Text( - 'Toggle syncing with the matrix server', + Strings.subtitleSettingsSyncToggle, ), trailing: Container( padding: EdgeInsets.symmetric(horizontal: 8), diff --git a/lib/views/syphon.dart b/lib/views/syphon.dart index f73befb48..598c4bdc5 100644 --- a/lib/views/syphon.dart +++ b/lib/views/syphon.dart @@ -13,6 +13,7 @@ import 'package:syphon/global/connectivity.dart'; import 'package:syphon/global/formatters.dart'; import 'package:syphon/global/notifications.dart'; import 'package:syphon/global/print.dart'; +import 'package:syphon/global/strings.dart'; import 'package:syphon/global/themes.dart'; import 'package:syphon/global/values.dart'; import 'package:syphon/storage/database.dart'; @@ -335,13 +336,13 @@ class SyphonState extends State with WidgetsBindingObserver { switch (alert.type) { case 'error': if (!ConnectionService.isConnected() && !alert.offline) { - alertOverride = 'Looks like you may be offline. Check your connection and try again.'; + alertOverride = Strings.alertOffline; } color = Colors.red; break; case 'warning': if (!ConnectionService.isConnected() && !alert.offline) { - alertOverride = 'Looks like you may be offline. Check your connection and try again.'; + alertOverride = Strings.alertOffline; } color = Colors.red; break; @@ -353,7 +354,7 @@ class SyphonState extends State with WidgetsBindingObserver { color = Colors.grey; } - final alertMessage = alertOverride ?? alert.message ?? alert.error ?? 'Unknown Error Occurred'; + final alertMessage = alertOverride ?? alert.message ?? alert.error ?? Strings.alertUnknown; globalScaffold.currentState?.showSnackBar(SnackBar( backgroundColor: color, @@ -363,7 +364,7 @@ class SyphonState extends State with WidgetsBindingObserver { ), duration: alert.duration, action: SnackBarAction( - label: alert.action ?? 'Dismiss', + label: alert.action ?? Strings.buttonDismiss, textColor: Colors.white, onPressed: () { if (alert.onAction != null) { diff --git a/lib/views/widgets/dialogs/dialog-color-picker.dart b/lib/views/widgets/dialogs/dialog-color-picker.dart index d321e25b6..ac99f56a2 100644 --- a/lib/views/widgets/dialogs/dialog-color-picker.dart +++ b/lib/views/widgets/dialogs/dialog-color-picker.dart @@ -8,7 +8,7 @@ import 'package:syphon/global/strings.dart'; class DialogColorPicker extends StatefulWidget { const DialogColorPicker({ Key? key, - this.title = 'Color Picker', + required this.title, // i18n Strings isn't a constant. You gotta pass it in required this.currentColor, this.advanced = false, this.resetColor, diff --git a/lib/views/widgets/dialogs/dialog-confirm-password.dart b/lib/views/widgets/dialogs/dialog-confirm-password.dart index 7884a6f6c..93aae52a2 100644 --- a/lib/views/widgets/dialogs/dialog-confirm-password.dart +++ b/lib/views/widgets/dialogs/dialog-confirm-password.dart @@ -16,8 +16,8 @@ import 'package:syphon/views/widgets/loader/loading-indicator.dart'; class DialogConfirmPassword extends StatelessWidget { const DialogConfirmPassword({ Key? key, - this.title = 'Confirm Password (Default)', - this.content = 'Please confirm your password (Default)', + required this.title, // i18n Strings isn't a constant. You gotta pass it in + required this.content, // i18n Strings isn't a constant. You gotta pass it in this.onConfirm, this.onCancel, }) : super(key: key); @@ -91,7 +91,7 @@ class DialogConfirmPassword extends StatelessWidget { border: OutlineInputBorder( borderRadius: BorderRadius.circular(30.0), ), - labelText: 'password', + labelText: Strings.labelPassword, ), ), ), diff --git a/lib/views/widgets/lists/list-local-images.dart b/lib/views/widgets/lists/list-local-images.dart index 820621748..294878fb9 100644 --- a/lib/views/widgets/lists/list-local-images.dart +++ b/lib/views/widgets/lists/list-local-images.dart @@ -9,6 +9,7 @@ import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart'; import 'package:syphon/global/colours.dart'; import 'package:syphon/global/dimensions.dart'; +import 'package:syphon/global/strings.dart'; import 'package:syphon/views/widgets/lifecycle.dart'; _empty(File file) {} @@ -84,7 +85,7 @@ class _ListLocalImagesState extends State with Lifecycle DialogStartChat( user: user, - title: 'Chat with ${user.displayName}', + title: Strings.listItemUserDetailsStartChat(user.displayName), content: Strings.confirmStartChat, onStartChat: () async { final newRoomId = await props.onCreateChatDirect(user: user); @@ -176,7 +176,7 @@ class ModalUserDetails extends StatelessWidget { props: props, ), title: Text( - 'Send A Message', + Strings.listItemUserDetailsSendMessage, style: Theme.of(context).textTheme.subtitle1, ), leading: Container( @@ -187,7 +187,7 @@ class ModalUserDetails extends StatelessWidget { fit: BoxFit.contain, width: Dimensions.iconSize - 2, height: Dimensions.iconSize - 2, - semanticsLabel: 'Create A Public Room', + semanticsLabel: Strings.semanticsCreatePublicRoom, color: Theme.of(context).iconTheme.color, ), ), @@ -198,7 +198,7 @@ class ModalUserDetails extends StatelessWidget { props: props, ), title: Text( - 'Invite To Room', + Strings.listItemUserDetailsRoomInvite, style: Theme.of(context).textTheme.subtitle1, ), leading: Container( @@ -215,7 +215,7 @@ class ModalUserDetails extends StatelessWidget { props: props, ), title: Text( - 'View Profile', + Strings.listItemUserDetailsViewProfile, style: Theme.of(context).textTheme.subtitle1, ), leading: Container( @@ -232,7 +232,9 @@ class ModalUserDetails extends StatelessWidget { Navigator.pop(context); }, title: Text( - props.blocked ? 'Unblock User' : 'Block User', + props.blocked + ? Strings.listItemUserDetailsUnblockUser + : Strings.listItemUserDetailsBlockUser, ), leading: Container( padding: EdgeInsets.all(4), From 56d3ab963e076ed68e545b3e63c16ee4ee1aac14 Mon Sep 17 00:00:00 2001 From: ereio Date: Sun, 9 Jan 2022 15:16:49 -0500 Subject: [PATCH 02/10] fix: issue with checking urls before opening in Android 11, due to privacy updates in OS --- ios/Runner.xcodeproj/project.pbxproj | 12 +++--- lib/global/weburl.dart | 15 ++++++++ lib/store/alerts/middleware.dart | 10 ++--- lib/store/auth/actions.dart | 7 +--- lib/views/home/home-screen.dart | 9 +---- lib/views/intro/signup/widgets/StepTerms.dart | 37 +++++-------------- lib/views/widgets/messages/message.dart | 10 +---- 7 files changed, 40 insertions(+), 60 deletions(-) create mode 100644 lib/global/weburl.dart diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index bfe95a660..75ab69beb 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -354,7 +354,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 2006; + CURRENT_PROJECT_VERSION = 2007; DEVELOPMENT_TEAM = W98LUTKH5G; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -370,7 +370,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - MARKETING_VERSION = 0.2.5; + MARKETING_VERSION = 0.2.6; PRODUCT_BUNDLE_IDENTIFIER = org.tether.tether; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -493,7 +493,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 2006; + CURRENT_PROJECT_VERSION = 2007; DEVELOPMENT_TEAM = W98LUTKH5G; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -509,7 +509,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - MARKETING_VERSION = 0.2.5; + MARKETING_VERSION = 0.2.6; PRODUCT_BUNDLE_IDENTIFIER = org.tether.tether; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -526,7 +526,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 2006; + CURRENT_PROJECT_VERSION = 2007; DEVELOPMENT_TEAM = W98LUTKH5G; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -542,7 +542,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - MARKETING_VERSION = 0.2.5; + MARKETING_VERSION = 0.2.6; PRODUCT_BUNDLE_IDENTIFIER = org.tether.tether; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; diff --git a/lib/global/weburl.dart b/lib/global/weburl.dart new file mode 100644 index 000000000..c8157b278 --- /dev/null +++ b/lib/global/weburl.dart @@ -0,0 +1,15 @@ +import 'dart:io'; + +import 'package:url_launcher/url_launcher.dart'; + +Future launchUrl(String url, {bool forceSafariVC = false}) async { +// TODO: confirm it can launch a URL with new Android 11 privacy settings + if (!Platform.isAndroid && !(await canLaunch(url))) { + throw 'Could not launch $url'; + } + + await launch( + url, + forceSafariVC: forceSafariVC, + ); +} diff --git a/lib/store/alerts/middleware.dart b/lib/store/alerts/middleware.dart index 9a3889259..01ff1cf8e 100644 --- a/lib/store/alerts/middleware.dart +++ b/lib/store/alerts/middleware.dart @@ -1,5 +1,6 @@ import 'package:redux/redux.dart'; import 'package:syphon/global/libs/matrix/errors.dart'; +import 'package:syphon/global/weburl.dart'; import 'package:syphon/store/alerts/actions.dart'; import 'package:syphon/store/index.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -26,14 +27,9 @@ dynamic alertMiddleware( // and conditions acceptance if (alert.contains(MatrixErrorsSoft.terms_and_conditions)) { final termsUrl = 'https${alert.split('https')[1]}'; - final termsUrlFormatted = - termsUrl.replaceFirst('.', '', termsUrl.length - 1); + final termsUrlFormatted = termsUrl.replaceFirst('.', '', termsUrl.length - 1); - if (await canLaunch(termsUrlFormatted)) { - return await launch(termsUrlFormatted, forceSafariVC: false); - } else { - throw 'Could not launch $termsUrl'; - } + await launchUrl(termsUrlFormatted); } break; diff --git a/lib/store/auth/actions.dart b/lib/store/auth/actions.dart index 7972b31ad..5935a62af 100644 --- a/lib/store/auth/actions.dart +++ b/lib/store/auth/actions.dart @@ -20,6 +20,7 @@ import 'package:syphon/global/notifications.dart'; import 'package:syphon/global/print.dart'; import 'package:syphon/global/strings.dart'; import 'package:syphon/global/values.dart'; +import 'package:syphon/global/weburl.dart'; import 'package:syphon/storage/index.dart'; import 'package:syphon/store/alerts/actions.dart'; import 'package:syphon/store/auth/context/actions.dart'; @@ -426,11 +427,7 @@ ThunkAction loginUserSSO({String? token}) { if (token == null) { final ssoUrl = 'https://${homeserver.baseUrl}${Values.matrixSSOUrl}'; - if (await canLaunch(ssoUrl)) { - return await launch(ssoUrl, forceSafariVC: false); - } else { - throw 'Could not launch $ssoUrl'; - } + return await launchUrl(ssoUrl, forceSafariVC: false); } final username = store.state.authStore.username; diff --git a/lib/views/home/home-screen.dart b/lib/views/home/home-screen.dart index 5f77cf585..bce36a748 100644 --- a/lib/views/home/home-screen.dart +++ b/lib/views/home/home-screen.dart @@ -13,6 +13,7 @@ import 'package:syphon/global/formatters.dart'; import 'package:syphon/global/libs/matrix/constants.dart'; import 'package:syphon/global/strings.dart'; import 'package:syphon/global/values.dart'; +import 'package:syphon/global/weburl.dart'; import 'package:syphon/store/events/messages/model.dart'; import 'package:syphon/store/events/selectors.dart'; import 'package:syphon/store/index.dart'; @@ -844,13 +845,7 @@ class _Props extends Equatable { return Future(() => true); }, onSelectHelp: () async { - try { - if (await canLaunch(Values.openHelpUrl)) { - await launch(Values.openHelpUrl); - } else { - throw 'Could not launch ${Values.openHelpUrl}'; - } - } catch (error) {} + await launchUrl(Values.openHelpUrl); }, ); } diff --git a/lib/views/intro/signup/widgets/StepTerms.dart b/lib/views/intro/signup/widgets/StepTerms.dart index 1471301ae..3e3b1b095 100644 --- a/lib/views/intro/signup/widgets/StepTerms.dart +++ b/lib/views/intro/signup/widgets/StepTerms.dart @@ -1,23 +1,17 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:redux/redux.dart'; -import 'package:url_launcher/url_launcher.dart'; import 'package:syphon/global/assets.dart'; import 'package:syphon/global/colours.dart'; import 'package:syphon/global/dimensions.dart'; import 'package:syphon/global/libs/matrix/auth.dart'; +import 'package:syphon/global/weburl.dart'; import 'package:syphon/store/auth/actions.dart'; import 'package:syphon/store/index.dart'; -// Store - -// Styling - class TermsStep extends StatelessWidget { TermsStep({Key? key}) : super(key: key); final focusNode = FocusNode(); @@ -27,7 +21,7 @@ class TermsStep extends StatelessWidget { distinct: true, converter: (Store store) => _Props.mapStateToProps(store), builder: (context, props) { - double width = MediaQuery.of(context).size.width; + final double width = MediaQuery.of(context).size.width; return Container( child: Flex( direction: Axis.vertical, @@ -49,8 +43,7 @@ class TermsStep extends StatelessWidget { children: [ SvgPicture.asset( Assets.heroSyncFiles, - semanticsLabel: - 'A couple of documents with a checked circle on the bottom', + semanticsLabel: 'A couple of documents with a checked circle on the bottom', ), Positioned( bottom: 0, @@ -91,7 +84,7 @@ class TermsStep extends StatelessWidget { ), Container( child: Stack( - overflow: Overflow.visible, + clipBehavior: Clip.none, children: [ Container( padding: EdgeInsets.symmetric( @@ -151,9 +144,7 @@ class TermsStep extends StatelessWidget { props.onToggleAgreement(); }, child: Icon( - props.agreement - ? Icons.check_box - : Icons.check_box_outline_blank, + props.agreement ? Icons.check_box : Icons.check_box_outline_blank, ), ), ), @@ -169,13 +160,9 @@ class TermsStep extends StatelessWidget { children: [ TextSpan( text: 'terms of service', - style: Theme.of(context) - .textTheme - .subtitle1! - .copyWith( + style: Theme.of(context).textTheme.subtitle1!.copyWith( fontWeight: FontWeight.w400, - decorationStyle: - TextDecorationStyle.solid, + decorationStyle: TextDecorationStyle.solid, ), ), ], @@ -201,7 +188,7 @@ class _Props extends Equatable { final Function onToggleAgreement; final Function onViewTermsOfService; - _Props({ + const _Props({ required this.homeserver, required this.agreement, required this.onToggleAgreement, @@ -228,11 +215,7 @@ class _Props extends Equatable { onViewTermsOfService: () async { try { final termsOfServiceUrl = store.state.authStore.credential!.termsUrl!; - if (await canLaunch(termsOfServiceUrl)) { - await launch(termsOfServiceUrl); - } else { - throw 'Could not launch $termsOfServiceUrl'; - } + launchUrl(termsOfServiceUrl); } catch (error) {} }); diff --git a/lib/views/widgets/messages/message.dart b/lib/views/widgets/messages/message.dart index baac7e35e..95477e12d 100644 --- a/lib/views/widgets/messages/message.dart +++ b/lib/views/widgets/messages/message.dart @@ -8,6 +8,7 @@ import 'package:syphon/global/dimensions.dart'; import 'package:syphon/global/formatters.dart'; import 'package:syphon/global/libs/matrix/constants.dart'; import 'package:syphon/global/strings.dart'; +import 'package:syphon/global/weburl.dart'; import 'package:syphon/store/events/messages/model.dart'; import 'package:syphon/store/events/messages/selectors.dart'; import 'package:syphon/store/index.dart'; @@ -216,14 +217,7 @@ class MessageWidget extends StatelessWidget { onDismiss: () => Navigator.pop(dialogContext), onConfirm: () async { Navigator.of(dialogContext).pop(); - - // TODO: confirm it can launch a URL with new Android 11 privacy settings - // if (await canLaunch(url)) { - try { - return launch(url, forceSafariVC: false); - } catch (error) { - throw 'Could not launch $url'; - } + await launchUrl(url); }, ), ); From c0daaeda58d4a29ba3d720d6254028b5b61f328f Mon Sep 17 00:00:00 2001 From: ereio Date: Sun, 9 Jan 2022 15:23:31 -0500 Subject: [PATCH 03/10] chore: update direct chat toggle copy --- assets/translations/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/translations/en.json b/assets/translations/en.json index ac5a3141c..8df25cfc1 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -126,7 +126,7 @@ "button-file": "File", "button-contact": "Contact", "button-location": "Location", - "list-item-chat-detail-toggle-direct-chat": "Toggle Direct Chat", + "list-item-chat-detail-toggle-direct-chat": "Direct Chat", "list-item-chat-detail-notification-setting": "Notification Settings", "list-item-chat-detail-notifications": "Notifications", "list-item-chat-detail-notification-sound": "Notification Sound", From 3fff02c9f7df2cb9c94c97c0efa3db1257fb3ee9 Mon Sep 17 00:00:00 2001 From: ereio Date: Sun, 9 Jan 2022 15:25:20 -0500 Subject: [PATCH 04/10] fix: unselect message after edit --- lib/views/home/chat/chat-screen.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/views/home/chat/chat-screen.dart b/lib/views/home/chat/chat-screen.dart index bad98a050..9cffc3c4e 100644 --- a/lib/views/home/chat/chat-screen.dart +++ b/lib/views/home/chat/chat-screen.dart @@ -250,6 +250,7 @@ class ChatScreenState extends State { setState(() { sending = false; editing = false; + selectedMessage = null; }); } From 368b00f11466385479bcf3e965abc47b8f2529b1 Mon Sep 17 00:00:00 2001 From: ereio Date: Sun, 9 Jan 2022 17:09:01 -0500 Subject: [PATCH 05/10] =?UTF-8?q?fix:=20remove=20the=20potato=20filter=20?= =?UTF-8?q?=F0=9F=A5=94,=20attempt=20to=20remove=20exif=20data=20before=20?= =?UTF-8?q?send,=20handle=20videos=20appearing=20=20media=20preview=20list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugins/GeneratedPluginRegistrant.java | 5 ++ lib/cache/serializer.dart | 1 - lib/cache/storage.dart | 1 - lib/global/print.dart | 11 +++ lib/store/alerts/middleware.dart | 1 - lib/store/auth/actions.dart | 10 +-- lib/store/auth/reducer.dart | 10 +-- lib/store/events/messages/selectors.dart | 44 +++++++++++ lib/store/media/actions.dart | 1 - lib/store/media/encryption.dart | 11 +-- lib/store/media/filters.dart | 74 ++++++++++++++++++ lib/store/rooms/actions.dart | 1 + lib/store/sync/actions.dart | 1 - .../chat/chat-detail-all-users-screen.dart | 2 +- .../home/chat/chat-detail-message-screen.dart | 2 +- lib/views/home/chat/chat-screen.dart | 11 ++- lib/views/home/chat/media-preview-screen.dart | 2 +- lib/views/home/chat/widgets/chat-input.dart | 7 +- .../groups/group-create-public-screen.dart | 12 +-- .../home/groups/invite-users-screen.dart | 18 +++-- lib/views/home/home-screen.dart | 1 - lib/views/home/profile/profile-screen.dart | 78 +++++++++---------- .../home/profile/profile-user-screen.dart | 2 +- .../home/search/search-chats-screen.dart | 5 +- .../home/search/search-groups-screen.dart | 2 +- .../home/search/search-users-screen.dart | 2 +- .../settings/advanced-settings-screen.dart | 8 +- lib/views/home/settings/blocked-screen.dart | 30 +++---- .../password/password-update-screen.dart | 21 ++--- .../password/password-update-step.dart | 17 ++-- .../home/settings/settings-chats-screen.dart | 2 +- .../settings/settings-devices-screen.dart | 10 +-- .../settings-notifications-screen.dart | 44 ++++------- .../home/settings/settings-proxy-screen.dart | 2 +- .../settings/settings-storage-screen.dart | 7 +- .../home/settings/settings-theme-screen.dart | 26 ++----- .../settings/widgets/profile-preview.dart | 8 +- lib/views/intro/intro-screen.dart | 25 ++---- .../login/forgot/password-forgot-screen.dart | 17 ++-- .../login/forgot/password-reset-screen.dart | 14 ++-- .../login/forgot/widgets/PageEmailVerify.dart | 5 +- .../forgot/widgets/PagePasswordReset.dart | 13 ++-- lib/views/intro/login/login-screen.dart | 27 ++++--- .../search/search-homeserver-screen.dart | 11 ++- lib/views/intro/signup/signup-screen.dart | 14 ++-- .../intro/signup/verification-screen.dart | 33 +++----- .../intro/signup/widgets/StepCaptcha.dart | 6 +- lib/views/intro/signup/widgets/StepEmail.dart | 16 ++-- .../intro/signup/widgets/StepHomeserver.dart | 2 +- .../intro/signup/widgets/StepPassword.dart | 9 +-- .../intro/signup/widgets/StepUsername.dart | 13 ++-- lib/views/intro/widgets/page-action.dart | 1 - .../intro/widgets/page-description-first.dart | 3 +- .../widgets/page-description-second.dart | 1 - .../intro/widgets/page-description-third.dart | 1 - lib/views/intro/widgets/page-landing.dart | 1 - lib/views/widgets/appbars/appbar-avatar.dart | 1 - lib/views/widgets/appbars/appbar-normal.dart | 1 - lib/views/widgets/appbars/appbar-search.dart | 4 +- lib/views/widgets/avatars/avatar-badge.dart | 2 +- lib/views/widgets/avatars/avatar.dart | 5 +- lib/views/widgets/buttons/button-outline.dart | 12 +-- lib/views/widgets/buttons/button-solid.dart | 18 ++--- .../widgets/buttons/button-text-opacity.dart | 3 +- lib/views/widgets/captcha.dart | 9 +-- .../widgets/containers/card-section.dart | 2 +- .../containers/fabs/fab-bar-expanding.dart | 8 +- .../widgets/containers/fabs/fab-ring.dart | 10 +-- lib/views/widgets/containers/media-card.dart | 1 - .../widgets/containers/menu-rounded.dart | 9 +-- lib/views/widgets/dialogs/dialog-captcha.dart | 15 ++-- .../widgets/dialogs/dialog-color-picker.dart | 8 +- .../dialogs/dialog-confirm-password.dart | 5 +- lib/views/widgets/dialogs/dialog-confirm.dart | 26 +++---- .../widgets/dialogs/dialog-explaination.dart | 1 - .../widgets/dialogs/dialog-invite-users.dart | 13 +--- lib/views/widgets/dialogs/dialog-rounded.dart | 1 - .../widgets/dialogs/dialog-start-chat.dart | 14 ++-- .../widgets/dialogs/dialog-text-input.dart | 1 - lib/views/widgets/image-matrix.dart | 2 +- .../widgets/lists/list-item-account.dart | 12 +-- lib/views/widgets/lists/list-item-user.dart | 1 - .../widgets/lists/list-local-images.dart | 12 ++- .../widgets/lists/list-user-bubbles.dart | 1 - lib/views/widgets/loader/index.dart | 1 - .../widgets/loader/loading-indicator.dart | 1 - lib/views/widgets/messages/message.dart | 6 +- .../widgets/modals/modal-image-options.dart | 1 - .../widgets/modals/modal-user-details.dart | 6 +- pubspec.lock | 7 ++ pubspec.yaml | 9 ++- 91 files changed, 462 insertions(+), 468 deletions(-) create mode 100644 lib/store/media/filters.dart diff --git a/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java b/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java index 29af73579..38d5a6238 100644 --- a/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java +++ b/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java @@ -40,6 +40,11 @@ public static void registerWith(@NonNull FlutterEngine flutterEngine) { } catch(Exception e) { Log.e(TAG, "Error registering plugin file_picker, com.mr.flutter.plugin.filepicker.FilePickerPlugin", e); } + try { + flutterEngine.getPlugins().add(new com.example.flutterimagecompress.FlutterImageCompressPlugin()); + } catch(Exception e) { + Log.e(TAG, "Error registering plugin flutter_image_compress, com.example.flutterimagecompress.FlutterImageCompressPlugin", e); + } try { flutterEngine.getPlugins().add(new com.jrai.flutter_keyboard_visibility.FlutterKeyboardVisibilityPlugin()); } catch(Exception e) { diff --git a/lib/cache/serializer.dart b/lib/cache/serializer.dart index a82ca10a8..55a614f66 100644 --- a/lib/cache/serializer.dart +++ b/lib/cache/serializer.dart @@ -1,7 +1,6 @@ import 'dart:convert'; import 'dart:typed_data'; -import 'package:flutter/foundation.dart'; import 'package:redux_persist/redux_persist.dart'; import 'package:sembast/sembast.dart'; import 'package:syphon/cache/index.dart'; diff --git a/lib/cache/storage.dart b/lib/cache/storage.dart index 05145c29b..afc2d9711 100644 --- a/lib/cache/storage.dart +++ b/lib/cache/storage.dart @@ -1,6 +1,5 @@ import 'dart:typed_data'; -import 'package:flutter/foundation.dart'; import 'package:redux_persist/redux_persist.dart'; import 'package:sembast/sembast.dart'; import 'package:syphon/cache/index.dart'; diff --git a/lib/global/print.dart b/lib/global/print.dart index eb033e605..d770aa35c 100644 --- a/lib/global/print.dart +++ b/lib/global/print.dart @@ -32,6 +32,17 @@ void _printJson(Map? jsonMap) { debugPrint(prettyEvent, wrapWidth: 2048); } +// TODO: convert with better tab completion +class Print { + static info(String content, {String? title}) => _printInfo(content, title: title); + static warn(String content, {String? title}) => _printWarning(content, title: title); + static error(String content, {String? title}) => _printError(content, title: title); + static debug(String content, {String? title}) => _printDebug(content, title: title); + static json(Map? json) => _printJson(json); +} + +final log = Print(); + PrintJson printJson = _printJson; PrintDebug printInfo = _printInfo; PrintDebug printDebug = _printDebug; diff --git a/lib/store/alerts/middleware.dart b/lib/store/alerts/middleware.dart index 01ff1cf8e..1f1c606c1 100644 --- a/lib/store/alerts/middleware.dart +++ b/lib/store/alerts/middleware.dart @@ -3,7 +3,6 @@ import 'package:syphon/global/libs/matrix/errors.dart'; import 'package:syphon/global/weburl.dart'; import 'package:syphon/store/alerts/actions.dart'; import 'package:syphon/store/index.dart'; -import 'package:url_launcher/url_launcher.dart'; /// /// Alert Middleware diff --git a/lib/store/auth/actions.dart b/lib/store/auth/actions.dart index 5935a62af..76a4a73a4 100644 --- a/lib/store/auth/actions.dart +++ b/lib/store/auth/actions.dart @@ -4,7 +4,6 @@ import 'dart:io'; import 'dart:math'; import 'package:crypto/crypto.dart'; -import 'package:device_info/device_info.dart'; import 'package:flutter/services.dart'; import 'package:redux/redux.dart'; import 'package:redux_thunk/redux_thunk.dart'; @@ -40,7 +39,6 @@ import 'package:syphon/store/sync/actions.dart'; import 'package:syphon/store/sync/background/storage.dart'; import 'package:syphon/store/user/actions.dart'; import 'package:uni_links/uni_links.dart'; -import 'package:url_launcher/url_launcher.dart'; import '../user/model.dart'; @@ -177,7 +175,7 @@ class ResetAuthStore {} class ResetSession {} -late StreamSubscription _sub; +late StreamSubscription _deeplinkSubscription; ThunkAction initDeepLinks() => (Store store) async { try { @@ -185,11 +183,13 @@ ThunkAction initDeepLinks() => (Store store) async { return; } - _sub = uriLinkStream.listen((Uri? uri) { + _deeplinkSubscription = uriLinkStream.listen((Uri? uri) { final token = uri!.queryParameters['loginToken']; + store.dispatch(SetLoading(loading: true)); store.dispatch(loginUserSSO(token: token)); }, onError: (err) { printError('[streamUniLinks] error $err'); + store.dispatch(SetLoading(loading: false)); }); } on PlatformException { store.dispatch(addAlert( @@ -206,7 +206,7 @@ ThunkAction initDeepLinks() => (Store store) async { ThunkAction disposeDeepLinks() => (Store store) async { try { - _sub.cancel(); + _deeplinkSubscription.cancel(); } catch (error) { printError(error.toString()); } diff --git a/lib/store/auth/reducer.dart b/lib/store/auth/reducer.dart index 471478d2f..be27aefb1 100644 --- a/lib/store/auth/reducer.dart +++ b/lib/store/auth/reducer.dart @@ -1,8 +1,8 @@ import 'package:syphon/store/auth/context/actions.dart'; -import '../user/model.dart'; import './actions.dart'; import './state.dart'; +import '../user/model.dart'; AuthStore authReducer([AuthStore state = const AuthStore(), dynamic action]) { switch (action.runtimeType) { @@ -79,8 +79,8 @@ AuthStore authReducer([AuthStore state = const AuthStore(), dynamic action]) { final availableUser = _action.availableUser; final availableUsers = List.from(state.availableUsers); - final existingIndex = availableUsers - .indexWhere((user) => user.userId == availableUser.userId); + final existingIndex = + availableUsers.indexWhere((user) => user.userId == availableUser.userId); if (existingIndex == -1) { availableUsers.add(availableUser); @@ -92,8 +92,8 @@ AuthStore authReducer([AuthStore state = const AuthStore(), dynamic action]) { final availableUser = _action.availableUser; final availableUsers = List.from(state.availableUsers); - final existingIndex = availableUsers - .indexWhere((user) => user.userId == availableUser.userId); + final existingIndex = + availableUsers.indexWhere((user) => user.userId == availableUser.userId); if (existingIndex != -1) { availableUsers.remove(availableUser); diff --git a/lib/store/events/messages/selectors.dart b/lib/store/events/messages/selectors.dart index fed2c9733..df6893ff1 100644 --- a/lib/store/events/messages/selectors.dart +++ b/lib/store/events/messages/selectors.dart @@ -3,6 +3,12 @@ import 'package:syphon/global/strings.dart'; import 'package:syphon/store/events/messages/model.dart'; import 'package:syphon/store/index.dart'; +bool selectIsMedia(Message message) { + final isBodyNull = message.body == null; + + return message.url != null && !isBodyNull; +} + String selectEventBody(Message message) { final isBodyEmpty = message.body == null || message.body!.isEmpty; @@ -42,6 +48,44 @@ String selectEventBody(Message message) { return message.body ?? ''; } +// TODO: switch to this when you have more time +String selectEventBodyNew(Message message) { + final isBodyEmpty = message.body == null || message.body!.isEmpty; + + var messageType = message.type; + + if (message.typeDecrypted != null) { + messageType = message.typeDecrypted; + } + + switch (messageType) { + case EventTypes.encrypted: + if (isBodyEmpty) { + return Strings.labelEncryptedMessage; + } + break; + case EventTypes.message: + // ignore: invariant_booleans + if (isBodyEmpty) { + return Strings.labelDeletedMessage; + } + break; + case EventTypes.callInvite: + return Strings.labelCallInvite; + + case EventTypes.callHangup: + return Strings.labelCallHangup; + + default: + if (message.typeDecrypted != null) { + return Strings.labelEncryptedMessage; + } + break; + } + + return message.body ?? ''; +} + // remove messages from blocked users List filterMessages( List messages, diff --git a/lib/store/media/actions.dart b/lib/store/media/actions.dart index 9ae4df8f2..2606e64a6 100644 --- a/lib/store/media/actions.dart +++ b/lib/store/media/actions.dart @@ -2,7 +2,6 @@ import 'dart:io'; import 'dart:typed_data'; import 'package:flutter/foundation.dart'; - import 'package:mime/mime.dart'; import 'package:redux/redux.dart'; import 'package:redux_thunk/redux_thunk.dart'; diff --git a/lib/store/media/encryption.dart b/lib/store/media/encryption.dart index e5c47a25b..2ce3efedc 100644 --- a/lib/store/media/encryption.dart +++ b/lib/store/media/encryption.dart @@ -1,10 +1,10 @@ import 'dart:convert'; import 'dart:io'; +import 'package:drift/drift.dart'; import 'package:encrypt/encrypt.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:mime/mime.dart'; -import 'package:drift/drift.dart'; import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart'; import 'package:syphon/global/print.dart'; @@ -50,8 +50,7 @@ class EncryptInfo { Map toJson() => _$EncryptInfoToJson(this); - factory EncryptInfo.fromJson(Map json) => - _$EncryptInfoFromJson(json); + factory EncryptInfo.fromJson(Map json) => _$EncryptInfoFromJson(json); } /// @@ -83,8 +82,7 @@ Future encryptMedia({ final keyUsed = Key.fromBase64(info.key!); final cipher = AES(keyUsed, mode: AESMode.ctr, padding: null); - final encryptedMedia = - cipher.encrypt(await localFile.readAsBytes(), iv: ivUsed); + final encryptedMedia = cipher.encrypt(await localFile.readAsBytes(), iv: ivUsed); final directory = await getTemporaryDirectory(); final encryptFile = File(path.join(directory.path, fileName)); @@ -107,8 +105,7 @@ Future decryptMediaData({ final keyUsed = Key.fromBase64(base64.normalize(key!)); final cipher = AES(keyUsed, mode: AESMode.ctr, padding: null); - return cipher.decrypt(Encrypted.fromBase64(base64.encode(localData)), - iv: ivUsed); + return cipher.decrypt(Encrypted.fromBase64(base64.encode(localData)), iv: ivUsed); } catch (error) { printError(error.toString()); rethrow; diff --git a/lib/store/media/filters.dart b/lib/store/media/filters.dart new file mode 100644 index 000000000..e20371b42 --- /dev/null +++ b/lib/store/media/filters.dart @@ -0,0 +1,74 @@ +import 'dart:io'; + +import 'package:flutter_image_compress/flutter_image_compress.dart'; +import 'package:mime/mime.dart'; +import 'package:path/path.dart' as path; +import 'package:path_provider/path_provider.dart'; +import 'package:syphon/global/print.dart'; +import 'package:syphon/store/media/converters.dart'; + +/// +/// Encrypt Media (for Matrix) +/// +/// a client should generate a single-use 256-bit AES key, +/// and encrypt the file using AES-CTR. The counter should be 64-bit long, +/// starting at 0 and prefixed by a random 64-bit Initialization Vector (IV), +/// which together form a 128-bit unique counter block. +/// +/// https://matrix.org/docs/spec/client_server/latest#sending-encrypted-attachments +/// +Future scrubMedia({ + required File localFile, + String? mediaName = 'media-default', +}) async { + try { + // Extension handling + final mimeTypeOption = lookupMimeType(localFile.path); + final mimeType = convertMimeTypes(localFile, mimeTypeOption); + + // Setting up params for saving encrypted file + final String fileType = mimeType; + final String fileExtension = fileType.split('/')[1]; + final String fileName = '$mediaName-scrubbed.$fileExtension'; + + var format; + + switch (fileExtension.toLowerCase()) { + case 'png': + format = CompressFormat.png; + break; + case 'jpeg': + format = CompressFormat.jpeg; + break; + case 'heic': + format = CompressFormat.heic; + break; + case 'webp': + format = CompressFormat.webp; + break; + } + + final mediaScrubbed = await FlutterImageCompress.compressWithFile( + localFile.absolute.path, + quality: 100, + // minWidth: , + // minHeight: , + format: format, + keepExif: false, + numberOfRetries: 1, + autoCorrectionAngle: false, + ); + + if (mediaScrubbed == null) { + throw 'Failed to remove EXIF data from media'; + } + + final directory = await getTemporaryDirectory(); + final tempFile = File(path.join(directory.path, fileName)); + + return await tempFile.writeAsBytes(mediaScrubbed, flush: true); + } catch (error) { + printError(error.toString()); + return null; + } +} diff --git a/lib/store/rooms/actions.dart b/lib/store/rooms/actions.dart index 89d413bb0..38bd5413e 100644 --- a/lib/store/rooms/actions.dart +++ b/lib/store/rooms/actions.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:collection/collection.dart' show IterableExtension; import 'package:flutter/foundation.dart'; + import 'package:redux/redux.dart'; import 'package:redux_thunk/redux_thunk.dart'; import 'package:syphon/global/libs/matrix/constants.dart'; diff --git a/lib/store/sync/actions.dart b/lib/store/sync/actions.dart index a9e56af4a..cda455299 100644 --- a/lib/store/sync/actions.dart +++ b/lib/store/sync/actions.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; - import 'package:redux/redux.dart'; import 'package:redux_thunk/redux_thunk.dart'; diff --git a/lib/views/home/chat/chat-detail-all-users-screen.dart b/lib/views/home/chat/chat-detail-all-users-screen.dart index 2f38e4e3d..9188920c7 100644 --- a/lib/views/home/chat/chat-detail-all-users-screen.dart +++ b/lib/views/home/chat/chat-detail-all-users-screen.dart @@ -1,5 +1,5 @@ import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:redux/redux.dart'; diff --git a/lib/views/home/chat/chat-detail-message-screen.dart b/lib/views/home/chat/chat-detail-message-screen.dart index 46d619138..0f66dbdbb 100644 --- a/lib/views/home/chat/chat-detail-message-screen.dart +++ b/lib/views/home/chat/chat-detail-message-screen.dart @@ -1,5 +1,5 @@ import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:intl/intl.dart'; diff --git a/lib/views/home/chat/chat-screen.dart b/lib/views/home/chat/chat-screen.dart index 9cffc3c4e..88f527ec7 100644 --- a/lib/views/home/chat/chat-screen.dart +++ b/lib/views/home/chat/chat-screen.dart @@ -13,7 +13,6 @@ import 'package:syphon/global/assets.dart'; import 'package:syphon/global/colours.dart'; import 'package:syphon/global/dimensions.dart'; import 'package:syphon/global/libs/matrix/constants.dart'; -import 'package:syphon/global/print.dart'; import 'package:syphon/global/strings.dart'; import 'package:syphon/store/crypto/actions.dart'; import 'package:syphon/store/crypto/events/actions.dart'; @@ -26,6 +25,7 @@ import 'package:syphon/store/events/selectors.dart'; import 'package:syphon/store/index.dart'; import 'package:syphon/store/media/actions.dart'; import 'package:syphon/store/media/encryption.dart'; +import 'package:syphon/store/media/filters.dart'; import 'package:syphon/store/rooms/actions.dart'; import 'package:syphon/store/rooms/room/model.dart'; import 'package:syphon/store/rooms/selectors.dart'; @@ -275,7 +275,7 @@ class ChatScreenState extends State { }); } - onSendMedia(File file, MessageType type, _Props props) async { + onSendMedia(File rawFile, MessageType type, _Props props) async { final store = StoreProvider.of(context); final encryptionEnabled = props.room.encryptionEnabled; @@ -291,6 +291,13 @@ class ChatScreenState extends State { File? encryptedFile; EncryptInfo? info; + // TODO: confirm this doesn't persist the potato filter 🥔 + var file = await scrubMedia(localFile: rawFile); + + if (file == null) { + file = rawFile; + } + try { if (encryptionEnabled) { info = EncryptInfo.generate(); diff --git a/lib/views/home/chat/media-preview-screen.dart b/lib/views/home/chat/media-preview-screen.dart index 672408a6c..583f62398 100644 --- a/lib/views/home/chat/media-preview-screen.dart +++ b/lib/views/home/chat/media-preview-screen.dart @@ -1,7 +1,7 @@ import 'dart:io'; import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_svg/svg.dart'; diff --git a/lib/views/home/chat/widgets/chat-input.dart b/lib/views/home/chat/widgets/chat-input.dart index 2db57f9cb..1f019124d 100644 --- a/lib/views/home/chat/widgets/chat-input.dart +++ b/lib/views/home/chat/widgets/chat-input.dart @@ -219,10 +219,13 @@ class ChatInputState extends State { } onAddPhoto() async { + // TODO: has bug with file path + // final pickerResult = await ImagePicker().pickImage( + // source: ImageSource.gallery, + // ); + final pickerResult = await ImagePicker().getImage( source: ImageSource.gallery, - maxWidth: Dimensions.avatarSizeMax, - maxHeight: Dimensions.avatarSizeMax, ); if (pickerResult == null) return; diff --git a/lib/views/home/groups/group-create-public-screen.dart b/lib/views/home/groups/group-create-public-screen.dart index 8543f63ba..87f529c4b 100644 --- a/lib/views/home/groups/group-create-public-screen.dart +++ b/lib/views/home/groups/group-create-public-screen.dart @@ -1,7 +1,7 @@ import 'dart:io'; import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:redux/redux.dart'; @@ -89,7 +89,7 @@ class CreateGroupPublicState extends State { converter: (Store store) => _Props.mapStateToProps(store), builder: (context, props) { final double width = MediaQuery.of(context).size.width; - final double imageSize = Dimensions.avatarSizeDetails; + const double imageSize = Dimensions.avatarSizeDetails; final backgroundColor = selectAvatarBackground(props.themeType); @@ -295,8 +295,8 @@ class CreateGroupPublicState extends State { label: 'Name*', textInputAction: TextInputAction.next, controller: nameController, - onSubmitted: (text) => - FocusScope.of(context).requestFocus(aliasFocus), + onSubmitted: (text) => FocusScope.of(context) + .requestFocus(aliasFocus), onChanged: (text) => setState(() { name = text; }), @@ -313,8 +313,8 @@ class CreateGroupPublicState extends State { textInputAction: TextInputAction.next, disableSpacing: true, focusNode: aliasFocus, - onSubmitted: (text) => - FocusScope.of(context).requestFocus(topicFocus), + onSubmitted: (text) => FocusScope.of(context) + .requestFocus(topicFocus), onChanged: (text) => setState(() { alias = text; }), diff --git a/lib/views/home/groups/invite-users-screen.dart b/lib/views/home/groups/invite-users-screen.dart index cc6b282cd..930073414 100644 --- a/lib/views/home/groups/invite-users-screen.dart +++ b/lib/views/home/groups/invite-users-screen.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_svg/svg.dart'; @@ -145,7 +145,8 @@ class InviteUsersState extends State with Lifecycle with Lifecycle(context); final roomId = arguments.roomId; @@ -263,7 +265,8 @@ class InviteUsersState extends State with Lifecycle with Lifecycle - onAttemptInvite(props: props, context: context, user: attemptableUser), + onPress: () => onAttemptInvite( + props: props, context: context, user: attemptableUser), type: ListItemUserType.Selectable, user: attemptableUser, enabled: creatingRoomDisplayName != searchable, @@ -359,7 +362,8 @@ class InviteUsersState extends State with Lifecycle onToggleInvite(user: user), - onPressAvatar: () => onShowUserDetails(context: context, user: user), + onPressAvatar: () => + onShowUserDetails(context: context, user: user), ); }, ) diff --git a/lib/views/home/home-screen.dart b/lib/views/home/home-screen.dart index ac494445d..77b29dabc 100644 --- a/lib/views/home/home-screen.dart +++ b/lib/views/home/home-screen.dart @@ -41,7 +41,6 @@ import 'package:syphon/views/widgets/containers/fabs/fab-ring.dart'; import 'package:syphon/views/widgets/containers/menu-rounded.dart'; import 'package:syphon/views/widgets/dialogs/dialog-confirm.dart'; import 'package:syphon/views/widgets/loader/index.dart'; -import 'package:url_launcher/url_launcher.dart'; enum Options { newGroup, markAllRead, inviteFriends, settings, licenses, help } diff --git a/lib/views/home/profile/profile-screen.dart b/lib/views/home/profile/profile-screen.dart index 99380d881..675dfec8a 100644 --- a/lib/views/home/profile/profile-screen.dart +++ b/lib/views/home/profile/profile-screen.dart @@ -1,7 +1,7 @@ import 'dart:io'; import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_redux/flutter_redux.dart'; @@ -92,7 +92,7 @@ class ProfileScreenState extends State { converter: (Store store) => _Props.mapStateToProps(store), onInitialBuild: onMounted, builder: (context, props) { - final double imageSize = Dimensions.avatarSizeDetails; + const double imageSize = Dimensions.avatarSizeDetails; // Space for confirming rebuilding Widget avatarWidget = Avatar( @@ -218,13 +218,12 @@ class ProfileScreenState extends State { ), ), Container( - margin: const EdgeInsets.all(8.0), - constraints: BoxConstraints( - maxHeight: Dimensions.inputHeight, - maxWidth: Dimensions.inputWidthMax, - ), - child: Row( - children: [ + margin: const EdgeInsets.all(8.0), + constraints: BoxConstraints( + maxHeight: Dimensions.inputHeight, + maxWidth: Dimensions.inputWidthMax, + ), + child: Row(children: [ TextFieldSecure( disabled: false, readOnly: true, @@ -241,9 +240,7 @@ class ProfileScreenState extends State { icon: Icon(Icons.copy), ), ), - ] - ) - ), + ])), ], ), Container( @@ -332,36 +329,35 @@ class _Props extends Equatable { ]; static _Props mapStateToProps(Store store) => _Props( - user: store.state.authStore.user, - loading: store.state.authStore.loading, - themeType: store.state.settingsStore.themeSettings.themeType, - onSaveProfile: ({ - File? avatarFileNew, - String? userIdNew, - String? displayNameNew, - }) async { - final currentUser = store.state.authStore.user; - - if (displayNameNew != null && currentUser.displayName != displayNameNew) { - final bool successful = await store.dispatch( - updateDisplayName(displayNameNew), - ); - if (!successful) return false; - } + user: store.state.authStore.user, + loading: store.state.authStore.loading, + themeType: store.state.settingsStore.themeSettings.themeType, + onSaveProfile: ({ + File? avatarFileNew, + String? userIdNew, + String? displayNameNew, + }) async { + final currentUser = store.state.authStore.user; - if (avatarFileNew != null) { - final bool successful = await store.dispatch( - updateAvatar(localFile: avatarFileNew), - ); - if (!successful) return false; - } + if (displayNameNew != null && currentUser.displayName != displayNameNew) { + final bool successful = await store.dispatch( + updateDisplayName(displayNameNew), + ); + if (!successful) return false; + } - await store.dispatch(fetchAuthUserProfile()); - return true; - }, - copyToClipboard: () async { - await Clipboard.setData(ClipboardData(text: store.state.authStore.user.userId)); - store.dispatch(addInfo(message: 'Copied User ID to clipboard')); //TODO i18n + if (avatarFileNew != null) { + final bool successful = await store.dispatch( + updateAvatar(localFile: avatarFileNew), + ); + if (!successful) return false; } - ); + + await store.dispatch(fetchAuthUserProfile()); + return true; + }, + copyToClipboard: () async { + await Clipboard.setData(ClipboardData(text: store.state.authStore.user.userId)); + store.dispatch(addInfo(message: 'Copied User ID to clipboard')); //TODO i18n + }); } diff --git a/lib/views/home/profile/profile-user-screen.dart b/lib/views/home/profile/profile-user-screen.dart index 3b892c5a3..dfc62cab7 100644 --- a/lib/views/home/profile/profile-user-screen.dart +++ b/lib/views/home/profile/profile-user-screen.dart @@ -1,5 +1,5 @@ import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:redux/redux.dart'; diff --git a/lib/views/home/search/search-chats-screen.dart b/lib/views/home/search/search-chats-screen.dart index 8ab23943e..d10ec58d5 100644 --- a/lib/views/home/search/search-chats-screen.dart +++ b/lib/views/home/search/search-chats-screen.dart @@ -1,5 +1,5 @@ import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_svg/svg.dart'; @@ -60,7 +60,8 @@ class ChatSearchState extends State with Lifecycle { ); }, contentPadding: Dimensions.listPadding, - title: Text(Strings.listItemAdvancedSettingsTestNotifications, style: Theme.of(context).textTheme.subtitle1), + title: Text(Strings.listItemAdvancedSettingsTestNotifications, + style: Theme.of(context).textTheme.subtitle1), ), ), Visibility( @@ -126,7 +127,8 @@ class AdvancedSettingsScreenState extends State { onTap: () { props.onForceFunction(); }, - title: Text(Strings.listItemAdvancedSettingsForceFunction, style: Theme.of(context).textTheme.subtitle1), + title: Text(Strings.listItemAdvancedSettingsForceFunction, + style: Theme.of(context).textTheme.subtitle1), ), ), ListTile( diff --git a/lib/views/home/settings/blocked-screen.dart b/lib/views/home/settings/blocked-screen.dart index f3c1361f4..b51a34b1f 100644 --- a/lib/views/home/settings/blocked-screen.dart +++ b/lib/views/home/settings/blocked-screen.dart @@ -1,22 +1,17 @@ -import 'dart:async'; - -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:redux/redux.dart'; -import 'package:syphon/views/widgets/appbars/appbar-normal.dart'; -import 'package:syphon/views/widgets/containers/card-section.dart'; -import 'package:syphon/views/widgets/loader/index.dart'; -import 'package:syphon/views/widgets/modals/modal-user-details.dart'; - import 'package:syphon/global/colours.dart'; import 'package:syphon/global/dimensions.dart'; import 'package:syphon/store/index.dart'; import 'package:syphon/store/user/model.dart'; import 'package:syphon/store/user/selectors.dart'; +import 'package:syphon/views/widgets/appbars/appbar-normal.dart'; import 'package:syphon/views/widgets/avatars/avatar.dart'; +import 'package:syphon/views/widgets/containers/card-section.dart'; +import 'package:syphon/views/widgets/loader/index.dart'; +import 'package:syphon/views/widgets/modals/modal-user-details.dart'; class BlockedScreen extends StatefulWidget { const BlockedScreen({Key? key}) : super(key: key); @@ -28,7 +23,7 @@ class BlockedScreen extends StatefulWidget { class BlockedScreenState extends State { bool loading = false; - BlockedScreenState({Key? key}); + BlockedScreenState(); // componentDidMount(){} @override @@ -83,9 +78,7 @@ class BlockedScreenState extends State { user.userId!, style: Theme.of(context).textTheme.caption!.merge( TextStyle( - color: props.loading - ? Color(Colours.greyDisabled) - : null, + color: props.loading ? Color(Colours.greyDisabled) : null, ), ), ), @@ -109,7 +102,7 @@ class BlockedScreenState extends State { buildUserList(context, props), Positioned( child: Loader( - loading: this.loading, + loading: loading, ), ), ], @@ -123,7 +116,7 @@ class _Props extends Equatable { final bool loading; final List usersBlocked; - _Props({ + const _Props({ required this.loading, required this.usersBlocked, }); @@ -136,8 +129,7 @@ class _Props extends Equatable { static _Props mapStateToProps(Store store) => _Props( loading: store.state.roomStore.loading, - usersBlocked: store.state.userStore.blocked - .map((id) => store.state.userStore.users[id]) - .toList(), + usersBlocked: + store.state.userStore.blocked.map((id) => store.state.userStore.users[id]).toList(), ); } diff --git a/lib/views/home/settings/password/password-update-screen.dart b/lib/views/home/settings/password/password-update-screen.dart index e2c1d48ae..894b516eb 100644 --- a/lib/views/home/settings/password/password-update-screen.dart +++ b/lib/views/home/settings/password/password-update-screen.dart @@ -1,17 +1,14 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:redux/redux.dart'; - -import 'package:syphon/views/behaviors.dart'; import 'package:syphon/global/dimensions.dart'; import 'package:syphon/global/strings.dart'; - import 'package:syphon/store/auth/actions.dart'; import 'package:syphon/store/index.dart'; +import 'package:syphon/views/behaviors.dart'; import 'package:syphon/views/widgets/buttons/button-solid.dart'; + import 'password-update-step.dart'; class PasswordUpdateScreen extends StatefulWidget { @@ -69,10 +66,8 @@ class PasswordUpdateState extends State { behavior: DefaultScrollBehavior(), child: SingleChildScrollView( child: Container( - width: - width, // set actual height and width for flex constraints - height: - height, // set actual height and width for flex constraints + width: width, // set actual height and width for flex constraints + height: height, // set actual height and width for flex constraints child: Flex( direction: Axis.vertical, mainAxisAlignment: MainAxisAlignment.center, @@ -100,8 +95,7 @@ class PasswordUpdateState extends State { onPageChanged: (index) { setState(() { currentStep = index; - onboarding = index != 0 && - index != sections.length - 1; + onboarding = index != 0 && index != sections.length - 1; }); }, ), @@ -125,8 +119,7 @@ class PasswordUpdateState extends State { child: ButtonSolid( text: Strings.buttonSave, loading: props.loading, - disabled: - !props.isPasswordValid || props.loading, + disabled: !props.isPasswordValid || props.loading, onPressed: () async { final result = await props.onSavePassword(); if (result) { diff --git a/lib/views/home/settings/password/password-update-step.dart b/lib/views/home/settings/password/password-update-step.dart index af5026b11..bfa4cc67d 100644 --- a/lib/views/home/settings/password/password-update-step.dart +++ b/lib/views/home/settings/password/password-update-step.dart @@ -1,11 +1,8 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:redux/redux.dart'; - import 'package:syphon/global/assets.dart'; import 'package:syphon/global/dimensions.dart'; import 'package:syphon/global/strings.dart'; @@ -16,11 +13,12 @@ import 'package:syphon/views/widgets/input/text-field-secure.dart'; class PasswordUpdateStep extends StatefulWidget { const PasswordUpdateStep({Key? key}) : super(key: key); + @override PasswordUpdateStepState createState() => PasswordUpdateStepState(); } class PasswordUpdateStepState extends State { - PasswordUpdateStepState({Key? key}); + PasswordUpdateStepState(); bool visibility = false; FocusNode currentFocusNode = FocusNode(); @@ -41,7 +39,7 @@ class PasswordUpdateStepState extends State { distinct: true, converter: (Store store) => _Props.mapStateToProps(store), builder: (context, props) { - double width = MediaQuery.of(context).size.width; + final double width = MediaQuery.of(context).size.width; return Container( child: Column( @@ -59,8 +57,7 @@ class PasswordUpdateStepState extends State { ), child: SvgPicture.asset( Assets.heroSignupPassword, - semanticsLabel: - 'User thinking up a password in a swirl of wind', + semanticsLabel: 'User thinking up a password in a swirl of wind', ), ), ), @@ -158,7 +155,7 @@ class PasswordUpdateStepState extends State { // Do your stuff setState(() { - visibility = !this.visibility; + visibility = !visibility; }); if (!passwordFocusNode.hasFocus) { @@ -208,7 +205,7 @@ class PasswordUpdateStepState extends State { borderRadius: BorderRadius.circular(24), ), child: Container( - padding: EdgeInsets.all((6)), + padding: EdgeInsets.all(6), child: Icon( Icons.check, color: Colors.white, diff --git a/lib/views/home/settings/settings-chats-screen.dart b/lib/views/home/settings/settings-chats-screen.dart index 7f001282d..74ee0bccb 100644 --- a/lib/views/home/settings/settings-chats-screen.dart +++ b/lib/views/home/settings/settings-chats-screen.dart @@ -1,5 +1,5 @@ import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:redux/redux.dart'; diff --git a/lib/views/home/settings/settings-devices-screen.dart b/lib/views/home/settings/settings-devices-screen.dart index 680f9a709..955482485 100644 --- a/lib/views/home/settings/settings-devices-screen.dart +++ b/lib/views/home/settings/settings-devices-screen.dart @@ -1,5 +1,5 @@ import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:redux/redux.dart'; @@ -110,10 +110,7 @@ class DeviceViewState extends State { color: Colors.white, onPressed: selectedDevices!.length != 1 ? null - : () => props!.onRenameDevice( - context, - selectedDevices![0] - ), + : () => props!.onRenameDevice(context, selectedDevices![0]), ), IconButton( icon: Icon(Icons.delete), @@ -347,7 +344,8 @@ class _Props extends Equatable { content: Strings.contentRenameDevice, label: device.displayName ?? '', onConfirm: (String newDisplayName) async { - await store.dispatch(renameDevice(deviceId: device.deviceId, displayName: newDisplayName)); + await store + .dispatch(renameDevice(deviceId: device.deviceId, displayName: newDisplayName)); store.dispatch(resetInteractiveAuth()); Navigator.of(dialogContext).pop(); }, diff --git a/lib/views/home/settings/settings-notifications-screen.dart b/lib/views/home/settings/settings-notifications-screen.dart index b74811f8d..b671df5e1 100644 --- a/lib/views/home/settings/settings-notifications-screen.dart +++ b/lib/views/home/settings/settings-notifications-screen.dart @@ -1,14 +1,10 @@ import 'dart:io'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - import 'package:equatable/equatable.dart'; - +import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:redux/redux.dart'; import 'package:syphon/global/algos.dart'; - import 'package:syphon/global/dimensions.dart'; import 'package:syphon/global/notifications.dart'; import 'package:syphon/global/strings.dart'; @@ -34,8 +30,7 @@ class NotificationSettingsScreen extends StatelessWidget { } } - onConfirmNotifications( - {required BuildContext context, required _Props props}) async { + onConfirmNotifications({required BuildContext context, required _Props props}) async { // If the platform is iOS, we'll want to confirm they // understand the native notification prompt first if (Platform.isIOS && !props.notificationsEnabled) { @@ -77,8 +72,7 @@ class NotificationSettingsScreen extends StatelessWidget { break; case StyleType.Itemized: default: - styleTypeDescription = - 'A new notification will appear for every notification'; + styleTypeDescription = 'A new notification will appear for every notification'; break; } @@ -87,9 +81,7 @@ class NotificationSettingsScreen extends StatelessWidget { body: Column( children: [ Visibility( - visible: Platform.isAndroid || - Platform.isMacOS || - Platform.isLinux, + visible: Platform.isAndroid || Platform.isMacOS || Platform.isLinux, child: CardSection( child: Column(children: [ Container( @@ -107,16 +99,12 @@ class NotificationSettingsScreen extends StatelessWidget { child: RichText( textAlign: TextAlign.left, text: TextSpan( - text: - 'Show notifications using a background service', + text: 'Show notifications using a background service', style: Theme.of(context).textTheme.caption, children: [ TextSpan( text: ' without ', - style: Theme.of(context) - .textTheme - .caption! - .copyWith( + style: Theme.of(context).textTheme.caption!.copyWith( fontWeight: FontWeight.w500, ), ), @@ -169,8 +157,7 @@ class NotificationSettingsScreen extends StatelessWidget { ListTile( enabled: Platform.isIOS, dense: true, - onTap: () => onConfirmNotifications( - context: context, props: props), + onTap: () => onConfirmNotifications(context: context, props: props), contentPadding: Dimensions.listPadding, title: Text( 'Notifications', @@ -180,8 +167,7 @@ class NotificationSettingsScreen extends StatelessWidget { value: props.remoteNotificationsEnabled, onChanged: !Platform.isIOS ? null - : (value) => onConfirmNotifications( - context: context, props: props), + : (value) => onConfirmNotifications(context: context, props: props), ), ), ListTile( @@ -295,16 +281,14 @@ class _Props extends Equatable { ) => _Props( // will not always be platform dependent - localNotificationsEnabled: Platform.isAndroid && - store.state.settingsStore.notificationSettings.enabled, - remoteNotificationsEnabled: Platform.isIOS && - store.state.settingsStore.notificationSettings.enabled, - notificationsEnabled: - store.state.settingsStore.notificationSettings.enabled, + localNotificationsEnabled: + Platform.isAndroid && store.state.settingsStore.notificationSettings.enabled, + remoteNotificationsEnabled: + Platform.isIOS && store.state.settingsStore.notificationSettings.enabled, + notificationsEnabled: store.state.settingsStore.notificationSettings.enabled, styleType: store.state.settingsStore.notificationSettings.styleType, toggleType: store.state.settingsStore.notificationSettings.toggleType, - httpPusherEnabled: - store.state.settingsStore.notificationSettings.pushers.isNotEmpty, + httpPusherEnabled: store.state.settingsStore.notificationSettings.pushers.isNotEmpty, onTogglePusher: () async { // await store.dispatch(fetchNotificationPushers()); store.dispatch(fetchNotifications()); diff --git a/lib/views/home/settings/settings-proxy-screen.dart b/lib/views/home/settings/settings-proxy-screen.dart index e4b046409..55bd66b5e 100644 --- a/lib/views/home/settings/settings-proxy-screen.dart +++ b/lib/views/home/settings/settings-proxy-screen.dart @@ -1,5 +1,5 @@ import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_redux/flutter_redux.dart'; diff --git a/lib/views/home/settings/settings-storage-screen.dart b/lib/views/home/settings/settings-storage-screen.dart index f98cd4e3a..b1d38d337 100644 --- a/lib/views/home/settings/settings-storage-screen.dart +++ b/lib/views/home/settings/settings-storage-screen.dart @@ -1,10 +1,7 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:redux/redux.dart'; - import 'package:syphon/global/dimensions.dart'; import 'package:syphon/global/values.dart'; import 'package:syphon/store/crypto/actions.dart'; @@ -75,7 +72,7 @@ class _Props extends Equatable { final Function onExportDeviceKey; final Function onImportDeviceKey; - _Props({ + const _Props({ required this.onExportDeviceKey, required this.onImportDeviceKey, }); diff --git a/lib/views/home/settings/settings-theme-screen.dart b/lib/views/home/settings/settings-theme-screen.dart index 52976c0ab..39163fedf 100644 --- a/lib/views/home/settings/settings-theme-screen.dart +++ b/lib/views/home/settings/settings-theme-screen.dart @@ -1,10 +1,7 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:redux/redux.dart'; - import 'package:syphon/global/colours.dart'; import 'package:syphon/global/dimensions.dart'; import 'package:syphon/global/strings.dart'; @@ -189,8 +186,7 @@ class _ThemeSettingsScreenState extends State { ), trailing: Switch( value: props.roomTypeBadgesEnabled, - onChanged: (value) => - props.onToggleRoomTypeBadges(), + onChanged: (value) => props.onToggleRoomTypeBadges(), activeColor: Color(props.primaryColor), ), onTap: () => props.onToggleRoomTypeBadges(), @@ -353,21 +349,15 @@ class _Props extends Equatable { primaryColor: store.state.settingsStore.themeSettings.primaryColor, accentColor: store.state.settingsStore.themeSettings.accentColor, appBarColor: store.state.settingsStore.themeSettings.appBarColor, - themeType: selectThemeTypeString( - store.state.settingsStore.themeSettings.themeType), + themeType: selectThemeTypeString(store.state.settingsStore.themeSettings.themeType), language: store.state.settingsStore.language, - fontName: selectFontNameString( - store.state.settingsStore.themeSettings.fontName), - fontSize: selectFontSizeString( - store.state.settingsStore.themeSettings.fontSize), - messageSize: selectMessageSizeString( - store.state.settingsStore.themeSettings.messageSize), - avatarShape: selectAvatarShapeString( - store.state.settingsStore.themeSettings.avatarShape), + fontName: selectFontNameString(store.state.settingsStore.themeSettings.fontName), + fontSize: selectFontSizeString(store.state.settingsStore.themeSettings.fontSize), + messageSize: selectMessageSizeString(store.state.settingsStore.themeSettings.messageSize), + avatarShape: selectAvatarShapeString(store.state.settingsStore.themeSettings.avatarShape), roomTypeBadgesEnabled: store.state.settingsStore.roomTypeBadgesEnabled, mainFabType: selectMainFabType(store.state.settingsStore.themeSettings), - mainFabLocation: - selectMainFabLocation(store.state.settingsStore.themeSettings), + mainFabLocation: selectMainFabLocation(store.state.settingsStore.themeSettings), onToggleRoomTypeBadges: () => store.dispatch( toggleRoomTypeBadges(), ), diff --git a/lib/views/home/settings/widgets/profile-preview.dart b/lib/views/home/settings/widgets/profile-preview.dart index e5a25e225..862270218 100644 --- a/lib/views/home/settings/widgets/profile-preview.dart +++ b/lib/views/home/settings/widgets/profile-preview.dart @@ -1,11 +1,8 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:redux/redux.dart'; import 'package:syphon/global/colours.dart'; - import 'package:syphon/global/dimensions.dart'; import 'package:syphon/store/index.dart'; import 'package:syphon/store/user/model.dart'; @@ -67,8 +64,7 @@ class ProfilePreview extends StatelessWidget { width: Dimensions.avatarSize, height: Dimensions.avatarSize, child: IconButton( - onPressed: () => - onModifyAccounts != null ? onModifyAccounts!() : null, + onPressed: () => onModifyAccounts != null ? onModifyAccounts!() : null, icon: Icon( Icons.more_horiz_rounded, color: Color(Colours.greyDefault), diff --git a/lib/views/intro/intro-screen.dart b/lib/views/intro/intro-screen.dart index 68bf69a44..b6c9f2214 100644 --- a/lib/views/intro/intro-screen.dart +++ b/lib/views/intro/intro-screen.dart @@ -1,6 +1,5 @@ import 'dart:io'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; @@ -70,9 +69,7 @@ class IntroScreenState extends State with Lifecycle { // TODO: decide on always showing alpha aggrement on intro if (alphaAgreement == null || true) { - final termsTitle = Platform.isIOS - ? Strings.titleDialogTerms - : Strings.titleDialogTermsAlpha; + final termsTitle = Platform.isIOS ? Strings.titleDialogTerms : Strings.titleDialogTermsAlpha; showDialog( context: context, @@ -149,8 +146,7 @@ class IntroScreenState extends State with Lifecycle { }, child: Text( Strings.buttonTextAgreement, - style: - TextStyle(color: Theme.of(context).primaryColor), + style: TextStyle(color: Theme.of(context).primaryColor), ), ), ), @@ -278,16 +274,14 @@ class IntroScreenState extends State with Lifecycle { dotWidth: 12, paintStyle: PaintingStyle.fill, strokeWidth: 12, - activeDotColor: - Theme.of(context).primaryColor, + activeDotColor: Theme.of(context).primaryColor, ), // your preferred effect ), ], ) : TouchableOpacity( activeOpacity: 0.4, - onTap: () => - Navigator.pushNamed(context, Routes.login), + onTap: () => Navigator.pushNamed(context, Routes.login), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -304,14 +298,9 @@ class IntroScreenState extends State with Lifecycle { child: Text( Strings.buttonTextLogin, textAlign: TextAlign.center, - style: Theme.of(context) - .textTheme - .bodyText2! - .copyWith( - color: - Theme.of(context).primaryColor, - decoration: - TextDecoration.underline, + style: Theme.of(context).textTheme.bodyText2!.copyWith( + color: Theme.of(context).primaryColor, + decoration: TextDecoration.underline, ), ), ), diff --git a/lib/views/intro/login/forgot/password-forgot-screen.dart b/lib/views/intro/login/forgot/password-forgot-screen.dart index ec527199b..c8b639114 100644 --- a/lib/views/intro/login/forgot/password-forgot-screen.dart +++ b/lib/views/intro/login/forgot/password-forgot-screen.dart @@ -1,5 +1,5 @@ import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_redux/flutter_redux.dart'; @@ -89,10 +89,8 @@ class ForgotPasswordState extends State { behavior: DefaultScrollBehavior(), child: SingleChildScrollView( child: Container( - width: - width, // set actual height and width for flex constraints - height: - height, // set actual height and width for flex constraints + width: width, // set actual height and width for flex constraints + height: height, // set actual height and width for flex constraints child: Flex( direction: Axis.vertical, mainAxisAlignment: MainAxisAlignment.center, @@ -140,15 +138,13 @@ class ForgotPasswordState extends State { child: ButtonSolid( text: Strings.buttonSendVerification, loading: loading, - disabled: !props.isEmailValid || - !props.isHomeserverValid, + disabled: !props.isEmailValid || !props.isHomeserverValid, onPressed: () async { setState(() { loading = true; }); - final result = await props - .onSendVerification(sendAttempt); + final result = await props.onSendVerification(sendAttempt); if (result) { onShowConfirmDialog(); @@ -175,8 +171,7 @@ class ForgotPasswordState extends State { loading = true; }); - final result = - await props.onConfirmVerification(); + final result = await props.onConfirmVerification(); if (result) { onVerificationConfirmed(); diff --git a/lib/views/intro/login/forgot/password-reset-screen.dart b/lib/views/intro/login/forgot/password-reset-screen.dart index 4f34336c9..6f4d4eb59 100644 --- a/lib/views/intro/login/forgot/password-reset-screen.dart +++ b/lib/views/intro/login/forgot/password-reset-screen.dart @@ -1,5 +1,5 @@ import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:redux/redux.dart'; @@ -71,10 +71,8 @@ class PasswordResetState extends State { behavior: DefaultScrollBehavior(), child: SingleChildScrollView( child: Container( - width: - width, // set actual height and width for flex constraints - height: - height, // set actual height and width for flex constraints + width: width, // set actual height and width for flex constraints + height: height, // set actual height and width for flex constraints child: Flex( direction: Axis.vertical, mainAxisAlignment: MainAxisAlignment.center, @@ -101,8 +99,7 @@ class PasswordResetState extends State { onPageChanged: (index) { setState(() { currentStep = index; - onboarding = index != 0 && - index != sections.length - 1; + onboarding = index != 0 && index != sections.length - 1; }); }, children: sections, @@ -127,8 +124,7 @@ class PasswordResetState extends State { child: ButtonSolid( text: Strings.buttonResetPassword, loading: props.loading, - disabled: - !props.isPasswordValid || props.loading, + disabled: !props.isPasswordValid || props.loading, onPressed: () async { final result = await props.onResetPassword(); diff --git a/lib/views/intro/login/forgot/widgets/PageEmailVerify.dart b/lib/views/intro/login/forgot/widgets/PageEmailVerify.dart index 44e85b776..ab8343158 100644 --- a/lib/views/intro/login/forgot/widgets/PageEmailVerify.dart +++ b/lib/views/intro/login/forgot/widgets/PageEmailVerify.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -326,7 +326,8 @@ class _Props extends Equatable { loading: store.state.authStore.loading, isEmailValid: store.state.authStore.isEmailValid, isHomeserverValid: store.state.authStore.homeserver.valid, - session: store.state.authStore.authSession != null && store.state.authStore.authSession!.isNotEmpty, + session: store.state.authStore.authSession != null && + store.state.authStore.authSession!.isNotEmpty, onSetEmail: (email) { return store.dispatch(setEmail(email: email)); }, diff --git a/lib/views/intro/login/forgot/widgets/PagePasswordReset.dart b/lib/views/intro/login/forgot/widgets/PagePasswordReset.dart index 9aa5538d0..a15cb4d36 100644 --- a/lib/views/intro/login/forgot/widgets/PagePasswordReset.dart +++ b/lib/views/intro/login/forgot/widgets/PagePasswordReset.dart @@ -1,11 +1,8 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:redux/redux.dart'; - import 'package:syphon/global/assets.dart'; import 'package:syphon/global/dimensions.dart'; import 'package:syphon/global/strings.dart'; @@ -16,11 +13,12 @@ import 'package:syphon/views/widgets/input/text-field-secure.dart'; class PasswordResetStep extends StatefulWidget { const PasswordResetStep({Key? key}) : super(key: key); + @override PasswordResetStepState createState() => PasswordResetStepState(); } class PasswordResetStepState extends State { - PasswordResetStepState({Key? key}); + PasswordResetStepState(); bool visibility = false; @@ -57,7 +55,7 @@ class PasswordResetStepState extends State { distinct: true, converter: (Store store) => _Props.mapStateToProps(store), builder: (context, props) { - double width = MediaQuery.of(context).size.width; + final double width = MediaQuery.of(context).size.width; return Column( mainAxisAlignment: MainAxisAlignment.end, @@ -74,8 +72,7 @@ class PasswordResetStepState extends State { ), child: SvgPicture.asset( Assets.heroSignupPassword, - semanticsLabel: - 'User thinking up a password in a swirl of wind', + semanticsLabel: 'User thinking up a password in a swirl of wind', ), ), ), diff --git a/lib/views/intro/login/login-screen.dart b/lib/views/intro/login/login-screen.dart index 62af7d1b9..d45a3b1ae 100644 --- a/lib/views/intro/login/login-screen.dart +++ b/lib/views/intro/login/login-screen.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'dart:math'; import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_redux/flutter_redux.dart'; @@ -361,7 +361,9 @@ class LoginScreenState extends State with Lifecycle { maxHeight: 180, ), child: SvgPicture.asset( - avatarHash % 2 == 0 ? Assets.heroAvatarFemale : Assets.heroAvatarMale, + avatarHash % 2 == 0 + ? Assets.heroAvatarFemale + : Assets.heroAvatarMale, width: width * 0.35, height: width * 0.35, ), @@ -437,30 +439,35 @@ class LoginScreenState extends State with Lifecycle { child: ButtonSolid( text: Strings.buttonLogin, loading: props.loading && currentAuthType == AuthTypes.Password, - disabled: !props.isPasswordLoginAttemptable || currentAuthType != null, + disabled: !props.isPasswordLoginAttemptable || + currentAuthType != null, onPressed: () => onLoginPassword(props), ), ), Visibility( - visible: props.isSSOLoginAvailable && !props.isPasswordLoginAvailable, + visible: + props.isSSOLoginAvailable && !props.isPasswordLoginAvailable, child: Container( padding: const EdgeInsets.only(top: 12, bottom: 12), child: ButtonSolid( text: Strings.buttonLoginSSO, loading: props.loading && currentAuthType == AuthTypes.SSO, - disabled: !props.isSSOLoginAttemptable || currentAuthType != null, + disabled: + !props.isSSOLoginAttemptable || currentAuthType != null, onPressed: () => onLoginSSO(props), ), ), ), Visibility( - visible: props.isSSOLoginAvailable && props.isPasswordLoginAvailable, + visible: + props.isSSOLoginAvailable && props.isPasswordLoginAvailable, child: Container( padding: const EdgeInsets.only(top: 12, bottom: 12), child: ButtonText( text: Strings.buttonLoginSSO, loading: props.loading && currentAuthType == AuthTypes.SSO, - disabled: !props.isSSOLoginAttemptable || currentAuthType != null, + disabled: + !props.isSSOLoginAttemptable || currentAuthType != null, onPressed: () => onLoginSSO(props), ), ), @@ -606,10 +613,12 @@ class _Props extends Equatable { await store.dispatch(selectHomeserver(hostname: hostname)); final _homeserver = store.state.authStore.homeserver; - if (_homeserver.signupTypes.isEmpty && !_homeserver.loginTypes.contains(MatrixAuthTypes.SSO)) { + if (_homeserver.signupTypes.isEmpty && + !_homeserver.loginTypes.contains(MatrixAuthTypes.SSO)) { store.dispatch(addInfo( origin: 'selectHomeserver', - message: 'No new signups allowed on this server, try another if creating an account', + message: + 'No new signups allowed on this server, try another if creating an account', )); } } diff --git a/lib/views/intro/search/search-homeserver-screen.dart b/lib/views/intro/search/search-homeserver-screen.dart index 1af948fdb..6b494ab6f 100644 --- a/lib/views/intro/search/search-homeserver-screen.dart +++ b/lib/views/intro/search/search-homeserver-screen.dart @@ -1,6 +1,6 @@ import 'package:equatable/equatable.dart'; import 'package:expandable/expandable.dart'; -import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:redux/redux.dart'; @@ -76,7 +76,9 @@ class SearchHomeserverScreenState extends State converter: (Store store) => _Props.mapStateToProps( store, // ignore: cast_nullable_to_non_nullable - signup: (ModalRoute.of(context)!.settings.arguments as SearchHomeserverArguments?)?.signup ?? false, + signup: + (ModalRoute.of(context)!.settings.arguments as SearchHomeserverArguments?)?.signup ?? + false, ), builder: (context, props) => Scaffold( appBar: AppBarSearch( @@ -220,8 +222,9 @@ class SearchHomeserverScreenState extends State ), ), Visibility( - visible: - props.searchText.isNotEmpty && props.searchText.isNotEmpty && props.homeservers.isEmpty, + visible: props.searchText.isNotEmpty && + props.searchText.isNotEmpty && + props.homeservers.isEmpty, child: Container( padding: EdgeInsets.only(top: 8, bottom: 8), child: GestureDetector( diff --git a/lib/views/intro/signup/signup-screen.dart b/lib/views/intro/signup/signup-screen.dart index 1b7bf04cb..f923aaa51 100644 --- a/lib/views/intro/signup/signup-screen.dart +++ b/lib/views/intro/signup/signup-screen.dart @@ -1,5 +1,5 @@ import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:redux/redux.dart'; @@ -142,7 +142,8 @@ class SignupScreenState extends State with Lifecycle onDidChange(_Props? oldProps, _Props props) { final ssoLoginChanged = props.isSSOLoginAvailable != oldProps?.isSSOLoginAvailable; - final passwordLoginChanged = props.isPasswordLoginAvailable != oldProps?.isPasswordLoginAvailable; + final passwordLoginChanged = + props.isPasswordLoginAvailable != oldProps?.isPasswordLoginAvailable; final signupTypesChanged = props.homeserver.signupTypes != oldProps?.homeserver.signupTypes; @@ -210,7 +211,8 @@ class SignupScreenState extends State with Lifecycle } final _homeserver = store.state.authStore.homeserver; - if (_homeserver.signupTypes.isEmpty && !_homeserver.loginTypes.contains(MatrixAuthTypes.SSO)) { + if (_homeserver.signupTypes.isEmpty && + !_homeserver.loginTypes.contains(MatrixAuthTypes.SSO)) { store.dispatch(addInfo( origin: 'selectHomeserver', message: 'No new signups allowed on this server, try another if creating an account', @@ -311,7 +313,8 @@ class SignupScreenState extends State with Lifecycle @override Widget build(BuildContext context) => StoreConnector( distinct: true, - onWillChange: onDidChange, // NOTE: bug / issue where onDidChange doesn't show correct oldProps + onWillChange: + onDidChange, // NOTE: bug / issue where onDidChange doesn't show correct oldProps converter: (Store store) => _Props.mapStateToProps(store), builder: (context, props) { final double width = MediaQuery.of(context).size.width; @@ -381,7 +384,8 @@ class SignupScreenState extends State with Lifecycle direction: Axis.vertical, children: [ Visibility( - visible: !(!props.isPasswordLoginAvailable && props.isSSOLoginAvailable), + visible: + !(!props.isPasswordLoginAvailable && props.isSSOLoginAvailable), child: Container( padding: const EdgeInsets.only(top: 12, bottom: 12), child: ButtonSolid( diff --git a/lib/views/intro/signup/verification-screen.dart b/lib/views/intro/signup/verification-screen.dart index a3f59f55d..65b5cef96 100644 --- a/lib/views/intro/signup/verification-screen.dart +++ b/lib/views/intro/signup/verification-screen.dart @@ -1,17 +1,14 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_svg/svg.dart'; import 'package:redux/redux.dart'; - import 'package:syphon/global/assets.dart'; -import 'package:syphon/global/strings.dart'; -import 'package:syphon/views/behaviors.dart'; import 'package:syphon/global/dimensions.dart'; +import 'package:syphon/global/strings.dart'; import 'package:syphon/store/auth/actions.dart'; import 'package:syphon/store/index.dart'; +import 'package:syphon/views/behaviors.dart'; import 'package:syphon/views/widgets/buttons/button-solid.dart'; import 'package:syphon/views/widgets/buttons/button-text.dart'; import 'package:syphon/views/widgets/dialogs/dialog-explaination.dart'; @@ -23,8 +20,7 @@ class VerificationScreen extends StatefulWidget { VerificationScreenState createState() => VerificationScreenState(); } -class VerificationScreenState extends State - with WidgetsBindingObserver { +class VerificationScreenState extends State with WidgetsBindingObserver { late bool sending; bool? success; @@ -118,7 +114,7 @@ class VerificationScreenState extends State ), ), Stack( - overflow: Overflow.visible, + clipBehavior: Clip.none, children: [ Container( padding: EdgeInsets.symmetric( @@ -128,8 +124,7 @@ class VerificationScreenState extends State child: Text( 'Verify your email address', textAlign: TextAlign.center, - style: - Theme.of(context).textTheme.headline5, + style: Theme.of(context).textTheme.headline5, ), ), Positioned( @@ -139,12 +134,9 @@ class VerificationScreenState extends State onTap: () { showDialog( context: context, - builder: (BuildContext context) => - DialogExplaination( - title: Strings - .titleDialogSignupEmailVerification, - content: Strings - .contentEmailVerification, + builder: (BuildContext context) => DialogExplaination( + title: Strings.titleDialogSignupEmailVerification, + content: Strings.contentEmailVerification, onConfirm: () { Navigator.pop(context); }, @@ -156,9 +148,7 @@ class VerificationScreenState extends State width: 20, child: Icon( Icons.info_outline, - color: Theme.of(context) - .colorScheme - .secondary, + color: Theme.of(context).colorScheme.secondary, size: 20, ), ), @@ -187,8 +177,7 @@ class VerificationScreenState extends State loading: sending || props.loading, disabled: sending || props.loading, onPressed: () async { - final result = await props.onCreateUser( - enableErrors: true); + final result = await props.onCreateUser(enableErrors: true); setState(() { success = result; }); diff --git a/lib/views/intro/signup/widgets/StepCaptcha.dart b/lib/views/intro/signup/widgets/StepCaptcha.dart index 471fd09cb..666f29a31 100644 --- a/lib/views/intro/signup/widgets/StepCaptcha.dart +++ b/lib/views/intro/signup/widgets/StepCaptcha.dart @@ -1,15 +1,11 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:redux/redux.dart'; - import 'package:syphon/global/assets.dart'; import 'package:syphon/global/colours.dart'; import 'package:syphon/global/dimensions.dart'; - import 'package:syphon/global/strings.dart'; import 'package:syphon/store/index.dart'; import 'package:syphon/views/widgets/buttons/button-text.dart'; diff --git a/lib/views/intro/signup/widgets/StepEmail.dart b/lib/views/intro/signup/widgets/StepEmail.dart index 1b15f985f..10b10c40f 100644 --- a/lib/views/intro/signup/widgets/StepEmail.dart +++ b/lib/views/intro/signup/widgets/StepEmail.dart @@ -1,18 +1,14 @@ import 'dart:async'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:redux/redux.dart'; - import 'package:syphon/global/assets.dart'; import 'package:syphon/global/dimensions.dart'; import 'package:syphon/global/libs/matrix/auth.dart'; import 'package:syphon/global/strings.dart'; - import 'package:syphon/store/auth/actions.dart'; import 'package:syphon/store/index.dart'; import 'package:syphon/views/widgets/dialogs/dialog-explaination.dart'; @@ -25,11 +21,12 @@ import 'package:syphon/views/widgets/input/text-field-secure.dart'; class EmailStep extends StatefulWidget { const EmailStep({Key? key}) : super(key: key); + @override EmailStepState createState() => EmailStepState(); } class EmailStepState extends State { - EmailStepState({Key? key}); + EmailStepState(); Timer? typingTimeout; final emailController = TextEditingController(); @@ -61,7 +58,7 @@ class EmailStepState extends State { ), ); - if (!props.loading && this.typingTimeout == null) { + if (!props.loading && typingTimeout == null) { if (props.isEmailValid && props.isEmailAvailable) { suffixWidget = Icon( Icons.check, @@ -135,8 +132,7 @@ class EmailStepState extends State { onTap: () { showDialog( context: context, - builder: (BuildContext context) => - DialogExplaination( + builder: (BuildContext context) => DialogExplaination( title: Strings.titleEmailRequirement, content: Strings.contentEmailRequirement, onConfirm: () { @@ -227,7 +223,7 @@ class EmailStepState extends State { borderRadius: BorderRadius.circular(24), ), child: Container( - padding: EdgeInsets.all((6)), + padding: EdgeInsets.all(6), child: suffixWidget, ), ), diff --git a/lib/views/intro/signup/widgets/StepHomeserver.dart b/lib/views/intro/signup/widgets/StepHomeserver.dart index c64e8803c..13d162702 100644 --- a/lib/views/intro/signup/widgets/StepHomeserver.dart +++ b/lib/views/intro/signup/widgets/StepHomeserver.dart @@ -1,5 +1,5 @@ import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_svg/flutter_svg.dart'; diff --git a/lib/views/intro/signup/widgets/StepPassword.dart b/lib/views/intro/signup/widgets/StepPassword.dart index 7d0e4bdef..78e5fa943 100644 --- a/lib/views/intro/signup/widgets/StepPassword.dart +++ b/lib/views/intro/signup/widgets/StepPassword.dart @@ -1,11 +1,8 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:redux/redux.dart'; - import 'package:syphon/global/assets.dart'; import 'package:syphon/global/dimensions.dart'; import 'package:syphon/global/strings.dart'; @@ -17,6 +14,7 @@ import 'package:syphon/views/widgets/input/text-field-secure.dart'; class PasswordStep extends StatefulWidget { const PasswordStep({Key? key}) : super(key: key); + @override PasswordStepState createState() => PasswordStepState(); } @@ -88,8 +86,7 @@ class PasswordStepState extends State { ), child: SvgPicture.asset( Assets.heroSignupPassword, - semanticsLabel: - 'User thinking up a password in a swirl of wind', + semanticsLabel: 'User thinking up a password in a swirl of wind', ), ), ), diff --git a/lib/views/intro/signup/widgets/StepUsername.dart b/lib/views/intro/signup/widgets/StepUsername.dart index 51413fc7a..276979375 100644 --- a/lib/views/intro/signup/widgets/StepUsername.dart +++ b/lib/views/intro/signup/widgets/StepUsername.dart @@ -1,13 +1,10 @@ import 'dart:async'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:redux/redux.dart'; - import 'package:syphon/global/assets.dart'; import 'package:syphon/global/dimensions.dart'; import 'package:syphon/global/strings.dart'; @@ -23,11 +20,12 @@ import 'package:syphon/views/widgets/input/text-field-secure.dart'; class UsernameStep extends StatefulWidget { const UsernameStep({Key? key}) : super(key: key); + @override UsernameStepState createState() => UsernameStepState(); } class UsernameStepState extends State { - UsernameStepState({Key? key}); + UsernameStepState(); Timer? typingTimeout; final usernameController = TextEditingController(); @@ -120,8 +118,7 @@ class UsernameStepState extends State { maxWidth: Dimensions.inputWidthMax, ), child: TextFieldSecure( - label: - props.isUsernameValid ? props.fullUserId : 'Username', + label: props.isUsernameValid ? props.fullUserId : 'Username', disableSpacing: true, valid: props.isUsernameValid, controller: usernameController, @@ -167,7 +164,7 @@ class UsernameStepState extends State { borderRadius: BorderRadius.circular(24), ), child: Container( - padding: EdgeInsets.all((6)), + padding: EdgeInsets.all(6), child: suffixWidget, ), ), diff --git a/lib/views/intro/widgets/page-action.dart b/lib/views/intro/widgets/page-action.dart index e40a0adbd..8086b45b5 100644 --- a/lib/views/intro/widgets/page-action.dart +++ b/lib/views/intro/widgets/page-action.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; diff --git a/lib/views/intro/widgets/page-description-first.dart b/lib/views/intro/widgets/page-description-first.dart index 52fc5e3fd..2d43dda74 100644 --- a/lib/views/intro/widgets/page-description-first.dart +++ b/lib/views/intro/widgets/page-description-first.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -45,7 +44,7 @@ class FirstDescriptionPage extends StatelessWidget { text: TextSpan( text: Strings.contentIntroFirstPartOne, style: Theme.of(context).textTheme.subtitle1, - children: [ + children: const [ TextSpan( text: 'Matrix', style: TextStyle( diff --git a/lib/views/intro/widgets/page-description-second.dart b/lib/views/intro/widgets/page-description-second.dart index 73d240e71..46216d4be 100644 --- a/lib/views/intro/widgets/page-description-second.dart +++ b/lib/views/intro/widgets/page-description-second.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; diff --git a/lib/views/intro/widgets/page-description-third.dart b/lib/views/intro/widgets/page-description-third.dart index 89de412ff..18144ce56 100644 --- a/lib/views/intro/widgets/page-description-third.dart +++ b/lib/views/intro/widgets/page-description-third.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; diff --git a/lib/views/intro/widgets/page-landing.dart b/lib/views/intro/widgets/page-landing.dart index 8dfececa6..05a84f9eb 100644 --- a/lib/views/intro/widgets/page-landing.dart +++ b/lib/views/intro/widgets/page-landing.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; diff --git a/lib/views/widgets/appbars/appbar-avatar.dart b/lib/views/widgets/appbars/appbar-avatar.dart index 64c30d241..4cdea50b9 100644 --- a/lib/views/widgets/appbars/appbar-avatar.dart +++ b/lib/views/widgets/appbars/appbar-avatar.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:syphon/global/dimensions.dart'; diff --git a/lib/views/widgets/appbars/appbar-normal.dart b/lib/views/widgets/appbars/appbar-normal.dart index b344e1343..3474f2d80 100644 --- a/lib/views/widgets/appbars/appbar-normal.dart +++ b/lib/views/widgets/appbars/appbar-normal.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:syphon/global/strings.dart'; diff --git a/lib/views/widgets/appbars/appbar-search.dart b/lib/views/widgets/appbars/appbar-search.dart index 2193c9396..8d4506b0b 100644 --- a/lib/views/widgets/appbars/appbar-search.dart +++ b/lib/views/widgets/appbars/appbar-search.dart @@ -1,6 +1,5 @@ import 'dart:async'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:syphon/global/strings.dart'; import 'package:syphon/views/widgets/lifecycle.dart'; @@ -50,8 +49,7 @@ class AppBarSearch extends StatefulWidget implements PreferredSizeWidget { Size get preferredSize => AppBar().preferredSize; } -class AppBarSearchState extends State - with Lifecycle { +class AppBarSearchState extends State with Lifecycle { final focusNode = FocusNode(); bool searching = false; diff --git a/lib/views/widgets/avatars/avatar-badge.dart b/lib/views/widgets/avatars/avatar-badge.dart index ec4f075a0..4bf4661d0 100644 --- a/lib/views/widgets/avatars/avatar-badge.dart +++ b/lib/views/widgets/avatars/avatar-badge.dart @@ -1,5 +1,5 @@ import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:redux/redux.dart'; diff --git a/lib/views/widgets/avatars/avatar.dart b/lib/views/widgets/avatars/avatar.dart index 4216c08dc..c982f1190 100644 --- a/lib/views/widgets/avatars/avatar.dart +++ b/lib/views/widgets/avatars/avatar.dart @@ -1,7 +1,7 @@ import 'dart:io'; import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:redux/redux.dart'; @@ -57,7 +57,8 @@ class Avatar extends StatelessWidget { builder: (context, props) { // TODO: uri is parsed as an empty string under dendrite final bool emptyAvi = uri == null && url == null || (uri?.isEmpty ?? true); - final Color backgroundColor = !emptyAvi || force ? Colors.transparent : background ?? Colors.grey; + final Color backgroundColor = + !emptyAvi || force ? Colors.transparent : background ?? Colors.grey; var borderRadius = BorderRadius.circular(size); diff --git a/lib/views/widgets/buttons/button-outline.dart b/lib/views/widgets/buttons/button-outline.dart index 48a6bb99f..9bc77c4cb 100644 --- a/lib/views/widgets/buttons/button-outline.dart +++ b/lib/views/widgets/buttons/button-outline.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:syphon/global/colours.dart'; @@ -44,10 +43,9 @@ class ButtonOutline extends StatelessWidget { child: TextButton( style: ButtonStyle( foregroundColor: MaterialStateProperty.resolveWith( - (Set states) => - states.contains(MaterialState.disabled) - ? Color(Colours.greyLight) - : Theme.of(context).primaryColor, + (Set states) => states.contains(MaterialState.disabled) + ? Color(Colours.greyLight) + : Theme.of(context).primaryColor, ), backgroundColor: MaterialStateProperty.resolveWith( (Set states) => @@ -70,9 +68,7 @@ class ButtonOutline extends StatelessWidget { fontSize: 20, fontWeight: FontWeight.w100, letterSpacing: 0.8, - color: disabled - ? Color(Colours.greyLight) - : Theme.of(context).primaryColor, + color: disabled ? Color(Colours.greyLight) : Theme.of(context).primaryColor, ), )), ), diff --git a/lib/views/widgets/buttons/button-solid.dart b/lib/views/widgets/buttons/button-solid.dart index d9c81f7f7..2cbfd4745 100644 --- a/lib/views/widgets/buttons/button-solid.dart +++ b/lib/views/widgets/buttons/button-solid.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:syphon/global/colours.dart'; @@ -36,16 +35,14 @@ class ButtonSolid extends StatelessWidget { child: TextButton( style: ButtonStyle( foregroundColor: MaterialStateProperty.resolveWith( - (Set states) => - states.contains(MaterialState.disabled) - ? Color(Colours.greyLight) - : Theme.of(context).primaryColor, + (Set states) => states.contains(MaterialState.disabled) + ? Color(Colours.greyLight) + : Theme.of(context).primaryColor, ), backgroundColor: MaterialStateProperty.resolveWith( - (Set states) => - states.contains(MaterialState.disabled) - ? Colors.grey - : Theme.of(context).primaryColor, + (Set states) => states.contains(MaterialState.disabled) + ? Colors.grey + : Theme.of(context).primaryColor, ), shape: MaterialStateProperty.resolveWith( (Set states) => RoundedRectangleBorder( @@ -64,8 +61,7 @@ class ButtonSolid extends StatelessWidget { fontSize: 20, fontWeight: FontWeight.w100, letterSpacing: 0.8, - color: - disabled ? Color(Colours.greyLight) : Colors.white, + color: disabled ? Color(Colours.greyLight) : Colors.white, ), )), ), diff --git a/lib/views/widgets/buttons/button-text-opacity.dart b/lib/views/widgets/buttons/button-text-opacity.dart index 6c3d61d29..bbae16902 100644 --- a/lib/views/widgets/buttons/button-text-opacity.dart +++ b/lib/views/widgets/buttons/button-text-opacity.dart @@ -1,11 +1,10 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:syphon/global/colours.dart'; import 'package:syphon/global/dimensions.dart'; class ButtonTextOpacity extends StatefulWidget { - ButtonTextOpacity({ + const ButtonTextOpacity({ Key? key, this.text, this.textWidget, diff --git a/lib/views/widgets/captcha.dart b/lib/views/widgets/captcha.dart index b82f4e53c..4e990418b 100644 --- a/lib/views/widgets/captcha.dart +++ b/lib/views/widgets/captcha.dart @@ -1,14 +1,11 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:syphon/global/assets.dart'; +import 'package:syphon/global/values.dart'; import 'package:syphon/views/widgets/lifecycle.dart'; import 'package:syphon/views/widgets/loader/loading-indicator.dart'; - import 'package:webview_flutter/webview_flutter.dart'; -import 'package:syphon/global/values.dart'; - /* * Captcha * renders the captcha needed to be completed @@ -55,9 +52,7 @@ class CaptchaState extends State with Lifecycle { return Stack( children: [ WebView( - baseUrl: widget.baseUrl != null - ? 'https://${widget.baseUrl}' - : 'https://matrix.org', + baseUrl: widget.baseUrl != null ? 'https://${widget.baseUrl}' : 'https://matrix.org', javascriptMode: JavascriptMode.unrestricted, javascriptChannels: { JavascriptChannel( diff --git a/lib/views/widgets/containers/card-section.dart b/lib/views/widgets/containers/card-section.dart index a61e5e3bd..715f05706 100644 --- a/lib/views/widgets/containers/card-section.dart +++ b/lib/views/widgets/containers/card-section.dart @@ -1,5 +1,5 @@ import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:redux/redux.dart'; diff --git a/lib/views/widgets/containers/fabs/fab-bar-expanding.dart b/lib/views/widgets/containers/fabs/fab-bar-expanding.dart index 9f6eb48e5..c67b2a722 100644 --- a/lib/views/widgets/containers/fabs/fab-bar-expanding.dart +++ b/lib/views/widgets/containers/fabs/fab-bar-expanding.dart @@ -1,13 +1,10 @@ -import 'package:flutter/foundation.dart'; +import 'package:equatable/equatable.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; - -import 'package:equatable/equatable.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_speed_dial/flutter_speed_dial.dart'; import 'package:flutter_svg/svg.dart'; import 'package:redux/redux.dart'; - import 'package:syphon/global/assets.dart'; import 'package:syphon/global/dimensions.dart'; import 'package:syphon/store/index.dart'; @@ -123,7 +120,6 @@ class _Props extends Equatable { ]; static _Props mapStateToProps(Store store) => _Props( - primaryColor: - selectPrimaryColor(store.state.settingsStore.themeSettings), + primaryColor: selectPrimaryColor(store.state.settingsStore.themeSettings), ); } diff --git a/lib/views/widgets/containers/fabs/fab-ring.dart b/lib/views/widgets/containers/fabs/fab-ring.dart index 4da14c12e..7e265db26 100644 --- a/lib/views/widgets/containers/fabs/fab-ring.dart +++ b/lib/views/widgets/containers/fabs/fab-ring.dart @@ -1,13 +1,10 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; - import 'package:equatable/equatable.dart'; import 'package:fab_circular_menu/fab_circular_menu.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_svg/svg.dart'; import 'package:redux/redux.dart'; - import 'package:syphon/global/assets.dart'; import 'package:syphon/global/dimensions.dart'; import 'package:syphon/store/index.dart'; @@ -139,7 +136,6 @@ class _Props extends Equatable { ]; static _Props mapStateToProps(Store store) => _Props( - primaryColor: - selectPrimaryColor(store.state.settingsStore.themeSettings), + primaryColor: selectPrimaryColor(store.state.settingsStore.themeSettings), ); } diff --git a/lib/views/widgets/containers/media-card.dart b/lib/views/widgets/containers/media-card.dart index e941086a6..360915ca1 100644 --- a/lib/views/widgets/containers/media-card.dart +++ b/lib/views/widgets/containers/media-card.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:syphon/global/colours.dart'; diff --git a/lib/views/widgets/containers/menu-rounded.dart b/lib/views/widgets/containers/menu-rounded.dart index 7dfa7f25a..3a3083d89 100644 --- a/lib/views/widgets/containers/menu-rounded.dart +++ b/lib/views/widgets/containers/menu-rounded.dart @@ -1,11 +1,8 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -/** - * RoundedPopupMenu - * Mostly an example for myself on how to override styling or other options on - * existing components app wide - */ +/// RoundedPopupMenu +/// Mostly an example for myself on how to override styling or other options on +/// existing components app wide class RoundedPopupMenu extends StatelessWidget { const RoundedPopupMenu({ Key? key, diff --git a/lib/views/widgets/dialogs/dialog-captcha.dart b/lib/views/widgets/dialogs/dialog-captcha.dart index 8ae7bc2a7..9d2e7a0d9 100644 --- a/lib/views/widgets/dialogs/dialog-captcha.dart +++ b/lib/views/widgets/dialogs/dialog-captcha.dart @@ -1,10 +1,7 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:redux/redux.dart'; - import 'package:syphon/global/dimensions.dart'; import 'package:syphon/global/libs/matrix/auth.dart'; import 'package:syphon/global/strings.dart'; @@ -61,8 +58,7 @@ class DialogCaptcha extends StatelessWidget { child: Captcha( baseUrl: props.hostname, publicKey: props.publicKey, - onVerified: (token) => - props.onCompleteCaptcha(token, context: context), + onVerified: (token) => props.onCompleteCaptcha(token, context: context), ), ), ), @@ -111,12 +107,11 @@ class Props extends Equatable { hostname: store.state.authStore.hostname, completed: store.state.authStore.captcha, publicKey: () { - return store.state.authStore.interactiveAuths['params'] - [MatrixAuthTypes.RECAPTCHA]['public_key'] ?? + return store.state.authStore.interactiveAuths['params'][MatrixAuthTypes.RECAPTCHA] + ['public_key'] ?? ''; }(), - onCompleteCaptcha: (String token, - {required BuildContext context}) async { + onCompleteCaptcha: (String token, {required BuildContext context}) async { await store.dispatch(updateCredential( type: MatrixAuthTypes.RECAPTCHA, value: token.toString(), diff --git a/lib/views/widgets/dialogs/dialog-color-picker.dart b/lib/views/widgets/dialogs/dialog-color-picker.dart index ac99f56a2..c38a8f6dd 100644 --- a/lib/views/widgets/dialogs/dialog-color-picker.dart +++ b/lib/views/widgets/dialogs/dialog-color-picker.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_colorpicker/flutter_colorpicker.dart'; @@ -115,8 +114,7 @@ class _DialogColorPickerState extends State { dialogHeight = height / 1.80; } - const optionsPadding = - EdgeInsets.symmetric(vertical: 8.0, horizontal: 20.0); + const optionsPadding = EdgeInsets.symmetric(vertical: 8.0, horizontal: 20.0); final options = [ SimpleDialogOption( @@ -194,9 +192,7 @@ class _DialogColorPickerState extends State { constraints: !widget.advanced ? null : BoxConstraints(minHeight: 460), child: SingleChildScrollView( child: Column(children: [ - widget.advanced - ? buildAdvancedPicker(context) - : buildDefaultPicker(context), + if (widget.advanced) buildAdvancedPicker(context) else buildDefaultPicker(context), Visibility( visible: widget.advanced, child: TextField( diff --git a/lib/views/widgets/dialogs/dialog-confirm-password.dart b/lib/views/widgets/dialogs/dialog-confirm-password.dart index 93aae52a2..094d8c046 100644 --- a/lib/views/widgets/dialogs/dialog-confirm-password.dart +++ b/lib/views/widgets/dialogs/dialog-confirm-password.dart @@ -1,11 +1,8 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:redux/redux.dart'; import 'package:syphon/global/colours.dart'; - import 'package:syphon/global/dimensions.dart'; import 'package:syphon/global/strings.dart'; import 'package:syphon/store/auth/actions.dart'; diff --git a/lib/views/widgets/dialogs/dialog-confirm.dart b/lib/views/widgets/dialogs/dialog-confirm.dart index 664a542f6..62fe0c7a6 100644 --- a/lib/views/widgets/dialogs/dialog-confirm.dart +++ b/lib/views/widgets/dialogs/dialog-confirm.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:syphon/global/dimensions.dart'; @@ -58,11 +57,7 @@ class DialogConfirm extends StatelessWidget { onPressed: () => onDismiss!(), textWidget: Text( Strings.buttonCancel.capitalize(), - style: Theme.of(context) - .textTheme - .subtitle1 - ?.merge(dismissStyle) - .copyWith( + style: Theme.of(context).textTheme.subtitle1?.merge(dismissStyle).copyWith( fontWeight: FontWeight.w500, ), ), @@ -70,16 +65,15 @@ class DialogConfirm extends StatelessWidget { ButtonText( disabled: loading, onPressed: () => onConfirm!(), - textWidget: - Text(confirmText ?? Strings.buttonConfirm.capitalize(), - style: Theme.of(context) - .textTheme - .subtitle1 - ?.copyWith( - color: Theme.of(context).colorScheme.secondary, - fontWeight: FontWeight.w500, - ) - .merge(confirmStyle)), + textWidget: Text(confirmText ?? Strings.buttonConfirm.capitalize(), + style: Theme.of(context) + .textTheme + .subtitle1 + ?.copyWith( + color: Theme.of(context).colorScheme.secondary, + fontWeight: FontWeight.w500, + ) + .merge(confirmStyle)), ), ], ), diff --git a/lib/views/widgets/dialogs/dialog-explaination.dart b/lib/views/widgets/dialogs/dialog-explaination.dart index cd5d45497..8646f1c88 100644 --- a/lib/views/widgets/dialogs/dialog-explaination.dart +++ b/lib/views/widgets/dialogs/dialog-explaination.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:syphon/global/dimensions.dart'; diff --git a/lib/views/widgets/dialogs/dialog-invite-users.dart b/lib/views/widgets/dialogs/dialog-invite-users.dart index d45c0d0cf..5f323ad1a 100644 --- a/lib/views/widgets/dialogs/dialog-invite-users.dart +++ b/lib/views/widgets/dialogs/dialog-invite-users.dart @@ -1,12 +1,8 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:redux/redux.dart'; - import 'package:syphon/global/libs/matrix/auth.dart'; import 'package:syphon/global/strings.dart'; - import 'package:syphon/store/auth/actions.dart'; import 'package:syphon/store/index.dart'; import 'package:syphon/store/user/model.dart'; @@ -111,11 +107,10 @@ class Props extends Equatable { static Props mapStateToProps(Store store) => Props( completed: store.state.authStore.captcha, publicKey: () { - return store.state.authStore.interactiveAuths['params'] - [MatrixAuthTypes.RECAPTCHA]['public_key']; + return store.state.authStore.interactiveAuths['params'][MatrixAuthTypes.RECAPTCHA] + ['public_key']; }(), - onCompleteCaptcha: (String token, - {required BuildContext context}) async { + onCompleteCaptcha: (String token, {required BuildContext context}) async { await store.dispatch(updateCredential( type: MatrixAuthTypes.RECAPTCHA, value: token.toString(), diff --git a/lib/views/widgets/dialogs/dialog-rounded.dart b/lib/views/widgets/dialogs/dialog-rounded.dart index bd1e4372f..6188a9164 100644 --- a/lib/views/widgets/dialogs/dialog-rounded.dart +++ b/lib/views/widgets/dialogs/dialog-rounded.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; class DialogRounded extends StatefulWidget { diff --git a/lib/views/widgets/dialogs/dialog-start-chat.dart b/lib/views/widgets/dialogs/dialog-start-chat.dart index c61adb0c4..21559b67b 100644 --- a/lib/views/widgets/dialogs/dialog-start-chat.dart +++ b/lib/views/widgets/dialogs/dialog-start-chat.dart @@ -1,9 +1,6 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:redux/redux.dart'; - import 'package:syphon/global/libs/matrix/auth.dart'; import 'package:syphon/global/strings.dart'; import 'package:syphon/store/auth/actions.dart'; @@ -97,7 +94,7 @@ class Props extends Equatable { final Function onCompleteCaptcha; - Props({ + const Props({ required this.completed, required this.publicKey, required this.onCompleteCaptcha, @@ -106,11 +103,10 @@ class Props extends Equatable { static Props mapStateToProps(Store store) => Props( completed: store.state.authStore.captcha, publicKey: () { - return store.state.authStore.interactiveAuths['params'] - [MatrixAuthTypes.RECAPTCHA]['public_key']; + return store.state.authStore.interactiveAuths['params'][MatrixAuthTypes.RECAPTCHA] + ['public_key']; }(), - onCompleteCaptcha: (String token, - {required BuildContext context}) async { + onCompleteCaptcha: (String token, {required BuildContext context}) async { await store.dispatch(updateCredential( type: MatrixAuthTypes.RECAPTCHA, value: token.toString(), diff --git a/lib/views/widgets/dialogs/dialog-text-input.dart b/lib/views/widgets/dialogs/dialog-text-input.dart index 5c35e8930..6461cf28b 100644 --- a/lib/views/widgets/dialogs/dialog-text-input.dart +++ b/lib/views/widgets/dialogs/dialog-text-input.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; diff --git a/lib/views/widgets/image-matrix.dart b/lib/views/widgets/image-matrix.dart index 10d655742..659f01d9e 100644 --- a/lib/views/widgets/image-matrix.dart +++ b/lib/views/widgets/image-matrix.dart @@ -1,7 +1,7 @@ import 'dart:typed_data'; import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:redux/redux.dart'; diff --git a/lib/views/widgets/lists/list-item-account.dart b/lib/views/widgets/lists/list-item-account.dart index f864c284f..343e838b5 100644 --- a/lib/views/widgets/lists/list-item-account.dart +++ b/lib/views/widgets/lists/list-item-account.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:syphon/global/colours.dart'; @@ -41,8 +40,7 @@ class ListItemAccount extends StatelessWidget { final Function? onPress; final Function? onPressAvatar; - Widget buildTouchType( - {required BuildContext context, required Widget child}) { + Widget buildTouchType({required BuildContext context, required Widget child}) { switch (type) { case ListItemUserType.Pressable: return GestureDetector( @@ -51,9 +49,7 @@ class ListItemAccount extends StatelessWidget { ); case ListItemUserType.Selectable: return InkWell( - splashColor: selected - ? Theme.of(context).selectedRowColor - : Colors.transparent, + splashColor: selected ? Theme.of(context).selectedRowColor : Colors.transparent, child: child, ); default: @@ -65,9 +61,7 @@ class ListItemAccount extends StatelessWidget { Widget build(BuildContext context) => Opacity( opacity: enabled || selected ? 1 : 0.7, child: Container( - color: selected - ? Theme.of(context).selectedRowColor - : Colors.transparent, + color: selected ? Theme.of(context).selectedRowColor : Colors.transparent, child: ListTile( enabled: enabled, selected: selected, diff --git a/lib/views/widgets/lists/list-item-user.dart b/lib/views/widgets/lists/list-item-user.dart index bcc8f8764..087108cb4 100644 --- a/lib/views/widgets/lists/list-item-user.dart +++ b/lib/views/widgets/lists/list-item-user.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:syphon/global/assets.dart'; diff --git a/lib/views/widgets/lists/list-local-images.dart b/lib/views/widgets/lists/list-local-images.dart index 294878fb9..7eafcf768 100644 --- a/lib/views/widgets/lists/list-local-images.dart +++ b/lib/views/widgets/lists/list-local-images.dart @@ -1,6 +1,5 @@ import 'dart:io'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:local_image_provider/device_image.dart'; import 'package:local_image_provider/local_image.dart'; @@ -41,7 +40,10 @@ class _ListLocalImagesState extends State with Lifecycle media.isImage).toList(); setState(() { images = latestImages; @@ -102,6 +104,10 @@ class _ListLocalImagesState extends State with Lifecycle with Lifecycle[ diff --git a/lib/views/widgets/lists/list-user-bubbles.dart b/lib/views/widgets/lists/list-user-bubbles.dart index c308a8b53..523732eff 100644 --- a/lib/views/widgets/lists/list-user-bubbles.dart +++ b/lib/views/widgets/lists/list-user-bubbles.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:syphon/global/colours.dart'; diff --git a/lib/views/widgets/loader/index.dart b/lib/views/widgets/loader/index.dart index 712b45452..ef313c6e9 100644 --- a/lib/views/widgets/loader/index.dart +++ b/lib/views/widgets/loader/index.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:syphon/global/dimensions.dart'; diff --git a/lib/views/widgets/loader/loading-indicator.dart b/lib/views/widgets/loader/loading-indicator.dart index 6fe456dc2..d0aa6c5f1 100644 --- a/lib/views/widgets/loader/loading-indicator.dart +++ b/lib/views/widgets/loader/loading-indicator.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:syphon/global/dimensions.dart'; diff --git a/lib/views/widgets/messages/message.dart b/lib/views/widgets/messages/message.dart index cc1e815ad..5130a1806 100644 --- a/lib/views/widgets/messages/message.dart +++ b/lib/views/widgets/messages/message.dart @@ -19,7 +19,6 @@ import 'package:syphon/views/widgets/dialogs/dialog-confirm.dart'; import 'package:syphon/views/widgets/image-matrix.dart'; import 'package:syphon/views/widgets/input/text-field-edit.dart'; import 'package:syphon/views/widgets/messages/styles.dart'; -import 'package:url_launcher/url_launcher.dart'; const MESSAGE_MARGIN_VERTICAL_LARGE = 6.0; const MESSAGE_MARGIN_VERTICAL_NORMAL = 4.0; @@ -232,7 +231,8 @@ class MessageWidget extends StatelessWidget { final hasReactions = message.reactions.isNotEmpty || selected; final isRead = message.timestamp < lastRead; final showAvatar = !isLastSender && !isUserSent && !messageOnly; - final isMedia = message.url != null; + final body = selectEventBody(message); + final isMedia = selectIsMedia(message); final removePadding = isMedia || (isEditing && selected); var textColor = Colors.white; @@ -360,8 +360,6 @@ class MessageWidget extends StatelessWidget { showInfoRow = true; } - final String body = selectEventBody(message); - // Indicates special event text instead of the message body if (message.body != body) { fontStyle = FontStyle.italic; diff --git a/lib/views/widgets/modals/modal-image-options.dart b/lib/views/widgets/modals/modal-image-options.dart index c87696e1d..3106847ed 100644 --- a/lib/views/widgets/modals/modal-image-options.dart +++ b/lib/views/widgets/modals/modal-image-options.dart @@ -1,6 +1,5 @@ import 'dart:io'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:image_picker/image_picker.dart'; diff --git a/lib/views/widgets/modals/modal-user-details.dart b/lib/views/widgets/modals/modal-user-details.dart index 19b9a7cc9..e60485dd4 100644 --- a/lib/views/widgets/modals/modal-user-details.dart +++ b/lib/views/widgets/modals/modal-user-details.dart @@ -1,5 +1,5 @@ import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_svg/svg.dart'; @@ -233,8 +233,8 @@ class ModalUserDetails extends StatelessWidget { }, title: Text( props.blocked - ? Strings.listItemUserDetailsUnblockUser - : Strings.listItemUserDetailsBlockUser, + ? Strings.listItemUserDetailsUnblockUser + : Strings.listItemUserDetailsBlockUser, ), leading: Container( padding: EdgeInsets.all(4), diff --git a/pubspec.lock b/pubspec.lock index 45937a340..2000ed145 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -407,6 +407,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.0.0-nullsafety.0" + flutter_image_compress: + dependency: "direct main" + description: + name: flutter_image_compress + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" flutter_keyboard_visibility: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 31c58e710..1d70eb239 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -91,9 +91,6 @@ dependencies: cupertino_icons: ^1.0.2 url_launcher: ^6.0.3 flutter_svg: ^0.22.0 - file_picker: ^4.1.1 - image_picker: ^0.8.4 - local_image_provider: ^4.0.1 flutter_keyboard_visibility: ^5.0.3 flutter_markdown: ^0.6.6 webview_flutter: ^2.0.13 @@ -108,6 +105,12 @@ dependencies: flutter_screen_lock: ^4.0.0 # window_utils: 1.0.2 # TODO: desktop only window sizing + ## media + file_picker: ^4.1.1 + image_picker: ^0.8.4 + local_image_provider: ^4.0.1 + flutter_image_compress: 1.1.0 + ### data uuid: ^3.0.4 json_annotation: ^4.0.0 From a94baad39a56b7c5dfdb47783f1820b25d7c6211 Mon Sep 17 00:00:00 2001 From: ereio Date: Sun, 9 Jan 2022 19:12:47 -0500 Subject: [PATCH 06/10] fix: issue with inviting users --- assets/translations/en.json | 2 +- lib/cache/serializer.dart | 1 + lib/cache/storage.dart | 1 + lib/global/strings.dart | 36 ++++++++++++------- .../home/groups/invite-users-screen.dart | 6 ++-- 5 files changed, 29 insertions(+), 17 deletions(-) diff --git a/assets/translations/en.json b/assets/translations/en.json index 8df25cfc1..bb5013e57 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -204,7 +204,7 @@ "message-edited-append": " (Edited)", "confirm-linkout": "Are you sure you want to open the following link?\n\n{}", "confirm-delete-keys": "Are you sure you want to delete your encryption keys for this device? This is very destructive and will probably render all your encrypted messages undecryptable.", - "confirm-invite": "Are you sure you want to invite the following user to the following chat?", + "confirm-invite": "Are you sure you want to invite the following users?", "confirm-invites-multiple": "Are you sure you want to invite the selected users to the following chat?", "confirm-start-chat": "Even if you don't send a message, the user will still see your invite to chat.", "confirm-attempt-chat": "Even if you don't send a message, the user will still see your invite to chat if they exist.\n\nDo you want to try chatting with this username?", diff --git a/lib/cache/serializer.dart b/lib/cache/serializer.dart index 55a614f66..a82ca10a8 100644 --- a/lib/cache/serializer.dart +++ b/lib/cache/serializer.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:typed_data'; +import 'package:flutter/foundation.dart'; import 'package:redux_persist/redux_persist.dart'; import 'package:sembast/sembast.dart'; import 'package:syphon/cache/index.dart'; diff --git a/lib/cache/storage.dart b/lib/cache/storage.dart index afc2d9711..05145c29b 100644 --- a/lib/cache/storage.dart +++ b/lib/cache/storage.dart @@ -1,5 +1,6 @@ import 'dart:typed_data'; +import 'package:flutter/foundation.dart'; import 'package:redux_persist/redux_persist.dart'; import 'package:sembast/sembast.dart'; import 'package:syphon/cache/index.dart'; diff --git a/lib/global/strings.dart b/lib/global/strings.dart index f90674e12..9b635e41d 100644 --- a/lib/global/strings.dart +++ b/lib/global/strings.dart @@ -114,28 +114,37 @@ class Strings { static final listItemSettingsSyncInterval = tr('list-item-settings-sync-interval'); static final listItemSettingsSyncToggle = tr('list-item-settings-sync-toggle'); - static String listItemUserDetailsStartChat(String? name) => tr('list-item-user-details-start-chat', args: ['$name']); + static String listItemUserDetailsStartChat(String? name) => + tr('list-item-user-details-start-chat', args: ['$name']); static final listItemUserDetailsRoomInvite = tr('list-item-user-details-room-invite'); static final listItemUserDetailsSendMessage = tr('list-item-user-details-send-message'); static final listItemUserDetailsViewProfile = tr('list-item-user-details-view-profile'); static final listItemUserDetailsUnblockUser = tr('list-item-user-details-unblock-user'); static final listItemUserDetailsBlockUser = tr('list-item-user-details-block-user'); - static final listItemImageOptionsPhotoSelectMethod = tr('list-item-image-options-photo-select-method'); + static final listItemImageOptionsPhotoSelectMethod = + tr('list-item-image-options-photo-select-method'); static final listItemImageOptionsTakePhoto = tr('list-item-image-options-take-photo'); - static final listItemImageOptionsPickFromGallery = tr('list-item-image-options-pick-from-gallery'); + static final listItemImageOptionsPickFromGallery = + tr('list-item-image-options-pick-from-gallery'); static final listItemImageOptionsRemovePhoto = tr('list-item-image-options-remove-photo'); - static String listItemContextSwitcherUserDisplayName(String? username) => tr('list-item-context-switcher-user-display-name', args: ['$username']); + static String listItemContextSwitcherUserDisplayName(String? username) => + tr('list-item-context-switcher-user-display-name', args: ['$username']); static final listItemContextSwitcherAccounts = tr('list-item-context-switcher-accounts'); static final listItemContextSwitcherAddAccount = tr('list-item-context-switcher-add-account'); static final listItemAdvancedSettingsLicenses = tr('list-item-advanced-settings-licenses'); - static final listItemAdvancedSettingsStartBackground = tr('list-item-advanced-settings-start-background'); - static final listItemAdvancedSettingsStopBackground = tr('list-item-advanced-settings-stop-background'); - static final listItemAdvancedSettingsTestNotifications = tr('list-item-advanced-settings-test-notifications'); - static final listItemAdvancedSettingsTestSyncLoop = tr('list-item-advanced-settings-test-sync-loop'); - static final listItemAdvancedSettingsForceFunction = tr('list-item-advanced-settings-force-function'); + static final listItemAdvancedSettingsStartBackground = + tr('list-item-advanced-settings-start-background'); + static final listItemAdvancedSettingsStopBackground = + tr('list-item-advanced-settings-stop-background'); + static final listItemAdvancedSettingsTestNotifications = + tr('list-item-advanced-settings-test-notifications'); + static final listItemAdvancedSettingsTestSyncLoop = + tr('list-item-advanced-settings-test-sync-loop'); + static final listItemAdvancedSettingsForceFunction = + tr('list-item-advanced-settings-force-function'); static final listItemSent = tr('list-item-sent'); static final listItemReceived = tr('list-item-received'); @@ -144,7 +153,8 @@ class Strings { static final listItemReadBy = tr('list-item-read-by'); static final listItemChatDetailToggleDirectChat = tr('list-item-chat-detail-toggle-direct-chat'); - static final listItemChatDetailNotificationSetting = tr('list-item-chat-detail-notification-setting'); + static final listItemChatDetailNotificationSetting = + tr('list-item-chat-detail-notification-setting'); static final listItemChatDetailNotifications = tr('list-item-chat-detail-notifications'); static final listItemChatDetailVibrate = tr('list-item-chat-detail-vibrate'); static final listItemChatDetailNotificationSound = tr('list-item-chat-detail-notification-sound'); @@ -225,7 +235,8 @@ class Strings { static final alertHiddenReadReceipts = tr('alert-hidden-read-receipts'); static final alertOffline = tr('alert-offline'); static final alertUnknown = tr('alert-unknown'); - static String alertCouldNotLaunchURL(String? url) => tr('alert-could-not-launch-url', args: ['$url']); + static String alertCouldNotLaunchURL(String? url) => + tr('alert-could-not-launch-url', args: ['$url']); static final alertNoImagesFound = tr('alert-no-images-found'); // Alert (Non-Flutter / Background Thread w/o i18n) @@ -257,9 +268,8 @@ class Strings { static final messageEditedAppend = tr('message-edited-append'); // Confirmations (use confirm*) - static final confirmInvite = tr('confirm-invite'); - static final confirmInvites = tr('confirm-invite-multiple'); + static final confirmInvites = tr('confirm-invites-multiple'); static final confirmStartChat = tr('confirm-start-chat'); static final confirmDeactivate = tr('prompt-confirm-deactivate'); static final confirmAttemptChat = tr('confirm-attempt-chat'); diff --git a/lib/views/home/groups/invite-users-screen.dart b/lib/views/home/groups/invite-users-screen.dart index 930073414..b5d25badf 100644 --- a/lib/views/home/groups/invite-users-screen.dart +++ b/lib/views/home/groups/invite-users-screen.dart @@ -175,18 +175,18 @@ class InviteUsersState extends State with Lifecycle DialogInviteUsers( + builder: (BuildContext dialogContext) => DialogInviteUsers( users: invites, title: 'Invite To ${room!.name}', content: - '${Strings.confirmInvites}${'\n\nSend ${invites.length} ${invitePlurialized.toLowerCase()} to ${room.name}?'}', + '${Strings.confirmInvite}${'\n\nSend ${invites.length} ${invitePlurialized.toLowerCase()} to ${room.name}?'}', action: 'send ${invitePlurialized.toLowerCase()}', onInviteUsers: () async { await Future.wait(invites.map((user) async { return props.onSendInvite(room: Room(id: roomId), user: user); })); - Navigator.pop(context); + Navigator.pop(dialogContext); Navigator.pop(context); }, ), From 48b219e71bc65f088d47ceb2324f4bca3c5de4f5 Mon Sep 17 00:00:00 2001 From: ereio Date: Sun, 9 Jan 2022 20:26:20 -0500 Subject: [PATCH 07/10] fix: remove exif info if possible, fix issue with quick image select sending --- lib/global/values.dart | 25 ++++++------------- lib/store/events/messages/formatters.dart | 1 + lib/store/media/actions.dart | 2 +- lib/store/media/filters.dart | 13 +++++++--- lib/views/home/chat/chat-screen.dart | 8 +++++- .../widgets/lists/list-local-images.dart | 6 ++++- pubspec.lock | 6 ++--- pubspec.yaml | 4 +-- 8 files changed, 37 insertions(+), 28 deletions(-) diff --git a/lib/global/values.dart b/lib/global/values.dart index 71763e195..2c7e6a68e 100644 --- a/lib/global/values.dart +++ b/lib/global/values.dart @@ -12,9 +12,9 @@ class Values { static const appNameLong = 'Syphon Messenger'; static const appDisplayName = 'Syphon'; - static const EMPTY_CHAT = 'Empty Chat'; static const empty = ''; static const UNKNOWN = 'Unknown'; + static const EMPTY_CHAT = 'Empty Chat'; static const DEFAULT_PROTOCOL = 'https://'; // Notifications and Background service @@ -27,32 +27,23 @@ class Values { static const channel_name_background_service = 'Background Sync'; static const channel_description = '$appName messaging client message and status notifications'; - static const captchaMatrixSiteKey = '6LcgI54UAAAAABGdGmruw6DdOocFpYVdjYBRe4zb'; - + // syphon related static const supportEmail = 'hello@syphon.org'; - - static const matrixSSOUrl = - '/_matrix/client/r0/login/sso/redirect?redirectUrl=syphon://syphon.org/login/token'; - static const openHelpUrl = 'mailto:$supportEmail?subject=Syphon%20Support%20-%20App&body=Hey%20Syphon%20Team%2C%0D%0A%0D%0A%3CLeave%20your%20feedback%2C%20questions%20or%20concerns%20here%3E%0D%0A%0D%0AThanks!'; - static const openSourceLibraries = [ - {'title': 'testing', 'license': 'MIT', 'version': '1.2.3'}, - ]; - + // matrix values static const homeserverDefault = 'matrix.org'; + static const clientSecretMatrix = 'MDWVwN79p5xIz7bgazVXvO8aabbVD0LN'; + static const captchaMatrixSiteKey = '6LcgI54UAAAAABGdGmruw6DdOocFpYVdjYBRe4zb'; + static const matrixSSOUrl = + '/_matrix/client/r0/login/sso/redirect?redirectUrl=syphon://syphon.org/login/token'; - // hello darkness, my old friend + // regexs - hello darkness, my old friend static const emailRegex = r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+"; - static const urlRegex = r'[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)'; - static const clientSecretMatrix = 'MDWVwN79p5xIz7bgazVXvO8aabbVD0LN'; - - static const redacted = 'redacted'; - // Animations static const animationDurationDefault = 350; // millis static const animationDurationDefaultFast = 275; diff --git a/lib/store/events/messages/formatters.dart b/lib/store/events/messages/formatters.dart index 54add392c..8ea555648 100644 --- a/lib/store/events/messages/formatters.dart +++ b/lib/store/events/messages/formatters.dart @@ -4,6 +4,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:mime/mime.dart'; import 'package:syphon/global/libs/matrix/constants.dart'; +import 'package:syphon/global/print.dart'; import 'package:syphon/store/events/messages/model.dart'; import 'package:syphon/store/media/converters.dart'; import 'package:syphon/store/media/encryption.dart'; diff --git a/lib/store/media/actions.dart b/lib/store/media/actions.dart index 2606e64a6..ca6507f2b 100644 --- a/lib/store/media/actions.dart +++ b/lib/store/media/actions.dart @@ -47,7 +47,7 @@ class UpdateMediaCache { ThunkAction uploadMedia({ required File localFile, - String? mediaName = 'profile-photo', + String? mediaName = 'media-default', }) { return (Store store) async { try { diff --git a/lib/store/media/filters.dart b/lib/store/media/filters.dart index e20371b42..aa983ceed 100644 --- a/lib/store/media/filters.dart +++ b/lib/store/media/filters.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:flutter/material.dart'; import 'package:flutter_image_compress/flutter_image_compress.dart'; import 'package:mime/mime.dart'; import 'package:path/path.dart' as path; @@ -26,10 +27,13 @@ Future scrubMedia({ final mimeTypeOption = lookupMimeType(localFile.path); final mimeType = convertMimeTypes(localFile, mimeTypeOption); - // Setting up params for saving encrypted file + // Image file info final String fileType = mimeType; final String fileExtension = fileType.split('/')[1]; final String fileName = '$mediaName-scrubbed.$fileExtension'; + final fileImage = await decodeImageFromList( + localFile.readAsBytesSync(), + ); var format; @@ -46,13 +50,16 @@ Future scrubMedia({ case 'webp': format = CompressFormat.webp; break; + default: + // Can't remove exif info for this media type + return localFile; } final mediaScrubbed = await FlutterImageCompress.compressWithFile( localFile.absolute.path, quality: 100, - // minWidth: , - // minHeight: , + minWidth: fileImage.width, + minHeight: fileImage.height, format: format, keepExif: false, numberOfRetries: 1, diff --git a/lib/views/home/chat/chat-screen.dart b/lib/views/home/chat/chat-screen.dart index 88f527ec7..681947dd9 100644 --- a/lib/views/home/chat/chat-screen.dart +++ b/lib/views/home/chat/chat-screen.dart @@ -4,6 +4,7 @@ import 'dart:io'; import 'package:crypto/crypto.dart'; import 'package:emoji_picker_flutter/emoji_picker_flutter.dart'; import 'package:equatable/equatable.dart'; +import 'package:exif/exif.dart'; import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_svg/svg.dart'; @@ -13,7 +14,9 @@ import 'package:syphon/global/assets.dart'; import 'package:syphon/global/colours.dart'; import 'package:syphon/global/dimensions.dart'; import 'package:syphon/global/libs/matrix/constants.dart'; +import 'package:syphon/global/print.dart'; import 'package:syphon/global/strings.dart'; +import 'package:syphon/global/values.dart'; import 'package:syphon/store/crypto/actions.dart'; import 'package:syphon/store/crypto/events/actions.dart'; import 'package:syphon/store/crypto/events/selectors.dart'; @@ -291,7 +294,10 @@ class ChatScreenState extends State { File? encryptedFile; EncryptInfo? info; - // TODO: confirm this doesn't persist the potato filter 🥔 + printDebug('STUFFF'); + printDebug(rawFile.path); + printDebug(rawFile.uri.toString()); + var file = await scrubMedia(localFile: rawFile); if (file == null) { diff --git a/lib/views/widgets/lists/list-local-images.dart b/lib/views/widgets/lists/list-local-images.dart index 7eafcf768..fd3528264 100644 --- a/lib/views/widgets/lists/list-local-images.dart +++ b/lib/views/widgets/lists/list-local-images.dart @@ -8,6 +8,7 @@ import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart'; import 'package:syphon/global/colours.dart'; import 'package:syphon/global/dimensions.dart'; +import 'package:syphon/global/print.dart'; import 'package:syphon/global/strings.dart'; import 'package:syphon/views/widgets/lifecycle.dart'; @@ -58,8 +59,11 @@ class _ListLocalImagesState extends State with Lifecycle=2.12.0 <3.0.0" @@ -121,7 +121,7 @@ dev_dependencies: build_runner: ^2.1.4 drift_dev: ^1.0.2 lint: ^1.5.3 - json_serializable: ^5.0.2 + json_serializable: ^6.1.3 flutter_launcher_icons: ^0.9.0 test: any From 6754d77c38b8b401c668510b015d27541cb4d44a Mon Sep 17 00:00:00 2001 From: ereio Date: Sun, 9 Jan 2022 20:27:14 -0500 Subject: [PATCH 08/10] chore: remove unused lib refs --- lib/views/home/chat/chat-screen.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/views/home/chat/chat-screen.dart b/lib/views/home/chat/chat-screen.dart index 681947dd9..9a19a2da3 100644 --- a/lib/views/home/chat/chat-screen.dart +++ b/lib/views/home/chat/chat-screen.dart @@ -4,7 +4,6 @@ import 'dart:io'; import 'package:crypto/crypto.dart'; import 'package:emoji_picker_flutter/emoji_picker_flutter.dart'; import 'package:equatable/equatable.dart'; -import 'package:exif/exif.dart'; import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_svg/svg.dart'; @@ -16,7 +15,6 @@ import 'package:syphon/global/dimensions.dart'; import 'package:syphon/global/libs/matrix/constants.dart'; import 'package:syphon/global/print.dart'; import 'package:syphon/global/strings.dart'; -import 'package:syphon/global/values.dart'; import 'package:syphon/store/crypto/actions.dart'; import 'package:syphon/store/crypto/events/actions.dart'; import 'package:syphon/store/crypto/events/selectors.dart'; From 5c6b7358771f4cb60e1625768f4d12d5d5b7381a Mon Sep 17 00:00:00 2001 From: ereio Date: Sun, 9 Jan 2022 20:40:10 -0500 Subject: [PATCH 09/10] fix: allow empty body media messages to be deleted as well --- changelog.md | 12 ++++++++++++ lib/store/events/messages/selectors.dart | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 1d695bbcf..9b7f17159 100644 --- a/changelog.md +++ b/changelog.md @@ -5,6 +5,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.2.7](https://github.com/syphon-org/syphon/releases/tag/0.2.6) - 2021-12-27 + + +### Added +- removes exif information for image uploads + +### Fixed +- fixed sending images from the quick select menu +- fixed inviting users to chats +- + + ## [0.2.6](https://github.com/syphon-org/syphon/releases/tag/0.2.6) - 2021-12-27 ### Fixed diff --git a/lib/store/events/messages/selectors.dart b/lib/store/events/messages/selectors.dart index df6893ff1..220cb4dd3 100644 --- a/lib/store/events/messages/selectors.dart +++ b/lib/store/events/messages/selectors.dart @@ -4,7 +4,7 @@ import 'package:syphon/store/events/messages/model.dart'; import 'package:syphon/store/index.dart'; bool selectIsMedia(Message message) { - final isBodyNull = message.body == null; + final isBodyNull = message.body == null || message.body!.isEmpty; return message.url != null && !isBodyNull; } From fc55f8244abcaf9c5ac59c87ae0c63fb801c0070 Mon Sep 17 00:00:00 2001 From: ereio Date: Sun, 9 Jan 2022 20:41:42 -0500 Subject: [PATCH 10/10] fix: set url to null to remove locally --- lib/store/events/actions.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/store/events/actions.dart b/lib/store/events/actions.dart index 83071feb1..091477ac7 100644 --- a/lib/store/events/actions.dart +++ b/lib/store/events/actions.dart @@ -364,7 +364,7 @@ ThunkAction deleteMessage({required Message message, required Room roo // TODO: confirm - 2021 // deleted messages returned remotely will have empty 'body' fields - final messageDeleted = message.copyWith(body: ''); + final messageDeleted = message.copyWith(body: '', url: null); if (room.encryptionEnabled) { return store.dispatch(AddMessagesDecrypted(roomId: room.id, messages: [messageDeleted]));