element-ios/Riot/Modules/Settings/Security/ManageSession/ManageSessionViewController.m
ismailgulek 79b8f80ce9
Release 1.9.12 (#7081)
* Update voice broadcast tiles UI (#6965)

* Translated using Weblate (German)

Currently translated at 100.0% (2307 of 2307 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/

* speeding the animation a bit

* tests and identifier improvements

* fix

* changelog

* removed unused code

* Avoid unnecessary send state request (#6970)

* comment

* Curate MXCrypto protocol methods

* Add voice broadcast initial state in bubble data (#6972)

- Add voice broadcast initial state in bubble data
- Remove the local record after sending

* Voice Broadcast: log and block unexpected state change

* Sing out bottom bar

* new line

* Enable WYSIWYG plain text support

* Remove change on Apple swift-collections revision

* removed RiotSettings a non RiotSwiftUI reference from the ViewState code

* fixed a test

* Complete MXCryptoV2 implementation

* Multi session logut

* Switch the CI to code 14 and the iOS 14 simulator, fix UI tests

* Fixes #6987 - Prevent ZXing from unnecessarily requesting camera access

* Fixes #6988 - Prevent actor switching when tearing down the rendezvous

* Separator fix

* Removed warnings

* add Z-Labs tag or rich text editor and update to the new label naming

* changelog

* Hide old sessions list when the new dm is enabled

* Add changelog.d file

* Sing out filtering

* Avoid simultaneous state changes (#6986)

* Improve kebab menu in UserSessionOverview

* Add UI tests

* Add changelog.d file

* No customization for emptycell (#7000)

* PSG-976 Exclude current session from security recommendations and other sessions

* Padding fix

* Fixed unit tests

* Add empty onLearnMoreAction closure

* Add InfoView skeleton

* Add UserSessionOverviewViewBindings

* Style info view

* Add bottom sheet modifier

* Localise content

* Add inactive sessions copy

* Fix bug in InlineTextButton

* Improve UserSessionCardView

* Add “learn more” button in UserOtherSessions

* Show bottom sheet in user other sessions

* Show rename info alert

* Refine UX

* Add iOS 15- fallback

* Refine InfoView

* Add UI tests

* Improve UserOtherSessionsUITests

* Improve InlineTextButton API

* Add changelod.d file

* Fix failing UTs

* Hide keyboard in UserSessionName

* Add .viewSessionInfo view action

* Voice Broadcast - BugFix - send the last chunk (#7002)

* Voice Broadcast - BugFix - send the last chunk with the right sequence number

- we reset now and teardown the service only after the last chunk is sent

* updated package + tests

* change log

* Bug Fix : Crash if the room has avatar and voice broadcast tiles

* Add MVVM-C for InfoSheet

* improving UI tests for slow CI

* removing comment

* test improvements for slow ci

* Show bottom sheet in other sessions screen

* Show bottom sheet in rename session screen

* Delete bottom sheet modifier

* Show rename sheet

* UI and unit tests

* Refresh fix

* Changelog

* Add InfoSheet SwiftUI preview

* simplify the test to make it pass on the CI

* Fix memory leak

* Cleanup UI tests

* improving tests for the CI

* Fixed IRC-style message and commands support in Rich text editor

* tests updated for the CI

* test improvements

* removing a test that can't pass on the CI due to its speed

* Changelog

* CryptoV2 changes

* Display crypto version

* Voice broadcast - Disable the sleep mode during the recording until we are able to handle it

Currently go to "sleep mode" pauses the voice broadcast recording

* Add issue automation for the VoIP team

* Renamed sign out to logout

* Renamed sign out to logout

* Renamed sign out to logout

* Sign out of all other sessions

* Fix typo in issue automation

* Fixed unit tests

* Translations update from Weblate (#7017)

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2311 of 2311 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/pt_BR/

* Translated using Weblate (Estonian)

Currently translated at 100.0% (2311 of 2311 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/

* Translated using Weblate (German)

Currently translated at 100.0% (2311 of 2311 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/

* Translated using Weblate (German)

Currently translated at 100.0% (2311 of 2311 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/

* Translated using Weblate (Dutch)

Currently translated at 100.0% (2311 of 2311 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/nl/

Co-authored-by: lvre <7uu3qrbvm@relay.firefox.com>
Co-authored-by: Priit Jõerüüt <riot@joeruut.com>
Co-authored-by: Vri <element@vrifox.cc>
Co-authored-by: Johan Smits <johan@smitsmail.net>

* Prepare for new sprint

* Prepare for new sprint

* Threads: added support to read receipts (MSC3771)

- Update after review

* Threads: added support to notifications count (MSC3773)

* Update RiotSwiftUI/Modules/UserSessions/UserOtherSessions/Test/UI/UserOtherSessionsUITests.swift

Co-authored-by: aringenbach <80891108+aringenbach@users.noreply.github.com>

* Update RiotSwiftUI/Modules/UserSessions/UserOtherSessions/Test/UI/UserOtherSessionsUITests.swift

Co-authored-by: aringenbach <80891108+aringenbach@users.noreply.github.com>

* Comment fix

* the test may fail on CI without blocking the task/check

* tests may fail on CI

* test improvement

* test may fail on CI

* Hide push toggles for http pushers when there is no server support

* changelog

* Code review fixes

* Threads: added support to read receipts (MSC3771)

- Update after review

* Synchronise composer and toolbar resizing animation duration

* Add kResizeComposerAnimationDuration constant description

* fix for 6946

* Threads: add support to labs flag for read receipts

* Cleanup

* Code review fixes, created DestructiveButton

* Update issue automation

Stop using deprecated ProjectNext API in favour of the new ProjectV2 one

* Update PR automation

Stop using deprecated ProjectNext API in favour of the new ProjectV2 one

* Code review fixes

* Map location info

* Map location info

* Add location feature in UserSessionsOverview

* Add “show location” feature in other sessions list

* Add “show location“ feature in session overview

* Fix Package.resolved

* Cleanup merge leftovers

* Cleanup code

* Cleanup

* Add show/hide ip persistency

* Add location info in UserOtherSessions

* Refine settings logic

* Mock settings in UserSessionsOverviewViewModel

* Add settings service in UserOtherSessionsViewModel

* Inject setting service in UserSessionOverviewViewModel

* Add changelog.d file

* Fix UTs

* Cleanup merge leftovers

* Add animations

* Fix failing test

* Amend title font

* Amend copies

* Device Manager: Session list item is not tappable everywhere

* changelog

* Threads notification count in main timeline including un participated threads

* Changed title and body

* Removed "Do not ask again" button

* Remove indication about plain text mode coming soon

* Prevent `Unable to activate constraint with anchors .. because they have no common ancestor.` crashes. Only link toasts to the top safe area instead of the navigation controller

* Revert "Replace attributed string height calculation with a more reliable implementation"

This reverts commit 81773cd1e5.

* Revert "Fix timeline items text height calculation"

This reverts commit 8f9eddee50.

* Revert "Fixes vector-im/element-ios/issues/6441 - Incorrect timeline item text height calculation (#6679)"

This reverts commit 405c2d8e32.

* Fixes vector-im/element-ios/issues/6441 - Incorrect timeline item text height calculation

* Prepare for new sprint

* Refine bottom sheet layout

* updated pod

* changelog

* Switch to using an API key for interactions with AppStoreConnect while on CI; update fastlane and dependencies

* Rich-text editor: Fix text formatting enabled inconsistent state

* Labs: Rich-text editor - Fix text formatting switch losing the current content of the composer

* Re-order View computed properties and move to private mark

* Add intrinsic sized bottom sheet

* Snooze controller

* Changelog

* Fix composer view model tests

* Rich-text editor: enable translations between Markdown and HTML when toggling text formatting

* Force a layout on the room bubble cell messageTextView to get a correct frame

* Move Move UserAgentParserTests

* Add UserSessionDetailsUITests

* Improve UserSessionNameUITests

* Cleanup tests

* Improve UserSessionNameViewModelTests

* Test empty state for UserOtherSessions

* Fix typo

* Cleanup unused code

* Add changelog.d file

* Threads: removed "unread_thread_notifications" from sync filters for server that doesn't support MSC3773

* Remove 10s wait on failed initial sync

* Threads: removed "unread_thread_notifications" from sync filters for server that doesn't support MSC3773

- Update after review

* Revert "Device Manager: Session list item is not tappable everywhere"

This reverts commit e6367cba4c.

* Fixup session list item is not tappable everywhere

* Fix accessibility id in UserOtherSessions

* Poll not usable after logging out and back in

* Changelog

* Removed init

* voice dictation now works

* plain text

* Add voice broadcast slider (#7010)

* Display number of unread messages above threads button

* Translations update from Weblate (#7080)

* Translated using Weblate (Dutch)

Currently translated at 100.0% (2311 of 2311 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/nl/

* Translated using Weblate (German)

Currently translated at 100.0% (2311 of 2311 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/

* Translated using Weblate (Dutch)

Currently translated at 100.0% (2312 of 2312 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/nl/

* Translated using Weblate (German)

Currently translated at 100.0% (2312 of 2312 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/

* Translated using Weblate (Albanian)

Currently translated at 99.6% (2303 of 2312 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sq/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2312 of 2312 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/pt_BR/

* Translated using Weblate (Ukrainian)

Currently translated at 100.0% (2312 of 2312 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/

* Translated using Weblate (Estonian)

Currently translated at 100.0% (2312 of 2312 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/

* Translated using Weblate (Indonesian)

Currently translated at 100.0% (2312 of 2312 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/id/

* Translated using Weblate (Slovak)

Currently translated at 100.0% (2312 of 2312 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sk/

* Translated using Weblate (Italian)

Currently translated at 100.0% (2312 of 2312 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/it/

* Translated using Weblate (German)

Currently translated at 100.0% (2313 of 2313 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/

* Translated using Weblate (Ukrainian)

Currently translated at 100.0% (2313 of 2313 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/

* Translated using Weblate (Indonesian)

Currently translated at 100.0% (2313 of 2313 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/id/

* Translated using Weblate (Dutch)

Currently translated at 100.0% (2315 of 2315 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/nl/

* Translated using Weblate (German)

Currently translated at 100.0% (2315 of 2315 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (2315 of 2315 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/hu/

* Translated using Weblate (Italian)

Currently translated at 100.0% (2315 of 2315 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/it/

* Translated using Weblate (Ukrainian)

Currently translated at 100.0% (2315 of 2315 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/

* Translated using Weblate (Estonian)

Currently translated at 100.0% (2315 of 2315 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/

* Translated using Weblate (Indonesian)

Currently translated at 100.0% (2315 of 2315 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/id/

* Translated using Weblate (Slovak)

Currently translated at 100.0% (2315 of 2315 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sk/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2315 of 2315 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/pt_BR/

* Translated using Weblate (Albanian)

Currently translated at 99.5% (2305 of 2315 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sq/

* Translated using Weblate (German)

Currently translated at 100.0% (2317 of 2317 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/

* Translated using Weblate (Japanese)

Currently translated at 66.2% (1534 of 2317 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2317 of 2317 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/pt_BR/

* Translated using Weblate (Ukrainian)

Currently translated at 100.0% (2317 of 2317 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/

* Translated using Weblate (Estonian)

Currently translated at 100.0% (2317 of 2317 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/

* Translated using Weblate (Indonesian)

Currently translated at 100.0% (2317 of 2317 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/id/

* Translated using Weblate (Slovak)

Currently translated at 100.0% (2317 of 2317 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sk/

* Translated using Weblate (Japanese)

Currently translated at 66.2% (1534 of 2317 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/

* Translated using Weblate (German)

Currently translated at 100.0% (2326 of 2326 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/

* Translated using Weblate (Ukrainian)

Currently translated at 100.0% (2326 of 2326 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/

* Translated using Weblate (Estonian)

Currently translated at 100.0% (2326 of 2326 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/

* Translated using Weblate (Ukrainian)

Currently translated at 100.0% (2326 of 2326 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/

* Translated using Weblate (Estonian)

Currently translated at 100.0% (2326 of 2326 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/

* Translated using Weblate (German)

Currently translated at 100.0% (2326 of 2326 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/

* Translated using Weblate (Ukrainian)

Currently translated at 100.0% (2326 of 2326 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/

* Translated using Weblate (Estonian)

Currently translated at 100.0% (2326 of 2326 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/

* Translated using Weblate (Slovak)

Currently translated at 100.0% (2326 of 2326 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sk/

* Translated using Weblate (Italian)

Currently translated at 100.0% (2326 of 2326 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/it/

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (2326 of 2326 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/hu/

* Translated using Weblate (Indonesian)

Currently translated at 100.0% (2326 of 2326 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/id/

* Translated using Weblate (French)

Currently translated at 97.6% (2272 of 2326 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/fr/

* Translated using Weblate (Russian)

Currently translated at 80.5% (1873 of 2326 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ru/

* Translated using Weblate (Russian)

Currently translated at 80.7% (1879 of 2326 strings)

Translation: Element iOS/Element iOS
Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ru/

Co-authored-by: Roel ter Maat <roel.termaat@nedap.com>
Co-authored-by: Vri <element@vrifox.cc>
Co-authored-by: Besnik Bleta <besnik@programeshqip.org>
Co-authored-by: lvre <7uu3qrbvm@relay.firefox.com>
Co-authored-by: Ihor Hordiichuk <igor_ck@outlook.com>
Co-authored-by: Priit Jõerüüt <riot@joeruut.com>
Co-authored-by: Linerly <linerly@protonmail.com>
Co-authored-by: Jozef Gaal <preklady@mayday.sk>
Co-authored-by: random <dictionary@tutamail.com>
Co-authored-by: Szimszon <github@oregpreshaz.eu>
Co-authored-by: Suguru Hirahara <ovestekona@protonmail.com>
Co-authored-by: Thibault Martin <mail@thibaultmart.in>
Co-authored-by: Platon Terekhov <ockenfels_vevent@aleeas.com>

* changelog.d: Upgrade MatrixSDK version ([v0.24.3](https://github.com/matrix-org/matrix-ios-sdk/releases/tag/v0.24.3)).

* version++

Co-authored-by: giomfo <gforet@matrix.org>
Co-authored-by: Yoan Pintas <y.pintas@gmail.com>
Co-authored-by: Vri <element@vrifox.cc>
Co-authored-by: Anderas <andyuhnak@gmail.com>
Co-authored-by: Mauro Romito <mauro.romito@element.io>
Co-authored-by: Velin92 <34335419+Velin92@users.noreply.github.com>
Co-authored-by: Giom Foret <giom@matrix.org>
Co-authored-by: Aleksandrs Proskurins <paleksandrs@gmail.com>
Co-authored-by: aringenbach <arnaudr@element.io>
Co-authored-by: manuroe <manuroe@users.noreply.github.com>
Co-authored-by: David Langley <langley.dave@gmail.com>
Co-authored-by: Stefan Ceriu <stefanc@matrix.org>
Co-authored-by: Alfonso Grillo <alfogrillo@gmail.com>
Co-authored-by: Alfonso Grillo <alfogrillo@element.io>
Co-authored-by: Kat Gerasimova <ekaterinag@element.io>
Co-authored-by: Element Translate Bot <admin@riot.im>
Co-authored-by: lvre <7uu3qrbvm@relay.firefox.com>
Co-authored-by: Priit Jõerüüt <riot@joeruut.com>
Co-authored-by: Johan Smits <johan@smitsmail.net>
Co-authored-by: gulekismail <ismailgulek0@gmail.com>
Co-authored-by: Gil Eluard <gile@element.io>
Co-authored-by: Aleksandrs Proskurins <aleksandrsp@element.io>
Co-authored-by: aringenbach <80891108+aringenbach@users.noreply.github.com>
Co-authored-by: Stefan Ceriu <stefan.ceriu@gmail.com>
Co-authored-by: Roel ter Maat <roel.termaat@nedap.com>
Co-authored-by: Besnik Bleta <besnik@programeshqip.org>
Co-authored-by: Ihor Hordiichuk <igor_ck@outlook.com>
Co-authored-by: Linerly <linerly@protonmail.com>
Co-authored-by: Jozef Gaal <preklady@mayday.sk>
Co-authored-by: random <dictionary@tutamail.com>
Co-authored-by: Szimszon <github@oregpreshaz.eu>
Co-authored-by: Suguru Hirahara <ovestekona@protonmail.com>
Co-authored-by: Thibault Martin <mail@thibaultmart.in>
Co-authored-by: Platon Terekhov <ockenfels_vevent@aleeas.com>
2022-11-15 16:40:36 +03:00

712 lines
25 KiB
Objective-C

/*
Copyright 2020 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#import "ManageSessionViewController.h"
#import <OLMKit/OLMKit.h>
#import "AvatarGenerator.h"
#import "ThemeService.h"
#import "GeneratedInterface-Swift.h"
@import DesignKit;
enum
{
SECTION_SESSION_INFO,
SECTION_ACTION,
SECTION_COUNT
};
enum {
SESSION_INFO_SESSION_NAME,
SESSION_INFO_TRUST,
SESSION_INFO_COUNT
};
enum {
ACTION_REMOVE_SESSION,
ACTION_COUNT
};
@interface ManageSessionViewController () <UserVerificationCoordinatorBridgePresenterDelegate>
{
// The device to display
MXDevice *device;
// Current alert (if any).
UIAlertController *currentAlert;
// Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change.
id kThemeServiceDidChangeThemeNotificationObserver;
// The current pushed view controller
UIViewController *pushedViewController;
}
@property (nonatomic, strong) UserVerificationCoordinatorBridgePresenter *userVerificationCoordinatorBridgePresenter;
@property (nonatomic, strong) ReauthenticationCoordinatorBridgePresenter *reauthenticationCoordinatorBridgePresenter;
@end
@implementation ManageSessionViewController
#pragma mark - Setup & Teardown
+ (ManageSessionViewController*)instantiateWithMatrixSession:(MXSession*)matrixSession andDevice:(MXDevice*)device;
{
ManageSessionViewController* viewController = [[UIStoryboard storyboardWithName:@"ManageSession" bundle:[NSBundle mainBundle]] instantiateInitialViewController];
[viewController addMatrixSession:matrixSession];
viewController->device = device;
return viewController;
}
#pragma mark - View life cycle
- (void)finalizeInit
{
[super finalizeInit];
// Setup `MXKViewControllerHandling` properties
self.enableBarTintColorStatusChange = NO;
self.rageShakeManager = [RageShakeManager sharedManager];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.navigationItem.title = [VectorL10n manageSessionTitle];
[self vc_removeBackTitle];
[self.tableView registerClass:MXKTableViewCellWithLabelAndTextField.class forCellReuseIdentifier:[MXKTableViewCellWithLabelAndTextField defaultReuseIdentifier]];
[self.tableView registerClass:MXKTableViewCellWithLabelAndSwitch.class forCellReuseIdentifier:[MXKTableViewCellWithLabelAndSwitch defaultReuseIdentifier]];
[self.tableView registerNib:MXKTableViewCellWithTextView.nib forCellReuseIdentifier:[MXKTableViewCellWithTextView defaultReuseIdentifier]];
// Enable self sizing cells
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 50;
// Observe user interface theme change.
kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
[self userInterfaceThemeDidChange];
}];
[self userInterfaceThemeDidChange];
[self registerDeviceChangesNotification];
}
- (void)userInterfaceThemeDidChange
{
[ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar];
self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor;
// Check the table view style to select its bg color.
self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.shared.theme.backgroundColor : ThemeService.shared.theme.headerBackgroundColor);
self.view.backgroundColor = self.tableView.backgroundColor;
self.tableView.separatorColor = ThemeService.shared.theme.lineBreakColor;
[self reloadData];
[self setNeedsStatusBarAppearanceUpdate];
}
- (UIStatusBarStyle)preferredStatusBarStyle
{
return ThemeService.shared.theme.statusBarStyle;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)destroy
{
// Release the potential pushed view controller
[self releasePushedViewController];
if (kThemeServiceDidChangeThemeNotificationObserver)
{
[[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver];
kThemeServiceDidChangeThemeNotificationObserver = nil;
}
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// Release the potential pushed view controller
[self releasePushedViewController];
// Refresh display
[self reloadData];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if (currentAlert)
{
[currentAlert dismissViewControllerAnimated:NO completion:nil];
currentAlert = nil;
}
}
#pragma mark - Internal methods
- (void)pushViewController:(UIViewController*)viewController
{
// Keep ref on pushed view controller
pushedViewController = viewController;
[self.navigationController pushViewController:viewController animated:YES];
}
- (void)releasePushedViewController
{
if (pushedViewController)
{
if ([pushedViewController isKindOfClass:[UINavigationController class]])
{
UINavigationController *navigationController = (UINavigationController*)pushedViewController;
for (id subViewController in navigationController.viewControllers)
{
if ([subViewController respondsToSelector:@selector(destroy)])
{
[subViewController destroy];
}
}
}
else if ([pushedViewController respondsToSelector:@selector(destroy)])
{
[(id)pushedViewController destroy];
}
pushedViewController = nil;
}
}
- (void)reset
{
// Remove observers
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)reloadData
{
// Trigger a full table reloadData
[self.tableView reloadData];
}
- (void)reloadDeviceWithCompletion:(void (^)(void))completion
{
MXWeakify(self);
[self.mainSession.matrixRestClient deviceByDeviceId:device.deviceId success:^(MXDevice *device) {
MXStrongifyAndReturnIfNil(self);
self->device = device;
[self reloadData];
completion();
} failure:^(NSError *error) {
MXLogDebug(@"[ManageSessionVC] reloadDeviceWithCompletion failed. Error: %@", error);
[self reloadData];
completion();
}];
}
#pragma mark - Data update
- (void)registerDeviceChangesNotification
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onDeviceInfoTrustLevelDidChangeNotification:)
name:MXDeviceInfoTrustLevelDidChangeNotification
object:nil];
}
- (void)onDeviceInfoTrustLevelDidChangeNotification:(NSNotification*)notification
{
MXDeviceInfo *deviceInfo = notification.object;
NSString *deviceId = deviceInfo.deviceId;
if ([deviceId isEqualToString:device.deviceId])
{
[self reloadDeviceWithCompletion:^{
}];
}
}
#pragma mark - Segues
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Keep ref on destinationViewController
[super prepareForSegue:segue sender:sender];
// FIXME add night mode
}
#pragma mark - UITableView data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return SECTION_COUNT;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger count = 0;
switch (section)
{
case SECTION_SESSION_INFO:
count = SESSION_INFO_COUNT;
break;
case SECTION_ACTION:
count = ACTION_COUNT;
break;
}
return count;
}
- (MXKTableViewCellWithLabelAndTextField*)getLabelAndTextFieldCell:(UITableView*)tableView forIndexPath:(NSIndexPath *)indexPath
{
MXKTableViewCellWithLabelAndTextField *cell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCellWithLabelAndTextField defaultReuseIdentifier] forIndexPath:indexPath];
cell.mxkLabelLeadingConstraint.constant = tableView.vc_separatorInset.left;
cell.mxkTextFieldLeadingConstraint.constant = 16;
cell.mxkTextFieldTrailingConstraint.constant = 15;
cell.mxkLabel.textColor = ThemeService.shared.theme.textPrimaryColor;
cell.mxkTextField.userInteractionEnabled = YES;
cell.mxkTextField.borderStyle = UITextBorderStyleNone;
cell.mxkTextField.textAlignment = NSTextAlignmentRight;
cell.mxkTextField.textColor = ThemeService.shared.theme.textSecondaryColor;
cell.mxkTextField.font = [UIFont systemFontOfSize:16];
cell.mxkTextField.placeholder = nil;
cell.accessoryType = UITableViewCellAccessoryNone;
cell.accessoryView = nil;
cell.alpha = 1.0f;
cell.userInteractionEnabled = YES;
[cell layoutIfNeeded];
return cell;
}
- (MXKTableViewCellWithLabelAndSwitch*)getLabelAndSwitchCell:(UITableView*)tableView forIndexPath:(NSIndexPath *)indexPath
{
MXKTableViewCellWithLabelAndSwitch *cell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCellWithLabelAndSwitch defaultReuseIdentifier] forIndexPath:indexPath];
cell.mxkLabelLeadingConstraint.constant = tableView.vc_separatorInset.left;
cell.mxkSwitchTrailingConstraint.constant = 15;
cell.mxkLabel.textColor = ThemeService.shared.theme.textPrimaryColor;
[cell.mxkSwitch removeTarget:self action:nil forControlEvents:UIControlEventValueChanged];
// Force layout before reusing a cell (fix switch displayed outside the screen)
[cell layoutIfNeeded];
return cell;
}
- (MXKTableViewCell*)getDefaultTableViewCell:(UITableView*)tableView
{
MXKTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCell defaultReuseIdentifier]];
if (!cell)
{
cell = [[MXKTableViewCell alloc] init];
}
else
{
cell.selectionStyle = UITableViewCellSelectionStyleDefault;
cell.accessoryType = UITableViewCellAccessoryNone;
cell.accessoryView = nil;
cell.imageView.image = nil;
}
cell.textLabel.accessibilityIdentifier = nil;
cell.textLabel.font = [UIFont systemFontOfSize:17];
cell.textLabel.textColor = ThemeService.shared.theme.textPrimaryColor;
cell.contentView.backgroundColor = UIColor.clearColor;
return cell;
}
- (MXKTableViewCell*)trustCellWithDevice:(MXDevice*)device forTableView:(UITableView*)tableView
{
MXKTableViewCell *cell = [self getDefaultTableViewCell:tableView];
NSString *deviceId = device.deviceId;
MXDeviceInfo *deviceInfo = [self.mainSession.crypto deviceWithDeviceId:deviceId ofUser:self.mainSession.myUser.userId];
cell.textLabel.numberOfLines = 0;
[cell vc_setAccessoryDisclosureIndicatorWithCurrentTheme];
if (deviceInfo.trustLevel.isVerified)
{
cell.textLabel.text = [VectorL10n manageSessionTrusted];
cell.imageView.image = AssetImages.encryptionTrusted.image;
}
else
{
cell.textLabel.text = [VectorL10n manageSessionNotTrusted];
cell.imageView.image = AssetImages.encryptionWarning.image;
}
return cell;
}
- (MXKTableViewCellWithTextView*)textViewCellForTableView:(UITableView*)tableView atIndexPath:(NSIndexPath *)indexPath
{
MXKTableViewCellWithTextView *textViewCell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCellWithTextView defaultReuseIdentifier] forIndexPath:indexPath];
textViewCell.mxkTextView.textColor = ThemeService.shared.theme.textPrimaryColor;
textViewCell.mxkTextView.font = [UIFont systemFontOfSize:17];
textViewCell.mxkTextView.backgroundColor = [UIColor clearColor];
textViewCell.mxkTextViewLeadingConstraint.constant = tableView.vc_separatorInset.left;
textViewCell.mxkTextViewTrailingConstraint.constant = tableView.vc_separatorInset.right;
textViewCell.mxkTextView.accessibilityIdentifier = nil;
return textViewCell;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger section = indexPath.section;
NSInteger row = indexPath.row;
// set the cell to a default value to avoid application crashes
UITableViewCell *cell = [[UITableViewCell alloc] init];
cell.backgroundColor = [UIColor redColor];
switch (section)
{
case SECTION_SESSION_INFO:
switch (row)
{
case SESSION_INFO_SESSION_NAME:
{
MXKTableViewCellWithLabelAndTextField *displaynameCell = [self getLabelAndTextFieldCell:tableView forIndexPath:indexPath];
displaynameCell.mxkLabel.text = [VectorL10n manageSessionName];
displaynameCell.mxkTextField.text = device.displayName;
displaynameCell.mxkTextField.userInteractionEnabled = NO;
displaynameCell.selectionStyle = UITableViewCellSelectionStyleDefault;
cell = displaynameCell;
break;
}
case SESSION_INFO_TRUST:
{
cell = [self trustCellWithDevice:device forTableView:tableView];
}
}
break;
case SECTION_ACTION:
switch (row)
{
case ACTION_REMOVE_SESSION:
{
MXKTableViewCellWithButton *removeSessionBtnCell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCellWithButton defaultReuseIdentifier]];
if (!removeSessionBtnCell)
{
removeSessionBtnCell = [[MXKTableViewCellWithButton alloc] init];
}
else
{
// Fix https://github.com/vector-im/riot-ios/issues/1354
removeSessionBtnCell.mxkButton.titleLabel.text = nil;
}
NSString *btnTitle = [VectorL10n manageSessionSignOut];
[removeSessionBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal];
[removeSessionBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted];
[removeSessionBtnCell.mxkButton setTintColor:ThemeService.shared.theme.warningColor];
removeSessionBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17];
removeSessionBtnCell.mxkButton.userInteractionEnabled = NO;
removeSessionBtnCell.selectionStyle = UITableViewCellSelectionStyleDefault;
cell = removeSessionBtnCell;
break;
}
}
break;
}
return cell;
}
- (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
switch (section)
{
case SECTION_SESSION_INFO:
return [VectorL10n manageSessionInfo];
case SECTION_ACTION:
return @"";
}
return nil;
}
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section
{
if ([view isKindOfClass:UITableViewHeaderFooterView.class])
{
// Customize label style
UITableViewHeaderFooterView *tableViewHeaderFooterView = (UITableViewHeaderFooterView*)view;
tableViewHeaderFooterView.textLabel.textColor = ThemeService.shared.theme.colors.secondaryContent;
tableViewHeaderFooterView.textLabel.font = ThemeService.shared.theme.fonts.footnote;
}
}
#pragma mark - UITableView delegate
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
{
cell.backgroundColor = ThemeService.shared.theme.backgroundColor;
if (cell.selectionStyle != UITableViewCellSelectionStyleNone)
{
// Update the selected background view
if (ThemeService.shared.theme.selectedBackgroundColor)
{
cell.selectedBackgroundView = [[UIView alloc] init];
cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor;
}
else
{
if (tableView.style == UITableViewStylePlain)
{
cell.selectedBackgroundView = nil;
}
else
{
cell.selectedBackgroundView.backgroundColor = nil;
}
}
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
if (section == SECTION_SESSION_INFO)
{
return 44;
}
return 24;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
if (section == SECTION_SESSION_INFO)
{
return 0;
}
return 24;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.tableView == tableView)
{
NSInteger section = indexPath.section;
NSInteger row = indexPath.row;
switch (section)
{
case SECTION_SESSION_INFO:
switch (row)
{
case SESSION_INFO_SESSION_NAME:
[self renameDevice];
break;
case SESSION_INFO_TRUST:
[self showTrustForDevice:device];
break;
}
break;
case SECTION_ACTION:
{
switch (row)
{
case ACTION_REMOVE_SESSION:
[self removeDevice];
break;
}
}
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
}
#pragma mark - actions
- (void)renameDevice
{
// Prompt the user to enter a device name.
[currentAlert dismissViewControllerAnimated:NO completion:nil];
MXWeakify(self);
currentAlert = [UIAlertController alertControllerWithTitle:[VectorL10n deviceDetailsRenamePromptTitle]
message:[VectorL10n deviceDetailsRenamePromptMessage]
preferredStyle:UIAlertControllerStyleAlert];
[currentAlert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
MXStrongifyAndReturnIfNil(self);
textField.secureTextEntry = NO;
textField.placeholder = nil;
textField.keyboardType = UIKeyboardTypeDefault;
textField.text = self->device.displayName;
}];
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n cancel]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
MXStrongifyAndReturnIfNil(self);
self->currentAlert = nil;
}]];
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n ok]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
MXStrongifyAndReturnIfNil(self);
NSString *text = [self->currentAlert textFields].firstObject.text;
self->currentAlert = nil;
// Hot change
self->device.displayName = text;
[self reloadData];
[self.activityIndicator startAnimating];
[self.mainSession.matrixRestClient setDeviceName:text forDeviceId:self->device.deviceId success:^{
[self reloadDeviceWithCompletion:^{
[self.activityIndicator stopAnimating];
}];
} failure:^(NSError *error) {
MXLogDebug(@"[ManageSessionVC] Rename device (%@) failed", self->device.deviceId);
[self reloadDeviceWithCompletion:^{
[self.activityIndicator stopAnimating];
[[AppDelegate theDelegate] showErrorAsAlert:error];
}];
}];
}]];
[self presentViewController:currentAlert animated:YES completion:nil];
}
- (void)showTrustForDevice:(MXDevice *)device
{
UserVerificationCoordinatorBridgePresenter *userVerificationCoordinatorBridgePresenter = [[UserVerificationCoordinatorBridgePresenter alloc] initWithPresenter:self
session:self.mainSession
userId:self.mainSession.myUser.userId
userDisplayName:nil
deviceId:device.deviceId];
userVerificationCoordinatorBridgePresenter.delegate = self;
[userVerificationCoordinatorBridgePresenter start];
self.userVerificationCoordinatorBridgePresenter = userVerificationCoordinatorBridgePresenter;
}
- (void)removeDevice
{
[self startActivityIndicator];
self.view.userInteractionEnabled = NO;
MXWeakify(self);
void (^animationCompletion)(void) = ^void () {
MXStrongifyAndReturnIfNil(self);
[self stopActivityIndicator];
self.view.userInteractionEnabled = YES;
[self.reauthenticationCoordinatorBridgePresenter dismissWithAnimated:YES completion:^{}];
self.reauthenticationCoordinatorBridgePresenter = nil;
};
NSString *title = [VectorL10n deviceDetailsDeletePromptTitle];
NSString *message = [VectorL10n deviceDetailsDeletePromptMessage];
AuthenticatedEndpointRequest *deleteDeviceRequest = [[AuthenticatedEndpointRequest alloc] initWithPath:[NSString stringWithFormat:@"%@/devices/%@", kMXAPIPrefixPathR0, [MXTools encodeURIComponent:device.deviceId]] httpMethod:@"DELETE" params:[[NSDictionary alloc] init]];
ReauthenticationCoordinatorParameters *coordinatorParameters = [[ReauthenticationCoordinatorParameters alloc] initWithSession:self.mainSession presenter:self title:title message:message authenticatedEndpointRequest:deleteDeviceRequest];
ReauthenticationCoordinatorBridgePresenter *reauthenticationPresenter = [ReauthenticationCoordinatorBridgePresenter new];
[reauthenticationPresenter presentWith:coordinatorParameters animated:YES success:^(NSDictionary<NSString *,id> *_Nullable authParams) {
MXStrongifyAndReturnIfNil(self);
[self.mainSession.matrixRestClient deleteDeviceByDeviceId:self->device.deviceId authParams:authParams success:^{
animationCompletion();
// We cannot stay in this screen anymore
[self withdrawViewControllerAnimated:YES completion:nil];
} failure:^(NSError *error) {
MXLogDebug(@"[ManageSessionVC] Delete device (%@) failed", self->device.deviceId);
animationCompletion();
[[AppDelegate theDelegate] showErrorAsAlert:error];
}];
} cancel:^{
animationCompletion();
} failure:^(NSError * _Nonnull error) {
animationCompletion();
[[AppDelegate theDelegate] showErrorAsAlert:error];
}];
self.reauthenticationCoordinatorBridgePresenter = reauthenticationPresenter;
}
#pragma mark - UserVerificationCoordinatorBridgePresenterDelegate
- (void)userVerificationCoordinatorBridgePresenterDelegateDidComplete:(UserVerificationCoordinatorBridgePresenter *)coordinatorBridgePresenter
{
[self reloadDeviceWithCompletion:^{}];
}
@end