mirror of
https://github.com/vector-im/element-ios.git
synced 2024-09-29 07:42:40 +00:00
Finish v0.10.0
This commit is contained in:
commit
25aa432a79
98 changed files with 8338 additions and 999 deletions
36
CHANGES.rst
36
CHANGES.rst
|
@ -1,3 +1,36 @@
|
|||
Changes in 0.10.0 (2019-10-11)
|
||||
===============================================
|
||||
|
||||
Improvements:
|
||||
* Upgrade MatrixKit version ([v0.11.1](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.11.1)).
|
||||
* Upgrade MatrixKit version ([v0.11.0](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.11.0)).
|
||||
* Widgets: Whitelist [MSC1961](https://github.com/matrix-org/matrix-doc/pull/1961) widget urls.
|
||||
* Settings: CALLS section: Always display the CallKit option but grey it out when not available (only on China).
|
||||
* VoIP: Fallback to matrix.org STUN server with a confirmation dialog (#2646).
|
||||
* Widgets: Whitelist [MSC1961](https://github.com/matrix-org/matrix-doc/pull/1961) widget urls
|
||||
* i18n: Enable Polish (pl).
|
||||
* Room members: third-party invites can now be revoked
|
||||
* Privacy: Prompt to accept integration manager policies on use (#2600).
|
||||
* Privacy: Make clear that device names are publicly readable (#2662).
|
||||
* Privacy: Remove the ability to set an IS at login/registration (#2661).
|
||||
* Privacy: Remove the bind true flag from 3PID calls on registration (#2648).
|
||||
* Privacy: Remove the bind true flag from 3PID adds in settings (#2650).
|
||||
* Privacy: Email help text on registration should be updated without binding (#2675).
|
||||
* Privacy: Use MXIdentityService to perform identity server requests (#2647).
|
||||
* Privacy: Support identity server v2 API authentication (#2603).
|
||||
* Privacy: Use the hashed v2 lookup API for 3PIDs (#2652).
|
||||
* Privacy: Prompt to accept identity server policies on firt use (#2602).
|
||||
* Privacy: Settings: Allow adding 3pids when no IS (#2659).
|
||||
* Privacy: Allow password reset when no IS (#2658).
|
||||
* Privacy: Allow email registration when no IS (#2657).
|
||||
* Privacy: Settings: Add a Discovery section (#2606).
|
||||
* Privacy: Make NSContactsUsageDescription more generic and mention that 3pids are now uploaded hashed (#2521).
|
||||
* Privacy: Settings: Add IDENTITY SERVER section (#2604).
|
||||
* Privacy: Make IS terms wording clearer when we fallback to vector.im (#2760).
|
||||
|
||||
Bug fix:
|
||||
* Theme: Make button theming work (#2734).
|
||||
|
||||
Changes in 0.9.5 (2019-09-20)
|
||||
===============================================
|
||||
|
||||
|
@ -29,7 +62,8 @@ Improvements:
|
|||
* Reactions: Emoji picker (#2370).
|
||||
* Widgets: Whitelist https://scalar-staging.vector.im/api (#2612).
|
||||
* Reactions: Show who reacted (#2591).
|
||||
* Media picking: Use native camera and use separate actions for camera and media picker (#638).
|
||||
* Media picking: Use native camera and use separate actions for camera and media picker (#638).
|
||||
* Ability to disable all identity server functionality via the config file (#2643).
|
||||
|
||||
Bug fix:
|
||||
* Crash when leaving settings due to backup section refresh animation.
|
||||
|
|
2
Podfile
2
Podfile
|
@ -7,7 +7,7 @@ use_frameworks!
|
|||
|
||||
# Different flavours of pods to MatrixKit
|
||||
# The current MatrixKit pod version
|
||||
$matrixKitVersion = '0.10.2'
|
||||
$matrixKitVersion = '0.11.1'
|
||||
|
||||
# The develop branch version
|
||||
#$matrixKitVersion = 'develop'
|
||||
|
|
40
Podfile.lock
40
Podfile.lock
|
@ -49,41 +49,41 @@ PODS:
|
|||
- MatomoTracker (6.0.1):
|
||||
- MatomoTracker/Core (= 6.0.1)
|
||||
- MatomoTracker/Core (6.0.1)
|
||||
- MatrixKit (0.10.2):
|
||||
- MatrixKit (0.11.1):
|
||||
- cmark (~> 0.24.1)
|
||||
- DTCoreText (~> 1.6.21)
|
||||
- HPGrowingTextView (~> 1.1)
|
||||
- libPhoneNumber-iOS (~> 0.9.13)
|
||||
- MatrixKit/Core (= 0.10.2)
|
||||
- MatrixSDK (= 0.13.1)
|
||||
- MatrixKit/Core (= 0.11.1)
|
||||
- MatrixSDK (= 0.14.0)
|
||||
- SwiftUTI (~> 1.0.6)
|
||||
- MatrixKit/AppExtension (0.10.2):
|
||||
- MatrixKit/AppExtension (0.11.1):
|
||||
- cmark (~> 0.24.1)
|
||||
- DTCoreText (~> 1.6.21)
|
||||
- DTCoreText/Extension
|
||||
- HPGrowingTextView (~> 1.1)
|
||||
- libPhoneNumber-iOS (~> 0.9.13)
|
||||
- MatrixSDK (= 0.13.1)
|
||||
- MatrixSDK (= 0.14.0)
|
||||
- SwiftUTI (~> 1.0.6)
|
||||
- MatrixKit/Core (0.10.2):
|
||||
- MatrixKit/Core (0.11.1):
|
||||
- cmark (~> 0.24.1)
|
||||
- DTCoreText (~> 1.6.21)
|
||||
- HPGrowingTextView (~> 1.1)
|
||||
- libPhoneNumber-iOS (~> 0.9.13)
|
||||
- MatrixSDK (= 0.13.1)
|
||||
- MatrixSDK (= 0.14.0)
|
||||
- SwiftUTI (~> 1.0.6)
|
||||
- MatrixSDK (0.13.1):
|
||||
- MatrixSDK/Core (= 0.13.1)
|
||||
- MatrixSDK/Core (0.13.1):
|
||||
- MatrixSDK (0.14.0):
|
||||
- MatrixSDK/Core (= 0.14.0)
|
||||
- MatrixSDK/Core (0.14.0):
|
||||
- AFNetworking (~> 3.2.0)
|
||||
- GZIP (~> 1.2.2)
|
||||
- libbase58 (~> 0.1.4)
|
||||
- OLMKit (~> 3.1.0)
|
||||
- Realm (~> 3.13.1)
|
||||
- MatrixSDK/JingleCallStack (0.13.1):
|
||||
- MatrixSDK/JingleCallStack (0.14.0):
|
||||
- JitsiMeetSDK (~> 2.1.0)
|
||||
- MatrixSDK/Core
|
||||
- MatrixSDK/SwiftSupport (0.13.1):
|
||||
- MatrixSDK/SwiftSupport (0.14.0):
|
||||
- MatrixSDK/Core
|
||||
- OLMKit (3.1.0):
|
||||
- OLMKit/olmc (= 3.1.0)
|
||||
|
@ -109,8 +109,8 @@ DEPENDENCIES:
|
|||
- DTCoreText
|
||||
- GBDeviceInfo (~> 5.2.0)
|
||||
- MatomoTracker (~> 6.0.1)
|
||||
- MatrixKit (= 0.10.2)
|
||||
- MatrixKit/AppExtension (= 0.10.2)
|
||||
- MatrixKit (= 0.11.1)
|
||||
- MatrixKit/AppExtension (= 0.11.1)
|
||||
- MatrixSDK/JingleCallStack
|
||||
- MatrixSDK/SwiftSupport
|
||||
- OLMKit
|
||||
|
@ -121,7 +121,7 @@ DEPENDENCIES:
|
|||
- zxcvbn-ios
|
||||
|
||||
SPEC REPOS:
|
||||
https://github.com/cocoapods/specs.git:
|
||||
trunk:
|
||||
- AFNetworking
|
||||
- cmark
|
||||
- DGCollectionViewLeftAlignFlowLayout
|
||||
|
@ -150,7 +150,7 @@ EXTERNAL SOURCES:
|
|||
|
||||
CHECKOUT OPTIONS:
|
||||
SwiftUTI:
|
||||
:commit: c21237f13e9fb31a07f3fcd5243c5cf79d75901c
|
||||
:commit: b6b46942fb3aad819610851f62a70e17a528444e
|
||||
:git: https://github.com/speramusinc/SwiftUTI.git
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
|
@ -166,8 +166,8 @@ SPEC CHECKSUMS:
|
|||
libbase58: 7c040313537b8c44b6e2d15586af8e21f7354efd
|
||||
libPhoneNumber-iOS: 0a32a9525cf8744fe02c5206eb30d571e38f7d75
|
||||
MatomoTracker: 3ae4f65a1f5ace8043bda7244888fee28a734de5
|
||||
MatrixKit: 208801ba995442a6daa913eb6d639bb918c91c24
|
||||
MatrixSDK: 16c8c4b530a7f9fb264baced52b6b0948b1d0a98
|
||||
MatrixKit: db698352271a738b3c0e2f1a331088ea41f90ae1
|
||||
MatrixSDK: 0f965f8700420696ab15bf48d827a03d98b0ffac
|
||||
OLMKit: 4ee0159d63feeb86d836fdcfefe418e163511639
|
||||
Realm: 50071da38fe079e0735e47c9f2eae738c68c5996
|
||||
Reusable: 82be188f29d96dc5eff0db7b2393bcc08d2cdd5b
|
||||
|
@ -176,6 +176,6 @@ SPEC CHECKSUMS:
|
|||
SwiftUTI: 917993c124f8eac25e88ced0202fc58d7eb50fa8
|
||||
zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c
|
||||
|
||||
PODFILE CHECKSUM: 131195037301d9bfb7465da86b3ea79aac686b74
|
||||
PODFILE CHECKSUM: 724a8f79621df730d939fff2b7e703f5c9ec3b06
|
||||
|
||||
COCOAPODS: 1.7.2
|
||||
COCOAPODS: 1.8.3
|
||||
|
|
|
@ -96,6 +96,17 @@
|
|||
32BF995321FA2A1300698084 /* SettingsKeyBackupViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BF995221FA2A1300698084 /* SettingsKeyBackupViewState.swift */; };
|
||||
32BF995521FA2AB700698084 /* SettingsKeyBackupViewAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BF995421FA2AB700698084 /* SettingsKeyBackupViewAction.swift */; };
|
||||
32BF995721FB07A400698084 /* SettingsKeyBackupTableViewSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BF995621FB07A400698084 /* SettingsKeyBackupTableViewSection.swift */; };
|
||||
32DB557522FDADE50016329E /* ServiceTermsModalCoordinatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32DB556922FDADE50016329E /* ServiceTermsModalCoordinatorType.swift */; };
|
||||
32DB557622FDADE50016329E /* ServiceTermsModalCoordinatorBridgePresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32DB556A22FDADE50016329E /* ServiceTermsModalCoordinatorBridgePresenter.swift */; };
|
||||
32DB557722FDADE50016329E /* ServiceTermsModalCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32DB556B22FDADE50016329E /* ServiceTermsModalCoordinator.swift */; };
|
||||
32DB557822FDADE50016329E /* ServiceTermsModalScreenViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32DB556D22FDADE50016329E /* ServiceTermsModalScreenViewState.swift */; };
|
||||
32DB557922FDADE50016329E /* ServiceTermsModalScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32DB556E22FDADE50016329E /* ServiceTermsModalScreenViewModel.swift */; };
|
||||
32DB557A22FDADE50016329E /* ServiceTermsModalScreenViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32DB556F22FDADE50016329E /* ServiceTermsModalScreenViewController.swift */; };
|
||||
32DB557B22FDADE50016329E /* ServiceTermsModalScreenViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 32DB557022FDADE50016329E /* ServiceTermsModalScreenViewController.storyboard */; };
|
||||
32DB557C22FDADE50016329E /* ServiceTermsModalScreenViewModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32DB557122FDADE50016329E /* ServiceTermsModalScreenViewModelType.swift */; };
|
||||
32DB557D22FDADE50016329E /* ServiceTermsModalScreenCoordinatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32DB557222FDADE50016329E /* ServiceTermsModalScreenCoordinatorType.swift */; };
|
||||
32DB557E22FDADE50016329E /* ServiceTermsModalScreenViewAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32DB557322FDADE50016329E /* ServiceTermsModalScreenViewAction.swift */; };
|
||||
32DB557F22FDADE50016329E /* ServiceTermsModalScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32DB557422FDADE50016329E /* ServiceTermsModalScreenCoordinator.swift */; };
|
||||
32F6B9692270623100BBA352 /* DeviceVerificationDataLoadingCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32F6B9632270623000BBA352 /* DeviceVerificationDataLoadingCoordinator.swift */; };
|
||||
32F6B96A2270623100BBA352 /* DeviceVerificationDataLoadingViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32F6B9642270623100BBA352 /* DeviceVerificationDataLoadingViewState.swift */; };
|
||||
32F6B96B2270623100BBA352 /* DeviceVerificationDataLoadingViewAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32F6B9652270623100BBA352 /* DeviceVerificationDataLoadingViewAction.swift */; };
|
||||
|
@ -147,6 +158,11 @@
|
|||
B110872521F098F0003554A5 /* ActivityIndicatorPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B110872121F098EF003554A5 /* ActivityIndicatorPresenter.swift */; };
|
||||
B110872621F098F0003554A5 /* ActivityIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B110872221F098F0003554A5 /* ActivityIndicatorView.swift */; };
|
||||
B120863722EF375F001F89E0 /* ReactionHistoryBridgeCoordinatorPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B120863622EF375F001F89E0 /* ReactionHistoryBridgeCoordinatorPresenter.swift */; };
|
||||
B125FE1B231D5BF200B72806 /* SettingsDiscoveryTableViewSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = B125FE1A231D5BF200B72806 /* SettingsDiscoveryTableViewSection.swift */; };
|
||||
B125FE1D231D5DE400B72806 /* SettingsDiscoveryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B125FE1C231D5DE400B72806 /* SettingsDiscoveryViewModel.swift */; };
|
||||
B125FE1F231D5DF700B72806 /* SettingsDiscoveryViewModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B125FE1E231D5DF700B72806 /* SettingsDiscoveryViewModelType.swift */; };
|
||||
B125FE21231D5E1D00B72806 /* SettingsDiscoveryViewAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B125FE20231D5E1D00B72806 /* SettingsDiscoveryViewAction.swift */; };
|
||||
B125FE23231D5E4300B72806 /* SettingsDiscoveryViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = B125FE22231D5E4300B72806 /* SettingsDiscoveryViewState.swift */; };
|
||||
B139C21B21FE5B9200BB68EC /* KeyBackupRecoverFromPassphraseViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B139C21A21FE5B9100BB68EC /* KeyBackupRecoverFromPassphraseViewModel.swift */; };
|
||||
B139C21D21FE5BF500BB68EC /* KeyBackupRecoverFromPassphraseViewModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B139C21C21FE5BF500BB68EC /* KeyBackupRecoverFromPassphraseViewModelType.swift */; };
|
||||
B139C21F21FE5D6600BB68EC /* KeyBackupRecoverFromPassphraseViewAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B139C21E21FE5D6600BB68EC /* KeyBackupRecoverFromPassphraseViewAction.swift */; };
|
||||
|
@ -168,6 +184,15 @@
|
|||
B14F143522144F6500FA0595 /* KeyBackupRecoverFromRecoveryKeyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B14F142D22144F6500FA0595 /* KeyBackupRecoverFromRecoveryKeyViewController.swift */; };
|
||||
B152C73122DF561E0041315A /* EmojiServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B152C73022DF561E0041315A /* EmojiServiceTests.swift */; };
|
||||
B152C73522DF599C0041315A /* apple_emojis_data.json in Resources */ = {isa = PBXBuildFile; fileRef = B152C73422DF599B0041315A /* apple_emojis_data.json */; };
|
||||
B157FA9F23264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B157FA9723264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsCoordinator.swift */; };
|
||||
B157FAA023264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsViewModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B157FA9823264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsViewModelType.swift */; };
|
||||
B157FAA123264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsCoordinatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B157FA9923264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsCoordinatorType.swift */; };
|
||||
B157FAA223264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsViewAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B157FA9A23264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsViewAction.swift */; };
|
||||
B157FAA323264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = B157FA9B23264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsViewState.swift */; };
|
||||
B157FAA423264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B157FA9C23264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsViewController.storyboard */; };
|
||||
B157FAA523264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B157FA9D23264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsViewModel.swift */; };
|
||||
B157FAA623264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B157FA9E23264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsViewController.swift */; };
|
||||
B157FAA823264BED00EBFBD4 /* SettingsDiscoveryThreePidDetailsCoordinatorBridgePresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B157FAA723264BED00EBFBD4 /* SettingsDiscoveryThreePidDetailsCoordinatorBridgePresenter.swift */; };
|
||||
B1664BC520F4E67600808783 /* FallbackViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = B1664BAD20F4E67500808783 /* FallbackViewController.xib */; };
|
||||
B1664BC620F4E67600808783 /* FallbackViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1664BAE20F4E67500808783 /* FallbackViewController.m */; };
|
||||
B1664BC720F4E67600808783 /* SharePresentingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1664BB220F4E67500808783 /* SharePresentingViewController.m */; };
|
||||
|
@ -481,6 +506,15 @@
|
|||
B1C3360222F1ED600021BA8D /* MediaPickerCoordinatorBridgePresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1C335FF22F1ED5F0021BA8D /* MediaPickerCoordinatorBridgePresenter.swift */; };
|
||||
B1C3360322F1ED600021BA8D /* MediaPickerCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1C3360022F1ED600021BA8D /* MediaPickerCoordinator.swift */; };
|
||||
B1C3361C22F32B4A0021BA8D /* SingleImagePickerPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1C3361B22F32B4A0021BA8D /* SingleImagePickerPresenter.swift */; };
|
||||
B1C45A84232A8C2600165425 /* SettingsIdentityServerCoordinatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1C45A7B232A8C2600165425 /* SettingsIdentityServerCoordinatorType.swift */; };
|
||||
B1C45A85232A8C2600165425 /* SettingsIdentityServerViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B1C45A7C232A8C2600165425 /* SettingsIdentityServerViewController.storyboard */; };
|
||||
B1C45A86232A8C2600165425 /* SettingsIdentityServerViewModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1C45A7D232A8C2600165425 /* SettingsIdentityServerViewModelType.swift */; };
|
||||
B1C45A87232A8C2600165425 /* SettingsIdentityServerCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1C45A7E232A8C2600165425 /* SettingsIdentityServerCoordinator.swift */; };
|
||||
B1C45A88232A8C2600165425 /* SettingsIdentityServerViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1C45A7F232A8C2600165425 /* SettingsIdentityServerViewState.swift */; };
|
||||
B1C45A89232A8C2600165425 /* SettingsIdentityServerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1C45A80232A8C2600165425 /* SettingsIdentityServerViewController.swift */; };
|
||||
B1C45A8A232A8C2600165425 /* SettingsIdentityServerCoordinatorBridgePresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1C45A81232A8C2600165425 /* SettingsIdentityServerCoordinatorBridgePresenter.swift */; };
|
||||
B1C45A8B232A8C2600165425 /* SettingsIdentityServerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1C45A82232A8C2600165425 /* SettingsIdentityServerViewModel.swift */; };
|
||||
B1C45A8C232A8C2600165425 /* SettingsIdentityServerViewAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1C45A83232A8C2600165425 /* SettingsIdentityServerViewAction.swift */; };
|
||||
B1C562CA2289C2690037F12A /* UIGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1C562C92289C2690037F12A /* UIGestureRecognizer.swift */; };
|
||||
B1C562CC228AB3510037F12A /* UIStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1C562CB228AB3510037F12A /* UIStackView.swift */; };
|
||||
B1C562D9228C0B760037F12A /* RoomContextualMenuItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1C562D8228C0B760037F12A /* RoomContextualMenuItem.swift */; };
|
||||
|
@ -704,6 +738,20 @@
|
|||
32D7159E2146CC6F00DF59C9 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Vector.strings; sourceTree = "<group>"; };
|
||||
32D7159F2146CC7F00DF59C9 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
32D715A02146CC8800DF59C9 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
32DAF8DB231813C800654A44 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
32DAF8DC231813D500654A44 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
32DAF8DD231813E100654A44 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Vector.strings; sourceTree = "<group>"; };
|
||||
32DB556922FDADE50016329E /* ServiceTermsModalCoordinatorType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceTermsModalCoordinatorType.swift; sourceTree = "<group>"; };
|
||||
32DB556A22FDADE50016329E /* ServiceTermsModalCoordinatorBridgePresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceTermsModalCoordinatorBridgePresenter.swift; sourceTree = "<group>"; };
|
||||
32DB556B22FDADE50016329E /* ServiceTermsModalCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceTermsModalCoordinator.swift; sourceTree = "<group>"; };
|
||||
32DB556D22FDADE50016329E /* ServiceTermsModalScreenViewState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceTermsModalScreenViewState.swift; sourceTree = "<group>"; };
|
||||
32DB556E22FDADE50016329E /* ServiceTermsModalScreenViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceTermsModalScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
32DB556F22FDADE50016329E /* ServiceTermsModalScreenViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceTermsModalScreenViewController.swift; sourceTree = "<group>"; };
|
||||
32DB557022FDADE50016329E /* ServiceTermsModalScreenViewController.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = ServiceTermsModalScreenViewController.storyboard; sourceTree = "<group>"; };
|
||||
32DB557122FDADE50016329E /* ServiceTermsModalScreenViewModelType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceTermsModalScreenViewModelType.swift; sourceTree = "<group>"; };
|
||||
32DB557222FDADE50016329E /* ServiceTermsModalScreenCoordinatorType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceTermsModalScreenCoordinatorType.swift; sourceTree = "<group>"; };
|
||||
32DB557322FDADE50016329E /* ServiceTermsModalScreenViewAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceTermsModalScreenViewAction.swift; sourceTree = "<group>"; };
|
||||
32DB557422FDADE50016329E /* ServiceTermsModalScreenCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceTermsModalScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
32F6B9632270623000BBA352 /* DeviceVerificationDataLoadingCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceVerificationDataLoadingCoordinator.swift; sourceTree = "<group>"; };
|
||||
32F6B9642270623100BBA352 /* DeviceVerificationDataLoadingViewState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceVerificationDataLoadingViewState.swift; sourceTree = "<group>"; };
|
||||
32F6B9652270623100BBA352 /* DeviceVerificationDataLoadingViewAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceVerificationDataLoadingViewAction.swift; sourceTree = "<group>"; };
|
||||
|
@ -768,6 +816,11 @@
|
|||
B110872121F098EF003554A5 /* ActivityIndicatorPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActivityIndicatorPresenter.swift; sourceTree = "<group>"; };
|
||||
B110872221F098F0003554A5 /* ActivityIndicatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActivityIndicatorView.swift; sourceTree = "<group>"; };
|
||||
B120863622EF375F001F89E0 /* ReactionHistoryBridgeCoordinatorPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionHistoryBridgeCoordinatorPresenter.swift; sourceTree = "<group>"; };
|
||||
B125FE1A231D5BF200B72806 /* SettingsDiscoveryTableViewSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsDiscoveryTableViewSection.swift; sourceTree = "<group>"; };
|
||||
B125FE1C231D5DE400B72806 /* SettingsDiscoveryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsDiscoveryViewModel.swift; sourceTree = "<group>"; };
|
||||
B125FE1E231D5DF700B72806 /* SettingsDiscoveryViewModelType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsDiscoveryViewModelType.swift; sourceTree = "<group>"; };
|
||||
B125FE20231D5E1D00B72806 /* SettingsDiscoveryViewAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsDiscoveryViewAction.swift; sourceTree = "<group>"; };
|
||||
B125FE22231D5E4300B72806 /* SettingsDiscoveryViewState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsDiscoveryViewState.swift; sourceTree = "<group>"; };
|
||||
B139C21A21FE5B9100BB68EC /* KeyBackupRecoverFromPassphraseViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverFromPassphraseViewModel.swift; sourceTree = "<group>"; };
|
||||
B139C21C21FE5BF500BB68EC /* KeyBackupRecoverFromPassphraseViewModelType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverFromPassphraseViewModelType.swift; sourceTree = "<group>"; };
|
||||
B139C21E21FE5D6600BB68EC /* KeyBackupRecoverFromPassphraseViewAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverFromPassphraseViewAction.swift; sourceTree = "<group>"; };
|
||||
|
@ -790,6 +843,15 @@
|
|||
B152C72D22DF55D80041315A /* RiotTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RiotTests-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
B152C73022DF561E0041315A /* EmojiServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiServiceTests.swift; sourceTree = "<group>"; };
|
||||
B152C73422DF599B0041315A /* apple_emojis_data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = apple_emojis_data.json; sourceTree = "<group>"; };
|
||||
B157FA9723264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsDiscoveryThreePidDetailsCoordinator.swift; sourceTree = "<group>"; };
|
||||
B157FA9823264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsViewModelType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsDiscoveryThreePidDetailsViewModelType.swift; sourceTree = "<group>"; };
|
||||
B157FA9923264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsCoordinatorType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsDiscoveryThreePidDetailsCoordinatorType.swift; sourceTree = "<group>"; };
|
||||
B157FA9A23264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsViewAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsDiscoveryThreePidDetailsViewAction.swift; sourceTree = "<group>"; };
|
||||
B157FA9B23264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsViewState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsDiscoveryThreePidDetailsViewState.swift; sourceTree = "<group>"; };
|
||||
B157FA9C23264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsViewController.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = SettingsDiscoveryThreePidDetailsViewController.storyboard; sourceTree = "<group>"; };
|
||||
B157FA9D23264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsDiscoveryThreePidDetailsViewModel.swift; sourceTree = "<group>"; };
|
||||
B157FA9E23264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsDiscoveryThreePidDetailsViewController.swift; sourceTree = "<group>"; };
|
||||
B157FAA723264BED00EBFBD4 /* SettingsDiscoveryThreePidDetailsCoordinatorBridgePresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsDiscoveryThreePidDetailsCoordinatorBridgePresenter.swift; sourceTree = "<group>"; };
|
||||
B1664BAD20F4E67500808783 /* FallbackViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = FallbackViewController.xib; sourceTree = "<group>"; };
|
||||
B1664BAE20F4E67500808783 /* FallbackViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FallbackViewController.m; sourceTree = "<group>"; };
|
||||
B1664BAF20F4E67500808783 /* FallbackViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FallbackViewController.h; sourceTree = "<group>"; };
|
||||
|
@ -1287,6 +1349,15 @@
|
|||
B1C335FF22F1ED5F0021BA8D /* MediaPickerCoordinatorBridgePresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaPickerCoordinatorBridgePresenter.swift; sourceTree = "<group>"; };
|
||||
B1C3360022F1ED600021BA8D /* MediaPickerCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaPickerCoordinator.swift; sourceTree = "<group>"; };
|
||||
B1C3361B22F32B4A0021BA8D /* SingleImagePickerPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleImagePickerPresenter.swift; sourceTree = "<group>"; };
|
||||
B1C45A7B232A8C2600165425 /* SettingsIdentityServerCoordinatorType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsIdentityServerCoordinatorType.swift; sourceTree = "<group>"; };
|
||||
B1C45A7C232A8C2600165425 /* SettingsIdentityServerViewController.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = SettingsIdentityServerViewController.storyboard; sourceTree = "<group>"; };
|
||||
B1C45A7D232A8C2600165425 /* SettingsIdentityServerViewModelType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsIdentityServerViewModelType.swift; sourceTree = "<group>"; };
|
||||
B1C45A7E232A8C2600165425 /* SettingsIdentityServerCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsIdentityServerCoordinator.swift; sourceTree = "<group>"; };
|
||||
B1C45A7F232A8C2600165425 /* SettingsIdentityServerViewState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsIdentityServerViewState.swift; sourceTree = "<group>"; };
|
||||
B1C45A80232A8C2600165425 /* SettingsIdentityServerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsIdentityServerViewController.swift; sourceTree = "<group>"; };
|
||||
B1C45A81232A8C2600165425 /* SettingsIdentityServerCoordinatorBridgePresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsIdentityServerCoordinatorBridgePresenter.swift; sourceTree = "<group>"; };
|
||||
B1C45A82232A8C2600165425 /* SettingsIdentityServerViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsIdentityServerViewModel.swift; sourceTree = "<group>"; };
|
||||
B1C45A83232A8C2600165425 /* SettingsIdentityServerViewAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsIdentityServerViewAction.swift; sourceTree = "<group>"; };
|
||||
B1C562C92289C2690037F12A /* UIGestureRecognizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIGestureRecognizer.swift; sourceTree = "<group>"; };
|
||||
B1C562CB228AB3510037F12A /* UIStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIStackView.swift; sourceTree = "<group>"; };
|
||||
B1C562D8228C0B760037F12A /* RoomContextualMenuItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomContextualMenuItem.swift; sourceTree = "<group>"; };
|
||||
|
@ -1701,6 +1772,40 @@
|
|||
path = KeyBackup;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
32DB556722FDADE50016329E /* ServiceTerms */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
32DB556822FDADE50016329E /* Modal */,
|
||||
);
|
||||
path = ServiceTerms;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
32DB556822FDADE50016329E /* Modal */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
32DB556922FDADE50016329E /* ServiceTermsModalCoordinatorType.swift */,
|
||||
32DB556A22FDADE50016329E /* ServiceTermsModalCoordinatorBridgePresenter.swift */,
|
||||
32DB556B22FDADE50016329E /* ServiceTermsModalCoordinator.swift */,
|
||||
32DB556C22FDADE50016329E /* Modal */,
|
||||
);
|
||||
path = Modal;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
32DB556C22FDADE50016329E /* Modal */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
32DB556D22FDADE50016329E /* ServiceTermsModalScreenViewState.swift */,
|
||||
32DB556E22FDADE50016329E /* ServiceTermsModalScreenViewModel.swift */,
|
||||
32DB556F22FDADE50016329E /* ServiceTermsModalScreenViewController.swift */,
|
||||
32DB557022FDADE50016329E /* ServiceTermsModalScreenViewController.storyboard */,
|
||||
32DB557122FDADE50016329E /* ServiceTermsModalScreenViewModelType.swift */,
|
||||
32DB557222FDADE50016329E /* ServiceTermsModalScreenCoordinatorType.swift */,
|
||||
32DB557322FDADE50016329E /* ServiceTermsModalScreenViewAction.swift */,
|
||||
32DB557422FDADE50016329E /* ServiceTermsModalScreenCoordinator.swift */,
|
||||
);
|
||||
path = Modal;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4220F60B660591FD80AF3428 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -1859,6 +1964,19 @@
|
|||
path = ActivityIndicator;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B125FE19231D5B5600B72806 /* Discovery */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B125FE1A231D5BF200B72806 /* SettingsDiscoveryTableViewSection.swift */,
|
||||
B125FE1E231D5DF700B72806 /* SettingsDiscoveryViewModelType.swift */,
|
||||
B125FE1C231D5DE400B72806 /* SettingsDiscoveryViewModel.swift */,
|
||||
B125FE20231D5E1D00B72806 /* SettingsDiscoveryViewAction.swift */,
|
||||
B125FE22231D5E4300B72806 /* SettingsDiscoveryViewState.swift */,
|
||||
B157FA9623264AE800EBFBD4 /* ThreePidDetails */,
|
||||
);
|
||||
path = Discovery;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B14F142522144F6400FA0595 /* RecoveryKey */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -1907,6 +2025,22 @@
|
|||
path = Data;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B157FA9623264AE800EBFBD4 /* ThreePidDetails */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B157FAA723264BED00EBFBD4 /* SettingsDiscoveryThreePidDetailsCoordinatorBridgePresenter.swift */,
|
||||
B157FA9923264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsCoordinatorType.swift */,
|
||||
B157FA9723264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsCoordinator.swift */,
|
||||
B157FA9823264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsViewModelType.swift */,
|
||||
B157FA9D23264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsViewModel.swift */,
|
||||
B157FA9A23264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsViewAction.swift */,
|
||||
B157FA9B23264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsViewState.swift */,
|
||||
B157FA9E23264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsViewController.swift */,
|
||||
B157FA9C23264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsViewController.storyboard */,
|
||||
);
|
||||
path = ThreePidDetails;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B1664BAB20F4E67500808783 /* Modules */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -2190,6 +2324,7 @@
|
|||
B1B5567620EE6C4C00210D55 /* Modules */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
32DB556722FDADE50016329E /* ServiceTerms */,
|
||||
3232AB94225730E100AD6A5C /* DeviceVerification */,
|
||||
B1B556EA20EE6C4C00210D55 /* Main */,
|
||||
B1B556CA20EE6C4C00210D55 /* TabBar */,
|
||||
|
@ -2227,6 +2362,8 @@
|
|||
B1B5567E20EE6C4C00210D55 /* SettingsViewController.m */,
|
||||
B1B5578120EF564900210D55 /* Views */,
|
||||
32BF994D21FA1C6300698084 /* KeyBackup */,
|
||||
B125FE19231D5B5600B72806 /* Discovery */,
|
||||
B1C45A7A232A8C2600165425 /* IdentityServer */,
|
||||
B1B5567B20EE6C4C00210D55 /* Language */,
|
||||
B1B5567820EE6C4C00210D55 /* PhoneCountry */,
|
||||
B1B5568020EE6C4C00210D55 /* DeactivateAccount */,
|
||||
|
@ -3342,6 +3479,22 @@
|
|||
path = Camera;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B1C45A7A232A8C2600165425 /* IdentityServer */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B1C45A81232A8C2600165425 /* SettingsIdentityServerCoordinatorBridgePresenter.swift */,
|
||||
B1C45A7B232A8C2600165425 /* SettingsIdentityServerCoordinatorType.swift */,
|
||||
B1C45A7E232A8C2600165425 /* SettingsIdentityServerCoordinator.swift */,
|
||||
B1C45A7D232A8C2600165425 /* SettingsIdentityServerViewModelType.swift */,
|
||||
B1C45A82232A8C2600165425 /* SettingsIdentityServerViewModel.swift */,
|
||||
B1C45A83232A8C2600165425 /* SettingsIdentityServerViewAction.swift */,
|
||||
B1C45A7F232A8C2600165425 /* SettingsIdentityServerViewState.swift */,
|
||||
B1C45A80232A8C2600165425 /* SettingsIdentityServerViewController.swift */,
|
||||
B1C45A7C232A8C2600165425 /* SettingsIdentityServerViewController.storyboard */,
|
||||
);
|
||||
path = IdentityServer;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B1C562D7228C0B4C0037F12A /* ContextualMenu */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -3759,6 +3912,7 @@
|
|||
es,
|
||||
ja,
|
||||
hu,
|
||||
pl,
|
||||
);
|
||||
mainGroup = F094A9991B78D8F000B1FBBF;
|
||||
productRefGroup = F094A9A31B78D8F000B1FBBF /* Products */;
|
||||
|
@ -3814,6 +3968,7 @@
|
|||
B1B5597020EFA85D00210D55 /* EncryptionInfoView.xib in Resources */,
|
||||
B1B558BC20EF768F00210D55 /* RoomMembershipBubbleCell.xib in Resources */,
|
||||
B1B5571F20EE6C4D00210D55 /* ContactDetailsViewController.xib in Resources */,
|
||||
B157FAA423264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsViewController.storyboard in Resources */,
|
||||
B1B558E220EF768F00210D55 /* RoomIncomingTextMsgBubbleCell.xib in Resources */,
|
||||
B105778B221304FA00334B1E /* KeyBackupSetupSuccessFromPassphraseViewController.storyboard in Resources */,
|
||||
B1664DA220F4F95800808783 /* Localizable.strings in Resources */,
|
||||
|
@ -3845,7 +4000,9 @@
|
|||
B1B558F620EF768F00210D55 /* RoomOutgoingTextMsgBubbleCell.xib in Resources */,
|
||||
B1B5574D20EE6C4D00210D55 /* MediaPickerViewController.xib in Resources */,
|
||||
B1B5575020EE6C4D00210D55 /* AuthenticationViewController.xib in Resources */,
|
||||
B1C45A85232A8C2600165425 /* SettingsIdentityServerViewController.storyboard in Resources */,
|
||||
B14F142E22144F6500FA0595 /* KeyBackupRecoverFromRecoveryKeyViewController.storyboard in Resources */,
|
||||
32DB557B22FDADE50016329E /* ServiceTermsModalScreenViewController.storyboard in Resources */,
|
||||
B1B5574320EE6C4D00210D55 /* CallViewController.xib in Resources */,
|
||||
F083BDEA1E7009ED00A9B29C /* ringback.mp3 in Resources */,
|
||||
F083BDF21E7009ED00A9B29C /* GoogleService-Info.plist in Resources */,
|
||||
|
@ -4155,6 +4312,7 @@
|
|||
324A2053225FC571004FE8B0 /* DeviceVerificationIncomingViewModel.swift in Sources */,
|
||||
B1B557A120EF58AD00210D55 /* ContactTableViewCell.m in Sources */,
|
||||
F083BE021E7009ED00A9B29C /* AvatarGenerator.m in Sources */,
|
||||
B157FAA023264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsViewModelType.swift in Sources */,
|
||||
B1B5573A20EE6C4D00210D55 /* GroupRoomsViewController.m in Sources */,
|
||||
B1B558F920EF768F00210D55 /* RoomOutgoingTextMsgWithoutSenderNameBubbleCell.m in Sources */,
|
||||
B1FDF56021F5FE5500BA3834 /* KeyBackupSetupPassphraseViewAction.swift in Sources */,
|
||||
|
@ -4165,6 +4323,7 @@
|
|||
B19EFA3B21F8BB4100FC070E /* KeyBackupRecoverCoordinator.swift in Sources */,
|
||||
B1B9DEDE22E9D9890065E677 /* EmojiServiceType.swift in Sources */,
|
||||
3232ABA9225730E100AD6A5C /* DeviceVerificationStartViewModel.swift in Sources */,
|
||||
32DB557C22FDADE50016329E /* ServiceTermsModalScreenViewModelType.swift in Sources */,
|
||||
B16932FA20F3C51A00746532 /* RecentCellData.m in Sources */,
|
||||
B16932F220F3C49E00746532 /* GroupsDataSource.m in Sources */,
|
||||
B1B5581C20EF625800210D55 /* RoomAvatarTitleView.m in Sources */,
|
||||
|
@ -4172,6 +4331,7 @@
|
|||
B1B5574B20EE6C4D00210D55 /* MediaAlbumContentViewController.m in Sources */,
|
||||
B1B5598820EFC3E000210D55 /* WidgetManager.m in Sources */,
|
||||
B1DB4F0E22316FFF0065DBFA /* UserNameColorGenerator.swift in Sources */,
|
||||
B157FAA123264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsCoordinatorType.swift in Sources */,
|
||||
B1057789221304EC00334B1E /* KeyBackupSetupSuccessFromPassphraseViewController.swift in Sources */,
|
||||
B1DCC61922E5E17100625807 /* EmojiPickerCoordinatorType.swift in Sources */,
|
||||
B1C3360122F1ED600021BA8D /* MediaPickerCoordinatorType.swift in Sources */,
|
||||
|
@ -4216,6 +4376,7 @@
|
|||
B1C3361C22F32B4A0021BA8D /* SingleImagePickerPresenter.swift in Sources */,
|
||||
B1B5572F20EE6C4D00210D55 /* ReadReceiptsViewController.m in Sources */,
|
||||
B1B558CB20EF768F00210D55 /* RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.m in Sources */,
|
||||
B157FAA823264BED00EBFBD4 /* SettingsDiscoveryThreePidDetailsCoordinatorBridgePresenter.swift in Sources */,
|
||||
B169330B20F3CA3A00746532 /* Contact.m in Sources */,
|
||||
B1A5B33E227ADF2A004CBA85 /* UIImage.swift in Sources */,
|
||||
B1D4752A21EE52B10067973F /* KeyBackupSetupIntroViewController.swift in Sources */,
|
||||
|
@ -4231,6 +4392,7 @@
|
|||
B1B5577420EE702900210D55 /* WidgetViewController.m in Sources */,
|
||||
B1DCC63122E7026F00625807 /* EmojiPickerHeaderView.swift in Sources */,
|
||||
B139C21B21FE5B9200BB68EC /* KeyBackupRecoverFromPassphraseViewModel.swift in Sources */,
|
||||
B1C45A8C232A8C2600165425 /* SettingsIdentityServerViewAction.swift in Sources */,
|
||||
32A6001E22C661100042C1D9 /* EditHistoryCoordinatorBridgePresenter.swift in Sources */,
|
||||
B1B5574A20EE6C4D00210D55 /* MediaPickerViewController.m in Sources */,
|
||||
B1B5598520EFC3E000210D55 /* RageShakeManager.m in Sources */,
|
||||
|
@ -4239,11 +4401,14 @@
|
|||
B1B558D420EF768F00210D55 /* RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.m in Sources */,
|
||||
B169331420F3CAFC00746532 /* PublicRoomTableViewCell.m in Sources */,
|
||||
32BF995721FB07A400698084 /* SettingsKeyBackupTableViewSection.swift in Sources */,
|
||||
B1C45A88232A8C2600165425 /* SettingsIdentityServerViewState.swift in Sources */,
|
||||
B14F142F22144F6500FA0595 /* KeyBackupRecoverFromRecoveryKeyViewModelType.swift in Sources */,
|
||||
32DB557822FDADE50016329E /* ServiceTermsModalScreenViewState.swift in Sources */,
|
||||
B1B558E120EF768F00210D55 /* RoomMembershipCollapsedBubbleCell.m in Sources */,
|
||||
B1B5571A20EE6C4D00210D55 /* SettingsViewController.m in Sources */,
|
||||
B1CE9EFD22148703000FAE6A /* SignOutAlertPresenter.swift in Sources */,
|
||||
32F6B9692270623100BBA352 /* DeviceVerificationDataLoadingCoordinator.swift in Sources */,
|
||||
B125FE1D231D5DE400B72806 /* SettingsDiscoveryViewModel.swift in Sources */,
|
||||
B1B5594720EF7BD000210D55 /* RoomCollectionViewCell.m in Sources */,
|
||||
B10CFBC32268D99D00A5842E /* JitsiService.swift in Sources */,
|
||||
B1B558C120EF768F00210D55 /* RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.m in Sources */,
|
||||
|
@ -4260,6 +4425,7 @@
|
|||
3275FD8C21A5A2C500B9C13D /* TermsView.swift in Sources */,
|
||||
B1B9DEE822EB34EF0065E677 /* ReactionHistoryCoordinatorType.swift in Sources */,
|
||||
B14F143122144F6500FA0595 /* KeyBackupRecoverFromRecoveryKeyViewState.swift in Sources */,
|
||||
32DB557F22FDADE50016329E /* ServiceTermsModalScreenCoordinator.swift in Sources */,
|
||||
B1098C1121ED07E4000DDA48 /* NavigationRouterType.swift in Sources */,
|
||||
B1B5573D20EE6C4D00210D55 /* WebViewViewController.m in Sources */,
|
||||
3209451221F1C1430088CAA2 /* BlackTheme.swift in Sources */,
|
||||
|
@ -4267,6 +4433,8 @@
|
|||
3232ABBC2257BE6500AD6A5C /* DeviceVerificationVerifyViewAction.swift in Sources */,
|
||||
F05927C91FDED836009F2A68 /* MXGroup+Riot.m in Sources */,
|
||||
B1B5594520EF7BD000210D55 /* TableViewCellWithCollectionView.m in Sources */,
|
||||
32DB557722FDADE50016329E /* ServiceTermsModalCoordinator.swift in Sources */,
|
||||
32DB557922FDADE50016329E /* ServiceTermsModalScreenViewModel.swift in Sources */,
|
||||
32891D75226728EE00C82226 /* DeviceVerificationDataLoadingViewController.swift in Sources */,
|
||||
32891D712264DF7B00C82226 /* DeviceVerificationVerifiedViewController.swift in Sources */,
|
||||
F083BDEF1E7009ED00A9B29C /* UINavigationController+Riot.m in Sources */,
|
||||
|
@ -4277,6 +4445,7 @@
|
|||
B1B5571920EE6C4D00210D55 /* LanguagePickerViewController.m in Sources */,
|
||||
3232AB512256558300AD6A5C /* TemplateScreenViewAction.swift in Sources */,
|
||||
3232AB4E2256558300AD6A5C /* TemplateScreenViewModelType.swift in Sources */,
|
||||
32DB557D22FDADE50016329E /* ServiceTermsModalScreenCoordinatorType.swift in Sources */,
|
||||
B1B5590520EF768F00210D55 /* RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m in Sources */,
|
||||
3232ABA5225730E100AD6A5C /* DeviceVerificationStartViewModelType.swift in Sources */,
|
||||
B1B558DD20EF768F00210D55 /* RoomIncomingEncryptedTextMsgBubbleCell.m in Sources */,
|
||||
|
@ -4287,6 +4456,7 @@
|
|||
B1D4752721EE4E630067973F /* KeyboardAvoider.swift in Sources */,
|
||||
B1D4752821EE4E630067973F /* KeyboardNotification.swift in Sources */,
|
||||
B1D1BDA622BBAFB500831367 /* ReactionsMenuView.swift in Sources */,
|
||||
32DB557A22FDADE50016329E /* ServiceTermsModalScreenViewController.swift in Sources */,
|
||||
B1B9DEF422EB426D0065E677 /* ReactionHistoryViewCell.swift in Sources */,
|
||||
B1B5573C20EE6C4D00210D55 /* MasterTabBarController.m in Sources */,
|
||||
B1DCC61B22E5E17100625807 /* EmojiPickerCoordinator.swift in Sources */,
|
||||
|
@ -4299,6 +4469,7 @@
|
|||
B1B5582C20EF666100210D55 /* DirectoryRecentTableViewCell.m in Sources */,
|
||||
B1B558E420EF768F00210D55 /* RoomMembershipWithPaginationTitleBubbleCell.m in Sources */,
|
||||
B1B5573620EE6C4D00210D55 /* GroupsViewController.m in Sources */,
|
||||
B125FE21231D5E1D00B72806 /* SettingsDiscoveryViewAction.swift in Sources */,
|
||||
3232ABB82257BE6500AD6A5C /* DeviceVerificationVerifyCoordinator.swift in Sources */,
|
||||
B142317A22CCFA2000FFA96A /* EditHistoryCell.swift in Sources */,
|
||||
B1DCC62622E60CC600625807 /* EmojiItem.swift in Sources */,
|
||||
|
@ -4310,7 +4481,11 @@
|
|||
B1DCC63922E85E9A00625807 /* EmojiMartStore.swift in Sources */,
|
||||
B1B5590620EF768F00210D55 /* RoomMembershipCollapsedWithPaginationTitleBubbleCell.m in Sources */,
|
||||
B139C21D21FE5BF500BB68EC /* KeyBackupRecoverFromPassphraseViewModelType.swift in Sources */,
|
||||
B157FA9F23264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsCoordinator.swift in Sources */,
|
||||
B1C45A8B232A8C2600165425 /* SettingsIdentityServerViewModel.swift in Sources */,
|
||||
B1C45A86232A8C2600165425 /* SettingsIdentityServerViewModelType.swift in Sources */,
|
||||
F083BE031E7009ED00A9B29C /* EventFormatter.m in Sources */,
|
||||
B157FAA623264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsViewController.swift in Sources */,
|
||||
B1DCC62422E60CA900625807 /* EmojiPickerCategoryViewData.swift in Sources */,
|
||||
324A2056225FC571004FE8B0 /* DeviceVerificationIncomingCoordinator.swift in Sources */,
|
||||
B16932F720F3C50E00746532 /* RecentsDataSource.m in Sources */,
|
||||
|
@ -4343,12 +4518,16 @@
|
|||
B1B12B2922942315002CB419 /* UITouch.swift in Sources */,
|
||||
B1B558CC20EF768F00210D55 /* RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.m in Sources */,
|
||||
B1B5571D20EE6C4D00210D55 /* HomeViewController.m in Sources */,
|
||||
B1C45A84232A8C2600165425 /* SettingsIdentityServerCoordinatorType.swift in Sources */,
|
||||
B1DCC63722E8541700625807 /* EmojiStore.swift in Sources */,
|
||||
3232ABA6225730E100AD6A5C /* DeviceVerificationStartViewController.swift in Sources */,
|
||||
B16932EA20F3C39000746532 /* UnifiedSearchRecentsDataSource.m in Sources */,
|
||||
B1C45A8A232A8C2600165425 /* SettingsIdentityServerCoordinatorBridgePresenter.swift in Sources */,
|
||||
B1B557DE20EF5FBB00210D55 /* FilesSearchTableViewCell.m in Sources */,
|
||||
B1B5574020EE6C4D00210D55 /* SegmentedViewController.m in Sources */,
|
||||
B1B5599320EFC5E400210D55 /* DecryptionFailure.m in Sources */,
|
||||
B125FE1F231D5DF700B72806 /* SettingsDiscoveryViewModelType.swift in Sources */,
|
||||
B157FAA323264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsViewState.swift in Sources */,
|
||||
B1098BF921ECFE65000DDA48 /* KeyBackupSetupCoordinator.swift in Sources */,
|
||||
B140B4A821F8AB4600E3F5FE /* KeyBackupRecoverCoordinatorBridgePresenter.swift in Sources */,
|
||||
B1098BFE21ECFE65000DDA48 /* KeyBackupSetupPassphraseViewModelType.swift in Sources */,
|
||||
|
@ -4382,6 +4561,7 @@
|
|||
B1B557BE20EF5B4500210D55 /* RoomInputToolbarView.m in Sources */,
|
||||
32A6001922C661100042C1D9 /* EditHistoryViewModelType.swift in Sources */,
|
||||
B1B5573B20EE6C4D00210D55 /* FavouritesViewController.m in Sources */,
|
||||
B1C45A87232A8C2600165425 /* SettingsIdentityServerCoordinator.swift in Sources */,
|
||||
B1B5579920EF575B00210D55 /* AuthInputsView.m in Sources */,
|
||||
B1B5597520EFB02A00210D55 /* InviteRecentTableViewCell.m in Sources */,
|
||||
B1B5571E20EE6C4D00210D55 /* ContactDetailsViewController.m in Sources */,
|
||||
|
@ -4404,6 +4584,7 @@
|
|||
B1B557D820EF5EA900210D55 /* RoomActivitiesView.m in Sources */,
|
||||
B1B9DEE922EB34EF0065E677 /* ReactionHistoryViewController.swift in Sources */,
|
||||
B1B5596620EF9E9B00210D55 /* RoomTableViewCell.m in Sources */,
|
||||
B1C45A89232A8C2600165425 /* SettingsIdentityServerViewController.swift in Sources */,
|
||||
B14F143322144F6500FA0595 /* KeyBackupRecoverFromRecoveryKeyViewModel.swift in Sources */,
|
||||
32A6001822C661100042C1D9 /* EditHistoryViewModel.swift in Sources */,
|
||||
B1B558D020EF768F00210D55 /* RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m in Sources */,
|
||||
|
@ -4423,6 +4604,7 @@
|
|||
B1B558C720EF768F00210D55 /* RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.m in Sources */,
|
||||
B1B558F020EF768F00210D55 /* RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m in Sources */,
|
||||
926FA53F1F4C132000F826C2 /* MXSession+Riot.m in Sources */,
|
||||
B125FE23231D5E4300B72806 /* SettingsDiscoveryViewState.swift in Sources */,
|
||||
B1B5593820EF7BAC00210D55 /* TableViewCellWithLabelAndLargeTextView.m in Sources */,
|
||||
B1DCC62222E60BE000625807 /* EmojiPickerItemViewData.swift in Sources */,
|
||||
3232AB502256558300AD6A5C /* TemplateScreenViewState.swift in Sources */,
|
||||
|
@ -4439,6 +4621,7 @@
|
|||
B1098BFF21ECFE65000DDA48 /* PasswordStrengthView.swift in Sources */,
|
||||
B1B558D220EF768F00210D55 /* RoomEncryptedDataBubbleCell.m in Sources */,
|
||||
B1B558FA20EF768F00210D55 /* RoomMembershipBubbleCell.m in Sources */,
|
||||
B157FAA223264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsViewAction.swift in Sources */,
|
||||
3232ABA1225730E100AD6A5C /* DeviceVerificationCoordinatorType.swift in Sources */,
|
||||
B1C562D9228C0B760037F12A /* RoomContextualMenuItem.swift in Sources */,
|
||||
323AB947232BD74600C1451F /* AuthFallBackViewController.m in Sources */,
|
||||
|
@ -4461,6 +4644,7 @@
|
|||
B1B557CC20EF5D8000210D55 /* DirectoryServerTableViewCell.m in Sources */,
|
||||
B1963B2B228F1C4900CBA17F /* BubbleReactionsView.swift in Sources */,
|
||||
B1B5575C20EE6C4D00210D55 /* DirectoryViewController.m in Sources */,
|
||||
32DB557622FDADE50016329E /* ServiceTermsModalCoordinatorBridgePresenter.swift in Sources */,
|
||||
B1B558BD20EF768F00210D55 /* RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.m in Sources */,
|
||||
B1B5577020EE702800210D55 /* WidgetPickerViewController.m in Sources */,
|
||||
B1B558D320EF768F00210D55 /* RoomOutgoingEncryptedTextMsgBubbleCell.m in Sources */,
|
||||
|
@ -4476,6 +4660,7 @@
|
|||
32B94DF9228EC26400716A26 /* ReactionsMenuViewAction.swift in Sources */,
|
||||
B1B5599420EFC5E400210D55 /* DecryptionFailureTracker.m in Sources */,
|
||||
F083BDF01E7009ED00A9B29C /* UIViewController+RiotSearch.m in Sources */,
|
||||
32DB557522FDADE50016329E /* ServiceTermsModalCoordinatorType.swift in Sources */,
|
||||
F083BDF91E7009ED00A9B29C /* RoomEmailInvitation.m in Sources */,
|
||||
B1D211E422C18E3800D939BD /* ReactionsMenuViewModelType.swift in Sources */,
|
||||
324A2055225FC571004FE8B0 /* DeviceVerificationIncomingViewModelType.swift in Sources */,
|
||||
|
@ -4484,6 +4669,7 @@
|
|||
3232ABB52257BE6400AD6A5C /* DeviceVerificationVerifyCoordinatorType.swift in Sources */,
|
||||
32BF994F21FA29A400698084 /* SettingsKeyBackupViewModel.swift in Sources */,
|
||||
B190F55D22CE5A9700AEB493 /* EditHistorySection.swift in Sources */,
|
||||
32DB557E22FDADE50016329E /* ServiceTermsModalScreenViewAction.swift in Sources */,
|
||||
32A6002022C66FCF0042C1D9 /* EditHistoryMessage.swift in Sources */,
|
||||
B1B5574920EE6C4D00210D55 /* RiotSplitViewController.m in Sources */,
|
||||
B1B5574E20EE6C4D00210D55 /* DirectoryServerPickerViewController.m in Sources */,
|
||||
|
@ -4497,6 +4683,7 @@
|
|||
3232AB482256558300AD6A5C /* FlowTemplateCoordinatorType.swift in Sources */,
|
||||
B1B9DEF122EB396B0065E677 /* ReactionHistoryViewData.swift in Sources */,
|
||||
B1B558F820EF768F00210D55 /* RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m in Sources */,
|
||||
B125FE1B231D5BF200B72806 /* SettingsDiscoveryTableViewSection.swift in Sources */,
|
||||
32242F0921E8B05F00725742 /* UIColor.swift in Sources */,
|
||||
B16932E720F3C37100746532 /* HomeMessagesSearchDataSource.m in Sources */,
|
||||
B1B558CE20EF768F00210D55 /* RoomOutgoingEncryptedAttachmentBubbleCell.m in Sources */,
|
||||
|
@ -4510,6 +4697,7 @@
|
|||
B1B9DEEE22EB34EF0065E677 /* ReactionHistoryViewAction.swift in Sources */,
|
||||
32B94DFA228EC26400716A26 /* ReactionsMenuButton.swift in Sources */,
|
||||
B1B9DEEC22EB34EF0065E677 /* ReactionHistoryViewModelType.swift in Sources */,
|
||||
B157FAA523264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsViewModel.swift in Sources */,
|
||||
B1C562E8228C7CF20037F12A /* ContextualMenuItemView.swift in Sources */,
|
||||
B14F143022144F6500FA0595 /* KeyBackupRecoverFromRecoveryKeyCoordinatorType.swift in Sources */,
|
||||
B1E5368921FB1E20001F3AFF /* UIButton.swift in Sources */,
|
||||
|
@ -4567,6 +4755,7 @@
|
|||
32D7159E2146CC6F00DF59C9 /* es */,
|
||||
3D78489221AC9E6500B98A7D /* ja */,
|
||||
3D78489521ACA25300B98A7D /* hu */,
|
||||
32DAF8DD231813E100654A44 /* pl */,
|
||||
);
|
||||
name = Vector.strings;
|
||||
sourceTree = "<group>";
|
||||
|
@ -4589,6 +4778,7 @@
|
|||
32D715A02146CC8800DF59C9 /* es */,
|
||||
3D78489021AC9E6400B98A7D /* ja */,
|
||||
3D78489321ACA25200B98A7D /* hu */,
|
||||
32DAF8DB231813C800654A44 /* pl */,
|
||||
);
|
||||
name = InfoPlist.strings;
|
||||
sourceTree = "<group>";
|
||||
|
@ -4611,6 +4801,7 @@
|
|||
32D7159F2146CC7F00DF59C9 /* es */,
|
||||
3D78489121AC9E6500B98A7D /* ja */,
|
||||
3D78489421ACA25300B98A7D /* hu */,
|
||||
32DAF8DC231813D500654A44 /* pl */,
|
||||
);
|
||||
name = Localizable.strings;
|
||||
sourceTree = "<group>";
|
||||
|
|
|
@ -38,6 +38,10 @@ extern NSString *const kAppDelegateDidTapStatusBarNotification;
|
|||
*/
|
||||
extern NSString *const kAppDelegateNetworkStatusDidChangeNotification;
|
||||
|
||||
extern NSString *const AppDelegateDidValidateEmailNotification;
|
||||
extern NSString *const AppDelegateDidValidateEmailNotificationSIDKey;
|
||||
extern NSString *const AppDelegateDidValidateEmailNotificationClientSecretKey;
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate, MXKCallViewControllerDelegate, UISplitViewControllerDelegate, UINavigationControllerDelegate, JitsiViewControllerDelegate, UNUserNotificationCenterDelegate>
|
||||
{
|
||||
BOOL isPushRegistered;
|
||||
|
|
|
@ -84,7 +84,11 @@
|
|||
NSString *const kAppDelegateDidTapStatusBarNotification = @"kAppDelegateDidTapStatusBarNotification";
|
||||
NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateNetworkStatusDidChangeNotification";
|
||||
|
||||
@interface AppDelegate () <PKPushRegistryDelegate, GDPRConsentViewControllerDelegate, DeviceVerificationCoordinatorBridgePresenterDelegate>
|
||||
NSString *const AppDelegateDidValidateEmailNotification = @"AppDelegateDidValidateEmailNotification";
|
||||
NSString *const AppDelegateDidValidateEmailNotificationSIDKey = @"AppDelegateDidValidateEmailNotificationSIDKey";
|
||||
NSString *const AppDelegateDidValidateEmailNotificationClientSecretKey = @"AppDelegateDidValidateEmailNotificationClientSecretKey";
|
||||
|
||||
@interface AppDelegate () <PKPushRegistryDelegate, GDPRConsentViewControllerDelegate, DeviceVerificationCoordinatorBridgePresenterDelegate, ServiceTermsModalCoordinatorBridgePresenterDelegate>
|
||||
{
|
||||
/**
|
||||
Reachability observer
|
||||
|
@ -233,6 +237,8 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
|
|||
@property (weak, nonatomic) UIAlertController *gdprConsentNotGivenAlertController;
|
||||
@property (weak, nonatomic) UIViewController *gdprConsentController;
|
||||
|
||||
@property (nonatomic, strong) ServiceTermsModalCoordinatorBridgePresenter *serviceTermsModalCoordinatorBridgePresenter;
|
||||
|
||||
/**
|
||||
Used to manage on boarding steps, like create DM with riot bot
|
||||
*/
|
||||
|
@ -647,6 +653,9 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
|
|||
// Register to GDPR consent not given notification
|
||||
[self registerUserConsentNotGivenNotification];
|
||||
|
||||
// Register to identity server terms not signed notification
|
||||
[self registerIdentityServiceTermsNotSignedNotification];
|
||||
|
||||
// Start monitoring reachability
|
||||
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
|
||||
|
||||
|
@ -692,9 +701,6 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
|
|||
[account resume];
|
||||
}
|
||||
|
||||
// Refresh local contact from the contact book.
|
||||
[self refreshLocalContacts];
|
||||
|
||||
_isAppForeground = YES;
|
||||
|
||||
if (@available(iOS 11.0, *))
|
||||
|
@ -2106,19 +2112,40 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
|
|||
return [self handleServerProvionningLink:webURL];
|
||||
}
|
||||
|
||||
NSString *validateEmailSubmitTokenPath = @"validate/email/submitToken";
|
||||
|
||||
NSString *validateEmailSubmitTokenAPIPathV1 = [NSString stringWithFormat:@"/%@/%@", kMXIdentityAPIPrefixPathV1, validateEmailSubmitTokenPath];
|
||||
NSString *validateEmailSubmitTokenAPIPathV2 = [NSString stringWithFormat:@"/%@/%@", kMXIdentityAPIPrefixPathV2, validateEmailSubmitTokenPath];
|
||||
|
||||
// Manage email validation link
|
||||
if ([webURL.path isEqualToString:@"/_matrix/identity/api/v1/validate/email/submitToken"])
|
||||
if ([webURL.path isEqualToString:validateEmailSubmitTokenAPIPathV1] || [webURL.path isEqualToString:validateEmailSubmitTokenAPIPathV2])
|
||||
{
|
||||
// Validate the email on the passed identity server
|
||||
NSString *identityServer = [NSString stringWithFormat:@"%@://%@", webURL.scheme, webURL.host];
|
||||
MXRestClient *identityRestClient = [[MXRestClient alloc] initWithHomeServer:identityServer andOnUnrecognizedCertificateBlock:nil];
|
||||
|
||||
MXSession *mainSession = self.mxSessions.firstObject;
|
||||
MXRestClient *homeserverRestClient;
|
||||
|
||||
if (mainSession.matrixRestClient)
|
||||
{
|
||||
homeserverRestClient = mainSession.matrixRestClient;
|
||||
}
|
||||
else
|
||||
{
|
||||
homeserverRestClient = [[MXRestClient alloc] initWithHomeServer:identityServer andOnUnrecognizedCertificateBlock:nil];
|
||||
}
|
||||
|
||||
MXIdentityService *identityService = [[MXIdentityService alloc] initWithIdentityServer:identityServer accessToken:nil andHomeserverRestClient:homeserverRestClient];
|
||||
|
||||
// Extract required parameters from the link
|
||||
NSArray<NSString*> *pathParams;
|
||||
NSMutableDictionary *queryParams;
|
||||
[self parseUniversalLinkFragment:webURL.absoluteString outPathParams:&pathParams outQueryParams:&queryParams];
|
||||
|
||||
[identityRestClient submit3PIDValidationToken:queryParams[@"token"] medium:kMX3PIDMediumEmail clientSecret:queryParams[@"client_secret"] sid:queryParams[@"sid"] success:^{
|
||||
NSString *clientSecret = queryParams[@"client_secret"];
|
||||
NSString *sid = queryParams[@"sid"];
|
||||
|
||||
[identityService submit3PIDValidationToken:queryParams[@"token"] medium:kMX3PIDMediumEmail clientSecret:clientSecret sid:sid success:^{
|
||||
|
||||
NSLog(@"[AppDelegate] handleUniversalLink. Email successfully validated.");
|
||||
|
||||
|
@ -2132,7 +2159,15 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
|
|||
else
|
||||
{
|
||||
// No nextLink in Vector world means validation for binding a new email
|
||||
NSLog(@"[AppDelegate] handleUniversalLink. TODO: Complete email binding");
|
||||
|
||||
// Post a notification about email validation to make a chance to SettingsDiscoveryThreePidDetailsViewModel to make it discoverable or not by the identity server.
|
||||
if (clientSecret && sid)
|
||||
{
|
||||
NSDictionary *userInfo = @{ AppDelegateDidValidateEmailNotificationClientSecretKey : clientSecret,
|
||||
AppDelegateDidValidateEmailNotificationSIDKey : sid };
|
||||
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:AppDelegateDidValidateEmailNotification object:nil userInfo:userInfo];
|
||||
}
|
||||
}
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
@ -2697,6 +2732,11 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
|
|||
// Let's call invite be valid for 1 minute
|
||||
mxSession.callManager.inviteLifetime = 60000;
|
||||
|
||||
if (RiotSettings.shared.allowStunServerFallback)
|
||||
{
|
||||
mxSession.callManager.fallbackSTUNServer = RiotSettings.shared.stunServerFallback;
|
||||
}
|
||||
|
||||
// Setup CallKit
|
||||
if ([MXCallKitAdapter callKitAvailable])
|
||||
{
|
||||
|
@ -2972,6 +3012,14 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
|
|||
// during this blocking task.
|
||||
dispatch_after(dispatch_walltime(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
|
||||
[[MXKContactManager sharedManager] addMatrixSession:mxSession];
|
||||
|
||||
// Load the local contacts on first account
|
||||
if ([MXKAccountManager sharedManager].accounts.count == 1)
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self refreshLocalContacts];
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Update home data sources
|
||||
|
@ -3869,8 +3917,21 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
|
|||
|
||||
- (void)refreshLocalContacts
|
||||
{
|
||||
// Do not scan local contacts in background if the user has not decided yet about using
|
||||
// an identity server
|
||||
BOOL doRefreshLocalContacts = NO;
|
||||
for (MXSession *session in mxSessionArray)
|
||||
{
|
||||
if (session.hasAccountDataIdentityServerValue)
|
||||
{
|
||||
doRefreshLocalContacts = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether the application is allowed to access the local contacts.
|
||||
if ([CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts] == CNAuthorizationStatusAuthorized)
|
||||
if (doRefreshLocalContacts
|
||||
&& [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts] == CNAuthorizationStatusAuthorized)
|
||||
{
|
||||
// Check the user permission for syncing local contacts. This permission was handled independently on previous application version.
|
||||
if (![MXKAppSettings standardAppSettings].syncLocalContacts)
|
||||
|
@ -3942,6 +4003,12 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
|
|||
NSString *btnTitle = [NSString stringWithFormat:NSLocalizedStringFromTable(@"active_call_details", @"Vector", nil), callViewController.callerNameLabel.text];
|
||||
[self addCallStatusBar:btnTitle];
|
||||
}
|
||||
|
||||
if ([callViewController isKindOfClass:[CallViewController class]]
|
||||
&& ((CallViewController*)callViewController).shouldPromptForStunServerFallback)
|
||||
{
|
||||
[self promptForStunServerFallback];
|
||||
}
|
||||
|
||||
if (completion)
|
||||
{
|
||||
|
@ -3975,6 +4042,52 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
|
|||
}
|
||||
}
|
||||
|
||||
- (void)promptForStunServerFallback
|
||||
{
|
||||
[_errorNotification dismissViewControllerAnimated:NO completion:nil];
|
||||
|
||||
NSString *stunFallbackHost = RiotSettings.shared.stunServerFallback;
|
||||
// Remove "stun:"
|
||||
stunFallbackHost = [stunFallbackHost componentsSeparatedByString:@":"].lastObject;
|
||||
|
||||
MXSession *mainSession = self.mxSessions.firstObject;
|
||||
NSString *homeServerName = mainSession.matrixRestClient.credentials.homeServerName;
|
||||
|
||||
NSString *message = [NSString stringWithFormat:@"%@\n\n%@",
|
||||
[NSString stringWithFormat:NSLocalizedStringFromTable(@"call_no_stun_server_error_message_1", @"Vector", nil), homeServerName],
|
||||
[NSString stringWithFormat: NSLocalizedStringFromTable(@"call_no_stun_server_error_message_2", @"Vector", nil), stunFallbackHost]];
|
||||
|
||||
_errorNotification = [UIAlertController alertControllerWithTitle:NSLocalizedStringFromTable(@"call_no_stun_server_error_title", @"Vector", nil)
|
||||
message:message
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
[_errorNotification addAction:[UIAlertAction actionWithTitle:[NSString stringWithFormat: NSLocalizedStringFromTable(@"call_no_stun_server_error_use_fallback_button", @"Vector", nil), stunFallbackHost]
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
RiotSettings.shared.allowStunServerFallback = YES;
|
||||
mainSession.callManager.fallbackSTUNServer = RiotSettings.shared.stunServerFallback;
|
||||
|
||||
[AppDelegate theDelegate].errorNotification = nil;
|
||||
}]];
|
||||
|
||||
[_errorNotification addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"]
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
RiotSettings.shared.allowStunServerFallback = NO;
|
||||
|
||||
[AppDelegate theDelegate].errorNotification = nil;
|
||||
}]];
|
||||
|
||||
// Display the error notification
|
||||
if (!isErrorNotificationSuspended)
|
||||
{
|
||||
[_errorNotification mxk_setAccessibilityIdentifier:@"AppDelegateErrorAlert"];
|
||||
[self showNotificationAlert:_errorNotification];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Jitsi call
|
||||
|
||||
- (void)displayJitsiViewControllerWithWidget:(Widget*)jitsiWidget andVideo:(BOOL)video
|
||||
|
@ -4718,6 +4831,84 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
|
|||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Identity server service terms
|
||||
|
||||
// Observe identity server terms not signed notification
|
||||
- (void)registerIdentityServiceTermsNotSignedNotification
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleIdentityServiceTermsNotSignedNotification:) name:MXIdentityServiceTermsNotSignedNotification object:nil];
|
||||
}
|
||||
|
||||
- (void)handleIdentityServiceTermsNotSignedNotification:(NSNotification*)notification
|
||||
{
|
||||
NSLog(@"[AppDelegate] IS Terms: handleIdentityServiceTermsNotSignedNotification.");
|
||||
|
||||
NSString *baseURL;
|
||||
NSString *accessToken;
|
||||
|
||||
MXJSONModelSetString(baseURL, notification.userInfo[MXIdentityServiceNotificationIdentityServerKey]);
|
||||
MXJSONModelSetString(accessToken, notification.userInfo[MXIdentityServiceNotificationAccessTokenKey]);
|
||||
|
||||
[self presentIdentityServerTermsWithBaseURL:baseURL andAccessToken:accessToken];
|
||||
}
|
||||
|
||||
- (void)presentIdentityServerTermsWithBaseURL:(NSString*)baseURL andAccessToken:(NSString*)accessToken
|
||||
{
|
||||
MXSession *mxSession = self.mxSessions.firstObject;
|
||||
|
||||
if (!mxSession || !baseURL || !accessToken || self.serviceTermsModalCoordinatorBridgePresenter.isPresenting)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ServiceTermsModalCoordinatorBridgePresenter *serviceTermsModalCoordinatorBridgePresenter = [[ServiceTermsModalCoordinatorBridgePresenter alloc] initWithSession:mxSession
|
||||
baseUrl:baseURL
|
||||
serviceType:MXServiceTypeIdentityService
|
||||
outOfContext:YES
|
||||
accessToken:accessToken];
|
||||
|
||||
serviceTermsModalCoordinatorBridgePresenter.delegate = self;
|
||||
|
||||
UIViewController *presentingViewController = self.window.rootViewController.presentedViewController ?: self.window.rootViewController;
|
||||
|
||||
[serviceTermsModalCoordinatorBridgePresenter presentFrom:presentingViewController animated:YES];
|
||||
self.serviceTermsModalCoordinatorBridgePresenter = serviceTermsModalCoordinatorBridgePresenter;
|
||||
}
|
||||
|
||||
- (void)serviceTermsModalCoordinatorBridgePresenterDelegateDidAccept:(ServiceTermsModalCoordinatorBridgePresenter * _Nonnull)coordinatorBridgePresenter
|
||||
{
|
||||
[coordinatorBridgePresenter dismissWithAnimated:YES completion:^{
|
||||
|
||||
}];
|
||||
self.serviceTermsModalCoordinatorBridgePresenter = nil;
|
||||
}
|
||||
|
||||
- (void)serviceTermsModalCoordinatorBridgePresenterDelegateDidDecline:(ServiceTermsModalCoordinatorBridgePresenter *)coordinatorBridgePresenter session:(MXSession *)session
|
||||
{
|
||||
NSLog(@"[AppDelegate] IS Terms: User has declined the use of the default IS.");
|
||||
|
||||
// The user does not want to use the proposed IS.
|
||||
// Disable IS feature on user's account
|
||||
[session setIdentityServer:nil andAccessToken:nil];
|
||||
[session setAccountDataIdentityServer:nil success:^{
|
||||
} failure:^(NSError *error) {
|
||||
NSLog(@"[AppDelegate] IS Terms: Error: %@", error);
|
||||
}];
|
||||
|
||||
[coordinatorBridgePresenter dismissWithAnimated:YES completion:^{
|
||||
|
||||
}];
|
||||
self.serviceTermsModalCoordinatorBridgePresenter = nil;
|
||||
}
|
||||
|
||||
- (void)serviceTermsModalCoordinatorBridgePresenterDelegateDidCancel:(ServiceTermsModalCoordinatorBridgePresenter * _Nonnull)coordinatorBridgePresenter
|
||||
{
|
||||
[coordinatorBridgePresenter dismissWithAnimated:YES completion:^{
|
||||
|
||||
}];
|
||||
self.serviceTermsModalCoordinatorBridgePresenter = nil;
|
||||
}
|
||||
|
||||
#pragma mark - Settings
|
||||
|
||||
- (void)setupUserDefaults
|
||||
|
|
|
@ -32,9 +32,11 @@
|
|||
<string>https://jitsi.riot.im</string>
|
||||
<key>integrationsWidgetsUrls</key>
|
||||
<array>
|
||||
<string>https://scalar-staging.riot.im/scalar/api</string>
|
||||
<string>https://scalar-staging.vector.im/api</string>
|
||||
<string>https://scalar.vector.im/_matrix/integrations/v1</string>
|
||||
<string>https://scalar.vector.im/api</string>
|
||||
<string>https://scalar-staging.vector.im/_matrix/integrations/v1</string>
|
||||
<string>https://scalar-staging.vector.im/api</string>
|
||||
<string>https://scalar-staging.riot.im/scalar/api</string>
|
||||
</array>
|
||||
<key>piwik</key>
|
||||
<dict>
|
||||
|
@ -57,6 +59,8 @@
|
|||
<false/>
|
||||
<key>createConferenceCallsWithJitsi</key>
|
||||
<true/>
|
||||
<key>stunServerFallback</key>
|
||||
<string>stun:turn.matrix.org</string>
|
||||
<key>enableRageShake</key>
|
||||
<true/>
|
||||
<key>maxAllowedMediaCacheSize</key>
|
||||
|
|
|
@ -820,3 +820,29 @@
|
|||
"image_picker_action_library" = "Избери от библиотеката";
|
||||
"camera_unavailable" = "Не е достъпна камера на вашето устройство";
|
||||
"photo_library_access_not_granted" = "%@ няма достъп до библиотеката със снимки. Моля, променете настройките на поверителността";
|
||||
"auth_forgot_password_error_no_configured_identity_server" = "Не е конфигуриран сървър за самоличност: добавете такъв за да може да възстановите паролата си.";
|
||||
"room_creation_error_invite_user_by_email_without_identity_server" = "Не е конфигуриран сървър за самоличност, така че не можете да поканите участник по имейл адрес.";
|
||||
"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Не е конфигуриран сървър за самоличност, така че не можете да започнете чат с контакт посредством имейл адрес.";
|
||||
// Service terms
|
||||
"service_terms_modal_title" = "Условия за ползване";
|
||||
"service_terms_modal_message" = "За да продължите е необходимо да приемете Условията за ползване.";
|
||||
"service_terms_modal_accept_button" = "Приемам";
|
||||
"service_terms_modal_description_for_identity_server" = "Бъдете откриваеми от потребители";
|
||||
"service_terms_modal_description_for_integration_manager" = "Използвайте ботове, връзки към други мрежи и стикери";
|
||||
"room_participants_remove_third_party_invite_prompt_msg" = "Сигурни ли сте, че искате да оттеглите тази покана?";
|
||||
// Errors
|
||||
"error_user_already_logged_in" = "Изглежда се опитвате да се свържете с друг сървър. Искате ли да излезе от профила?";
|
||||
"room_accessiblity_scroll_to_bottom" = "Отиди най-долу";
|
||||
"room_accessibility_search" = "Търси";
|
||||
"room_accessibility_integrations" = "Интеграции";
|
||||
"room_accessibility_upload" = "Качи";
|
||||
"room_accessibility_call" = "Обади се";
|
||||
"room_accessibility_hangup" = "Затвори";
|
||||
"media_type_accessibility_image" = "Снимка";
|
||||
"media_type_accessibility_audio" = "Аудио";
|
||||
"media_type_accessibility_video" = "Видео";
|
||||
"media_type_accessibility_location" = "Местоположение";
|
||||
"media_type_accessibility_file" = "Файл";
|
||||
"media_type_accessibility_sticker" = "Стикер";
|
||||
// Widget Picker
|
||||
"widget_picker_title" = "Интеграции";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Permissions usage explanations
|
||||
"NSCameraUsageDescription" = "Die Kamera wird verwendet um Fotos und Videos aufzunehmen sowie Video-Anrufe zu führen.";
|
||||
"NSPhotoLibraryUsageDescription" = "Die Foto-Bibliothek wird verwendet um Fotos und Videos zu senden.";
|
||||
"NSMicrophoneUsageDescription" = "Das Mikrofon wird verwendet um Videos aufzunehmen sowie Gespräche zu führen.";
|
||||
"NSContactsUsageDescription" = "Um dir zu zeigen, welche deiner Kontakte bereits Riot oder Matrix benutzen, können wir die E-Mail-Adressen und Telefonnummern deines Adressbuches an deinen Matrix-Identitätsserver senden. New Vector speichert diese Daten nicht und nutzt sie auch für keine anderen Zwecke. Für mehr Informationen sieh dir bitte die Datenschutz-Seite in den App-Einstellungen an.";
|
||||
"NSCameraUsageDescription" = "Die Kamera wird verwendet, um Fotos und Videos aufzunehmen sowie Videoanrufe durchzuführen.";
|
||||
"NSPhotoLibraryUsageDescription" = "Die Fotobibliothek wird verwendet, um Fotos und Videos zu versenden.";
|
||||
"NSMicrophoneUsageDescription" = "Das Mikrofon wird verwendet, um Videos aufzunehmen sowie Gespräche zu führen.";
|
||||
"NSContactsUsageDescription" = "Riot kann E-Mail-Adressen und Telefonnummern aus deinem Adressbuch zu deinem Matrix-Identitätsserver schicken, um Kontakte zu finden, die bereits Matrix verwenden. Wenn verfügbar, werden persönliche Daten vor dem Versand gehasht. Für weitere Informationen schaue bitte in die Datenschutzerklärung deines Identitätsservers.";
|
||||
"NSCalendarsUsageDescription" = "Sieh dir deine geplanten Meetings in der App an.";
|
||||
|
|
|
@ -243,8 +243,8 @@
|
|||
"settings_new_password" = "neues Passwort";
|
||||
"settings_confirm_password" = "bestätige Passwort";
|
||||
"settings_password_updated" = "Dein Passwort wurde aktualisiert";
|
||||
"settings_crypto_device_name" = "Gerätename: ";
|
||||
"settings_crypto_device_key" = "\nGeräte-Schlüssel: ";
|
||||
"settings_crypto_device_name" = "Öffentlicher Gerätename: ";
|
||||
"settings_crypto_device_key" = "\nGeräteschlüssel:\n";
|
||||
"settings_crypto_export" = "Schlüssel exportieren";
|
||||
"room_details_settings" = "Einstellungen";
|
||||
"room_details_photo" = "Raum-Bild";
|
||||
|
@ -309,7 +309,7 @@
|
|||
"room_event_action_redact" = "Entfernen";
|
||||
"room_warning_about_encryption" = "Ende-zu-Ende Verschlüsselung ist in Beta und ist evtl. nicht zuverlässig.\n\nMan sollte noch nicht darauf vertrauen, dass die Daten sicher sind.\n\nGeräte werden den Verlauf vor dem Beitritt des Raumes nicht entschlüsseln können.\n\nVerschlüsselte Nachrichten sind nicht lesbar auf Clients, die Verschlüsselung noch nicht implementiert haben.";
|
||||
"unknown_devices_alert" = "Dieser Raum enthält unbekannte Geräte, die nicht verifiziert wurden.\nDas bedeutet, es gibt keine Garantie, dass sie dem User gehören, der angegeben ist.\nWir empfehlen eine Überprüfung für jedes Gerät, bevor du weitermachst, aber du kannst die Nachricht erneut senden ohne Verifikation.";
|
||||
"room_preview_unlinked_email_warning" = "Diese Einladung wurde an %@ gesendet, die Adresse ist nicht mit diesem Konto verbunden. Du kannst dich mit einem anderen Konto anmelden, oder diese E-Mail-Adresse deinem Konto hinzufügen.";
|
||||
"room_preview_unlinked_email_warning" = "Diese Einladung wurde an %@ gesendet, das diesem Konto nicht zugeordnet ist. Möglicherweise möchten Sie sich mit einem anderen Konto anmelden oder diese E-Mail zu Ihrem Konto hinzufügen.";
|
||||
"room_preview_try_join_an_unknown_room" = "Du versuchst auf %@ zuzugreifen. Möchtest du dem Raum beitreten um teilzunehmen?";
|
||||
"settings_config_identity_server" = "Identitätsserver ist %@";
|
||||
"settings_labs" = "Labor";
|
||||
|
@ -415,7 +415,7 @@
|
|||
"contacts_user_directory_section" = "NUTZER VERZEICHNIS";
|
||||
"contacts_user_directory_offline_section" = "NUTZER VERZEICHNIS (offline)";
|
||||
"auth_home_server_placeholder" = "URL (z.B. https://matrix.org)";
|
||||
"auth_identity_server_placeholder" = "URL (z.B. https://matrix.org)";
|
||||
"auth_identity_server_placeholder" = "URL (z. B. https://vector.im)";
|
||||
"room_ongoing_conference_call_close" = "Schließen";
|
||||
"room_conference_call_no_power" = "Du brauchst die Berechtigung Konferenzgespräche in diesem Raum zu verwalten";
|
||||
"settings_labs_create_conference_with_jitsi" = "Erstelle Konferenzgespräche mit Jitsi";
|
||||
|
@ -511,8 +511,8 @@
|
|||
"room_do_not_have_permission_to_post" = "Du hast keine Berechtigung in diesem Raum zu posten";
|
||||
"room_event_action_kick_prompt_reason" = "Grund für den Rauswurf des Benutzers";
|
||||
"room_event_action_ban_prompt_reason" = "Grund für die Verbannung des Benutzers";
|
||||
"room_action_send_photo_or_video" = "Sende Foto oder Video";
|
||||
"room_action_send_sticker" = "Sende Sticker";
|
||||
"room_action_send_photo_or_video" = "Foto oder Video senden";
|
||||
"room_action_send_sticker" = "Sticker senden";
|
||||
"settings_deactivate_account" = "DEAKTIVIERE ACCOUNT";
|
||||
"settings_deactivate_my_account" = "Deaktivere meinen Account";
|
||||
"widget_sticker_picker_no_stickerpacks_alert" = "Du hast aktuell keine Sticker-Packete aktiviert.";
|
||||
|
@ -544,7 +544,7 @@
|
|||
"room_replacement_link" = "Die Konversation wird hier fortgesetzt.";
|
||||
"room_predecessor_information" = "Dieser Raum ist die Fortsetzung einer anderen Konversation.";
|
||||
"room_predecessor_link" = "Tippe hier um ältere Nachrichten zu sehen.";
|
||||
"settings_labs_room_members_lazy_loading" = "Raummitglieder nachladen";
|
||||
"settings_labs_room_members_lazy_loading" = "Raummitglieder später laden";
|
||||
"settings_labs_room_members_lazy_loading_error_message" = "Dein Heimserver unterstützt das verzögerte Laden von Raummitgliedern noch nicht. Versuche es später erneut.";
|
||||
"room_event_action_view_decrypted_source" = "Zeige entschlüsselten Quellcode";
|
||||
"room_recents_server_notice_section" = "SYSTEMBENACHRICHTIGUNGEN";
|
||||
|
@ -561,11 +561,11 @@
|
|||
"settings_key_backup_info" = "Verschlüsselte Nachrichten sind durch Ende-zu-Ende-Verschlüsselung gesichert. Ausschließlich du und der/die Empfänger besitzen die Schlüssel, um diese Nachrichten zu lesen.";
|
||||
"settings_key_backup_info_checking" = "Überprüfe...";
|
||||
"settings_key_backup_info_none" = "Deine Schlüssel werden von diesem Gerät nicht gesichert.";
|
||||
"settings_key_backup_info_signout_warning" = "Sichere deine Schlüssel bevor du dich abmeldest, damit du sie nicht verlierst.";
|
||||
"settings_key_backup_info_signout_warning" = "Schließen Sie dieses Gerät an die Schlüsselsicherung an, bevor Sie sich abmelden, um den Verlust von Schlüsseln zu vermeiden, die sich möglicherweise nur auf diesem Gerät befinden.";
|
||||
"settings_key_backup_info_version" = "Schlüssel Sicherheitskopie Version: %@";
|
||||
"settings_key_backup_info_algorithm" = "Algorithmus";
|
||||
"settings_key_backup_info_valid" = "Dieses Gerät sichert deine Schlüssel.";
|
||||
"settings_key_backup_info_not_valid" = "Dieses Gerät sichert deine Schlüssel nicht.";
|
||||
"settings_key_backup_info_not_valid" = "Dieses Gerät sichert Ihre Schlüssel nicht, es ist jedoch eine Sicherungskopie vorhanden, die Sie wiederherstellen und später hinzufügen können.";
|
||||
"settings_key_backup_info_progress" = "Sichere %@ Schlüssel...";
|
||||
"settings_key_backup_info_progress_done" = "Alle Schlüssel wurden gesichert";
|
||||
"settings_key_backup_info_trust_signature_unknown" = "Sicherheitskopie hat eine Signatur vom Gerät mit der ID: %@";
|
||||
|
@ -674,7 +674,7 @@
|
|||
"key_backup_recover_connent_banner_subtitle" = "Schlüssel dieses Geräts sichern";
|
||||
// MARK: - Device Verification
|
||||
"device_verification_title" = "Gerät verifizieren";
|
||||
"device_verification_cancelled" = "Die Gegenseite hat die Verifikation abgebrochen";
|
||||
"device_verification_cancelled" = "Die Gegenstelle hat die Überprüfung abgebrochen.";
|
||||
"device_verification_cancelled_by_me" = "Die Verifikation wurde abgebrochen. Grund: %@";
|
||||
"device_verification_error_cannot_load_device" = "Konnte Geräteinformationen nicht laden.";
|
||||
// Mark: Incoming
|
||||
|
@ -736,7 +736,7 @@
|
|||
"device_verification_emoji_bell" = "Glocke";
|
||||
"device_verification_emoji_anchor" = "Anker";
|
||||
"device_verification_emoji_headphones" = "Kopfhörer";
|
||||
"close" = "Schließen";
|
||||
"close" = "Beenden";
|
||||
"auth_softlogout_signed_out" = "Sie sind abgemeldet";
|
||||
"auth_softlogout_sign_in" = "Einloggen";
|
||||
"auth_softlogout_reason" = "Ihr Homeserver-Administrator (%1$@) hat Sie von Ihrem Konto %2$@ (%3$@) abgemeldet.";
|
||||
|
@ -775,7 +775,7 @@
|
|||
"device_verification_emoji_rooster" = "Hahn";
|
||||
"device_verification_emoji_globe" = "Globus";
|
||||
"device_verification_emoji_smiley" = "Lächeln";
|
||||
"device_verification_emoji_spanner" = "Spanner";
|
||||
"device_verification_emoji_spanner" = "Schraubenschlüssel";
|
||||
"device_verification_emoji_thumbs up" = "Daumen hoch";
|
||||
"device_verification_emoji_hourglass" = "Sanduhr";
|
||||
"device_verification_emoji_clock" = "Uhr";
|
||||
|
@ -798,3 +798,20 @@
|
|||
"emoji_picker_flags_category" = "Flaggen";
|
||||
// MARK: Reaction history
|
||||
"reaction_history_title" = "Reaktionen";
|
||||
"room_action_camera" = "Foto oder Video aufnehmen";
|
||||
// Media picker
|
||||
"media_picker_title" = "Mediathek";
|
||||
// Image picker
|
||||
"image_picker_action_camera" = "Foto aufnehmen";
|
||||
"image_picker_action_library" = "Aus der Mediathek auswählen";
|
||||
"camera_unavailable" = "Die Kamera ist auf Ihrem Gerät nicht verfügbar";
|
||||
"photo_library_access_not_granted" = "%@ hat keine Berechtigung zum Zugriff auf die Fotobibliothek. Bitte ändern Sie die Datenschutzeinstellungen";
|
||||
"auth_forgot_password_error_no_configured_identity_server" = "Es ist kein Identitätsserver konfiguriert: Fügen Sie einen hinzu, um Ihr Kennwort zurückzusetzen.";
|
||||
"room_creation_error_invite_user_by_email_without_identity_server" = "Es ist kein Identitätsserver konfiguriert, sodass Sie keinen Teilnehmer mit einer E-Mail hinzufügen können.";
|
||||
"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Es ist kein Identitätsserver konfiguriert, sodass Sie keinen Chat mit einem Kontakt über eine E-Mail starten können.";
|
||||
// Service terms
|
||||
"service_terms_modal_title" = "Nutzungsbedingungen";
|
||||
"service_terms_modal_message" = "Um fortzufahren, müssen Sie die Bedingungen dieses Dienstes akzeptieren.";
|
||||
"service_terms_modal_accept_button" = "Akzeptieren";
|
||||
"service_terms_modal_description_for_identity_server" = "Für andere auffindbar sein";
|
||||
"service_terms_modal_description_for_integration_manager" = "Verwenden Sie Bots, Bridges, Widgets und Sticker-Packs";
|
||||
|
|
|
@ -18,6 +18,6 @@
|
|||
"NSCameraUsageDescription" = "The camera is used to take photos and videos, make video calls.";
|
||||
"NSPhotoLibraryUsageDescription" = "The photo library is used to send photos and videos.";
|
||||
"NSMicrophoneUsageDescription" = "The microphone is used to take videos, make calls.";
|
||||
"NSContactsUsageDescription" = "In order to show you which of your contacts are already using Riot or Matrix, we can send the email addresses and phone numbers in your address book to your Matrix Identity Server. New Vector does not store this data or use it for any other purpose. For more information please see the privacy policy page in application settings.";
|
||||
"NSContactsUsageDescription" = "To discover contacts already using Matrix, Riot can send email addresses and phone numbers in your address book to your chosen Matrix identity server. Where supported, personal data is hashed before sending - please check your identity server's privacy policy for more details.";
|
||||
"NSCalendarsUsageDescription" = "See your scheduled meetings in the app.";
|
||||
|
||||
|
|
|
@ -77,26 +77,28 @@
|
|||
"auth_repeat_password_placeholder" = "Repeat password";
|
||||
"auth_repeat_new_password_placeholder" = "Confirm your new password";
|
||||
"auth_home_server_placeholder" = "URL (e.g. https://matrix.org)";
|
||||
"auth_identity_server_placeholder" = "URL (e.g. https://matrix.org)";
|
||||
"auth_identity_server_placeholder" = "URL (e.g. https://vector.im)";
|
||||
"auth_invalid_login_param" = "Incorrect username and/or password";
|
||||
"auth_invalid_user_name" = "User names may only contain letters, numbers, dots, hyphens and underscores";
|
||||
"auth_invalid_password" = "Password too short (min 6)";
|
||||
"auth_invalid_email" = "This doesn't look like a valid email address";
|
||||
"auth_invalid_phone" = "This doesn't look like a valid phone number";
|
||||
"auth_missing_password" = "Missing password";
|
||||
"auth_add_email_message" = "Add an email address to your account to let users discover you, and to reset your password.";
|
||||
"auth_add_phone_message" = "Add a phone number to your account to let users discover you.";
|
||||
"auth_add_email_phone_message" = "Add an email address and/or a phone number to your account to let users discover you. Email address will also let you reset your password.";
|
||||
"auth_add_email_and_phone_message" = "Add an email address and a phone number to your account to let users discover you. Email address will also let you reset your password.";
|
||||
"auth_add_email_message_2" = "Set an email for account recovery, and later to be optionally discoverable by people who know you.";
|
||||
"auth_add_phone_message_2" = "Set a phone, and later to be optionally discoverable by people who know you.";
|
||||
"auth_add_email_phone_message_2" = "Set an email for account recovery. Use later email or phone to be optionally discoverable by people who know you.";
|
||||
"auth_missing_email" = "Missing email address";
|
||||
"auth_missing_phone" = "Missing phone number";
|
||||
"auth_missing_email_or_phone" = "Missing email address or phone number";
|
||||
"auth_email_in_use" = "This email address is already in use";
|
||||
"auth_phone_in_use" = "This phone number is already in use";
|
||||
"auth_email_is_required" = "No identity server is configured so you cannot add an email address in order to reset your password in the future.";
|
||||
"auth_phone_is_required" = "No identity server is configured so you cannot add a phone number in order to reset your password in the future.";
|
||||
"auth_untrusted_id_server" = "The identity server is not trusted";
|
||||
"auth_password_dont_match" = "Passwords don't match";
|
||||
"auth_username_in_use" = "Username in use";
|
||||
"auth_forgot_password" = "Forgot password?";
|
||||
"auth_forgot_password_error_no_configured_identity_server" = "No identity server is configured: add one to reset your password.";
|
||||
"auth_email_not_found" = "Failed to send email: This email address was not found";
|
||||
"auth_use_server_options" = "Use custom server options (advanced)";
|
||||
"auth_email_validation_message" = "Please check your email to continue registration";
|
||||
|
@ -111,6 +113,7 @@
|
|||
"auth_reset_password_next_step_button" = "I have verified my email address";
|
||||
"auth_reset_password_error_unauthorized" = "Failed to verify email address: make sure you clicked the link in the email";
|
||||
"auth_reset_password_error_not_found" = "Your email address does not appear to be associated with a Matrix ID on this homeserver.";
|
||||
"auth_reset_password_error_is_required" = "No identity server is configured: add one in server options to reset your password.";
|
||||
"auth_reset_password_success_message" = "Your password has been reset.\n\nYou have been logged out of all devices and will no longer receive push notifications. To re-enable notifications, re-log in on each device.";
|
||||
"auth_add_email_and_phone_warning" = "Registration with email and phone number at once is not supported yet until the api exists. Only the phone number will be taken into account. You may add your email to your profile in settings.";
|
||||
"auth_accept_policies" = "Please review and accept the policies of this homeserver:";
|
||||
|
@ -146,6 +149,7 @@
|
|||
"room_creation_make_private" = "Make private";
|
||||
"room_creation_wait_for_creation" = "A room is already being created. Please wait.";
|
||||
"room_creation_invite_another_user" = "Search / invite by User ID, Name or email";
|
||||
"room_creation_error_invite_user_by_email_without_identity_server" = "No identity server is configured so you cannot add a participant with an email.";
|
||||
|
||||
// Room recents
|
||||
"room_recents_directory_section" = "ROOM DIRECTORY";
|
||||
|
@ -197,6 +201,7 @@
|
|||
// Contacts
|
||||
"contacts_address_book_section" = "LOCAL CONTACTS";
|
||||
"contacts_address_book_matrix_users_toggle" = "Matrix users only";
|
||||
"contacts_address_book_no_identity_server" = "No identity server configured";
|
||||
"contacts_address_book_no_contact" = "No local contacts";
|
||||
"contacts_address_book_permission_required" = "Permission required to access local contacts";
|
||||
"contacts_address_book_permission_denied" = "You didn't allow Riot to access your local contacts";
|
||||
|
@ -212,7 +217,7 @@
|
|||
"room_participants_leave_prompt_msg" = "Are you sure you want to leave the room?";
|
||||
"room_participants_remove_prompt_title" = "Confirmation";
|
||||
"room_participants_remove_prompt_msg" = "Are you sure you want to remove %@ from this chat?";
|
||||
"room_participants_remove_third_party_invite_msg" = "Remove third-party invite is not supported yet until the api exists";
|
||||
"room_participants_remove_third_party_invite_prompt_msg" = "Are you sure you want to revoke this invite?";
|
||||
"room_participants_invite_prompt_title" = "Confirmation";
|
||||
"room_participants_invite_prompt_msg" = "Are you sure you want to invite %@ to this chat?";
|
||||
"room_participants_filter_room_members" = "Filter room members";
|
||||
|
@ -220,6 +225,7 @@
|
|||
"room_participants_invite_malformed_id_title" = "Invite Error";
|
||||
"room_participants_invite_malformed_id" = "Malformed ID. Should be an email address or a Matrix ID like '@localpart:domain'";
|
||||
"room_participants_invited_section" = "INVITED";
|
||||
"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "No identity server is configured so you cannot start a chat with a contact using an email.";
|
||||
|
||||
"room_participants_online" = "Online";
|
||||
"room_participants_offline" = "Offline";
|
||||
|
@ -370,6 +376,8 @@
|
|||
"settings_user_settings" = "USER SETTINGS";
|
||||
"settings_notifications_settings" = "NOTIFICATION SETTINGS";
|
||||
"settings_calls_settings" = "CALLS";
|
||||
"settings_discovery_settings" = "DISCOVERY";
|
||||
"settings_identity_server_settings" = "IDENTITY SERVER";
|
||||
"settings_user_interface" = "USER INTERFACE";
|
||||
"settings_ignored_users" = "IGNORED USERS";
|
||||
"settings_contacts" = "LOCAL CONTACTS";
|
||||
|
@ -400,6 +408,9 @@
|
|||
"settings_change_password" = "Change password";
|
||||
"settings_night_mode" = "Night Mode";
|
||||
"settings_fail_to_update_profile" = "Fail to update profile";
|
||||
"settings_three_pids_management_information_part1" = "Manage which email addresses or phone numbers you can use to log in or recover your account here. Control who can find you in ";
|
||||
"settings_three_pids_management_information_part2" = "Discovery";
|
||||
"settings_three_pids_management_information_part3" = ".";
|
||||
|
||||
"settings_enable_push_notif" = "Notifications on this device";
|
||||
"settings_show_decrypted_content" = "Show decrypted content";
|
||||
|
@ -417,6 +428,9 @@
|
|||
|
||||
"settings_enable_callkit" = "Integrated calling";
|
||||
"settings_callkit_info" = "Receive incoming calls on your lock screen. See your Riot calls in the system's call history. If iCloud is enabled, this call history will be shared with Apple.";
|
||||
"settings_calls_stun_server_fallback_button" = "Allow fallback call assist server";
|
||||
"settings_calls_stun_server_fallback_description" = "Allow fallback call assist server %@ when your homeserver does not offer one (your IP address would be shared during a call).";
|
||||
|
||||
"settings_ui_language" = "Language";
|
||||
"settings_ui_theme" = "Theme";
|
||||
"settings_ui_theme_auto" = "Auto";
|
||||
|
@ -458,9 +472,9 @@
|
|||
"settings_fail_to_update_password" = "Fail to update password";
|
||||
"settings_password_updated" = "Your password has been updated";
|
||||
|
||||
"settings_crypto_device_name" = "Device name: ";
|
||||
"settings_crypto_device_name" = "Device Public Name: ";
|
||||
"settings_crypto_device_id" = "\nDevice ID: ";
|
||||
"settings_crypto_device_key" = "\nDevice key: ";
|
||||
"settings_crypto_device_key" = "\nDevice key:\n";
|
||||
"settings_crypto_export" = "Export keys";
|
||||
"settings_crypto_blacklist_unverified_devices" = "Encrypt to verified devices only";
|
||||
|
||||
|
@ -491,6 +505,60 @@
|
|||
"settings_key_backup_delete_confirmation_prompt_title" = "Delete Backup";
|
||||
"settings_key_backup_delete_confirmation_prompt_msg" = "Are you sure? You will lose your encrypted messages if your keys are not backed up properly.";
|
||||
|
||||
"settings_devices_description" = "A device's public name is visible to people you communicate with";
|
||||
|
||||
"settings_discovery_no_identity_server" = "You are not currently using an identity server. To be discoverable by existing contacts you known, add one.";
|
||||
"settings_discovery_terms_not_signed" = "Agree to the Identity Server (%@) Terms of Service to allow yourself to be discoverable by email address or phone number.";
|
||||
"settings_discovery_three_pids_management_information_part1" = "Manage which email addresses or phone numbers other users can use to discover you and use to invite you to rooms. Add or remove email addresses or phone numbers from this list in ";
|
||||
"settings_discovery_three_pids_management_information_part2" = "User Settings";
|
||||
"settings_discovery_three_pids_management_information_part3" = ".";
|
||||
"settings_discovery_error_message" = "An error occured. Please retry.";
|
||||
|
||||
"settings_discovery_three_pid_details_title_email" = "Manage email";
|
||||
"settings_discovery_three_pid_details_information_email" = "Manage preferences for this email address, which other users can use to discover you and use to invite you to rooms. Add or remove email addresses in Accounts.";
|
||||
"settings_discovery_three_pid_details_title_phone_number" = "Manage phone number";
|
||||
"settings_discovery_three_pid_details_information_phone_number" = "Manage preferences for this phone number, which other users can use to discover you and use to invite you to rooms. Add or remove phone numbers in Accounts.";
|
||||
|
||||
"settings_discovery_three_pid_details_share_action" = "Share";
|
||||
"settings_discovery_three_pid_details_revoke_action" = "Revoke";
|
||||
"settings_discovery_three_pid_details_cancel_email_validation_action" = "Cancel email validation";
|
||||
"settings_discovery_three_pid_details_enter_sms_code_action" = "Enter SMS activation code";
|
||||
|
||||
"settings_identity_server_description" = "Using the identity server set above, you can discover and be discoverable by existing contacts you know.";
|
||||
"settings_identity_server_no_is" = "No identity server configured";
|
||||
"settings_identity_server_no_is_description" = "You are not currently using an identity server. To discover and be discoverable by existing contacts you know, add one above.";
|
||||
|
||||
|
||||
// Identity server settings
|
||||
"identity_server_settings_title" = "Identity Server";
|
||||
|
||||
"identity_server_settings_description" = "You are currently using %@ to discover and be discoverable by existing contacts you know.";
|
||||
"identity_server_settings_no_is_description" = "You are not currently using an identity server. To discover and be discoverable by existing contacts, add one above.";
|
||||
|
||||
"identity_server_settings_place_holder" = "Enter an identity server";
|
||||
|
||||
"identity_server_settings_add" = "Add";
|
||||
"identity_server_settings_change" = "Change";
|
||||
|
||||
"identity_server_settings_disconnect_info" = "Disconnecting from your identity server will mean you won’t be discoverable by other users and be able to invite others by email or phone.";
|
||||
"identity_server_settings_disconnect" = "Disconnect";
|
||||
|
||||
"identity_server_settings_alert_no_terms_title" = "Identity server has no terms of services";
|
||||
"identity_server_settings_alert_no_terms" = "The identity server you have chosen does not have any terms of service. Only continue if you trust the owner of the server.";
|
||||
|
||||
"identity_server_settings_alert_change_title" = "Change identity server";
|
||||
"identity_server_settings_alert_change" = "Disconnect from the identity server %1$@ and connect to %2$@ instead?";
|
||||
|
||||
"identity_server_settings_alert_disconnect_title" = "Disconnect identity server";
|
||||
"identity_server_settings_alert_disconnect" = "Disconnect from the identity server %@?";
|
||||
"identity_server_settings_alert_disconnect_button" = "Disconnect";
|
||||
"identity_server_settings_alert_disconnect_still_sharing_3pid" = "You are still sharing your personal data on the identity server %@.\n\nWe recommend that you remove your email addresses and phone numbers from the identity server before disconnecting.";
|
||||
"identity_server_settings_alert_disconnect_still_sharing_3pid_button" = "Disconnect anyway";
|
||||
|
||||
"identity_server_settings_alert_error_terms_not_accepted" = "You must accept terms of %@ to set it as identity server.";
|
||||
"identity_server_settings_alert_error_invalid_identity_server" = "%@ is not a valid identity server.";
|
||||
|
||||
|
||||
// Room Details
|
||||
"room_details_title" = "Room Details";
|
||||
"room_details_people" = "Members";
|
||||
|
@ -641,6 +709,11 @@
|
|||
"call_already_displayed" = "There is already a call in progress.";
|
||||
"call_jitsi_error" = "Failed to join the conference call.";
|
||||
|
||||
"call_no_stun_server_error_title" ="Call failed due to misconfigured server";
|
||||
"call_no_stun_server_error_message_1" ="Please ask the administrator of your homeserver %@ to configure a TURN server in order for calls to work reliably.";
|
||||
"call_no_stun_server_error_message_2" ="Alternatively, you can try to use the public server at %@, but this will not be as reliable, and it will share your IP address with that server. You can also manage this in Settings";
|
||||
"call_no_stun_server_error_use_fallback_button" = "Try using %@";
|
||||
|
||||
// No VoIP support
|
||||
"no_voip_title" = "Incoming call";
|
||||
"no_voip" = "%@ is calling you but %@ does not support calls yet.\nYou can ignore this notification and answer the call from another device or you can reject it.";
|
||||
|
@ -709,6 +782,21 @@
|
|||
"gdpr_consent_not_given_alert_message" = "To continue using the %@ homeserver you must review and agree to the terms and conditions.";
|
||||
"gdpr_consent_not_given_alert_review_now_action" = "Review now";
|
||||
|
||||
// Service terms
|
||||
"service_terms_modal_title" = "Terms Of Service";
|
||||
"service_terms_modal_message" = "To continue you need to accept the terms of this service (%@).";
|
||||
"service_terms_modal_accept_button" = "Accept";
|
||||
"service_terms_modal_decline_button" = "Decline";
|
||||
|
||||
"service_terms_modal_description_for_identity_server_1" = "Find others by phone or email";
|
||||
"service_terms_modal_description_for_identity_server_2" = "Be found by phone or email";
|
||||
"service_terms_modal_description_for_integration_manager" = "Use Bots, bridges, widgets and sticker packs";
|
||||
|
||||
// Service terms - Variant for identity server when displayed out of a context
|
||||
"service_terms_modal_title_identity_server" = "Contact discovery";
|
||||
"service_terms_modal_message_identity_server" = "Accept the terms of the identity server (%@) to discover contacts.";
|
||||
|
||||
|
||||
// Deactivate account
|
||||
|
||||
"deactivate_account_title" = "Deactivate Account";
|
||||
|
@ -958,3 +1046,7 @@
|
|||
|
||||
// MARK: Reaction history
|
||||
"reaction_history_title" = "Reactions";
|
||||
|
||||
|
||||
// Generic errors
|
||||
"error_invite_3pid_with_no_identity_server" = "Add an identity server in your settings to invite by email.";
|
||||
|
|
|
@ -2,5 +2,5 @@
|
|||
"NSCameraUsageDescription" = "Kamera argazkiak eta bideoak ateratzeko eta bideo deiak egiteko erabiltzen da.";
|
||||
"NSPhotoLibraryUsageDescription" = "Argazkien liburutegia argazkiak eta bideoak bidaltzeko erabiltzen da.";
|
||||
"NSMicrophoneUsageDescription" = "Mikrofonoa bideoak atera eta deiak egiteko erabiltzen da.";
|
||||
"NSContactsUsageDescription" = "Zure kontaktuetatik Riot edo Matrix jada darabiltenak erakusteko, zure kontaktu liburuko e-mail helbideak eta telefono zenbakiak bidali ditzakegu identitate zerbitzarira. New Vector enpresak ez ditu datu hauek gordetzen edo beste ezertarako erabiltzen. Informazio gehiagorako ikusi pribatutasun politikari buruzko orria aplikazioaren ezarpenetan.";
|
||||
"NSContactsUsageDescription" = "Zure kontaktuetatik Riot edo Matrix jada darabiltenak erakusteko, zure kontaktu liburuko e-mail helbideak eta telefono zenbakiak bidali ditzakegu identitate-zerbitzarira. New Vector enpresak ez ditu datu hauek gordetzen edo beste ezertarako erabiltzen. Informazio gehiagorako ikusi pribatutasun politikari buruzko orria aplikazioaren ezarpenetan.";
|
||||
"NSCalendarsUsageDescription" = "Ikusi zure programatutako batzarrak aplikazioan.";
|
||||
|
|
|
@ -798,3 +798,23 @@
|
|||
"emoji_picker_objects_category" = "Objektuak";
|
||||
"emoji_picker_symbols_category" = "Sinboloak";
|
||||
"emoji_picker_flags_category" = "Banderak";
|
||||
"auth_forgot_password_error_no_configured_identity_server" = "Ez da identitate zerbitzaririk konfiguratu: gehitu bat zure pasahitza berrezartzeko.";
|
||||
"room_creation_error_invite_user_by_email_without_identity_server" = "Ez da identitate zerbitzaririk konfiguratu, beraz ezin duzu parte-hartzaile bat e-mail bidez gehitu.";
|
||||
"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Ez da identitate zerbitzaririk konfiguratu, beraz ezin duzu kontaktu batekin txat bat hasi e-mail bat erabiliz.";
|
||||
"room_event_action_reaction_history" = "Erreakzioen historiala";
|
||||
"room_action_camera" = "Atera argazkia edo bideoa";
|
||||
// Media picker
|
||||
"media_picker_title" = "Multimedia liburutegia";
|
||||
// Image picker
|
||||
"image_picker_action_camera" = "Atera argazkia";
|
||||
"image_picker_action_library" = "Hautatu liburutegitik";
|
||||
"camera_unavailable" = "Kamera ez dago erabilgarri zure gailuan";
|
||||
"photo_library_access_not_granted" = "%@(e)k ez du argazki liburutegia erabiltzeko baimenik, aldatu pribatutasun ezarpenak";
|
||||
// Service terms
|
||||
"service_terms_modal_title" = "Erabilera baldintzak";
|
||||
"service_terms_modal_message" = "Jarraitzeko, zerbitzu honen erabilera baldintzak onartu behar dituzu.";
|
||||
"service_terms_modal_accept_button" = "Onartu";
|
||||
"service_terms_modal_description_for_identity_server" = "Izan besteentzat aurkigarria";
|
||||
"service_terms_modal_description_for_integration_manager" = "Erabili botak, zubiak, trepetak eta eranskailu multzoak";
|
||||
// MARK: Reaction history
|
||||
"reaction_history_title" = "Erreakzioak";
|
||||
|
|
|
@ -2,5 +2,5 @@
|
|||
"NSCameraUsageDescription" = "L'appareil photo est utilisé pour prendre des photos et des vidéos et pour passer des appels vidéo.";
|
||||
"NSPhotoLibraryUsageDescription" = "La photothèque est utilisée pour envoyer des photos et des vidéos.";
|
||||
"NSMicrophoneUsageDescription" = "Le microphone est utilisé pour prendre des vidéos et passer des appels.";
|
||||
"NSContactsUsageDescription" = "Afin d’afficher qui parmis vos contacts utilise déjà Riot ou Matrix, nous pouvons envoyer les adresses e-mails et les numéros de téléphone de votre carnet d'adresse à votre Serveur d'Identité Matrix. New Vector ne stocke pas ces données et ne les utilise pas à d'autres fins. Pour plus d'informations, veuillez consulter la page de politique de confidentialité dans les paramètres de l'application.";
|
||||
"NSContactsUsageDescription" = "Pour découvrir vos contacts qui utilisent déjà Matrix, Riot peut envoyer les adresses e-mails et les numéros de téléphone de votre carnet d’adresse à votre serveur d’identité Matrix. Si votre serveur d’identité le prend en charge, les données personnelles sont hachées avant l’envoi − vérifiez sa politique de vie privée pour plus de détails.";
|
||||
"NSCalendarsUsageDescription" = "Voir vos rendez-vous prévus dans l’application.";
|
||||
|
|
|
@ -303,9 +303,9 @@
|
|||
"settings_confirm_password" = "confirmer le mot de passe";
|
||||
"settings_fail_to_update_password" = "Échec de la modification du mot de passe";
|
||||
"settings_password_updated" = "Votre mot de passe a été modifié";
|
||||
"settings_crypto_device_name" = "Nom de l'appareil : ";
|
||||
"settings_crypto_device_name" = "Nom public de l’appareil : ";
|
||||
"settings_crypto_device_id" = "\nIdentifiant de l'appareil : ";
|
||||
"settings_crypto_device_key" = "\nClé de l'appareil : ";
|
||||
"settings_crypto_device_key" = "\nClé de l’appareil :\n";
|
||||
"settings_crypto_export" = "Exporter les clés";
|
||||
"settings_crypto_blacklist_unverified_devices" = "Chiffrer uniquement vers les appareils vérifiés";
|
||||
// Room Details
|
||||
|
@ -456,7 +456,7 @@
|
|||
// Events formatter
|
||||
"event_formatter_member_updates" = "%tu modifications dans les membres";
|
||||
"auth_home_server_placeholder" = "URL (par ex. https://matrix.org)";
|
||||
"auth_identity_server_placeholder" = "URL (par ex. https://matrix.org)";
|
||||
"auth_identity_server_placeholder" = "URL (par ex. https://vector.im)";
|
||||
"room_ongoing_conference_call_with_close" = "Téléconférence en cours. Rejoindre en %@ ou %@. %@.";
|
||||
"room_ongoing_conference_call_close" = "Fermer";
|
||||
"room_conference_call_no_power" = "Permissions requises pour gérer la téléconférence dans ce salon";
|
||||
|
@ -821,3 +821,93 @@
|
|||
"image_picker_action_library" = "Choisir dans la médiathèque";
|
||||
"camera_unavailable" = "L’appareil photo n’est pas disponible sur votre appareil";
|
||||
"photo_library_access_not_granted" = "%@ n’a pas la permission pour accéder à la médiathèque, veuillez modifier les options de vie privée";
|
||||
"auth_forgot_password_error_no_configured_identity_server" = "Aucun serveur d’identité n’est configuré : ajoutez-en un pour réinitialiser votre mot de passe.";
|
||||
"room_creation_error_invite_user_by_email_without_identity_server" = "Aucun serveur d’identité n’est configuré donc vous ne pouvez pas ajouter de participant avec un e-mail.";
|
||||
"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Aucun serveur d’identité n’est configuré donc vous ne pouvez pas commencer de discussion avec un contact en utilisant un e-mail.";
|
||||
// Service terms
|
||||
"service_terms_modal_title" = "Conditions de service";
|
||||
"service_terms_modal_message" = "Pour continuer vous devez accepter les conditions de ce service (%@).";
|
||||
"service_terms_modal_accept_button" = "Accepter";
|
||||
"service_terms_modal_description_for_identity_server" = "Se rendre découvrable pour les autres";
|
||||
"service_terms_modal_description_for_integration_manager" = "Utiliser des robots, des passerelles, des widgets et des packs de stickers";
|
||||
"room_participants_remove_third_party_invite_prompt_msg" = "Voulez-vous vraiment retirer cette invitation ?";
|
||||
// Errors
|
||||
"error_user_already_logged_in" = "On dirait que vous essayez de vous connecter à un autre serveur d’accueil. Voulez-vous vous déconnecter ?";
|
||||
"room_accessiblity_scroll_to_bottom" = "Défiler vers le bas";
|
||||
"room_accessibility_search" = "Chercher";
|
||||
"room_accessibility_integrations" = "Intégrations";
|
||||
"room_accessibility_upload" = "Envoyer";
|
||||
"room_accessibility_call" = "Appeler";
|
||||
"room_accessibility_hangup" = "Raccrocher";
|
||||
"media_type_accessibility_image" = "Image";
|
||||
"media_type_accessibility_audio" = "Audio";
|
||||
"media_type_accessibility_video" = "Vidéo";
|
||||
"media_type_accessibility_location" = "Emplacement";
|
||||
"media_type_accessibility_file" = "Fichier";
|
||||
"media_type_accessibility_sticker" = "Sticker";
|
||||
// Widget Picker
|
||||
"widget_picker_title" = "Intégrations";
|
||||
"auth_add_email_message_2" = "Définissez une adresse e-mail pour la récupération de compte, et pour être éventuellement découvrable par les personnes qui vous connaissent.";
|
||||
"auth_add_phone_message_2" = "Définissez un numéro de téléphone pour être éventuellement découvrable par les personnes qui vous connaissent.";
|
||||
"auth_add_email_phone_message_2" = "Définissez une adresse e-mail pour la récupération de compte. Vous pouvez ensuite utiliser votre e-mail ou votre numéro de téléphone pour être découvrable par les personnes qui vous connaissent.";
|
||||
"auth_email_is_required" = "Aucun serveur d’identité n’est configuré donc vous ne pouvez pas ajouter d’adresse e-mail pour pouvoir réinitialiser votre mot de passe dans le futur.";
|
||||
"auth_phone_is_required" = "Aucun serveur d’identité n’est configuré donc vous ne pouvez pas ajouter de numéro de téléphone pour pouvoir réinitialiser votre mot de passe dans le futur.";
|
||||
"auth_reset_password_error_is_required" = "Aucun serveur d’identité n’est configuré : ajoutez-en un dans les options du serveur pour réinitialiser votre mot de passe.";
|
||||
"contacts_address_book_no_identity_server" = "Aucun serveur d’identité n’est configuré";
|
||||
"settings_discovery_settings" = "DÉCOUVERTE";
|
||||
"settings_identity_server_settings" = "SERVEUR D’IDENTITÉ";
|
||||
"settings_three_pids_management_information_part1" = "Gérez quelles adresse e-mail et quels numéros de téléphone vous pouvez utiliser pour vous connecter ou récupérer votre compte ici. Contrôlez qui vous pouvez trouver dans ";
|
||||
"settings_three_pids_management_information_part2" = "Découverte";
|
||||
"settings_three_pids_management_information_part3" = ".";
|
||||
"settings_calls_stun_server_fallback_button" = "Autoriser le serveur d’assistance d’appel de secours";
|
||||
"settings_calls_stun_server_fallback_description" = "Autorise le serveur d’assistance d’appel de secours %@ quand votre serveur d’accueil n’en offre pas (votre adresse IP serait partagée lors d’un appel).";
|
||||
"settings_devices_description" = "Le nom public de l’appareil est visible pour les personnes avec qui vous communiquez";
|
||||
"settings_discovery_no_identity_server" = "Vous n’utilisez actuellement aucun serveur d’identité. Pour être découvrable par les contacts existants que vous connaissez, ajoutez-en un.";
|
||||
"settings_discovery_terms_not_signed" = "Acceptez les conditions de service du serveur d’identité (%@) pour vous permettre d’être découvrable avec une adresse e-mail ou un numéro de téléphone.";
|
||||
"settings_discovery_three_pids_management_information_part1" = "Gérez quelles adresses e-mail ou numéros de téléphone peuvent être utilisés par les autres utilisateurs pour vous découvrir et pour vous inviter dans des salons. Ajoutez ou supprimez des adresses e-mail ou des numéros de téléphones depuis cette liste dans les ";
|
||||
"settings_discovery_three_pids_management_information_part2" = "Paramètres utilisateur";
|
||||
"settings_discovery_three_pids_management_information_part3" = ".";
|
||||
"settings_discovery_error_message" = "Une erreur est survenue. Réessayez.";
|
||||
"settings_discovery_three_pid_details_title_email" = "Gérer l’e-mail";
|
||||
"settings_discovery_three_pid_details_information_email" = "Gérer les préférences pour cette adresse e-mail, que les autres utilisateurs peuvent utiliser pour vous découvrir et pour vous inviter dans des salons. Ajoutez ou supprimez des adresses e-mail dans Comptes.";
|
||||
"settings_discovery_three_pid_details_title_phone_number" = "Gérer le numéro de téléphone";
|
||||
"settings_discovery_three_pid_details_information_phone_number" = "Gérer les préférences pour ce numéro de téléphone, que les autres utilisateurs peuvent utiliser pour vous découvrir et pour vous inviter dans des salons. Ajoutez ou supprimez des numéros de téléphone dans Comptes.";
|
||||
"settings_discovery_three_pid_details_share_action" = "Partager";
|
||||
"settings_discovery_three_pid_details_revoke_action" = "Révoquer";
|
||||
"settings_discovery_three_pid_details_cancel_email_validation_action" = "Annuler la validation de l’e-mail";
|
||||
"settings_discovery_three_pid_details_enter_sms_code_action" = "Saisir le code d’activation par SMS";
|
||||
"settings_identity_server_description" = "En utilisant le serveur d’identité ci-dessus, vous pouvez découvrir et être découvrable par les contacts existants que vous connaissez.";
|
||||
"settings_identity_server_no_is" = "Aucun serveur d’identité n’est configuré";
|
||||
"settings_identity_server_no_is_description" = "Vous n’utilisez actuellement aucun serveur d’identité. Pour découvrir et être découvrable par les contacts existants que vous connaissez, ajoutez-en un ci-dessus.";
|
||||
// Identity server settings
|
||||
"identity_server_settings_title" = "Serveur d’identité";
|
||||
"identity_server_settings_description" = "Vous utilisez actuellement %@ pour découvrir et être découvrable par les contacts existants que vous connaissez.";
|
||||
"identity_server_settings_no_is_description" = "Vous n’utilisez actuellement aucun serveur d’identité. Pour découvrir et être découvrable par vos contacts existants, ajoutez-en un ci-dessus.";
|
||||
"identity_server_settings_place_holder" = "Saisir un serveur d’identité";
|
||||
"identity_server_settings_add" = "Ajouter";
|
||||
"identity_server_settings_change" = "Modifier";
|
||||
"identity_server_settings_disconnect_info" = "La déconnexion de votre serveur d’identité signifie que vous ne pourrez pas être découvrable par les autres utilisateurs et inviter d’autres personnes par e-mail ou par téléphone.";
|
||||
"identity_server_settings_disconnect" = "Se déconnecter";
|
||||
"identity_server_settings_alert_no_terms_title" = "Le serveur d’identité n’a pas de conditions de service";
|
||||
"identity_server_settings_alert_no_terms" = "Le serveur d’identité que vous avez choisi n’a pas de conditions de service. Continuez uniquement si vous faites confiance au propriétaire de ce serveur.";
|
||||
"identity_server_settings_alert_change_title" = "Modifier le serveur d’identité";
|
||||
"identity_server_settings_alert_change" = "Se déconnecter du serveur d’identité %1$@ et se connecter à %2$@ à la place ?";
|
||||
"identity_server_settings_alert_disconnect_title" = "Se déconnecter du serveur d’identité";
|
||||
"identity_server_settings_alert_disconnect" = "Se déconnecter du serveur d’identité %@ ?";
|
||||
"identity_server_settings_alert_disconnect_button" = "Se déconnecter";
|
||||
"identity_server_settings_alert_disconnect_still_sharing_3pid" = "Vous partagez toujours vos données personnelles sur le serveur d’identité %@.\n\nNous recommandons que vous supprimiez vos adresses e-mail et vos numéros de téléphone du serveur d’identité avant de vous déconnecter.";
|
||||
"identity_server_settings_alert_disconnect_still_sharing_3pid_button" = "Se déconnecter quand même";
|
||||
"identity_server_settings_alert_error_terms_not_accepted" = "Vous devez accepter les conditions de %@ pour le définir comme serveur d’identité.";
|
||||
"identity_server_settings_alert_error_invalid_identity_server" = "%@ n’est pas un serveur d’identité valide.";
|
||||
"call_no_stun_server_error_title" = "L’appel a échoué en raison d’un serveur mal configuré";
|
||||
"call_no_stun_server_error_message_1" = "Demandez à l’administrateur de votre serveur d’accueil %@ de configurer un serveur TURN afin que les appels fonctionnent de manière fiable.";
|
||||
"call_no_stun_server_error_message_2" = "Sinon, vous pouvez essayer d’utiliser le serveur public à %@, mais ça ne sera pas fiable et ça partagera votre adresse IP avec ce serveur. Vous pouvez aussi gérer cela dans les Paramètres";
|
||||
"call_no_stun_server_error_use_fallback_button" = "Essayer d’utiliser %@";
|
||||
// Generic errors
|
||||
"error_invite_3pid_with_no_identity_server" = "Ajoutez un serveur d’identité dans vos paramètres pour inviter par e-mail.";
|
||||
"service_terms_modal_decline_button" = "Refuser";
|
||||
"service_terms_modal_description_for_identity_server_1" = "Trouver d’autres personnes par téléphone ou par e-mail";
|
||||
"service_terms_modal_description_for_identity_server_2" = "Être trouvé par téléphone ou par e-mail";
|
||||
// Service terms - Variant for identity server when displayed out of a context
|
||||
"service_terms_modal_title_identity_server" = "Découverte des contacts";
|
||||
"service_terms_modal_message_identity_server" = "Acceptez les conditions du serveur d’identité (%@) pour découvrir des contacts.";
|
||||
|
|
|
@ -2,5 +2,5 @@
|
|||
"NSCameraUsageDescription" = "A kamera fényképek, videók készítéséhez és videóhívásokhoz lesz használva.";
|
||||
"NSPhotoLibraryUsageDescription" = "A fénykép galéria fényképek és videók küldéséhez lesz használva.";
|
||||
"NSMicrophoneUsageDescription" = "A mikrofon videók készítéséhez és hívásokhoz lesz használva.";
|
||||
"NSContactsUsageDescription" = "Ahhoz, hogy meg tudjuk mutatni melyik ismerősöd használja már a Riot-ot vagy Matrix-ot, el tudjuk küldeni az e-mail címeket és telefonszámokat a címjegyzékedből a Matrix Azonosítási Szerverének. „New Vector” nem tárolja és semmilyen más célra nem használja ezeket az információkat. További információkért olvasd el az adatkezelési oldalt az alkalmazás beállításaiban.";
|
||||
"NSContactsUsageDescription" = "Az olyan ismerősök felderítéséhez akik már használják a Matrixot, Riot el tudja küldeni a címjegyzékben található e-mail címeket és telefonszámokat az általad választott Matrix azonosítási szervernek. Ahol lehetséges a személyes adatok hash-elve lesznek - kérlek ellenőrizd az azonosítási szervered adatvédelmi szabályait.";
|
||||
"NSCalendarsUsageDescription" = "Nézd meg a találkozóidat az alkalmazásban.";
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
"auth_repeat_password_placeholder" = "Jelszó megerősítés";
|
||||
"auth_repeat_new_password_placeholder" = "Új jelszó megerősítés";
|
||||
"auth_home_server_placeholder" = "URL (pl. https://matrix.org)";
|
||||
"auth_identity_server_placeholder" = "URL (pl. https://matrix.org)";
|
||||
"auth_identity_server_placeholder" = "URL (pl. https://vector.im)";
|
||||
"auth_invalid_login_param" = "Hibás felhasználói név és/vagy jelszó";
|
||||
"auth_invalid_user_name" = "A felhasználói név tartalmazhat betűket, számokat, pontokat, kötőjeleket és aláhúzást";
|
||||
"auth_invalid_password" = "Jelszó túl rövid (min. 6 karakter)";
|
||||
|
@ -349,9 +349,9 @@
|
|||
"settings_confirm_password" = "jelszó megerősítése";
|
||||
"settings_fail_to_update_password" = "A jelszó frissítése nem sikerült";
|
||||
"settings_password_updated" = "A jelszavad frissítve";
|
||||
"settings_crypto_device_name" = "Eszköz neve: ";
|
||||
"settings_crypto_device_name" = "Eszköz nyilvános neve: ";
|
||||
"settings_crypto_device_id" = "\nEszköz azonosítója: ";
|
||||
"settings_crypto_device_key" = "\nEszköz kulcsa: ";
|
||||
"settings_crypto_device_key" = "\nEszköz kulcsa:\n";
|
||||
"settings_crypto_export" = "Kulcsok kimentése";
|
||||
"settings_crypto_blacklist_unverified_devices" = "Csak ellenőrzött eszközöknek titkosít";
|
||||
"settings_deactivate_my_account" = "Felhasználói fiókom felfüggesztése";
|
||||
|
@ -818,3 +818,95 @@
|
|||
"room_event_action_reaction_history" = "Reakciók története";
|
||||
// MARK: Reaction history
|
||||
"reaction_history_title" = "Reakciók";
|
||||
"auth_forgot_password_error_no_configured_identity_server" = "Azonosítási szerver nincs beállítva: a jelszó visszaállításhoz adj hozzá egyet.";
|
||||
"room_creation_error_invite_user_by_email_without_identity_server" = "Azonosítási szerver nincs beállítva, így e-mail cím alapján nem tudsz hozzáadni résztvevőt.";
|
||||
"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Azonosítási szerver nincs beállítva, így e-mail cím alapján nem tudsz beszélgetést kezdeményezni.";
|
||||
"room_action_camera" = "Fotó vagy videó készítése";
|
||||
// Media picker
|
||||
"media_picker_title" = "Média könyvtár";
|
||||
// Image picker
|
||||
"image_picker_action_camera" = "Fotó készítése";
|
||||
"image_picker_action_library" = "Válassz a könyvtárból";
|
||||
"camera_unavailable" = "A kamera nem érhető el az eszközödön";
|
||||
"photo_library_access_not_granted" = "A fénykép könyvár eléréséhez %@ nem rendelkezik engedéllyel, kérlek változtasd meg az adatvédelmi beállításokat";
|
||||
// Service terms
|
||||
"service_terms_modal_title" = "Felhasználási feltételek";
|
||||
"service_terms_modal_message" = "A folytatáshoz el kell fogadnod a felhasználási feltételeket (%@).";
|
||||
"service_terms_modal_accept_button" = "Elfogad";
|
||||
"service_terms_modal_description_for_identity_server" = "Látható mások számára";
|
||||
"service_terms_modal_description_for_integration_manager" = "Használjon botokat, hidakat, kisalkalmazásokat és matrica csomagokat";
|
||||
"room_participants_remove_third_party_invite_prompt_msg" = "Biztos vagy benne, hogy visszavonod ezt a meghívót?";
|
||||
// Errors
|
||||
"error_user_already_logged_in" = "Úgy tűnik másik matrix szerverhez próbálsz csatlakozni. Ki szeretnél jelentkezni?";
|
||||
"room_accessiblity_scroll_to_bottom" = "Görgess az aljára";
|
||||
"room_accessibility_search" = "Keresés";
|
||||
"room_accessibility_integrations" = "Integrációk";
|
||||
"room_accessibility_upload" = "Feltöltés";
|
||||
"room_accessibility_call" = "Hívás";
|
||||
"room_accessibility_hangup" = "Letesz";
|
||||
"media_type_accessibility_image" = "Kép";
|
||||
"media_type_accessibility_audio" = "Hang";
|
||||
"media_type_accessibility_video" = "Videó";
|
||||
"media_type_accessibility_location" = "Helyzet";
|
||||
"media_type_accessibility_file" = "Fájl";
|
||||
"media_type_accessibility_sticker" = "Matrica";
|
||||
// Widget Picker
|
||||
"widget_picker_title" = "Integrációk";
|
||||
"auth_add_email_message_2" = "E-mail cím beállítása fiók visszaállításhoz és, hogy később az ismerősök megtalálhassanak.";
|
||||
"auth_add_phone_message_2" = "Telefonszám beállítása, hogy később az ismerősök megtalálhassanak.";
|
||||
"auth_add_email_phone_message_2" = "E-mail cím beállítása fiók visszaállításhoz. Használj később e-mail címet vagy telefonszámot, hogy az ismerősök megtalálhassanak.";
|
||||
"auth_email_is_required" = "Azonosítási szerver nincs beállítva, így nem tudsz hozzáadni e-mail címet amivel vissza lehetne állítani a jelszót a későbbiekben.";
|
||||
"auth_phone_is_required" = "Azonosítási szerver nincs beállítva, így nem tudsz hozzáadni telefonszámot, hogy vissza lehetne állítani a jelszót a későbbiekben.";
|
||||
"auth_reset_password_error_is_required" = "Azonosítási szerver nincs beállítva: adj hozzá egyet a szerver beállításoknál, hogy a jelszót vissza lehessen állítani.";
|
||||
"contacts_address_book_no_identity_server" = "Azonosítási szerver nincs beállítva";
|
||||
"settings_discovery_settings" = "FELDERÍTÉS";
|
||||
"settings_identity_server_settings" = "AZONOSÍTÁSI SZERVER";
|
||||
"settings_three_pids_management_information_part1" = "Állítsd be melyik e-mail címmel vagy telefonszámmal lehessen bejelentkezni vagy visszaállítani a fiókot. Add meg ki találhat meg itt: ";
|
||||
"settings_three_pids_management_information_part2" = "Felderítés";
|
||||
"settings_three_pids_management_information_part3" = ".";
|
||||
"settings_calls_stun_server_fallback_button" = "Másodlagos hívást segítő szerver engedélyezése";
|
||||
"settings_calls_stun_server_fallback_description" = "Másodlagos hívást segítő szerver (%@) engedélyezése ha a matrix szervered nem ajánl fel másikat (az IP címed a hívás ideje alatt meg lesz osztva).";
|
||||
"settings_devices_description" = "Az eszköz nyilvános neve látható azoknál az embereknél akikkel beszélgetsz";
|
||||
"settings_discovery_no_identity_server" = "Jelenleg nem használsz azonosítási szervert. Ahhoz, hogy az ismerősök megtalálhassanak adj hozzá egyet.";
|
||||
"settings_discovery_terms_not_signed" = "Egyetértés az Azonosítási Szerver (%@) Felhasználási Feltételeivel, hogy e-mail címmel vagy telefonszámmal megtalálható lehess.";
|
||||
"settings_discovery_three_pids_management_information_part1" = "E-mail címek és telefonszámok beállítása amivel más felhasználók megtalálhatnak és meghívhatna szobákba. E-mail cím és telefonszám hozzáadása és törlése a listából itt: ";
|
||||
"settings_discovery_three_pids_management_information_part2" = "Felhasználói Beállítások";
|
||||
"settings_discovery_three_pids_management_information_part3" = ".";
|
||||
"settings_discovery_error_message" = "Hiba történt. Kérlek próbáld újra.";
|
||||
"settings_discovery_three_pid_details_title_email" = "E-mail címek kezelése";
|
||||
"settings_discovery_three_pid_details_information_email" = "E-mail cím beállítások kezelése, amivel más felhasználók megtalálhatnak és meghívhatnak a szobákba. E-mail cím hozzáadása és törlése a Fiókokban.";
|
||||
"settings_discovery_three_pid_details_title_phone_number" = "Telefonszám kezelése";
|
||||
"settings_discovery_three_pid_details_information_phone_number" = "Telefonszám beállítások kezelése, amivel más felhasználók megtalálhatnak és meghívhatnak a szobákba. Telefonszám hozzáadása és törlése a Fiókokban.";
|
||||
"settings_discovery_three_pid_details_share_action" = "Megoszt";
|
||||
"settings_discovery_three_pid_details_revoke_action" = "Visszavon";
|
||||
"settings_discovery_three_pid_details_cancel_email_validation_action" = "E-mail azonosítás visszavonása";
|
||||
"settings_discovery_three_pid_details_enter_sms_code_action" = "Add meg az SMS aktiválási kódot";
|
||||
"settings_identity_server_description" = "Az alábbi azonosítási szerver használatával megtalálhatod a barátaidat és te is megtalálható leszel az ismerőseidnek.";
|
||||
"settings_identity_server_no_is" = "Azonosítási szerver nincs beállítva";
|
||||
"settings_identity_server_no_is_description" = "Jelenleg nem használsz azonosítási szervert. Ahhoz, hogy megtalálhass másokat és az ismerősök megtalálhassanak adj hozzá egyet alább.";
|
||||
// Identity server settings
|
||||
"identity_server_settings_title" = "Azonosítási Szerver";
|
||||
"identity_server_settings_description" = "Jelenleg ezt használod: %@, hogy megtalálj másokat és megtalálhassanak ismerősök.";
|
||||
"identity_server_settings_no_is_description" = "Jelenleg nem használsz azonosítási szervert. Ahhoz, hogy megtalálj másokat és megtalálhassanak ismerősök adj meg egyet alább.";
|
||||
"identity_server_settings_place_holder" = "Adj meg egy azonosítási szervet";
|
||||
"identity_server_settings_add" = "Hozzáad";
|
||||
"identity_server_settings_change" = "Módosít";
|
||||
"identity_server_settings_disconnect_info" = "Ha lecsatlakozol az azonosítási szerverről azt eredményezi, hogy mások nem fognak megtalálni és nem tudnak meghívni e-mail vagy telefonszám alapján.";
|
||||
"identity_server_settings_disconnect" = "Lecsatlakozás";
|
||||
"identity_server_settings_alert_no_terms_title" = "Az azonosítási szervernek nincs felhasználási feltétele";
|
||||
"identity_server_settings_alert_no_terms" = "Az általad választott azonosítási szervernek nincs felhasználási feltétele. Csak akkor lépj tovább ha megbízol a szolgáltatás tulajdonosában.";
|
||||
"identity_server_settings_alert_change_title" = "Azonosítási szerver megváltoztatása";
|
||||
"identity_server_settings_alert_change" = "Lecsatlakozol erről az azonosítási szerverről: %1$@ és csatlakozol ehhez: %2$@?";
|
||||
"identity_server_settings_alert_disconnect_title" = "Azonosítási szerverről lecsatlakozás";
|
||||
"identity_server_settings_alert_disconnect" = "Lecsatlakozol erről az azonosítási szerverről: %@?";
|
||||
"identity_server_settings_alert_disconnect_button" = "Lecsatlakozás";
|
||||
"identity_server_settings_alert_disconnect_still_sharing_3pid" = "Továbbra is megosztod a személyes adataidat ezzel az azonosítási szerverrel: %@.\n\nAzt javasoljuk, hogy az azonosítási szerverről való lecsatlakozás előtt először töröld az e-mail címeidet és telefonszámaidat.";
|
||||
"identity_server_settings_alert_disconnect_still_sharing_3pid_button" = "Mindenképpen lecsatlakozás";
|
||||
"identity_server_settings_alert_error_terms_not_accepted" = "Mielőtt beállíthatnád azonosítási szervernek el kell fogadnod a feltételeket: %@.";
|
||||
"identity_server_settings_alert_error_invalid_identity_server" = "%@ nem egy érvényes azonosítási szerver.";
|
||||
"call_no_stun_server_error_title" = "A hívás a hibásan konfigurált szerver miatt sikertelen";
|
||||
"call_no_stun_server_error_message_1" = "Kérlek kérd meg a matrix szervered (%@) adminisztrátorát, hogy állítson be egy TURN szervert a hívások megbízható működéséhez.";
|
||||
"call_no_stun_server_error_message_2" = "Alternatív megoldásként használhatod a nyilvános szervert itt: %@, de ez lehet, hogy nem lesz annyira megbízható és megosztja az IP címedet a szerverrel. Ezt a Beállításokban módosíthatod";
|
||||
"call_no_stun_server_error_use_fallback_button" = "Próbáld használni ezt: %@";
|
||||
// Generic errors
|
||||
"error_invite_3pid_with_no_identity_server" = "Az e-mail címmel való meghíváshoz adj hozzá egy azonosítási szervert a beállításaidnál.";
|
||||
|
|
|
@ -2,4 +2,5 @@
|
|||
"NSCameraUsageDescription" = "La fotocamera viene utilizzata per scattare fotografie, registrare video ed eseguire videochiamate.";
|
||||
"NSPhotoLibraryUsageDescription" = "La libreria fotografica viene utilizzata per inviare foto e video.";
|
||||
"NSMicrophoneUsageDescription" = "Il microfono viene utilizzato per registrare video ed effettuare chiamate.";
|
||||
"NSContactsUsageDescription" = "Per mostrare i tuoi contatti che stanno già usando Riot o Matrix, possiamo inviare gli indirizzi email e i numeri di telefono della tua rubrica al tuo server identità. New Vector non memorizza e non usa per altri scopi questi dati. Per maggiori informazioni guarda l'informativa sulla privacy presente nelle impostazioni di questa applicazione.";
|
||||
"NSContactsUsageDescription" = "Per scoprire i contatti che già usano Matrix, Riot può inviare gli indirizzi email e i numeri di telefono della tua rubrica al server identità che hai scelto. Se supportato, viene fatto un hash dei dati personali prima dell'invio - controlla la politica sulla privacy del tuo server di identità per maggiori informazioni.";
|
||||
"NSCalendarsUsageDescription" = "Vedi le tue riunioni programmate nell'app.";
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
"auth_repeat_password_placeholder" = "Ripeti password";
|
||||
"auth_repeat_new_password_placeholder" = "Conferma la nuova password";
|
||||
"auth_home_server_placeholder" = "URL (es. https://matrix.org)";
|
||||
"auth_identity_server_placeholder" = "URL (es. https://matrix.org)";
|
||||
"auth_identity_server_placeholder" = "URL (es. https://vector.im)";
|
||||
"auth_invalid_login_param" = "Nome utente e/o password non corretti";
|
||||
"auth_invalid_user_name" = "Il nome utente può contenere solo lettere, numeri, punti, trattini e linee basse";
|
||||
"auth_invalid_password" = "Password troppo breve (min 6)";
|
||||
|
@ -174,7 +174,7 @@
|
|||
"room_participants_filter_room_members" = "Filtra i membri della stanza";
|
||||
"room_participants_invite_another_user" = "Cerca / invita per ID utente, nome o email";
|
||||
"room_participants_invite_malformed_id_title" = "Errore durante l'invito";
|
||||
"room_participants_invite_malformed_id" = "ID malformato. Dovrebbe essere un indirizzo email o un ID Matrix come '@localpart:domain'";
|
||||
"room_participants_invite_malformed_id" = "ID incorretto. Dovrebbe essere un indirizzo email o un ID Matrix come '@localpart:domain'";
|
||||
"room_participants_invited_section" = "INVITATI";
|
||||
"room_participants_online" = "Online";
|
||||
"room_participants_offline" = "Offline";
|
||||
|
@ -201,7 +201,7 @@
|
|||
"room_participants_action_start_video_call" = "Avvia videochiamata";
|
||||
"room_participants_action_mention" = "Citazione";
|
||||
// Chat
|
||||
"room_jump_to_first_unread" = "Primo messaggio non letto";
|
||||
"room_jump_to_first_unread" = "Vai al primo messaggio non letto";
|
||||
"room_new_message_notification" = "%d nuovo messaggio";
|
||||
"room_new_messages_notification" = "%d nuovi messaggi";
|
||||
"room_one_user_is_typing" = "%@ sta scrivendo…";
|
||||
|
@ -221,10 +221,10 @@
|
|||
"room_ongoing_conference_call" = "Chiamata di conferenza in corso. Unisciti come %@ o %@.";
|
||||
"room_ongoing_conference_call_with_close" = "Chiamata di conferenza in corso. Unisciti come %@ o %@. %@.";
|
||||
"room_ongoing_conference_call_close" = "Chiudi";
|
||||
"room_conference_call_no_power" = "Hai bisogno i permessi per gestire le chiamate di gruppo in questa stanza";
|
||||
"room_conference_call_no_power" = "Hai bisogno dei permessi per gestire le chiamate di gruppo in questa stanza";
|
||||
"room_prompt_resend" = "Rinvia tutto";
|
||||
"room_prompt_cancel" = "annulla tutto";
|
||||
"room_resend_unsent_messages" = "Rinvia i messaggi non spediti";
|
||||
"room_resend_unsent_messages" = "Reinvia i messaggi non spediti";
|
||||
"room_delete_unsent_messages" = "Elimina messaggi non spediti";
|
||||
"room_event_action_copy" = "Copia";
|
||||
"room_event_action_quote" = "Cita";
|
||||
|
@ -233,19 +233,19 @@
|
|||
"room_event_action_share" = "Condividi";
|
||||
"room_event_action_permalink" = "Collegamento permanente";
|
||||
"room_event_action_view_source" = "Vedi sorgente";
|
||||
"room_event_action_view_decrypted_source" = "Vedi sorgente decriptato";
|
||||
"room_event_action_view_decrypted_source" = "Vedi sorgente decriptata";
|
||||
"room_event_action_report" = "Segnala contenuto";
|
||||
"room_event_action_report_prompt_reason" = "Motivo per segnalare questo contenuto";
|
||||
"room_event_action_kick_prompt_reason" = "Motivo per buttare fuori questo utente";
|
||||
"room_event_action_ban_prompt_reason" = "Motivo per bandire questo utente";
|
||||
"room_event_action_report_prompt_reason" = "Motivo della segnalazione";
|
||||
"room_event_action_kick_prompt_reason" = "Motivo per cui rimuovi questo utente";
|
||||
"room_event_action_ban_prompt_reason" = "Motivo per cui banni questo utente";
|
||||
"room_event_action_report_prompt_ignore_user" = "Vuoi nascondere tutti i messaggi da questo utente?";
|
||||
"room_event_action_save" = "Salva";
|
||||
"room_event_action_resend" = "Rinvia";
|
||||
"room_event_action_resend" = "Reinvia";
|
||||
"room_event_action_delete" = "Elimina";
|
||||
"room_event_action_cancel_send" = "Annulla invio";
|
||||
"room_event_action_cancel_download" = "Annulla download";
|
||||
"room_event_action_view_encryption" = "Informazioni crittografia";
|
||||
"room_warning_about_encryption" = "La crittografia da-utente-a-utente è in fase sperimentale e potrebbe non essere affidabile.\n\nNon dovesti ancora fidarti di questo per proteggere i tuoi dati.\n\nI dispositivi non potranno decifrare la cronologia dei messaggi precedenti all'entrata nella stanza.\n\nI messaggi cifrati non saranno visibili dalle applicazioni che non hanno ancora implementato la crittografia.";
|
||||
"room_warning_about_encryption" = "La crittografia da-utente-a-utente è in fase sperimentale e potrebbe non esser ancora affidabile.\n\nNon dovesti ancora farci affidamento per proteggere i tuoi dati.\n\nI dispositivi non potranno decrittare la cronologia dei messaggi precedenti all'entrata nella stanza.\n\nI messaggi crittografati non saranno visibili dalle applicazioni che non hanno ancora implementato la crittografia.";
|
||||
"room_event_failed_to_send" = "Invio fallito";
|
||||
"room_action_send_photo_or_video" = "Invia foto o video";
|
||||
"room_action_send_sticker" = "Invia sticker";
|
||||
|
@ -262,7 +262,7 @@
|
|||
"room_resource_usage_limit_reached_message_contact_3" = " per aumentare questo limite.";
|
||||
// Unknown devices
|
||||
"unknown_devices_alert_title" = "La stanza contiene dispositivi sconosciuti";
|
||||
"unknown_devices_alert" = "Questa stanza contiene dispositivi sconosciuti che non sono stati verificati.\nCiò significa che non esiste alcuna garanzia che i dispositivi appartengano agli utenti che ne rivendicano il possesso.\nSi consiglia di passare attraverso il processo di verifica per ogni dispositivo prima di continuare, ma è possibile inviare ugualmente il messaggio senza fare la verifica se preferisci.";
|
||||
"unknown_devices_alert" = "Questa stanza contiene dispositivi sconosciuti che non sono stati verificati.\nCiò significa che non esiste alcuna garanzia che i dispositivi siano davvero quelli di chi dice di possederli.\nPrima di continuare si consiglia di effettuare la verifica di ogni dispositivo, ma se vuoi è comunque possibile rispedire il messaggio senza fare alcuna verifica.";
|
||||
"unknown_devices_send_anyway" = "Invia comunque";
|
||||
"unknown_devices_call_anyway" = "Chiama comunque";
|
||||
"unknown_devices_answer_anyway" = "Rispondi comunque";
|
||||
|
@ -277,19 +277,19 @@
|
|||
"room_title_one_member" = "1 membro";
|
||||
// Room Preview
|
||||
"room_preview_invitation_format" = "Sei stato invitato ad unirti in questa stanza da %@";
|
||||
"room_preview_subtitle" = "Questa è l'anteprima della stanza. Le interazioni con la stanza sono state disabilitate.";
|
||||
"room_preview_unlinked_email_warning" = "Questo invito è stato spedito da %@, che non è associato a questo account. È possibile che tu voglia connetterti con un altro account, o aggiungere l'email al tuo account.";
|
||||
"room_preview_subtitle" = "Questa è l'anteprima della stanza. Le interazioni con la stanza sono disabilitate.";
|
||||
"room_preview_unlinked_email_warning" = "Questo invito è stato spedito da %@, che non è associato a questo account. È possibile che tu voglia connetterti con un altro account o aggiungere questo indirizzo email al tuo account.";
|
||||
"room_preview_try_join_an_unknown_room" = "Stai provando ad accedere a %@. Desideri entrare per partecipare alla discussione?";
|
||||
"room_preview_try_join_an_unknown_room_default" = "una stanza";
|
||||
// Settings
|
||||
"settings_title" = "Impostazioni";
|
||||
"account_logout_all" = "Sconnetti tutti gli account";
|
||||
"settings_config_no_build_info" = "Nessuna informazione di compilazione";
|
||||
"settings_config_no_build_info" = "Nessuna informazione di build";
|
||||
"settings_mark_all_as_read" = "Segna tutti i messaggi come letti";
|
||||
"settings_report_bug" = "Segnala errore";
|
||||
"settings_clear_cache" = "Elimina cache";
|
||||
"settings_config_home_server" = "Il server home è %@";
|
||||
"settings_config_identity_server" = "Il server identità è %@";
|
||||
"settings_config_home_server" = "L'Homeserver è %@";
|
||||
"settings_config_identity_server" = "L'Identity server è %@";
|
||||
"settings_config_user_id" = "Connesso come %@";
|
||||
"settings_user_settings" = "IMPOSTAZIONI UTENTE";
|
||||
"settings_notifications_settings" = "IMPOSTAZIONI NOTIFICHE";
|
||||
|
@ -303,11 +303,11 @@
|
|||
"settings_flair" = "Mostra predisposizione se permesso";
|
||||
"settings_devices" = "DISPOSITIVI";
|
||||
"settings_cryptography" = "CRITTOGRAFIA";
|
||||
"settings_key_backup" = "BACKUP CHIAVE";
|
||||
"settings_key_backup" = "BACKUP DELLE CHIAVI";
|
||||
"settings_deactivate_account" = "DISATTIVA ACCOUNT";
|
||||
"settings_sign_out" = "Disconnetti";
|
||||
"settings_sign_out_confirmation" = "Sei sicuro?";
|
||||
"settings_sign_out_e2e_warn" = "Perderai le tue chiavi di crittografia da-utente-a-utente. Questo significa che non potrai più leggere i vecchi messaggi nelle stanze cifrate su questo dispositivo.";
|
||||
"settings_sign_out_e2e_warn" = "Perderai le tue chiavi di crittografia da-utente-a-utente. Questo significa che non potrai più leggere i vecchi messaggi nelle stanze crittografate su questo dispositivo.";
|
||||
"settings_profile_picture" = "Immagine profilo";
|
||||
"settings_display_name" = "Nome visualizzato";
|
||||
"settings_first_name" = "Nome";
|
||||
|
@ -324,8 +324,8 @@
|
|||
"settings_night_mode" = "Modalità notte";
|
||||
"settings_fail_to_update_profile" = "Errore nell'aggiornamento del profilo";
|
||||
"settings_enable_push_notif" = "Notifiche per questo dispositivo";
|
||||
"settings_show_decrypted_content" = "Mostra contenuto decriptato";
|
||||
"settings_global_settings_info" = "Impostazioni globali di notifica sono disponibili nel tuo %@ web client";
|
||||
"settings_show_decrypted_content" = "Mostra contenuto decrittato";
|
||||
"settings_global_settings_info" = "Le impostazioni globali di notifica sono disponibili nel tuo %@ web client";
|
||||
"settings_pin_rooms_with_missed_notif" = "Segna le stanze con notifiche perse";
|
||||
"settings_pin_rooms_with_unread" = "Segna le stanze con messaggi non letti";
|
||||
"settings_on_denied_notification" = "Le notifiche non sono permesse per %@, abilitale nelle impostazioni del tuo dispositivo";
|
||||
|
@ -345,15 +345,15 @@
|
|||
"settings_labs_e2e_encryption" = "Crittografia da-utente-a-utente";
|
||||
"settings_labs_e2e_encryption_prompt_message" = "Per finire la configurazione della crittografia devi rieseguire l'accesso.";
|
||||
"settings_labs_room_members_lazy_loading" = "Caricamento posticipato dei membri della stanza";
|
||||
"settings_labs_room_members_lazy_loading_error_message" = "Il tuo server home non supporta ancora il caricamento posticipato dei membri delle stanze. Prova in seguito.";
|
||||
"settings_labs_room_members_lazy_loading_error_message" = "Il tuo Homeserver non supporta ancora il caricamento intelligente dei membri delle stanze. Prova in seguito.";
|
||||
"settings_labs_create_conference_with_jitsi" = "Crea una videoconferenza con jitsi";
|
||||
"settings_version" = "Versione %@";
|
||||
"settings_olm_version" = "Versione olm %@";
|
||||
"settings_olm_version" = "Versione Olm %@";
|
||||
"settings_copyright" = "Copyright";
|
||||
"settings_copyright_url" = "https://riot.im/copyright";
|
||||
"settings_term_conditions" = "Termini e condizioni";
|
||||
"settings_term_conditions_url" = "https://riot.im/tac_apple";
|
||||
"settings_privacy_policy" = "Politica sulla privacy";
|
||||
"settings_privacy_policy" = "Privacy Policy";
|
||||
"settings_privacy_policy_url" = "https://riot.im/privacy";
|
||||
"settings_third_party_notices" = "Avvisi di terze parti";
|
||||
"settings_send_crash_report" = "Invia dati di utilizzo anonimi";
|
||||
|
@ -361,22 +361,22 @@
|
|||
"settings_old_password" = "vecchia password";
|
||||
"settings_new_password" = "nuova password";
|
||||
"settings_confirm_password" = "conferma password";
|
||||
"settings_fail_to_update_password" = "Fallito l'aggiornamento password";
|
||||
"settings_fail_to_update_password" = "Aggiornamento password fallito";
|
||||
"settings_password_updated" = "La tua password è stata aggiornata";
|
||||
"settings_crypto_device_name" = "Nome dispositivo: ";
|
||||
"settings_crypto_device_name" = "Nome pubblico dispositivo: ";
|
||||
"settings_crypto_device_id" = "\nID Dispositivo: ";
|
||||
"settings_crypto_device_key" = "\nChiave dispositivo: ";
|
||||
"settings_crypto_device_key" = "\nChiave dispositivo:\n";
|
||||
"settings_crypto_export" = "Esporta chiavi";
|
||||
"settings_crypto_blacklist_unverified_devices" = "Cripta solo per i dispositivi verificati";
|
||||
"settings_crypto_blacklist_unverified_devices" = "Crittografa solo per i dispositivi verificati";
|
||||
"settings_deactivate_my_account" = "Disattiva il mio account";
|
||||
"settings_key_backup_info" = "I messaggi criptati sono protetti con la cifratura end-to-end. Solo tu e il/i destinatario/i avete le chiavi per leggere questi messaggi.";
|
||||
"settings_key_backup_info" = "I messaggi crittografati sono protetti con la crittografia da-utente-a-utente. Solo tu e il/i destinatario/i avete le chiavi per leggere questi messaggi.";
|
||||
"settings_key_backup_info_checking" = "Verifica...";
|
||||
"settings_key_backup_info_none" = "Nessun backup programmato per le chiavi da questo dispositivo.";
|
||||
"settings_key_backup_info_signout_warning" = "Fai un backup sicuro delle tue chiavi prima di uscire per evitare di perderle.";
|
||||
"settings_key_backup_info_none" = "Nessun Backup programmato per le Chiavi da questo dispositivo.";
|
||||
"settings_key_backup_info_signout_warning" = "Connetti questo dispositivo al backup chiavi prima di disconnetterti per evitare di perdere eventuali chiavi presenti solo qui.";
|
||||
"settings_key_backup_info_version" = "Versione backup chiave: %@";
|
||||
"settings_key_backup_info_algorithm" = "Algoritmo: %@";
|
||||
"settings_key_backup_info_valid" = "Questo dispositivo sta eseguendo il backup delle tue chiavi.";
|
||||
"settings_key_backup_info_not_valid" = "Questo dispositivo non sta eseguendo il backup delle tue chiavi.";
|
||||
"settings_key_backup_info_not_valid" = "Questo dispositivo non sta eseguendo il Backup delle tue Chiavi, ma é disponibile un vecchio Backup da cui puoi ripristinarle.";
|
||||
"settings_key_backup_info_progress" = "Backup di %@ chiavi…";
|
||||
"settings_key_backup_info_progress_done" = "Backup di tutte le chiavi completato";
|
||||
"settings_key_backup_info_trust_signature_unknown" = "Il backup ha una firma dal dispositivo con ID: %@";
|
||||
|
@ -389,7 +389,7 @@
|
|||
"settings_key_backup_button_restore" = "Ripristina da backup";
|
||||
"settings_key_backup_button_delete" = "Elimina backup";
|
||||
"settings_key_backup_delete_confirmation_prompt_title" = "Elimina backup";
|
||||
"settings_key_backup_delete_confirmation_prompt_msg" = "Sei sicuro? Perderai i tuoi messaggi cifrati se le tue chiavi non sono salvate correttamente.";
|
||||
"settings_key_backup_delete_confirmation_prompt_msg" = "Sei sicuro? Se non hai eseguito un Backup delle Chiavi perderai i tuoi messaggi crittografati.";
|
||||
// Room Details
|
||||
"room_details_title" = "Dettagli stanza";
|
||||
"room_details_people" = "Membri";
|
||||
|
@ -406,7 +406,7 @@
|
|||
"room_details_access_section_invited_only" = "Solo le persone che sono state invitate";
|
||||
"room_details_access_section_anyone_apart_from_guest" = "Chiunque conosca il link della stanza, eccetto gli ospiti";
|
||||
"room_details_access_section_anyone" = "Chiunque conosca il link della stanza, compresi gli ospiti";
|
||||
"room_details_access_section_no_address_warning" = "Per indirizzare ad una stanza tramite link, essa deve avere un indirizzo";
|
||||
"room_details_access_section_no_address_warning" = "Per poter essere linkata, la stanza deve avere un indirizzo";
|
||||
"room_details_access_section_directory_toggle" = "Mostra questa stanza nell'elenco delle stanze";
|
||||
"room_details_history_section" = "Chi può leggere la cronologia?";
|
||||
"room_details_history_section_anyone" = "Chiunque";
|
||||
|
@ -414,16 +414,16 @@
|
|||
"room_details_history_section_members_only_since_invited" = "Solo i membri (dal momento in cui vengono invitati)";
|
||||
"room_details_history_section_members_only_since_joined" = "Solo i membri (dal momento in cui entrano nella stanza)";
|
||||
"room_details_history_section_prompt_title" = "Avvertimento sulla privacy";
|
||||
"room_details_history_section_prompt_msg" = "La leggibilità della cronologia sarà modificata solo per i futuri messaggi di questa stanza. La visibilità dei messaggi esistenti rimarrà invariata.";
|
||||
"room_details_history_section_prompt_msg" = "I permessi di lettura di questa stanza saranno modificati solo per i messaggi futuri. I permessi di lettura dei messaggi esistenti rimarranno invariati.";
|
||||
"room_details_addresses_section" = "Indirizzi";
|
||||
"room_details_no_local_addresses" = "Questa stanza non ha indirizzi locali";
|
||||
"room_details_new_address" = "Aggiungi nuovo indirizzo";
|
||||
"room_details_new_address_placeholder" = "Aggiungi nuovo indirizzo (es. #foo%@)";
|
||||
"room_details_addresses_invalid_address_prompt_title" = "Formato soprannome non valido";
|
||||
"room_details_addresses_invalid_address_prompt_msg" = "%@ non è un formato valido per un soprannome";
|
||||
"room_details_addresses_invalid_address_prompt_title" = "Il formato dell'indirizzo non é valido";
|
||||
"room_details_addresses_invalid_address_prompt_msg" = "%@ non è un formato valido per un alias";
|
||||
"room_details_addresses_disable_main_address_prompt_title" = "Avviso per l'indirizzo principale";
|
||||
"room_details_addresses_disable_main_address_prompt_msg" = "Non avrai nessun indirizzo principale specificato. L'indirizzo principale per questa stanza sarà selezionato casualmente";
|
||||
"room_details_flair_section" = "Mostra insegna per le comunità";
|
||||
"room_details_addresses_disable_main_address_prompt_msg" = "Non hai specificato un indirizzo principale. L'indirizzo principale per questa stanza sarà selezionato casualmente";
|
||||
"room_details_flair_section" = "Mostra predisposizione per le comunità";
|
||||
"room_details_new_flair_placeholder" = "Aggiungi nuovo ID della comunità (es. +foo%@)";
|
||||
"room_details_flair_invalid_id_prompt_title" = "Formato non valido";
|
||||
"room_details_flair_invalid_id_prompt_msg" = "%@ non è un identificatore valido per una comunità";
|
||||
|
@ -433,23 +433,23 @@
|
|||
"room_details_advanced_enable_e2e_encryption" = "Abilita crittografia (attenzione: non può più essere disabilitata!)";
|
||||
"room_details_advanced_e2e_encryption_enabled" = "Crittografia abilitata in questa stanza";
|
||||
"room_details_advanced_e2e_encryption_disabled" = "Crittografia non abilitata in questa stanza.";
|
||||
"room_details_advanced_e2e_encryption_blacklist_unverified_devices" = "Cripta solo per i dispositivi verificati";
|
||||
"room_details_fail_to_update_avatar" = "Fallita modifica dell'immagine stanza";
|
||||
"room_details_fail_to_update_room_name" = "Fallita modifica del nome stanza";
|
||||
"room_details_fail_to_update_topic" = "Fallita modifica dell'argomento";
|
||||
"room_details_fail_to_update_room_guest_access" = "Fallita modifica dell'accesso agli ospiti alla stanza";
|
||||
"room_details_fail_to_update_room_join_rule" = "Fallita modifica delle regole di accesso";
|
||||
"room_details_fail_to_update_room_directory_visibility" = "Fallita modifica della visibilità nell'elenco stanze";
|
||||
"room_details_fail_to_update_history_visibility" = "Fallita modifica della visibilità della cronologia";
|
||||
"room_details_fail_to_add_room_aliases" = "Fallita aggiunta dei nuovi indirizzi stanza";
|
||||
"room_details_fail_to_remove_room_aliases" = "Fallita rimozione degli indirizzi stanza";
|
||||
"room_details_fail_to_update_room_canonical_alias" = "Fallita modifica dell'indirizzo principale";
|
||||
"room_details_fail_to_update_room_communities" = "Fallita modifica delle comunità collegate";
|
||||
"room_details_fail_to_update_room_direct" = "Fallita modifica nel rendere diretta questa stanza";
|
||||
"room_details_fail_to_enable_encryption" = "Fallita attivazione della cifratura in questa stanza";
|
||||
"room_details_advanced_e2e_encryption_blacklist_unverified_devices" = "Crittografa solo per i dispositivi verificati";
|
||||
"room_details_fail_to_update_avatar" = "La modifica dell'immagine stanza é fallita";
|
||||
"room_details_fail_to_update_room_name" = "La modifica del nome della stanza é fallita";
|
||||
"room_details_fail_to_update_topic" = "La modifica dell'argomento é fallita";
|
||||
"room_details_fail_to_update_room_guest_access" = "La modifica dell'accesso ospiti alla stanza é fallita";
|
||||
"room_details_fail_to_update_room_join_rule" = "La modifica delle regole di accesso é fallita";
|
||||
"room_details_fail_to_update_room_directory_visibility" = "la modifica della visibilità nell'elenco stanze é fallita";
|
||||
"room_details_fail_to_update_history_visibility" = "La modifica della visibilità della cronologia é fallita";
|
||||
"room_details_fail_to_add_room_aliases" = "L'ggiunta dei nuovi indirizzi stanza é fallita";
|
||||
"room_details_fail_to_remove_room_aliases" = "La rimozione degli indirizzi stanza é fallita";
|
||||
"room_details_fail_to_update_room_canonical_alias" = "La modifica dell'indirizzo principale é fallita";
|
||||
"room_details_fail_to_update_room_communities" = "La modifica delle comunità collegate é fallita";
|
||||
"room_details_fail_to_update_room_direct" = "La modifica di questa stanza in Chat Diretta é fallita";
|
||||
"room_details_fail_to_enable_encryption" = "L'attivazione della crittografia in questa stanza é fallita";
|
||||
"room_details_save_changes_prompt" = "Vuoi salvare le modifiche?";
|
||||
"room_details_set_main_address" = "Imposta come indirizzo principale";
|
||||
"room_details_unset_main_address" = "Non più come indirizzo principale";
|
||||
"room_details_unset_main_address" = "Non utilizzare più come indirizzo principale";
|
||||
"room_details_copy_room_id" = "Copia ID stanza";
|
||||
"room_details_copy_room_address" = "Copia indirizzo stanza";
|
||||
"room_details_copy_room_url" = "Copia URL stanza";
|
||||
|
@ -466,31 +466,31 @@
|
|||
"group_invitation_format" = "%@ ti ha invitato ad unirti a questa comunità";
|
||||
// Group participants
|
||||
"group_participants_add_participant" = "Aggiungi membri";
|
||||
"group_participants_leave_prompt_title" = "Lascia stanza";
|
||||
"group_participants_leave_prompt_title" = "Lascia la stanza";
|
||||
"group_participants_leave_prompt_msg" = "Sei sicuro di voler uscire dalla stanza?";
|
||||
"group_participants_remove_prompt_title" = "Conferma";
|
||||
"group_participants_remove_prompt_msg" = "Sei sicuro di voler rimuovere %@ da questa chat?";
|
||||
"group_participants_invite_prompt_title" = "Conferma";
|
||||
"group_participants_invite_prompt_msg" = "Sei sicuro di voler invitare %@ in questa stanza?";
|
||||
"group_participants_filter_members" = "Filtra membri comunità";
|
||||
"group_participants_filter_members" = "Filtra i membri della comunità";
|
||||
"group_participants_invite_another_user" = "Cerca / invita per ID utente o nome";
|
||||
"group_participants_invite_malformed_id_title" = "Invito fallito";
|
||||
"group_participants_invite_malformed_id" = "ID malformato. Dovrebbe essere ID Matrix come '@localpart:domain'";
|
||||
"group_participants_invited_section" = "INVITATI";
|
||||
// Group rooms
|
||||
"group_rooms_filter_rooms" = "Filtra stanze comunità";
|
||||
"group_rooms_filter_rooms" = "Filtra le stanze della comunità";
|
||||
// Read Receipts
|
||||
"read_receipts_list" = "Elenco ricevute di lettura";
|
||||
"receipt_status_read" = "Letto: ";
|
||||
// Media picker
|
||||
"media_picker_library" = "Galleria";
|
||||
"media_picker_library" = "Galleria Immagini";
|
||||
"media_picker_select" = "Seleziona";
|
||||
// Directory
|
||||
"directory_title" = "Elenco";
|
||||
"directory_server_picker_title" = "Seleziona un elenco";
|
||||
"directory_server_all_rooms" = "Tutte le stanze sul server %@";
|
||||
"directory_server_all_native_rooms" = "Tutte le stanze Matrix native";
|
||||
"directory_server_type_homeserver" = "Digita un server home per elencare le sue stanze pubbliche";
|
||||
"directory_server_type_homeserver" = "Digita un Homeserver per vedere l'elenco delle sue stanze pubbliche";
|
||||
"directory_server_placeholder" = "matrix.org";
|
||||
// Events formatter
|
||||
"event_formatter_member_updates" = "%tu cambi d'appartenenza";
|
||||
|
@ -498,20 +498,20 @@
|
|||
"event_formatter_widget_removed" = "%@ widget rimosso da %@";
|
||||
"event_formatter_jitsi_widget_added" = "Conferenza VoIP aggiunta da %@";
|
||||
"event_formatter_jitsi_widget_removed" = "Conferenza VoIP rimossa da %@";
|
||||
"event_formatter_rerequest_keys_part1_link" = "Richiedi di nuovo le chiavi di cifratura";
|
||||
"event_formatter_rerequest_keys_part1_link" = "Richiedi nuovamente le chiavi di crittografia";
|
||||
"event_formatter_rerequest_keys_part2" = " dai tuoi altri dispositivi.";
|
||||
// Others
|
||||
"or" = "o";
|
||||
"you" = "Tu";
|
||||
"today" = "Oggi";
|
||||
"yesterday" = "Ieri";
|
||||
"network_offline_prompt" = "La connessione a internet sembra essere disconnessa.";
|
||||
"homeserver_connection_lost" = "Non riesco a connettermi al server home.";
|
||||
"network_offline_prompt" = "La connessione a internet sembra essere assente.";
|
||||
"homeserver_connection_lost" = "Non riesco a connettermi all'Homeserver.";
|
||||
"public_room_section_title" = "Stanze pubbliche (in %@):";
|
||||
"bug_report_prompt" = "L'applicazione è andata in crash l'ultima volta. Desideri aprire la schermata di segnalazione del crash?";
|
||||
"rage_shake_prompt" = "Sembra che tu stia scuotendo il dispositivo con frustrazione. Desideri aprire la schermata di segnalazione errore?";
|
||||
"rage_shake_prompt" = "Sembra che tu stia scuotendo il dispositivo con rabbia. Vuoi aprire la schermata di segnalazione errore?";
|
||||
"do_not_ask_again" = "Non chiedere più";
|
||||
"camera_access_not_granted" = "%@ non ha il permesso per usare la fotocamera, modifica le impostazioni privacy";
|
||||
"camera_access_not_granted" = "%@ non ha il permesso di usare la fotocamera. Modifica le impostazioni di privacy";
|
||||
"large_badge_value_k_format" = "%.1fK";
|
||||
"room_does_not_exist" = "%@ non esiste";
|
||||
// Call
|
||||
|
@ -519,19 +519,19 @@
|
|||
"call_incoming_video_prompt" = "Videochiamata in arrivo da %@";
|
||||
"call_incoming_voice" = "Chiamata in arrivo...";
|
||||
"call_incoming_video" = "Videochiamata in arrivo...";
|
||||
"call_already_displayed" = "Già presente una chiamata in corso.";
|
||||
"call_jitsi_error" = "Fallito ingresso alla chiamata di conferenza.";
|
||||
"call_already_displayed" = "C'é già una chiamata in corso.";
|
||||
"call_jitsi_error" = "L'accesso alla chiamata in conferenza é fallito.";
|
||||
// No VoIP support
|
||||
"no_voip_title" = "Chiamata in arrivo";
|
||||
"no_voip" = "%@ ti sta chiamando, ma %@ non supporta ancora le chiamate.\nPuoi ignorare questa notifica e rispondere alla chiamata da un altro dispositivo o puoi rifiutare la chiamata.";
|
||||
"no_voip" = "%@ ti sta chiamando, ma %@ non supporta ancora le chiamate.\nPuoi ignorare questa notifica e rispondere alla chiamata da un altro dispositivo oppure puoi rifiutare la chiamata.";
|
||||
// Crash report
|
||||
"google_analytics_use_prompt" = "Vuoi aiutare a migliorare %@ inviando automaticamente in modo anonimo i dati di utilizzo e le segnalazioni di crash?";
|
||||
// Crypto
|
||||
"e2e_enabling_on_app_update" = "Riot ora supporta la crittografia da-utente-a-utente ma devi rieseguire l'accesso per abilitarla.\n\nPuoi farlo adesso oppure dopo dalle impostazioni dell'applicazione.";
|
||||
"e2e_need_log_in_again" = "È necessario eseguire nuovamente l'accesso per generare le chiavi di crittografia da-utente-a-utente per questo dispositivo ed inviare la chiave pubblica al server home.\nCiò può capitare solo una volta; ci scusiamo per l'inconveniente.";
|
||||
"e2e_enabling_on_app_update" = "Riot ora supporta la crittografia da-utente-a-utente ma devi eseguire nuovamente l'accesso per abilitarla.\n\nPuoi farlo ora o più tardi dalle impostazioni dell'applicazione.";
|
||||
"e2e_need_log_in_again" = "È necessario eseguire nuovamente l'accesso per generare le chiavi di crittografia da-utente-a-utente per questo dispositivo ed inviare la chiave pubblica all'Homeserver.\nVa fatto una sola volta; scusa per il disturbo.";
|
||||
// Key backup wrong version
|
||||
"e2e_key_backup_wrong_version_title" = "Nuovo backup chiave";
|
||||
"e2e_key_backup_wrong_version" = "È stato rilevato un nuovo backup chiavi per messaggi sicuri. \n\nSe non sei stato tu, imposta una nuova passphrase dalle impostazioni.";
|
||||
"e2e_key_backup_wrong_version_title" = "Nuovo Backup delle chiavi";
|
||||
"e2e_key_backup_wrong_version" = "È stato effettuato un nuovo Backup delle chiavi per i messaggi crittografati. \n\nSe non sei stato tu, imposta una nuova frase di sicurezza dalle impostazioni.";
|
||||
"e2e_key_backup_wrong_version_button_settings" = "Impostazioni";
|
||||
"e2e_key_backup_wrong_version_button_wasme" = "Sono stato io";
|
||||
// Bug report
|
||||
|
@ -548,14 +548,14 @@
|
|||
// Widget
|
||||
"widget_no_power_to_manage" = "Hai bisogno dei permessi per gestire i widget in questa stanza";
|
||||
"widget_creation_failure" = "Creazione del widget fallita";
|
||||
"widget_sticker_picker_no_stickerpacks_alert" = "Non hai ancora alcun pacco di adesivi attivo.";
|
||||
"widget_sticker_picker_no_stickerpacks_alert" = "Non hai nessun pacchetto sticker attivo.";
|
||||
"widget_sticker_picker_no_stickerpacks_alert_add_now" = "Aggiungerne qualcuno ora?";
|
||||
// Widget Integration Manager
|
||||
"widget_integration_need_to_be_able_to_invite" = "Devi poter inviare utenti per compiere questa azione.";
|
||||
"widget_integration_need_to_be_able_to_invite" = "Devi poter invitare utenti per compiere questa azione.";
|
||||
"widget_integration_unable_to_create" = "Impossibile creare il widget.";
|
||||
"widget_integration_failed_to_send_request" = "Invio della richiesta fallito.";
|
||||
"widget_integration_room_not_recognised" = "Questa stanza non è riconosciuta.";
|
||||
"widget_integration_positive_power_level" = "Il livello di potere deve essere un intero positivo.";
|
||||
"widget_integration_positive_power_level" = "Il livello dei permessi deve avere un valore intero e positivo.";
|
||||
"widget_integration_must_be_in_room" = "Non sei in questa stanza.";
|
||||
"widget_integration_no_permission_in_room" = "Non hai i permessi per eseguire l'azione in questa stanza.";
|
||||
"widget_integration_missing_room_id" = "room_id mancante nella richiesta.";
|
||||
|
@ -572,15 +572,15 @@
|
|||
"e2e_room_key_request_share_without_verifying" = "Condividi senza verificare";
|
||||
"e2e_room_key_request_ignore_request" = "Ignora richiesta";
|
||||
// GDPR
|
||||
"gdpr_consent_not_given_alert_message" = "Per continuare ad usare l'homeserver %@ devi leggere e accettare i termini e le condizioni di utilizzo.";
|
||||
"gdpr_consent_not_given_alert_message" = "Per continuare ad usare l'Homeserver %@ devi leggere e accettare i termini e le condizioni di utilizzo.";
|
||||
"gdpr_consent_not_given_alert_review_now_action" = "Leggi adesso";
|
||||
"deactivate_account_title" = "Disattiva account";
|
||||
"deactivate_account_informations_part1" = "Questo renderà il tuo account permanentemente inutilizzabile. Non ci potrai più accedere e nessuno potrà ri-registrare lo stesso ID utente. Il tuo account abbandonerà tutte le stanze a cui partecipa e i dettagli del tuo account saranno rimossi dal server identità. ";
|
||||
"deactivate_account_informations_part1" = "Questo renderà il tuo account inutilizzabile per sempre. Non ci potrai più accedere e nessuno potrà riutilizzare questo ID utente. Il tuo account abbandonerà tutte le stanze a cui partecipa e i dettagli del tuo account saranno rimossi dall'Identity Server. ";
|
||||
"deactivate_account_informations_part2_emphasize" = "Questa azione è irreversibile.";
|
||||
"deactivate_account_informations_part3" = "\n\nDisattivare il tuo account ";
|
||||
"deactivate_account_informations_part4_emphasize" = "non eliminerà in modo automatico i messaggi che hai inviato. ";
|
||||
"deactivate_account_informations_part5" = "Se vuoi che siano dimenticati i tuoi messaggi, seleziona la casella qua sotto\n\nLa visibilità dei messaggi in Matrix è simile alle email. \"Dimenticare i tuoi messaggi\" significa che quelli che hai inviato non verranno condivisi con alcun utente nuovo o non registrato, ma gli utenti registrati che hanno avuto accesso ai tuoi messaggi avranno ancora accesso alla loro copia.";
|
||||
"deactivate_account_forget_messages_information_part1" = "Per favore dimenticate tutti i messaggi che ho inviato al momento della disattivazione del mio account (";
|
||||
"deactivate_account_informations_part5" = "Se vuoi che i tuoi messaggi siano dimenticati, seleziona la casella qui sotto\n\nLa visibilità dei messaggi in Matrix è simile alle email: \"dimenticare i tuoi messaggi\" significa che quelli che hai già inviato non verranno condivisi con nessun utente nuovo o non registrato, ma gli utenti registrati che già hanno avuto accesso ai tuoi messaggi potranno ancora accedere alla loro copia.";
|
||||
"deactivate_account_forget_messages_information_part1" = "Dal momento in cui disattivo il mio account dimentica tutti i messaggi che ho inviato in precedenza (";
|
||||
"deactivate_account_forget_messages_information_part2_emphasize" = "Attenzione";
|
||||
"deactivate_account_forget_messages_information_part3" = ": gli utenti futuri vedranno un elenco incompleto di conversazioni)";
|
||||
"deactivate_account_validate_action" = "Disattiva account";
|
||||
|
@ -588,32 +588,32 @@
|
|||
"deactivate_account_password_alert_message" = "Per proseguire, inserisci la tua password";
|
||||
// Re-request confirmation dialog
|
||||
"rerequest_keys_alert_title" = "Richiesta inviata";
|
||||
"rerequest_keys_alert_message" = "Avvia Riot su un altro dispositivo che possa decifrare il messaggio, in modo da inviare le chiavi a questo dispositivo.";
|
||||
"rerequest_keys_alert_message" = "Avvia Riot su un altro dispositivo che possa decrittare il messaggio, in modo da poter inviare le chiavi a questo dispositivo.";
|
||||
"key_backup_setup_title" = "Backup chiave";
|
||||
"key_backup_setup_skip_alert_title" = "Sei sicuro?";
|
||||
"key_backup_setup_skip_alert_message" = "Potresti perdere i tuoi messaggi cifrati se ti disconnetti o perdi il dispositivo.";
|
||||
"key_backup_setup_skip_alert_message" = "Se ti disconnetti oppure perdi il dispositivo potresti perdere i tuoi messaggi crittografati.";
|
||||
"key_backup_setup_skip_alert_skip_action" = "Salta";
|
||||
"key_backup_setup_intro_title" = "Non perdere mai i messaggi cifrati";
|
||||
"key_backup_setup_intro_info" = "I messaggi nelle stanze cifrate sono protetti con la cifratura end-to-end. Solo tu e il/i destinatario/i avete le chiavi per leggere questi messaggi. \n \nFai un backup sicuro delle tue chiavi per evitare di perderle.";
|
||||
"key_backup_setup_intro_title" = "Non perdere mai i messaggi crittografati";
|
||||
"key_backup_setup_intro_info" = "I messaggi nelle stanze crittografate sono protetti con crittografia da-utente-a-utente. Solo tu e il/i destinatario/i avete le chiavi per leggere questi messaggi. \n \nFai un backup delle tue chiavi per evitare di perderle.";
|
||||
"key_backup_setup_intro_setup_action_without_existing_backup" = "Inizia ad usare il backup chiavi";
|
||||
"key_backup_setup_intro_manual_export_info" = "(Avanzato)";
|
||||
"key_backup_setup_intro_manual_export_action" = "Esporta manualmente le chiavi";
|
||||
"key_backup_setup_passphrase_title" = "Proteggi il tuo backup con una frase d'accesso";
|
||||
"key_backup_setup_passphrase_info" = "Salveremo una copia cifrata delle tue chiavi nel tuo homeserver. Proteggi il tuo backup con una frase d'accesso (passphrase) per tenerlo sicuro. \n \nPer una massima sicurezza, dovrebbe essere diversa dalla password del tuo account.";
|
||||
"key_backup_setup_passphrase_info" = "Salveremo una copia crittografata delle tue chiavi nel tuo Homeserver. Proteggi il tuo backup con una frase di sicurezza per tenerlo sicuro. \n \nPer una massima sicurezza, dovrebbe essere diversa dalla password del tuo account.";
|
||||
"key_backup_setup_passphrase_passphrase_title" = "Inserisci";
|
||||
"key_backup_setup_passphrase_passphrase_placeholder" = "Inserisci passphrase";
|
||||
"key_backup_setup_passphrase_passphrase_placeholder" = "Inserisci frase d'accesso";
|
||||
"key_backup_setup_passphrase_passphrase_valid" = "Bene!";
|
||||
"key_backup_setup_passphrase_passphrase_invalid" = "Prova ad aggiungere una parola";
|
||||
"key_backup_setup_passphrase_confirm_passphrase_title" = "Conferma";
|
||||
"key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Conferma passphrase";
|
||||
"key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Conferma frase d'accesso";
|
||||
"key_backup_setup_passphrase_confirm_passphrase_valid" = "Bene!";
|
||||
"key_backup_setup_passphrase_confirm_passphrase_invalid" = "Le passphrase devono corrispondere";
|
||||
"key_backup_setup_passphrase_set_passphrase_action" = "Imposta passphrase";
|
||||
"key_backup_setup_passphrase_setup_recovery_key_info" = "Oppure, proteggi il tuo backup con una chiave di ripristino, salvandola in un luogo sicuro.";
|
||||
"key_backup_setup_passphrase_confirm_passphrase_invalid" = "Le frasi d'accesso devono corrispondere";
|
||||
"key_backup_setup_passphrase_set_passphrase_action" = "Imposta frase d'accesso";
|
||||
"key_backup_setup_passphrase_setup_recovery_key_info" = "Oppure proteggi il tuo backup con una chiave di ripristino, salvandola in un luogo sicuro.";
|
||||
"key_backup_setup_passphrase_setup_recovery_key_action" = "(Avanzato) Imposta con chiave di ripristino";
|
||||
"key_backup_setup_success_title" = "Completato!";
|
||||
// Success from passphrase
|
||||
"key_backup_setup_success_from_passphrase_info" = "Backup delle tue chiavi in corso.\n\nLa tua chiave di ripristino è una rete di sicurezza - puoi usarla per recuperare l'accesso ai tuoi messaggi cifrati se dimentichi la tua passphrase. \n\nTieni la tua chiave di ripristino in un luogo sicuro, come un password manager (o una cassaforte).";
|
||||
"key_backup_setup_success_from_passphrase_info" = "Backup delle tue chiavi in corso.\n\nLa tua chiave di ripristino è uno strumento di sicurezza - puoi usarla per recuperare l'accesso ai tuoi messaggi crittografati se dimentichi la tua frase d'accesso. \n\nTieni la tua chiave di ripristino in un luogo sicuro, come un password manager (o una cassaforte).";
|
||||
"key_backup_setup_success_from_passphrase_save_recovery_key_action" = "Salva chiave di ripristino";
|
||||
"key_backup_setup_success_from_passphrase_done_action" = "Fatto";
|
||||
// Success from recovery key
|
||||
|
@ -622,15 +622,15 @@
|
|||
"key_backup_setup_success_from_recovery_key_make_copy_action" = "Fai una copia";
|
||||
"key_backup_setup_success_from_recovery_key_made_copy_action" = "Ho fatto una copia";
|
||||
"key_backup_recover_title" = "Messaggi sicuri";
|
||||
"key_backup_recover_invalid_passphrase_title" = "Passphrase di ripristino non corretta";
|
||||
"key_backup_recover_invalid_passphrase" = "Impossibile decifrare il backup con questa passphrase: verifica di avere inserito la passphrase di ripristino corretta.";
|
||||
"key_backup_recover_invalid_passphrase_title" = "Frase di sicurezza non corretta";
|
||||
"key_backup_recover_invalid_passphrase" = "Impossibile decifrare il backup con questa frase di sicurezza. Verifica di avere inserito la frase di sicurezza corretta.";
|
||||
"key_backup_recover_invalid_recovery_key_title" = "La chiave di ripristino non corrisponde";
|
||||
"key_backup_recover_invalid_recovery_key" = "Impossibile decifrare il backup con questa chiave di ripristino: verifica di avere inserito la chiave di ripristino corretta.";
|
||||
"key_backup_recover_from_passphrase_info" = "Usa la tua chiave di ripristino per sbloccare la cronologia dei messaggi cifrati";
|
||||
"key_backup_recover_invalid_recovery_key" = "Impossibile decrittare il backup con questa chiave di recupero: verifica che la chiave di recupero sia corretta.";
|
||||
"key_backup_recover_from_passphrase_info" = "Usa la tua chiave di ripristino per sbloccare la cronologia dei messaggi crittografati";
|
||||
"key_backup_recover_from_passphrase_passphrase_title" = "Inserisci";
|
||||
"key_backup_recover_from_passphrase_passphrase_placeholder" = "Inserisci passphrase";
|
||||
"key_backup_recover_from_passphrase_passphrase_placeholder" = "Inserisci frase d'accesso";
|
||||
"key_backup_recover_from_passphrase_recover_action" = "Sblocca cronologia";
|
||||
"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "Non conosci la tua passphrase di ripristino? Puoi ";
|
||||
"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "Non conosci la tua frase d'accesso? Puoi ";
|
||||
"key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "usa la tua chiave di ripristino";
|
||||
"key_backup_recover_from_passphrase_lost_passphrase_action_part3" = ".";
|
||||
"key_backup_recover_from_recovery_key_info" = "Usa la tua chiave di ripristino per sbloccare la cronologia dei tuoi messaggi sicuri";
|
||||
|
@ -640,18 +640,249 @@
|
|||
"key_backup_recover_from_recovery_key_lost_recovery_key_action" = "Hai perso la chiave di ripristino? Puoi crearne una nuova nelle impostazioni.";
|
||||
"key_backup_recover_success_info" = "Backup ripristinato!";
|
||||
"key_backup_recover_done_action" = "Fatto";
|
||||
"key_backup_setup_banner_title" = "Non perdere mai i messaggi cifrati";
|
||||
"key_backup_setup_banner_title" = "Non perdere mai i messaggi crittografati";
|
||||
"key_backup_setup_banner_subtitle" = "Inizia ad usare il backup chiavi";
|
||||
"key_backup_recover_banner_title" = "Non perdere mai i messaggi cifrati";
|
||||
"key_backup_recover_banner_title" = "Non perdere mai i messaggi crittografati";
|
||||
"sign_out_existing_key_backup_alert_title" = "Sei sicuro di volerti disconnettere?";
|
||||
"sign_out_existing_key_backup_alert_sign_out_action" = "Disconnetti";
|
||||
"sign_out_non_existing_key_backup_alert_title" = "Se ti disconnetti ora, perderai l'accesso ai tuoi messaggi cifrati";
|
||||
"sign_out_non_existing_key_backup_alert_setup_key_backup_action" = "Inizia ad usare il backup chiavi";
|
||||
"sign_out_non_existing_key_backup_alert_discard_key_backup_action" = "Non voglio i miei messaggi cifrati";
|
||||
"sign_out_non_existing_key_backup_sign_out_confirmation_alert_title" = "Perderai i tuoi messaggi cifrati";
|
||||
"sign_out_non_existing_key_backup_sign_out_confirmation_alert_message" = "Perderai l'accesso ai tuoi messaggi cifrati a meno che non fai il backup delle tue chiavi prima di disconnetterti.";
|
||||
"sign_out_non_existing_key_backup_alert_title" = "Se ti disconnetti ora, perderai l'accesso ai tuoi messaggi crittografati";
|
||||
"sign_out_non_existing_key_backup_alert_setup_key_backup_action" = "Inizia ad usare il Backup delle chiavi";
|
||||
"sign_out_non_existing_key_backup_alert_discard_key_backup_action" = "Non voglio i miei messaggi crittografati";
|
||||
"sign_out_non_existing_key_backup_sign_out_confirmation_alert_title" = "Perderai i tuoi messaggi crittografati";
|
||||
"sign_out_non_existing_key_backup_sign_out_confirmation_alert_message" = "Perderai l'accesso ai tuoi messaggi crittografati a meno che non fai il Backup delle tue chiavi prima di disconnetterti.";
|
||||
"sign_out_non_existing_key_backup_sign_out_confirmation_alert_sign_out_action" = "Disconnetti";
|
||||
"sign_out_non_existing_key_backup_sign_out_confirmation_alert_backup_action" = "Backup";
|
||||
"sign_out_key_backup_in_progress_alert_title" = "Backup chiave in corso. Se ti disconnetti ora, perderai l'accesso ai tuoi messaggi cifrati.";
|
||||
"sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "Non voglio i miei messaggi cifrati";
|
||||
"sign_out_key_backup_in_progress_alert_cancel_action" = "Aspetto";
|
||||
"sign_out_key_backup_in_progress_alert_title" = "Backup chiavi in corso. Se ti disconnetti ora, perderai l'accesso ai tuoi messaggi crittografati.";
|
||||
"sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "Non voglio i miei messaggi crittografati";
|
||||
"sign_out_key_backup_in_progress_alert_cancel_action" = "Attendo";
|
||||
"close" = "Chiudi";
|
||||
"auth_forgot_password_error_no_configured_identity_server" = "Nessun identità server è configurata: aggiungine uno per reimpostare la password.";
|
||||
"auth_softlogout_signed_out" = "Sei uscito";
|
||||
"auth_softlogout_sign_in" = "Accedi";
|
||||
"auth_softlogout_reason" = "L'amministratore homeserver (%1$@) ti ha disconnesso dal tuo account %2$@ (%3$@).";
|
||||
"auth_softlogout_recover_encryption_keys" = "Accedi per recuperare le chiavi di crittografia archiviate esclusivamente su questo dispositivo. Ti servono per leggere tutti i tuoi messaggi sicuri su qualsiasi dispositivo.";
|
||||
"auth_softlogout_clear_data" = "Cancella dati personali";
|
||||
"auth_softlogout_clear_data_message_1" = "Avviso: i tuoi dati personali (comprese le chiavi di crittografia) sono ancora memorizzati su questo dispositivo.";
|
||||
"auth_softlogout_clear_data_message_2" = "Cancellalo se hai finito di utilizzare questo dispositivo o desideri accedere a un altro account.";
|
||||
"auth_softlogout_clear_data_button" = "Cancella tutti i dati";
|
||||
"auth_softlogout_clear_data_sign_out_title" = "Sei sicuro?";
|
||||
"auth_softlogout_clear_data_sign_out_msg" = "Sei sicuro di voler cancellare tutti i dati attualmente memorizzati su questo dispositivo? Accedi di nuovo per accedere ai dati e ai messaggi del tuo account.";
|
||||
"auth_softlogout_clear_data_sign_out" = "disconnessione";
|
||||
"room_creation_error_invite_user_by_email_without_identity_server" = "Nessuna identità server è configurata, quindi non è possibile aggiungere un partecipante con un'e-mail.";
|
||||
"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Non è stato configurato alcun Identity Server, quindi non è possibile avviare una chat con un contatto tramite e-mail.";
|
||||
"room_event_action_reply" = "Rispondi";
|
||||
"room_event_action_edit" = "Modifica";
|
||||
"room_event_action_reaction_show_all" = "Mostra tutto";
|
||||
"room_event_action_reaction_show_less" = "Mostra meno";
|
||||
"room_event_action_reaction_history" = "Cronologia reazioni";
|
||||
"room_action_camera" = "Scatta foto o video";
|
||||
"room_action_send_file" = "Invia File";
|
||||
"room_action_reply" = "Rispondi";
|
||||
"room_message_edits_history_title" = "Modifica messaggio";
|
||||
"settings_labs_message_reaction" = "Reagisci ai messaggi con emoji";
|
||||
"room_participants_remove_third_party_invite_prompt_msg" = "Sei sicuro di voler revocare l'invito?";
|
||||
"settings_key_backup_button_connect" = "Connetti questo dispositivo al Backup delle Chiavi";
|
||||
// Media picker
|
||||
"media_picker_title" = "Media library";
|
||||
// Image picker
|
||||
"image_picker_action_camera" = "Scatta foto";
|
||||
"image_picker_action_library" = "Seleziona dalla Libreria Immagini";
|
||||
"event_formatter_message_edited_mention" = "(modificato)";
|
||||
"camera_unavailable" = "La Fotocamera su questo dispositivo non é disponibile";
|
||||
"photo_library_access_not_granted" = "%@ non ha il permesso di accedere alla Photo Library. Modifica le impostazioni di privacy";
|
||||
// Widget
|
||||
"widget_no_integrations_server_configured" = "Il Server Integrazioni non é stato configurato";
|
||||
"widget_integrations_server_failed_to_connect" = "La connessione al Server Integrazioni é fallita";
|
||||
// Service terms
|
||||
"service_terms_modal_title" = "Termini del servizio";
|
||||
"service_terms_modal_message" = "Per continuare devi accettare i Termini di servizio (%@).";
|
||||
"service_terms_modal_accept_button" = "Accetta";
|
||||
"service_terms_modal_description_for_identity_server" = "Gli altri utenti possono trovarti";
|
||||
"service_terms_modal_description_for_integration_manager" = "Usa bot, widget e stickers";
|
||||
"key_backup_setup_intro_setup_connect_action_with_existing_backup" = "Connetti questo dispositivo al Backup delle chiavi";
|
||||
"key_backup_recover_connent_banner_subtitle" = "Connetti questo dispositivo al Backup delle chiavi";
|
||||
// MARK: - Device Verification
|
||||
"device_verification_title" = "Verifica dispositivo";
|
||||
"device_verification_security_advice" = "Per avere la massima sicurezza ti consigliamo di farlo di persona o utilizzando un altro sistema di comunicazione sicura";
|
||||
"device_verification_cancelled" = "L'altro utente/dispositivo ha annullato la verifica.";
|
||||
"device_verification_cancelled_by_me" = "La verifica é stata cancellata. Motivo: %@";
|
||||
"device_verification_error_cannot_load_device" = "Non si riescono a recuperare le informazioni riguardanti il dipositivo.";
|
||||
// Mark: Incoming
|
||||
"device_verification_incoming_title" = "Richiesta di verifica in corso";
|
||||
"device_verification_incoming_description_1" = "Verifica questo dispositivo per contrassegnarlo come fidato. Verificare che i dispositivi dei tuoi contatti siano fidati dà maggiore tranquillità quando usi messaggi crittografati da-utente-a-utente con loro.";
|
||||
"device_verification_incoming_description_2" = "Effettuando la verifica, il tuo dispositivo e quello del tuo contatto verranno reciprocamente contrassegnati come fidati.";
|
||||
// MARK: Start
|
||||
"device_verification_start_title" = "Verifica confrontando un breve testo";
|
||||
"device_verification_start_wait_partner" = "Attendi che il tuo contatto accetti...";
|
||||
"device_verification_start_use_legacy" = "Non accade nulla? Non tutti i dispositivi supportano la verifica interattiva. Usa la verifica classica.";
|
||||
"device_verification_start_verify_button" = "Inizia verifica";
|
||||
"device_verification_start_use_legacy_action" = "Usa verifica Legacy";
|
||||
// MARK: Verify
|
||||
"device_verification_verify_title_emoji" = "Verifica questo dispositivo confermando che i seguenti emoji appaiono sullo schermo del tuo contatto";
|
||||
"device_verification_verify_title_number" = "Verifica questo dispositivo confermando che il seguente numero appare sullo schermo del tuo contatto";
|
||||
"device_verification_verify_wait_partner" = "In attesa che il tuo contatto confermi...";
|
||||
// MARK: Verified
|
||||
"device_verification_verified_title" = "Verificato!";
|
||||
"device_verification_verified_description_1" = "Hai verificato correttamente questo dispositivo.";
|
||||
"device_verification_verified_description_2" = "Rendi sicuri i tuoi messaggi con questo contatto usando la crittografia da-utente-a-utente in modo che nessun'altro possa leggerli.";
|
||||
"device_verification_verified_got_it_button" = "Fatto";
|
||||
// MARK: Emoji
|
||||
"device_verification_emoji_dog" = "Cane";
|
||||
"device_verification_emoji_cat" = "Gatto";
|
||||
"device_verification_emoji_lion" = "Leone";
|
||||
"device_verification_emoji_horse" = "Cavallo";
|
||||
"device_verification_emoji_unicorn" = "Unicorno";
|
||||
"device_verification_emoji_pig" = "Maiale";
|
||||
"device_verification_emoji_elephant" = "Elefante";
|
||||
"device_verification_emoji_rabbit" = "Coniglio";
|
||||
"device_verification_emoji_panda" = "Panda";
|
||||
"device_verification_emoji_rooster" = "Gallo";
|
||||
"device_verification_emoji_penguin" = "Pinguino";
|
||||
"device_verification_emoji_turtle" = "Tartaruga";
|
||||
"device_verification_emoji_fish" = "Pesce";
|
||||
"device_verification_emoji_octopus" = "Polipo";
|
||||
"device_verification_emoji_butterfly" = "Farfalla";
|
||||
"device_verification_emoji_flower" = "Fiore";
|
||||
"device_verification_emoji_tree" = "Albero";
|
||||
"device_verification_emoji_cactus" = "Cactus";
|
||||
"device_verification_emoji_mushroom" = "Fungo";
|
||||
"device_verification_emoji_globe" = "Terra";
|
||||
"device_verification_emoji_moon" = "Luna";
|
||||
"device_verification_emoji_cloud" = "Nuvola";
|
||||
"device_verification_emoji_fire" = "Fuoco";
|
||||
"device_verification_emoji_banana" = "Banana";
|
||||
"device_verification_emoji_apple" = "Mela";
|
||||
"device_verification_emoji_strawberry" = "Fragola";
|
||||
"device_verification_emoji_corn" = "Pannocchia";
|
||||
"device_verification_emoji_pizza" = "Pizza";
|
||||
"device_verification_emoji_cake" = "Torta";
|
||||
"device_verification_emoji_heart" = "Cuore";
|
||||
"device_verification_emoji_smiley" = "Sorriso";
|
||||
"device_verification_emoji_robot" = "Robot";
|
||||
"device_verification_emoji_hat" = "Cappello";
|
||||
"device_verification_emoji_glasses" = "Occhiali";
|
||||
"device_verification_emoji_spanner" = "Chiave inglese";
|
||||
"device_verification_emoji_santa" = "Babbo Natale";
|
||||
"device_verification_emoji_thumbs up" = "Pollice su";
|
||||
"device_verification_emoji_umbrella" = "Ombrello";
|
||||
"device_verification_emoji_hourglass" = "Clessidra";
|
||||
"device_verification_emoji_clock" = "Orologio";
|
||||
"device_verification_emoji_gift" = "Regalo";
|
||||
"device_verification_emoji_light bulb" = "Lampadina";
|
||||
"device_verification_emoji_book" = "Libro";
|
||||
"device_verification_emoji_pencil" = "Matita";
|
||||
"device_verification_emoji_paperclip" = "Graffetta";
|
||||
"device_verification_emoji_scissors" = "Forbici";
|
||||
"device_verification_emoji_lock" = "Lucchetto";
|
||||
"device_verification_emoji_key" = "Chiave";
|
||||
"device_verification_emoji_hammer" = "Martello";
|
||||
"device_verification_emoji_telephone" = "Telefono";
|
||||
"device_verification_emoji_flag" = "Bandiera";
|
||||
"device_verification_emoji_train" = "Treno";
|
||||
"device_verification_emoji_bicycle" = "Bicicletta";
|
||||
"device_verification_emoji_aeroplane" = "Aeroplano";
|
||||
"device_verification_emoji_rocket" = "Razzo";
|
||||
"device_verification_emoji_trophy" = "Coppa";
|
||||
"device_verification_emoji_ball" = "Palla";
|
||||
"device_verification_emoji_guitar" = "Chitarra";
|
||||
"device_verification_emoji_trumpet" = "Tromba";
|
||||
"device_verification_emoji_bell" = "Campana";
|
||||
"device_verification_emoji_anchor" = "Ancora";
|
||||
"device_verification_emoji_headphones" = "Cuffie";
|
||||
"device_verification_emoji_folder" = "Cartella";
|
||||
"device_verification_emoji_pin" = "Puntina";
|
||||
// MARK: File upload
|
||||
"file_upload_error_title" = "Caricamento File";
|
||||
"file_upload_error_unsupported_file_type_message" = "Tipo di File non supportato.";
|
||||
// MARK: Emoji picker
|
||||
"emoji_picker_title" = "Reazioni";
|
||||
"emoji_picker_people_category" = "Smiley & Persone";
|
||||
"emoji_picker_nature_category" = "Animali & Natura";
|
||||
"emoji_picker_foods_category" = "Cibo & Bevande";
|
||||
"emoji_picker_activity_category" = "Attività";
|
||||
"emoji_picker_places_category" = "Viaggi & Luoghi";
|
||||
"emoji_picker_objects_category" = "Oggetti";
|
||||
"emoji_picker_symbols_category" = "Simboli";
|
||||
"emoji_picker_flags_category" = "Bandiere";
|
||||
// MARK: Reaction history
|
||||
"reaction_history_title" = "Reazioni";
|
||||
// Errors
|
||||
"error_user_already_logged_in" = "Sembra tu stia tentando di connetterti ad un altro Homeserver. Vuoi disconnetterti?";
|
||||
"room_accessiblity_scroll_to_bottom" = "Scorri in fondo";
|
||||
"room_accessibility_search" = "Cerca";
|
||||
"room_accessibility_integrations" = "Integrazioni";
|
||||
"room_accessibility_upload" = "Invia";
|
||||
"room_accessibility_call" = "Chiama";
|
||||
"room_accessibility_hangup" = "Riaggancia";
|
||||
"media_type_accessibility_image" = "Immagine";
|
||||
"media_type_accessibility_audio" = "Audio";
|
||||
"media_type_accessibility_video" = "Video";
|
||||
"media_type_accessibility_location" = "Posizione";
|
||||
"media_type_accessibility_file" = "File";
|
||||
"media_type_accessibility_sticker" = "Adesivo";
|
||||
// Widget Picker
|
||||
"widget_picker_title" = "Integrazioni";
|
||||
"auth_add_email_message_2" = "Imposta un'email per il recupero dell'account, più tardi anche per essere trovabile dalle persone che ti conoscono.";
|
||||
"auth_add_phone_message_2" = "Imposta un telefono, più tardi anche per essere trovabile dalle persone che ti conoscono.";
|
||||
"auth_add_email_phone_message_2" = "Imposta un'email per il recupero dell'account. Più tardi usa l'email o il telefono per essere trovabile dalle persone che ti conoscono.";
|
||||
"auth_email_is_required" = "Nessun server di identità configurato, perciò non puoi aggiungere un indirizzo email per ripristinare la password in futuro.";
|
||||
"auth_phone_is_required" = "Nessun server di identità configurato, perciò non puoi aggiungere un numero di telefono per ripristinare la password in futuro.";
|
||||
"auth_reset_password_error_is_required" = "Nessun server di identità configurato: aggiungine uno nelle opzioni server per ripristinare la password.";
|
||||
"contacts_address_book_no_identity_server" = "Nessun server di identità configurato";
|
||||
"settings_discovery_settings" = "SCOPRI";
|
||||
"settings_identity_server_settings" = "SERVER IDENTITÀ";
|
||||
"settings_three_pids_management_information_part1" = "Gestisci qui quali indirizzi email o numeri di telefono puoi usare per accedere o recuperare l'account. Controlla chi può trovarti in ";
|
||||
"settings_three_pids_management_information_part2" = "Scopri";
|
||||
"settings_three_pids_management_information_part3" = ".";
|
||||
"settings_calls_stun_server_fallback_button" = "Permetti server di assistenza alle chiamate di fallback";
|
||||
"settings_calls_stun_server_fallback_description" = "Consenti server di assistenza alle chiamate di fallback %@ quando il tuo homeserver non ne offre uno (il tuo indirizzo IP verrà condiviso durante una chiamata).";
|
||||
"settings_devices_description" = "Il nome pubblico di un dispositivo è visibile dalle persone con cui comunichi";
|
||||
"settings_discovery_no_identity_server" = "Attualmente non stai usando un server di identità. Per essere trovabile dai contatti esistenti che conosci, aggiungine uno.";
|
||||
"settings_discovery_terms_not_signed" = "Accetta le condizioni di servizio del server di identità (%@) per poter essere trovabile tramite indirizzo email o numero di telefono.";
|
||||
"settings_discovery_three_pids_management_information_part1" = "Gestisci quali indirizzi email o numeri di telefono gli altri utenti possono usare per trovarti e invitarti nelle stanze. Aggiungi o rimuovi indirizzi email o numeri di telefono da questa lista in ";
|
||||
"settings_discovery_three_pids_management_information_part2" = "Impostazioni utente";
|
||||
"settings_discovery_three_pids_management_information_part3" = ".";
|
||||
"settings_discovery_error_message" = "C'è stato un errore. Riprova.";
|
||||
"settings_discovery_three_pid_details_title_email" = "Gestisci email";
|
||||
"settings_discovery_three_pid_details_information_email" = "Gestisci le impostazioni di questo indirizzo email che altri utenti possono usare per trovarti o invitarti in altre stanze. Aggiungi o rimuovi gli indirizzi email in Accounts.";
|
||||
"settings_discovery_three_pid_details_title_phone_number" = "Gestisci il numero di telefono";
|
||||
"settings_discovery_three_pid_details_information_phone_number" = "Gestisci le impostazioni di questo numero di telefono che altri utenti possono usare per trovarti o invitarti in altre stanze. Aggiungi o rimuovi i numeri di telefono in Accounts.";
|
||||
"settings_discovery_three_pid_details_share_action" = "Condividi";
|
||||
"settings_discovery_three_pid_details_revoke_action" = "Cancella";
|
||||
"settings_discovery_three_pid_details_cancel_email_validation_action" = "Annulla la validazione dell'email";
|
||||
"settings_discovery_three_pid_details_enter_sms_code_action" = "Inserisci il codice d'attivazione SMS";
|
||||
"settings_identity_server_description" = "Utilizzando l'Identity Server impostato potrai trovare e farti trovare dai contatti esistenti.";
|
||||
"settings_identity_server_no_is" = "Nessun Identity Server configurato";
|
||||
"settings_identity_server_no_is_description" = "Non stai usando alcun Identity Server. Selezionane uno per trovare e farti trovare dai contatti esistenti.";
|
||||
// Identity server settings
|
||||
"identity_server_settings_title" = "// Impostazioni dell'Identity Server";
|
||||
"identity_server_settings_description" = "Per trovare e farti trovare dai tuoi contatti stai usando %@.";
|
||||
"identity_server_settings_no_is_description" = "Non stai usando alcun Identity Server. Selezionane uno per trovare e farti trovare dai contatti esistenti.";
|
||||
"identity_server_settings_place_holder" = "Inserisci un Identity Server";
|
||||
"identity_server_settings_add" = "Aggiungi";
|
||||
"identity_server_settings_change" = "Cambia";
|
||||
"identity_server_settings_disconnect_info" = "Usare un Identity Server è facoltativo. Se scegli di non usarne uno gli altri utenti non potranno trovarti e tu non potrai invitarli per email o telefono.";
|
||||
"identity_server_settings_disconnect" = "Disconnetti";
|
||||
"identity_server_settings_alert_no_terms_title" = "L'Identity Server non ha Termini di servizio";
|
||||
"identity_server_settings_alert_no_terms" = "L'Identity Server che hai scelto non ha Termini di servizio. Prosegui solo se ti fidi del gestore del server.";
|
||||
"identity_server_settings_alert_change_title" = "Cambia Identity Server";
|
||||
"identity_server_settings_alert_change" = "Vuoi scollegarti dall'Identyty Server %1$@ e connetterti invece a %2$@?";
|
||||
"identity_server_settings_alert_disconnect_title" = "Scollega dall'Identity Server";
|
||||
"identity_server_settings_alert_disconnect" = "Vuoi scollegarti dall'Identity Server %@?";
|
||||
"identity_server_settings_alert_disconnect_button" = "Scollega";
|
||||
"identity_server_settings_alert_disconnect_still_sharing_3pid" = "L'Identity Server %@ può ancora condividere le tue informazioni personali.\n\nTi raccomandiamo di rimuovere tutti i tuoi indirizzi email e numeri di telefono dall'Identity Server prima di scollegarti.";
|
||||
"identity_server_settings_alert_disconnect_still_sharing_3pid_button" = "Scollegati comunque";
|
||||
"identity_server_settings_alert_error_terms_not_accepted" = "Devi accettare le condizioni di %@ per impostarlo come tuo Identity Server.";
|
||||
"identity_server_settings_alert_error_invalid_identity_server" = "%@ non é un Identity Server valido.";
|
||||
"call_no_stun_server_error_title" = "Chiamata fallita a causa di una configurazione errata del server";
|
||||
"call_no_stun_server_error_message_1" = "Chiedi all'amministratore del tuo Homeserver %@ di configurare un server TURN in modo che le chiamate funzionino come si deve.";
|
||||
"call_no_stun_server_error_message_2" = "In alternativa puoi provare ad usare il server pubblico a %@, ma non é molto affidabile e il tuo indirizzo IP verrà condiviso con tale server. Puoi gestire questa cosa nelle Impostazioni";
|
||||
"call_no_stun_server_error_use_fallback_button" = "Prova ad usare %@";
|
||||
"service_terms_modal_decline_button" = "Rifiuta";
|
||||
"service_terms_modal_description_for_identity_server_1" = "Trova altri utenti attraverso l'email o il numero di telefono";
|
||||
"service_terms_modal_description_for_identity_server_2" = "Fatti trovare attraverso il tuo numero di telefono e la tua email";
|
||||
// Service terms - Variant for identity server when displayed out of a context
|
||||
"service_terms_modal_title_identity_server" = "Trova contatti";
|
||||
"service_terms_modal_message_identity_server" = "Accetta i Termini di servizio dell'Identity Server (%@) per trovare altri contatti.";
|
||||
// Generic errors
|
||||
"error_invite_3pid_with_no_identity_server" = "Aggiungi un Identity Server nelle Impostazioni per poter invitare utenti tramite email.";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Permissions usage explanations
|
||||
"NSCameraUsageDescription" = "카메라는 사진과 영상 촬영, 영상통화를 하는데 쓰입니다.";
|
||||
"NSCameraUsageDescription" = "카메라는 사진과 영상 촬영, 영상 통화를 하는 데 쓰입니다.";
|
||||
"NSPhotoLibraryUsageDescription" = "포토 라이브러리는 사진과 영상을 보내는데 쓰입니다.";
|
||||
"NSMicrophoneUsageDescription" = "마이크는 영상 촬영, 통화에 쓰입니다.";
|
||||
"NSContactsUsageDescription" = "연락처에 있는 상대가 이미 Riot이나 Matrix를 이용하고 있다는 걸 보여주기 위해 연락처의 이메일 주소와 전화번호를 Matrix 아이덴티티 서버로 보낼 수 있습니다. 새 Vector는 이 자료를 저장하거나 다른 용도로 사용하지 않습니다. 자세한 내용은 애플리케이션 설정에 있는 개인정보 보호정책을 읽어주세요.";
|
||||
"NSContactsUsageDescription" = "이미 Matrix를 사용하는 연락처 사람들을 검색하기 위해, Riot은 당신이 선택한 Matrix ID 서버로 이메일 주소와 전화번호를 보낼 수 있습니다. 서버가 지원된다면, 개인 정보는 보내기 전에 해시됩니다 - 더 자세한 정보는 ID 서버의 개인 정보 정책을 확인해주세요.";
|
||||
"NSCalendarsUsageDescription" = "앱에서 예정된 회의를 봅니다.";
|
||||
|
|
|
@ -1,34 +1,56 @@
|
|||
/* New message from a specific person, not referencing a room */
|
||||
"MSG_FROM_USER" = "%@가 보낸 메시지";
|
||||
"MSG_FROM_USER" = "%@님이 메시지를 보냈습니다";
|
||||
/* New message from a specific person in a named room */
|
||||
"MSG_FROM_USER_IN_ROOM" = "%@ 방에 게시 %@";
|
||||
"MSG_FROM_USER_IN_ROOM" = "%@님, %@ 방에 게시함";
|
||||
/* New message from a specific person, not referencing a room. Content included. */
|
||||
"MSG_FROM_USER_WITH_CONTENT" = "%@: %@";
|
||||
/* New message from a specific person in a named room. Content included. */
|
||||
"MSG_FROM_USER_IN_ROOM_WITH_CONTENT" = "%@: %@ 안의 %@";
|
||||
"MSG_FROM_USER_IN_ROOM_WITH_CONTENT" = "%@님, %@ 방에서: %@";
|
||||
/* New action message from a specific person, not referencing a room. */
|
||||
"ACTION_FROM_USER" = "* %@ %@";
|
||||
/* New action message from a specific person in a named room. */
|
||||
"ACTION_FROM_USER_IN_ROOM" = "%@: * %@ %@";
|
||||
/* New action message from a specific person, not referencing a room. */
|
||||
"IMAGE_FROM_USER" = "%@ 보낸 사진 %@";
|
||||
"IMAGE_FROM_USER" = "%@님이 사진을 보냈습니다 %@";
|
||||
/* A single unread message in a room */
|
||||
"SINGLE_UNREAD_IN_ROOM" = "%@에서 메시지를 받았습니다";
|
||||
"SINGLE_UNREAD_IN_ROOM" = "%@ 방에서 메시지를 받았습니다";
|
||||
/* A single unread message */
|
||||
"SINGLE_UNREAD" = "메시지를 받았습니다";
|
||||
/* A user has invited you to a chat */
|
||||
"USER_INVITE_TO_CHAT" = "%@가 대화에 당신을 초대했습니다";
|
||||
"USER_INVITE_TO_CHAT" = "%@님이 당신을 대화에 초대했습니다";
|
||||
/* A user has invited you to an (unamed) group chat */
|
||||
"USER_INVITE_TO_CHAT_GROUP_CHAT" = "%@가 그룹 대화에 당신을 초대했습니다";
|
||||
"USER_INVITE_TO_CHAT_GROUP_CHAT" = "%@님이 그룹 대화에 당신을 초대했습니다";
|
||||
/* Incoming one-to-one voice call */
|
||||
"VOICE_CALL_FROM_USER" = "%@이 건 통화";
|
||||
"VOICE_CALL_FROM_USER" = "%@님이 건 전화";
|
||||
/* Incoming one-to-one video call */
|
||||
"VIDEO_CALL_FROM_USER" = "%@가 건 영상통화";
|
||||
"VIDEO_CALL_FROM_USER" = "%@님이 건 영상 통화";
|
||||
/* Incoming unnamed voice conference invite from a specific person */
|
||||
"VOICE_CONF_FROM_USER" = "%@이 건 그룹통화";
|
||||
"VOICE_CONF_FROM_USER" = "%@님이 건 그룹 통화";
|
||||
/* Incoming unnamed video conference invite from a specific person */
|
||||
"VIDEO_CONF_FROM_USER" = "%@이 건 영상그룹통화";
|
||||
"VIDEO_CONF_FROM_USER" = "%@님이 건 영상 그룹 통화";
|
||||
/* Sticker from a specific person, not referencing a room. */
|
||||
"STICKER_FROM_USER" = "%@가 스티커를 보냈습니다";
|
||||
"STICKER_FROM_USER" = "%@님이 스티커를 보냈습니다";
|
||||
/* A user has invited you to a named room */
|
||||
"USER_INVITE_TO_NAMED_ROOM" = "%@가 %@로 당신을 초대했습니다";
|
||||
"USER_INVITE_TO_NAMED_ROOM" = "%@님이 %@ 방으로 당신을 초대했습니다";
|
||||
/* Message title for a specific person in a named room */
|
||||
"MSG_FROM_USER_IN_ROOM_TITLE" = "%@님, %@ 방에 있음";
|
||||
/* New action message from a specific person in a named room. */
|
||||
"IMAGE_FROM_USER_IN_ROOM" = "%@님이 사진을 보냈습니다 %@, %@ 방에서";
|
||||
/* Multiple unread messages in a room */
|
||||
"UNREAD_IN_ROOM" = "%@개의 새 메시지, %@ 방에서";
|
||||
/* Multiple unread messages from a specific person, not referencing a room */
|
||||
"MSGS_FROM_USER" = "%@개의 새 메시지, %@님으로부터";
|
||||
/* Multiple unread messages from two people */
|
||||
"MSGS_FROM_TWO_USERS" = "%@개의 새 메시지, %@님과 %@님으로부터";
|
||||
/* Multiple unread messages from three people */
|
||||
"MSGS_FROM_THREE_USERS" = "%@개의 새 메시지, %@님과 %@님, %@님으로부터";
|
||||
/* Multiple unread messages from two plus people (ie. for 4+ people: 'others' replaces the third person) */
|
||||
"MSGS_FROM_TWO_PLUS_USERS" = "%@개의 새 메시지, %@님과 %@님 외 여러 명으로부터";
|
||||
/* Multiple messages in two rooms */
|
||||
"MSGS_IN_TWO_ROOMS" = "%@개의 새 메시지, %@ 방과 %@ 방에서";
|
||||
/* Look, stuff's happened, alright? Just open the app. */
|
||||
"MSGS_IN_TWO_PLUS_ROOMS" = "%@개의 새 메시지, %@ 방과 %@ 방 외 여러 방에서";
|
||||
/* Incoming named voice conference invite from a specific person */
|
||||
"VOICE_CONF_NAMED_FROM_USER" = "%@님이 건 그룹 통화: '%@'";
|
||||
/* Incoming named video conference invite from a specific person */
|
||||
"VIDEO_CONF_NAMED_FROM_USER" = "%@님이 건 영상 그룹 통화: '%@'";
|
||||
|
|
|
@ -13,12 +13,874 @@
|
|||
"create" = "만들기";
|
||||
"start" = "시작";
|
||||
"leave" = "떠나기";
|
||||
"remove" = "지우기";
|
||||
"remove" = "감추기";
|
||||
"invite" = "초대";
|
||||
"retry" = "다시해보기";
|
||||
"retry" = "다시 시도";
|
||||
"on" = "켜기";
|
||||
"off" = "끄기";
|
||||
"cancel" = "취소";
|
||||
"save" = "저장";
|
||||
"preview" = "미리보기";
|
||||
"preview" = "미리 보기";
|
||||
"camera" = "카메라";
|
||||
// String for App Store
|
||||
"store_short_description" = "안전한 분산 대화/VoIP";
|
||||
"store_full_description" = "여러분의 통제 하에 완전히 유연한 대화 앱. Riot은 여러분이 원하는 방식으로 대화할 수 있도록 합니다. 개방형 분산 커뮤니티의 표준 - [matrix]를 위해 제작됨. \n \n무료 matrix.org 계정을 만들고, https://modular.im에서 자신만의 서버, 혹은 다른 Matrix 서버를 얻으세요. \n \n왜 Riot.im을 선택해야 하나요? \n \n완전한 대화: 원하는 대로 팀이나 친구, 커뮤니티를 중심으로 방을 만드세요! 대화, 파일 공유, 위젯 추가와 음성 및 영상 통화 - 모두 무료입니다. \n \n강력한 통합: 여러분이 알고 사랑하는 도구와 함께 Riot.im을 사용하세요. Riot.im이라면 다른 대화 앱의 사용자와 그룹까지도 대화할 수 있습니다. \n \n개인 및 보안: 대화를 비밀로 유지하세요. 최첨단 종단간 암호화로 비밀 대화를 은밀하게 유지해줍니다. \n \n오픈 소스: Matrix로 만들어진 오픈 소스입니다. 자신의 데이터를 자신의 서버에 소유하거나, 신뢰하는 서버에 맡기세요. \n \n어디에 있든: 모든 기기나 https://riot.im에서 완전히 동기화된 메시지 기록으로 연락을 유지합니다.";
|
||||
"join" = "참가";
|
||||
"decline" = "끊기";
|
||||
"accept" = "수락";
|
||||
"voice" = "음성";
|
||||
"video" = "영상";
|
||||
"active_call" = "현재 전화";
|
||||
"active_call_details" = "현재 전화 (%@)";
|
||||
"later" = "나중에";
|
||||
"rename" = "이름 다시 짓기";
|
||||
"collapse" = "접기";
|
||||
"send_to" = "%@님에게 보내기";
|
||||
"sending" = "보내는 중";
|
||||
"close" = "닫기";
|
||||
// Authentication
|
||||
"auth_login" = "로그인";
|
||||
"auth_register" = "등록";
|
||||
"auth_submit" = "제출";
|
||||
"auth_skip" = "넘기기";
|
||||
"auth_login_single_sign_on" = "통합 인증(SSO)으로 로그인";
|
||||
"auth_send_reset_email" = "초기화 이메일 보내기";
|
||||
"auth_return_to_login" = "로그인 화면으로 돌아가기";
|
||||
"auth_user_id_placeholder" = "이메일 혹은 사용자 이름";
|
||||
"auth_password_placeholder" = "비밀번호";
|
||||
"auth_new_password_placeholder" = "새 비밀번호";
|
||||
"auth_user_name_placeholder" = "사용자 이름";
|
||||
"auth_optional_email_placeholder" = "이메일 주소 (선택)";
|
||||
"auth_email_placeholder" = "이메일 주소";
|
||||
"auth_optional_phone_placeholder" = "전화번호 (선택)";
|
||||
"auth_phone_placeholder" = "전화번호";
|
||||
"auth_repeat_password_placeholder" = "비밀번호 다시 입력";
|
||||
"auth_repeat_new_password_placeholder" = "새 비밀번호 확인";
|
||||
"auth_home_server_placeholder" = "URL (예: https://matrix.org)";
|
||||
"auth_identity_server_placeholder" = "URL (예: https://vector.im)";
|
||||
"auth_invalid_login_param" = "맞지 않은 사용자 이름 혹은 비밀번호";
|
||||
"auth_invalid_user_name" = "사용자 이름에는 문자, 숫자, 점, 하이픈(-)과 밑줄(_)만 들어갑니다";
|
||||
"auth_invalid_password" = "비밀번호가 너무 짧음 (최소 6자 이상)";
|
||||
"auth_invalid_email" = "올바른 이메일 주소가 아닙니다";
|
||||
"auth_invalid_phone" = "올바른 전화번호가 아닙니다";
|
||||
"auth_missing_password" = "비밀번호가 누락되었습니다";
|
||||
"auth_add_email_message" = "계정에 이메일 주소를 추가해 다른 사용자가 당신을 검색할 수 있고, 비밀번호를 다시 설정할 수 있습니다.";
|
||||
"auth_add_phone_message" = "계정에 전화번호를 추가해 다른 사용자가 당신을 검색할 수 있습니다.";
|
||||
"auth_add_email_phone_message" = "계정에 이메일 주소 그리고/혹은 전화번호를 추가해 다른 사용자가 당신을 검색할 수 있습니다. 이메일 주소는 비밀번호를 다시 설정하는 데에도 사용됩니다.";
|
||||
"auth_add_email_and_phone_message" = "이메일 주소와 전화번호를 추가해 다른 사용자가 당신을 검색할 수 있습니다. 이메일 주소는 비밀번호를 다시 설정하는 데에도 사용됩니다.";
|
||||
"auth_missing_email" = "이메일 주소가 누락되었습니다";
|
||||
"auth_missing_phone" = "전화번호가 누락되었습니다";
|
||||
"auth_missing_email_or_phone" = "이메일 주소 혹은 전화번호가 누락되었습니다";
|
||||
"auth_email_in_use" = "이 이메일 주소는 이미 사용 중입니다";
|
||||
"auth_phone_in_use" = "이 전화번호는 이미 사용 중입니다";
|
||||
"auth_untrusted_id_server" = "ID 서버를 신뢰할 수 없습니다";
|
||||
"auth_password_dont_match" = "비밀번호가 맞지 않음";
|
||||
"auth_username_in_use" = "사용 중인 사용자 이름";
|
||||
"auth_forgot_password" = "비밀번호를 잊었습니까?";
|
||||
"auth_forgot_password_error_no_configured_identity_server" = "ID 서버를 설정할 수 없음: 비밀번호를 다시 설정하기 위해 하나를 추가하세요.";
|
||||
"auth_email_not_found" = "이메일 전송에 실패함: 이 이메일 주소를 찾을 수 없음";
|
||||
"auth_use_server_options" = "맞춤 서버 옵션 사용 (고급)";
|
||||
"auth_email_validation_message" = "가입을 계속하려면 이메일을 확인해주세요";
|
||||
"auth_msisdn_validation_title" = "확인 보류 중";
|
||||
"auth_msisdn_validation_message" = "활성 코드가 있는 SMS를 보냈습니다. 아래에 이 코드를 입력해주세요.";
|
||||
"auth_msisdn_validation_error" = "전화번호를 확인할 수 없습니다.";
|
||||
"auth_recaptcha_message" = "이 홈서버는 당신이 로봇이 아닌지 알고 싶습니다";
|
||||
"auth_reset_password_message" = "비밀번호를 다시 설정하려면, 계정에 연결된 이메일 주소를 입력하세요:";
|
||||
"auth_reset_password_missing_email" = "계정에 연결된 이메일 주소를 입력해야 합니다.";
|
||||
"auth_reset_password_missing_password" = "새 비밀번호를 입력해야 합니다.";
|
||||
"auth_reset_password_email_validation_message" = "이메일을 %@(으)로 보냈습니다. 링크를 따라간 뒤, 아래를 클릭하세요.";
|
||||
"auth_reset_password_next_step_button" = "저는 제 이메일 주소를 확인했습니다";
|
||||
"auth_reset_password_error_unauthorized" = "이메일 주소 확인에 실패함: 이메일에 있는 링크를 클릭했는 지 확인하세요";
|
||||
"auth_reset_password_error_not_found" = "이메일 주소가 이 홈서버의 Matrix ID에 연결되어 있지 않습니다.";
|
||||
"auth_reset_password_success_message" = "비밀번호가 다시 설정되었습니다.\n\n모든 기기에서 로그아웃되며 더 이상 푸시 알림을 받을 수 없습니다. 알림을 다시 켜려면 각 기기마다 다시 로그인하세요.";
|
||||
"auth_add_email_and_phone_warning" = "API가 있기 전까진 이메일과 전화번호를 동시에 등록하는 것을 지원하지 않습니다. 오직 계정에는 전화번호만 들어갑니다. 설정에서 프로필에 이메일을 추가할 수 있습니다.";
|
||||
"auth_accept_policies" = "이 홈서버의 정책을 검토하고 수락해주세요:";
|
||||
"auth_autodiscover_invalid_response" = "잘못된 홈서버 검색 응답";
|
||||
"auth_softlogout_signed_out" = "로그아웃했습니다";
|
||||
"auth_softlogout_sign_in" = "로그인";
|
||||
"auth_softlogout_reason" = "당신의 홈서버 (%1$@) 관리자가 당신의 계정 %2$@을(를) 로그아웃했습니다 (%3$@).";
|
||||
"auth_softlogout_recover_encryption_keys" = "이 기기에 독점적으로 저장된 암호화 키를 복구하려면 로그인하세요. 이 키가 있어야 기기에서 모든 보안 메시지를 읽을 수 있습니다.";
|
||||
"auth_softlogout_clear_data" = "개인 정보 지우기";
|
||||
"auth_softlogout_clear_data_message_1" = "경고: (암호화 키를 포함한) 개인 정보는 이 기기에 여전히 저장됩니다.";
|
||||
"auth_softlogout_clear_data_message_2" = "이 기기를 그만 사용하거나 다른 계정으로 로그인하고 싶은 경우에 지우세요.";
|
||||
"auth_softlogout_clear_data_button" = "모든 데이터 지우기";
|
||||
"auth_softlogout_clear_data_sign_out_title" = "확신합니까?";
|
||||
"auth_softlogout_clear_data_sign_out_msg" = "현재 이 기기에 저장된 모든 데이터를 지우겠습니까? 계정 데이터와 메시지에 접근하도록 다시 로그인하세요.";
|
||||
"auth_softlogout_clear_data_sign_out" = "로그아웃";
|
||||
// Chat creation
|
||||
"room_creation_title" = "새 대화";
|
||||
"room_creation_account" = "계정";
|
||||
"room_creation_appearance" = "모습";
|
||||
"room_creation_appearance_name" = "이름";
|
||||
"room_creation_appearance_picture" = "대화 사진 (선택)";
|
||||
"room_creation_privacy" = "개인";
|
||||
"room_creation_private_room" = "이 대화는 개인입니다";
|
||||
"room_creation_public_room" = "이 대화는 공개입니다";
|
||||
"room_creation_make_public" = "공개로 하기";
|
||||
"room_creation_make_public_prompt_title" = "이 대화를 공개로 합니까?";
|
||||
"room_creation_make_public_prompt_msg" = "이 대화를 공개로 하겠습니까? 누구나 메시지를 읽고 대화에 참여할 수 있습니다.";
|
||||
"room_creation_keep_private" = "개인으로 유지";
|
||||
"room_creation_make_private" = "개인으로 하기";
|
||||
"room_creation_wait_for_creation" = "방을 이미 만드는 중입니다. 기다려주세요.";
|
||||
"room_creation_invite_another_user" = "검색 / 사용자 ID, 이름 또는 이메일로 초대";
|
||||
"room_creation_error_invite_user_by_email_without_identity_server" = "ID 서버가 설정되지 않아 이메일로 참가자를 추가할 수 없습니다.";
|
||||
// Room recents
|
||||
"room_recents_directory_section" = "방 목록";
|
||||
"room_recents_directory_section_network" = "네트워크";
|
||||
"room_recents_favourites_section" = "즐겨찾기";
|
||||
"room_recents_people_section" = "사람";
|
||||
"room_recents_conversations_section" = "방";
|
||||
"room_recents_no_conversation" = "방 없음";
|
||||
"room_recents_low_priority_section" = "중요하지 않음";
|
||||
"room_recents_server_notice_section" = "시스템 경고";
|
||||
"room_recents_invites_section" = "초대";
|
||||
"room_recents_start_chat_with" = "대화 시작";
|
||||
"room_recents_create_empty_room" = "방 만들기";
|
||||
"room_recents_join_room" = "방 참가";
|
||||
"room_recents_join_room_title" = "방 참가";
|
||||
"room_recents_join_room_prompt" = "방 ID 또는 방 별칭을 입력";
|
||||
// People tab
|
||||
"people_invites_section" = "초대";
|
||||
"people_conversation_section" = "대화";
|
||||
"people_no_conversation" = "대화 없음";
|
||||
// Rooms tab
|
||||
"room_directory_no_public_room" = "이용할 수 있는 공개 방 없음";
|
||||
// Groups tab
|
||||
"group_invite_section" = "초대";
|
||||
"group_section" = "커뮤니티";
|
||||
// Search
|
||||
"search_rooms" = "방";
|
||||
"search_messages" = "메시지";
|
||||
"search_people" = "사람";
|
||||
"search_files" = "파일";
|
||||
"search_default_placeholder" = "검색";
|
||||
"search_people_placeholder" = "사용자 ID, 이름 또는 이메일로 검색";
|
||||
"search_no_result" = "결과 없음";
|
||||
"search_in_progress" = "검색 중…";
|
||||
// Directory
|
||||
"directory_cell_title" = "목록 찾기";
|
||||
"directory_cell_description" = "%tu개의 방";
|
||||
"directory_search_results_title" = "목록 결과 찾기";
|
||||
"directory_search_results" = "%@(으)로 찾은 %tu개의 결과";
|
||||
"directory_search_results_more_than" = ">%@(으)로 찾은 %tu개의 결과";
|
||||
"directory_searching_title" = "목록 검색 중…";
|
||||
"directory_search_fail" = "데이터 가져오기에 실패함";
|
||||
// Contacts
|
||||
"contacts_address_book_section" = "로컬 연락처";
|
||||
"contacts_address_book_matrix_users_toggle" = "Matrix 사용자만";
|
||||
"contacts_address_book_no_contact" = "로컬 연락처 없음";
|
||||
"contacts_address_book_permission_required" = "로컬 연락처에 접근하는데 필요한 권한";
|
||||
"contacts_address_book_permission_denied" = "Riot이 로컬 연락처에 접근하도록 허용하지 않음";
|
||||
"contacts_user_directory_section" = "사용자 목록";
|
||||
"contacts_user_directory_offline_section" = "사용자 목록 (오프라인)";
|
||||
// Chat participants
|
||||
"room_participants_title" = "참가자";
|
||||
"room_participants_add_participant" = "참가자 추가";
|
||||
"room_participants_one_participant" = "1명의 참가자";
|
||||
"room_participants_multi_participants" = "%d명의 참가자";
|
||||
"room_participants_leave_prompt_title" = "방 떠나기";
|
||||
"room_participants_leave_prompt_msg" = "방을 떠나겠습니까?";
|
||||
"room_participants_remove_prompt_title" = "확인";
|
||||
"room_participants_remove_prompt_msg" = "이 대화에서 %@을(를) 제거하겠습니까?";
|
||||
"room_participants_remove_third_party_invite_msg" = "API가 있기 전까진 제 3자 초대를 제거하는 것은 아직 지원하지 않습니다";
|
||||
"room_participants_invite_prompt_title" = "확인";
|
||||
"room_participants_invite_prompt_msg" = "%@님을 이 대화에 초대하겠습니까?";
|
||||
"room_participants_filter_room_members" = "방 구성원 필터";
|
||||
"room_participants_invite_another_user" = "검색 / 사용자 ID, 이름 또는 이메일로 초대";
|
||||
"room_participants_invite_malformed_id_title" = "초대 오류";
|
||||
"room_participants_invite_malformed_id" = "잘못된 ID. 이메일 주소 혹은 '@localpart:domain'과 같은 Matrix ID이어야 합니다";
|
||||
"room_participants_invited_section" = "초대받음";
|
||||
"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "ID 서버가 설정되지 않아서 이메일을 사용하는 연락처와 대화를 시작할 수 없습니다.";
|
||||
"room_participants_online" = "온라인";
|
||||
"room_participants_offline" = "오프라인";
|
||||
"room_participants_unknown" = "알 수 없음";
|
||||
"room_participants_idle" = "대기 중";
|
||||
"room_participants_now" = "지금";
|
||||
"room_participants_ago" = "전";
|
||||
"room_participants_action_section_admin_tools" = "관리자 도구";
|
||||
"room_participants_action_section_direct_chats" = "다이렉트 대화";
|
||||
"room_participants_action_section_devices" = "기기";
|
||||
"room_participants_action_section_other" = "기타";
|
||||
"room_participants_action_invite" = "초대";
|
||||
"room_participants_action_leave" = "이 방 떠나기";
|
||||
"room_participants_action_remove" = "이 방에서 제거";
|
||||
"room_participants_action_ban" = "이 방에서 차단";
|
||||
"room_participants_action_unban" = "차단 풀기";
|
||||
"room_participants_action_ignore" = "이 사용자의 모든 메시지 숨기기";
|
||||
"room_participants_action_unignore" = "이 사용자의 모든 메시지 보이기";
|
||||
"room_participants_action_set_default_power_level" = "보통 사용자로 다시 설정";
|
||||
"room_participants_action_set_moderator" = "중재자로 하기";
|
||||
"room_participants_action_set_admin" = "관리자로 하기";
|
||||
"room_participants_action_start_new_chat" = "새 대화 시작";
|
||||
"room_participants_action_start_voice_call" = "음성 통화 시작";
|
||||
"room_participants_action_start_video_call" = "영상 통화 시작";
|
||||
"room_participants_action_mention" = "언급";
|
||||
// Chat
|
||||
"room_jump_to_first_unread" = "처음으로 읽지 않은 메시지로 가기";
|
||||
"room_new_message_notification" = "%d개의 새 메시지";
|
||||
"room_new_messages_notification" = "%d개의 새 메시지";
|
||||
"room_one_user_is_typing" = "%@님이 입력하는 중…";
|
||||
"room_two_users_are_typing" = "%@님 & %@님이 입력하는 중…";
|
||||
"room_many_users_are_typing" = "%@님, %@님 외 여러 명이 입력하는 중…";
|
||||
"room_message_placeholder" = "(암호화 안 된) 메시지를 보내세요…";
|
||||
"room_message_reply_to_placeholder" = "(암호화 안 된) 답장을 보내세요…";
|
||||
"room_message_unable_open_link_error_message" = "링크를 열 수 없습니다.";
|
||||
"room_do_not_have_permission_to_post" = "이 방에 글을 올릴 권한이 없습니다";
|
||||
"encrypted_room_message_placeholder" = "암호화된 메시지를 보내세요…";
|
||||
"encrypted_room_message_reply_to_placeholder" = "암호화된 답장을 보내세요…";
|
||||
"room_message_short_placeholder" = "메시지를 보내세요…";
|
||||
"room_message_reply_to_short_placeholder" = "답장을 보내세요…";
|
||||
"room_offline_notification" = "서버와의 연결이 끊겼습니다.";
|
||||
"room_unsent_messages_notification" = "메시지가 보내지지 않았습니다. %1$s, %2$s, 둘 중 어느 것을 하겠습니까?";
|
||||
"room_unsent_messages_unknown_devices_notification" = "알 수 없는 기기가 있어 메시지가 보내지지 않았습니다. %1$s, %2$s, 둘 중 어느 것을 하겠습니까?";
|
||||
"room_ongoing_conference_call" = "회의 전화가 진행 중입니다. %1$s 또는 %2$s로 참가하세요.";
|
||||
"room_ongoing_conference_call_with_close" = "회의 전화가 진행 중입니다. %1$s 또는 %2$s로 참가하세요. %@.";
|
||||
"room_ongoing_conference_call_close" = "닫기";
|
||||
"room_conference_call_no_power" = "이 방에서 회의 전화를 관리할 권한이 필요합니다";
|
||||
"room_prompt_resend" = "모두 다시 보내기";
|
||||
"room_prompt_cancel" = "모두 취소하기";
|
||||
"room_resend_unsent_messages" = "보내지지 않은 메시지 다시 보내기";
|
||||
"room_delete_unsent_messages" = "보내지지 않은 메시지 삭제하기";
|
||||
"room_event_action_copy" = "복사";
|
||||
"room_event_action_quote" = "인용";
|
||||
"room_event_action_redact" = "감추기";
|
||||
"room_event_action_more" = "더 보기";
|
||||
"room_event_action_share" = "공유";
|
||||
"room_event_action_permalink" = "고유 링크";
|
||||
"room_event_action_view_source" = "소스 보기";
|
||||
"room_event_action_view_decrypted_source" = "암호화된 소스 보기";
|
||||
"room_event_action_report" = "내용 보고하기";
|
||||
"room_event_action_report_prompt_reason" = "이 내용을 보고하는 이유";
|
||||
"room_event_action_kick_prompt_reason" = "이 사용자를 추방하는 이유";
|
||||
"room_event_action_ban_prompt_reason" = "이 사용자를 차단하는 이유";
|
||||
"room_event_action_report_prompt_ignore_user" = "이 사용자의 모든 메시지를 숨기겠습니까?";
|
||||
"room_event_action_save" = "저장";
|
||||
"room_event_action_resend" = "다시 보내기";
|
||||
"room_event_action_delete" = "삭제";
|
||||
"room_event_action_cancel_send" = "보내기 취소";
|
||||
"room_event_action_cancel_download" = "다운로드 취소";
|
||||
"room_event_action_view_encryption" = "암호화 정보";
|
||||
"room_event_action_reply" = "답장";
|
||||
"room_event_action_edit" = "편집";
|
||||
"room_event_action_reaction_show_all" = "모두 보이기";
|
||||
"room_event_action_reaction_show_less" = "적게 보이기";
|
||||
"room_event_action_reaction_history" = "리액션 기록";
|
||||
"room_warning_about_encryption" = "종단간 암호화는 베타 버전이고 신뢰하지 못할 수 있습니다.\n\n아직 데이터를 보호한다고 신뢰하지 마세요.\n\n기기가 방에 참가하기 전에 아직 기록을 해독할 수 없습니다.\n\n아직 암호화를 구현하지 않았기 때문에 암호화된 메시지는 클라이언트에 나타나지 않습니다.";
|
||||
"room_event_failed_to_send" = "보내기에 실패함";
|
||||
"room_action_camera" = "사진 또는 영상 찍기";
|
||||
"room_action_send_photo_or_video" = "사진 또는 영상 보내기";
|
||||
"room_action_send_sticker" = "스티커 보내기";
|
||||
"room_action_send_file" = "파일 보내기";
|
||||
"room_action_reply" = "답장";
|
||||
"room_replacement_information" = "이 방은 대체되었으며 더 이상 활동하지 않습니다.";
|
||||
"room_replacement_link" = "대화는 여기서 이어집니다.";
|
||||
"room_predecessor_information" = "이 방에서 다른 대화가 이어집니다.";
|
||||
"room_predecessor_link" = "여기를 눌러 과거 메시지를 보세요.";
|
||||
"room_resource_limit_exceeded_message_contact_1" = " 제발 ";
|
||||
"room_resource_limit_exceeded_message_contact_2_link" = "서비스 관리자와 연락해서";
|
||||
"room_resource_limit_exceeded_message_contact_3" = " 이 서비스를 계속 사용하세요.";
|
||||
"room_resource_usage_limit_reached_message_1_default" = "이 홈서버가 리소스 한도를 초과했습니다 따라서 ";
|
||||
"room_resource_usage_limit_reached_message_1_monthly_active_user" = "이 홈서버가 월 간 활성 사용자 한도를 초과했습니다 따라서 ";
|
||||
"room_resource_usage_limit_reached_message_2" = "일부 사용자는 로그인할 수 없습니다.";
|
||||
"room_resource_usage_limit_reached_message_contact_3" = " 한도를 높이세요.";
|
||||
"room_message_edits_history_title" = "메시지 편집";
|
||||
// Unknown devices
|
||||
"unknown_devices_alert_title" = "방에 알 수 없는 기기가 있음";
|
||||
"unknown_devices_alert" = "이 방에 확인되지 않은 알 수 없는 기기가 있습니다.이 기기가 확인한 사용자의 것이라는 보장이 없습니다.\n계속하기 전에 각 기기마다 확인 절차를 거치기를 권합니다, 하지만 원한다면 확인하지 않고 메시지를 다시 보낼 수 있습니다.";
|
||||
"unknown_devices_send_anyway" = "무시하고 보내기";
|
||||
"unknown_devices_call_anyway" = "무시하고 전화";
|
||||
"unknown_devices_answer_anyway" = "무시하고 답하기";
|
||||
"unknown_devices_verify" = "확인하기…";
|
||||
"unknown_devices_title" = "알 수 없는 기기";
|
||||
// Room Title
|
||||
"room_title_new_room" = "새 방";
|
||||
"room_title_multiple_active_members" = "%@/%@ 활동 중인 구성원";
|
||||
"room_title_one_active_member" = "%@/%@ 활동 중인 구성원";
|
||||
"room_title_invite_members" = "구성원 초대";
|
||||
"room_title_members" = "%@명의 구성원";
|
||||
"room_title_one_member" = "1명의 구성원";
|
||||
// Room Preview
|
||||
"room_preview_invitation_format" = "%@님에게 이 방을 초대받았습니다";
|
||||
"room_preview_subtitle" = "이 방의 미리 보기입니다. 방 상호작용은 꺼져 있습니다.";
|
||||
"room_preview_unlinked_email_warning" = "이 초대는 %@님이 보냈습니다, 이 계정과는 연관이 없습니다. 다른 계정으로 로그인하거나, 이 이메일을 계정에 추가하세요.";
|
||||
"room_preview_try_join_an_unknown_room" = "%@(으)로 접근하려 했습니다. 토론에 참여하기 위해 참가하는 건가요?";
|
||||
"room_preview_try_join_an_unknown_room_default" = "방";
|
||||
// Settings
|
||||
"settings_title" = "설정";
|
||||
"account_logout_all" = "모든 계정에서 로그아웃";
|
||||
"settings_config_no_build_info" = "빌드 정보 없음";
|
||||
"settings_mark_all_as_read" = "모든 메시지를 읽음으로 표시";
|
||||
"settings_report_bug" = "버그 신고";
|
||||
"settings_clear_cache" = "캐시 지우기";
|
||||
"settings_config_home_server" = "홈서버: %@";
|
||||
"settings_config_identity_server" = "ID 서버: %@";
|
||||
"settings_config_user_id" = "사용자 ID: %@";
|
||||
"settings_user_settings" = "사용자 설정";
|
||||
"settings_notifications_settings" = "알림 설정";
|
||||
"settings_calls_settings" = "전화";
|
||||
"settings_user_interface" = "사용자 인터페이스";
|
||||
"settings_ignored_users" = "무시한 사용자";
|
||||
"settings_contacts" = "로컬 연락처";
|
||||
"settings_advanced" = "고급";
|
||||
"settings_other" = "기타";
|
||||
"settings_labs" = "연구실";
|
||||
"settings_flair" = "허용되는 곳에 재능 보이기";
|
||||
"settings_devices" = "기기";
|
||||
"settings_cryptography" = "암호화";
|
||||
"settings_key_backup" = "키 백업";
|
||||
"settings_deactivate_account" = "계정 비활성화";
|
||||
"settings_sign_out" = "로그아웃";
|
||||
"settings_sign_out_confirmation" = "확신합니까?";
|
||||
"settings_sign_out_e2e_warn" = "종단간 암호화 키를 잃게 됩니다. 더 이상 이 기기로 암호화된 방의 예전 메시지를 읽을 수 없게 됩니다.";
|
||||
"settings_profile_picture" = "프로필 사진";
|
||||
"settings_display_name" = "표시 이름";
|
||||
"settings_first_name" = "성";
|
||||
"settings_surname" = "이름";
|
||||
"settings_remove_prompt_title" = "확인";
|
||||
"settings_remove_email_prompt_msg" = "이메일 주소 %@을(를) 제거하겠습니까?";
|
||||
"settings_remove_phone_prompt_msg" = "전화번호 %@을(를) 지우겠습니까?";
|
||||
"settings_email_address" = "이메일";
|
||||
"settings_email_address_placeholder" = "이메일 주소를 입력하세요";
|
||||
"settings_add_email_address" = "이메일 주소 추가";
|
||||
"settings_phone_number" = "휴대 전화";
|
||||
"settings_add_phone_number" = "전화번호 추가";
|
||||
"settings_change_password" = "비밀번호 변경";
|
||||
"settings_night_mode" = "야간 모드";
|
||||
"settings_fail_to_update_profile" = "프로필 업데이트에 실패함";
|
||||
"settings_enable_push_notif" = "이 기기에서 알림";
|
||||
"settings_show_decrypted_content" = "암호화된 내용 보이기";
|
||||
"settings_global_settings_info" = "당신의 %@ 웹 클라이언트에 전역 알림 설정이 켜졌습니다";
|
||||
"settings_pin_rooms_with_missed_notif" = "알림을 놓친 방을 고정";
|
||||
"settings_pin_rooms_with_unread" = "읽지 않은 메시지가 있는 방을 고정";
|
||||
"settings_on_denied_notification" = "%@에 의해 알림이 거부됬습니다, 기기 설정에서 %@을(를) 허용해주세요";
|
||||
"settings_enable_callkit" = "통합 전화";
|
||||
"settings_callkit_info" = "잠금 화면에서 오는 전화를 받습니다. 시스템의 통화 내역에서 Riot 통화를 확인하세요. iCloud가 켜져있다면, 이 통화 기록은 Apple과 공유됩니다.";
|
||||
"settings_ui_language" = "언어";
|
||||
"settings_ui_theme" = "테마";
|
||||
"settings_ui_theme_auto" = "자동";
|
||||
"settings_ui_theme_light" = "밝게";
|
||||
"settings_ui_theme_dark" = "어둡게";
|
||||
"settings_ui_theme_black" = "검정";
|
||||
"settings_ui_theme_picker_title" = "테마를 선택하세요";
|
||||
"settings_ui_theme_picker_message" = "\"자동\"은 기기의 \"색상 반전\" 설정을 사용합니다";
|
||||
"settings_unignore_user" = "%@님의 모든 메시지를 표시합니까?";
|
||||
"settings_contacts_discover_matrix_users" = "이메일과 전화번호로 사용자를 검색";
|
||||
"settings_contacts_phonebook_country" = "국제전화 나라 번호";
|
||||
"settings_labs_e2e_encryption" = "종단간 암호화";
|
||||
"settings_labs_e2e_encryption_prompt_message" = "암호화 설정을 마치려면 다시 로그인하세요.";
|
||||
"settings_labs_room_members_lazy_loading" = "방 구성원 불러오기 지연";
|
||||
"settings_labs_room_members_lazy_loading_error_message" = "홈서버가 아직 방 구성원 불러오기 지연을 지원하지 않습니다. 나중에 다시 시도해보세요.";
|
||||
"settings_labs_create_conference_with_jitsi" = "Jitsi로 회의 전화 만들기";
|
||||
"settings_labs_message_reaction" = "메시지에 이모지로 리액션하기";
|
||||
"settings_version" = "버전 %@";
|
||||
"settings_olm_version" = "Olm 버전 %@";
|
||||
"settings_copyright" = "저작권";
|
||||
"settings_copyright_url" = "https://riot.im/copyright";
|
||||
"settings_term_conditions" = "이용 약관";
|
||||
"settings_term_conditions_url" = "https://riot.im/tac_apple";
|
||||
"settings_privacy_policy" = "개인 정보 정책";
|
||||
"settings_privacy_policy_url" = "https://riot.im/privacy";
|
||||
"settings_third_party_notices" = "제 3자 공지";
|
||||
"settings_send_crash_report" = "충돌 & 사용 데이터 보내기";
|
||||
"settings_enable_rageshake" = "분노의 흔들기로 버그 신고";
|
||||
"settings_old_password" = "이전 비밀번호";
|
||||
"settings_new_password" = "새 비밀번호";
|
||||
"settings_confirm_password" = "비밀번호 확인";
|
||||
"settings_fail_to_update_password" = "비밀번호 업데이트에 실패함";
|
||||
"settings_password_updated" = "비밀번호가 업데이트되었습니다";
|
||||
"settings_crypto_device_name" = "기기 공개 이름: ";
|
||||
"settings_crypto_device_id" = "\n기기 ID: ";
|
||||
"settings_crypto_device_key" = "\n기기 키:\n";
|
||||
"settings_crypto_export" = "키 내보내기";
|
||||
"settings_crypto_blacklist_unverified_devices" = "확인된 기기만 암호화";
|
||||
"settings_deactivate_my_account" = "내 계정 비활성화";
|
||||
"settings_key_backup_info" = "암호화된 메시지는 종단간 암호화로 보호됩니다. 오직 당신과 참가자만 키를 갖고 있어서 이 메시지를 읽을 수 있습니다.";
|
||||
"settings_key_backup_info_checking" = "확인 중...";
|
||||
"settings_key_backup_info_none" = "키가 이 기기에서 백업되지 않았습니다.";
|
||||
"settings_key_backup_info_signout_warning" = "이 기기에만 있을 수 있는 키를 잃지 않도록, 로그아웃하기 전에 이 기기를 키 백업에 연결하세요.";
|
||||
"settings_key_backup_info_version" = "키 백업 버전: %@";
|
||||
"settings_key_backup_info_algorithm" = "알고리즘: %@";
|
||||
"settings_key_backup_info_valid" = "이 기기는 키를 백업하고 있습니다.";
|
||||
"settings_key_backup_info_not_valid" = "이 기기는 키를 백업하고 있지 않습니다, 하지만 존재하는 백업이 있고 이것을 복구한 뒤 키를 추가할 수 있습니다.";
|
||||
"settings_key_backup_info_progress" = "%@ 키를 백업하는 중...";
|
||||
"settings_key_backup_info_progress_done" = "모든 키가 백업됨";
|
||||
"settings_key_backup_info_trust_signature_unknown" = "백업은 기기로부터 ID로 된 서명을 갖습니다: %@";
|
||||
"settings_key_backup_info_trust_signature_valid" = "백업이 이 기기로부터 올바른 서명을 갖고 있음";
|
||||
"settings_key_backup_info_trust_signature_valid_device_verified" = "백업이 %@(으)로부터 올바른 서명을 갖고 있음";
|
||||
"settings_key_backup_info_trust_signature_valid_device_unverified" = "백업이 %@(으)로부터 서명을 갖고 있음";
|
||||
"settings_key_backup_info_trust_signature_invalid_device_verified" = "백업이 %@(으)로부터 올바르지 않은 서명을 갖고 있음";
|
||||
"settings_key_backup_info_trust_signature_invalid_device_unverified" = "백업이 %@(으)로부터 올바르지 않은 서명을 갖고 있음";
|
||||
"settings_key_backup_button_create" = "키 백업 시작";
|
||||
"settings_key_backup_button_restore" = "백업에서 복구";
|
||||
"settings_key_backup_button_delete" = "백업 삭제";
|
||||
"settings_key_backup_button_connect" = "이 기기를 키 백업에 연결";
|
||||
"settings_key_backup_delete_confirmation_prompt_title" = "백업 삭제";
|
||||
"settings_key_backup_delete_confirmation_prompt_msg" = "확신합니까? 키가 정상적으로 백업되지 않으면 암호화된 메시지를 잃게 됩니다.";
|
||||
// Room Details
|
||||
"room_details_title" = "방 세부 사항";
|
||||
"room_details_people" = "구성원";
|
||||
"room_details_files" = "파일";
|
||||
"room_details_settings" = "설정";
|
||||
"room_details_photo" = "방 사진";
|
||||
"room_details_room_name" = "방 이름";
|
||||
"room_details_topic" = "주제";
|
||||
"room_details_favourite_tag" = "즐겨찾기";
|
||||
"room_details_low_priority_tag" = "중요하지 않음";
|
||||
"room_details_mute_notifs" = "알림 음소거";
|
||||
"room_details_direct_chat" = "다이렉트 대화";
|
||||
"room_details_access_section" = "이 방에 누가 접근할 수 있나요?";
|
||||
"room_details_access_section_invited_only" = "초대한 사람들만";
|
||||
"room_details_access_section_anyone_apart_from_guest" = "방의 링크를 아는 누구나, 손님 제외";
|
||||
"room_details_access_section_anyone" = "방의 링크를 아는 누구나, 손님 포함";
|
||||
"room_details_access_section_no_address_warning" = "방으로 링크를 주려면, 주소가 필요합니다";
|
||||
"room_details_access_section_directory_toggle" = "이 방을 방 목록에 배치";
|
||||
"room_details_history_section" = "누가 기록을 읽을 수 있나요?";
|
||||
"room_details_history_section_anyone" = "누구나";
|
||||
"room_details_history_section_members_only" = "(이 옵션을 선택한 시점부터) 구성원만";
|
||||
"room_details_history_section_members_only_since_invited" = "(초대받은 시점부터) 구성원만";
|
||||
"room_details_history_section_members_only_since_joined" = "(참가한 시점부터) 구성원만";
|
||||
"room_details_history_section_prompt_title" = "개인 정보 경고";
|
||||
"room_details_history_section_prompt_msg" = "이 방에서 기록을 읽을 수 있는 사람의 변경 사항은 이후 메시지부터 적용됩니다. 존재하는 기록의 가시성은 변하지 않습니다.";
|
||||
"room_details_addresses_section" = "주소";
|
||||
"room_details_no_local_addresses" = "이 방은 로컬 주소가 없습니다";
|
||||
"room_details_new_address" = "새 주소 추가";
|
||||
"room_details_new_address_placeholder" = "새 주소 추가 (예: #foo%@)";
|
||||
"room_details_addresses_invalid_address_prompt_title" = "잘못된 별칭 형식";
|
||||
"room_details_addresses_invalid_address_prompt_msg" = "%@은(는) 별칭에 올바른 형식이 아닙니다";
|
||||
"room_details_addresses_disable_main_address_prompt_title" = "기본 주소 경고";
|
||||
"room_details_addresses_disable_main_address_prompt_msg" = "지정한 기본 주소가 없습니다. 이 방의 기본 주소는 무작위로 지정됩니다";
|
||||
"room_details_flair_section" = "커뮤니티 별 재능 보이기";
|
||||
"room_details_new_flair_placeholder" = "새 커뮤니티 ID 추가 (예: +foo%@)";
|
||||
"room_details_flair_invalid_id_prompt_title" = "잘못된 형식";
|
||||
"room_details_flair_invalid_id_prompt_msg" = "%@은(는) 커뮤니티의 올바른 ID가 아닙니다";
|
||||
"room_details_banned_users_section" = "차단한 사용자";
|
||||
"room_details_advanced_section" = "고급";
|
||||
"room_details_advanced_room_id" = "방 ID:";
|
||||
"room_details_advanced_enable_e2e_encryption" = "암호화 켜짐 (경고: 다시 끌 수 없습니다!)";
|
||||
"room_details_advanced_e2e_encryption_enabled" = "이 방의 암호화가 켜졌습니다";
|
||||
"room_details_advanced_e2e_encryption_disabled" = "이 방의 암호화가 꺼졌습니다.";
|
||||
"room_details_advanced_e2e_encryption_blacklist_unverified_devices" = "확인된 기기만 암호화";
|
||||
"room_details_fail_to_update_avatar" = "방 사진 업데이트에 실패함";
|
||||
"room_details_fail_to_update_room_name" = "방 이름 업데이트에 실패함";
|
||||
"room_details_fail_to_update_topic" = "주제 업데이트에 실패함";
|
||||
"room_details_fail_to_update_room_guest_access" = "방 손님 접근 업데이트에 실패함";
|
||||
"room_details_fail_to_update_room_join_rule" = "참가 규칙 업데이트에 실패함";
|
||||
"room_details_fail_to_update_room_directory_visibility" = "방 목록 가시성 업데이트에 실패함";
|
||||
"room_details_fail_to_update_history_visibility" = "기록 가시성 업데이트에 실패함";
|
||||
"room_details_fail_to_add_room_aliases" = "새 방 주소 추가에 실패함";
|
||||
"room_details_fail_to_remove_room_aliases" = "방 주소 삭제에 실패함";
|
||||
"room_details_fail_to_update_room_canonical_alias" = "기본 주소 업데이트에 실패함";
|
||||
"room_details_fail_to_update_room_communities" = "관련된 커뮤니티 업데이트에 실패함";
|
||||
"room_details_fail_to_update_room_direct" = "이 방의 다이렉트 플래그 업데이트에 실패함";
|
||||
"room_details_fail_to_enable_encryption" = "이 방의 암호화 켜기에 실패함";
|
||||
"room_details_save_changes_prompt" = "변경 사항을 저장할까요?";
|
||||
"room_details_set_main_address" = "기본 주소로 설정";
|
||||
"room_details_unset_main_address" = "기본 주소로 설정 해제";
|
||||
"room_details_copy_room_id" = "방 ID 복사";
|
||||
"room_details_copy_room_address" = "방 주소 복사";
|
||||
"room_details_copy_room_url" = "방 URL 복사";
|
||||
// Group Details
|
||||
"group_details_title" = "커뮤니티 세부 사항";
|
||||
"group_details_home" = "홈";
|
||||
"group_details_people" = "사람";
|
||||
"group_details_rooms" = "방";
|
||||
// Group Home
|
||||
"group_home_one_member_format" = "1멍의 구성원";
|
||||
"group_home_multi_members_format" = "%tu명의 구성원";
|
||||
"group_home_one_room_format" = "1개의 방";
|
||||
"group_home_multi_rooms_format" = "%tu개의 방";
|
||||
"group_invitation_format" = "%@님이 이 커뮤니티에 당신을 초대했습니다";
|
||||
// Group participants
|
||||
"group_participants_add_participant" = "참가자 추가";
|
||||
"group_participants_leave_prompt_title" = "그룹 떠나기";
|
||||
"group_participants_leave_prompt_msg" = "그룹을 떠나겠습니까?";
|
||||
"group_participants_remove_prompt_title" = "확인";
|
||||
"group_participants_remove_prompt_msg" = "이 그룹에서 %@을(를) 감추겠습니까?";
|
||||
"group_participants_invite_prompt_title" = "확인";
|
||||
"group_participants_invite_prompt_msg" = "이 그룹에 %@님을 초대하겠습니까?";
|
||||
"group_participants_filter_members" = "커뮤니티 구성원 필터";
|
||||
"group_participants_invite_another_user" = "사용자 ID 또는 이름으로 검색 / 초대";
|
||||
"group_participants_invite_malformed_id_title" = "초대 오류";
|
||||
"group_participants_invite_malformed_id" = "잘못된 ID. '@localpart:domain'과 같은 Matrix ID이어야 합니다";
|
||||
"group_participants_invited_section" = "초대받음";
|
||||
// Group rooms
|
||||
"group_rooms_filter_rooms" = "커뮤니티 방 필터";
|
||||
// Read Receipts
|
||||
"read_receipts_list" = "읽은 기록 목록";
|
||||
"receipt_status_read" = "읽음: ";
|
||||
// Media picker
|
||||
"media_picker_title" = "미디어 라이브러리";
|
||||
"media_picker_library" = "라이브러리";
|
||||
"media_picker_select" = "선택";
|
||||
// Image picker
|
||||
"image_picker_action_camera" = "사진 찍기";
|
||||
"image_picker_action_library" = "라이브러리에서 선택";
|
||||
// Directory
|
||||
"directory_title" = "목록";
|
||||
"directory_server_picker_title" = "목록을 선택";
|
||||
"directory_server_all_rooms" = "%@ 서버에 있는 모든 방";
|
||||
"directory_server_all_native_rooms" = "모든 네이티브 Matrix 방";
|
||||
"directory_server_type_homeserver" = "홈서버를 입력하면 공개 방 목록을 나열합니다";
|
||||
"directory_server_placeholder" = "matrix.org";
|
||||
// Events formatter
|
||||
"event_formatter_member_updates" = "%tu명의 구성원 변경 사항";
|
||||
"event_formatter_widget_added" = "%@ 위젯을 %@님이 추가했습니다";
|
||||
"event_formatter_widget_removed" = "%@ 위젯을 %@님이 제거했습니다";
|
||||
"event_formatter_jitsi_widget_added" = "%@님이 VoIP 회의를 추가했습니다";
|
||||
"event_formatter_jitsi_widget_removed" = "%@님이 VoIP 회의를 제거했습니다";
|
||||
"event_formatter_rerequest_keys_part1_link" = "암호화 키 다시 요청";
|
||||
"event_formatter_rerequest_keys_part2" = " 다른 기기에서.";
|
||||
"event_formatter_message_edited_mention" = "(편집됨)";
|
||||
// Others
|
||||
"or" = "또는";
|
||||
"you" = "당신";
|
||||
"today" = "오늘";
|
||||
"yesterday" = "어제";
|
||||
"network_offline_prompt" = "인터넷이 오프라인입니다.";
|
||||
"homeserver_connection_lost" = "홈 서버에 연결할 수 없습니다.";
|
||||
"public_room_section_title" = "공개 방 (%@에 있음):";
|
||||
"bug_report_prompt" = "애플리케이션이 방금 충돌했군요.\n충돌 보고서를 제출하겠습니까?";
|
||||
"rage_shake_prompt" = "좌절감에 휴대 전화를 흔들고 있군요. 버그 보고서를 제출하겠습니까?";
|
||||
"do_not_ask_again" = "다시 묻지 않기";
|
||||
"camera_access_not_granted" = "%@님은 카메라를 사용할 권한이 없습니다, 개인 정보 설정을 바꿔주세요";
|
||||
"camera_unavailable" = "카메라는 이 기기에서 이용할 수 없습니다";
|
||||
"photo_library_access_not_granted" = "%@님은 사진 라이브러리에 접근할 권한이 없습니다, 개인 정보 설정을 바꿔주세요";
|
||||
"large_badge_value_k_format" = "%.1fK";
|
||||
"room_does_not_exist" = "%@님은 없습니다";
|
||||
// Call
|
||||
"call_incoming_voice_prompt" = "%@님으로부터 온 음성 통화";
|
||||
"call_incoming_video_prompt" = "%@님으로부터 온 영상 통화";
|
||||
"call_incoming_voice" = "전화 오는 중...";
|
||||
"call_incoming_video" = "오는 영상 통화...";
|
||||
"call_already_displayed" = "이미 전화가 진행 중입니다.";
|
||||
"call_jitsi_error" = "회의 전화 참가에 실패했습니다.";
|
||||
// No VoIP support
|
||||
"no_voip_title" = "전화 오는 중";
|
||||
"no_voip" = "%@님이 당신에게 전화를 걸고 있지만 %@은(는) 아직 전화를 지원하지 않습니다.\n이 알림을 무시하고 다른 기기에서 전화를 받거나 전화를 거절할 수 있습니다.";
|
||||
// Crash report
|
||||
"google_analytics_use_prompt" = "%@이(가) 개선하도록 자동으로 익명의 충돌 보고서와 사용 데이터를 제공하겠습니까?";
|
||||
// Crypto
|
||||
"e2e_enabling_on_app_update" = "Riot는 이제 종단간 암호화를 지원하지만 암호화를 켜려면 다시 로그인해야 합니다.\n\n지금 다시 로그인하거나 나중에 애플리케이션 설정에서 할 수 있습니다.";
|
||||
"e2e_need_log_in_again" = "이 기기에 종단간 암호화 키를 생성하고 공개 키를 홈서버에 제출하려면 다시 로그인해야 함니다.\n한 번만 하면 됩니다, 불편을 드려 죄송합니다.";
|
||||
// Key backup wrong version
|
||||
"e2e_key_backup_wrong_version_title" = "새 키 백업";
|
||||
"e2e_key_backup_wrong_version" = "새 보안 메시지 키 백업이 감지되었습니다.\n\n당신이 한 것이 아니라면 설정에서 새 암호를 설정하세요.";
|
||||
"e2e_key_backup_wrong_version_button_settings" = "설정";
|
||||
"e2e_key_backup_wrong_version_button_wasme" = "접니다";
|
||||
// Bug report
|
||||
"bug_report_title" = "버그 신고";
|
||||
"bug_report_description" = "버그를 설명해주세요. 무엇을 했나요? 무엇을 생각하고 했나요? 실제로 어떤 일이 일어났나요?";
|
||||
"bug_crash_report_title" = "충돌 보고서";
|
||||
"bug_crash_report_description" = "충돌 이전에 어떤 일을 했는 지 설명해주세요:";
|
||||
"bug_report_logs_description" = "문제를 진단하기 위해, 이 클라이언트의 로그를 이 버그 보고서에 제출합니다. 위의 문자만 보내지길 원한다면, 선택을 해제해주세요:";
|
||||
"bug_report_send_logs" = "로그 보내기";
|
||||
"bug_report_send_screenshot" = "스크린샷 보내기";
|
||||
"bug_report_progress_zipping" = "로그 수집 중";
|
||||
"bug_report_progress_uploading" = "신고 업로드 중";
|
||||
"bug_report_send" = "보내기";
|
||||
// Widget
|
||||
"widget_no_integrations_server_configured" = "설정된 통합 서버가 없음";
|
||||
"widget_integrations_server_failed_to_connect" = "통합 서버 연결에 실패함";
|
||||
"widget_no_power_to_manage" = "이 방에서 위젯을 관리할 권한이 없습니다";
|
||||
"widget_creation_failure" = "위젯 생성에 실패함";
|
||||
"widget_sticker_picker_no_stickerpacks_alert" = "현재 활성화된 스티커팩이 없습니다.";
|
||||
"widget_sticker_picker_no_stickerpacks_alert_add_now" = "지금 추가할까요?";
|
||||
// Widget Integration Manager
|
||||
"widget_integration_need_to_be_able_to_invite" = "그렇게 하려면 사용자를 초대할 수 있어야 합니다.";
|
||||
"widget_integration_unable_to_create" = "위젯 생성에 실패했습니다.";
|
||||
"widget_integration_failed_to_send_request" = "요청 보내기에 실패했습니다.";
|
||||
"widget_integration_room_not_recognised" = "이 방은 인식하지 않습니다.";
|
||||
"widget_integration_positive_power_level" = "권한 등급은 양의 정수이어야 합니다.";
|
||||
"widget_integration_must_be_in_room" = "당신은 이 방에 없습니다.";
|
||||
"widget_integration_no_permission_in_room" = "이 방에 그런 작업을 할 권한이 없습니다.";
|
||||
"widget_integration_missing_room_id" = "요청에 room_id가 없습니다.";
|
||||
"widget_integration_missing_user_id" = "요청에 user_id가 없습니다.";
|
||||
"widget_integration_room_not_visible" = "방 %@이(가) 보이지 않습니다.";
|
||||
// Share extension
|
||||
"share_extension_auth_prompt" = "내용을 공유하려면 기본 앱에 로그인";
|
||||
"share_extension_failed_to_encrypt" = "보내기에 실패함. 기본 앱에서 이 방의 암호화 설정을 확인하세요";
|
||||
// Room key request dialog
|
||||
"e2e_room_key_request_title" = "암호화 키 요청";
|
||||
"e2e_room_key_request_message_new_device" = "암호화 키를 요청한 새 기기 '%@'을(를) 추가했습니다.";
|
||||
"e2e_room_key_request_message" = "확인하지 않은 기기 '%@'이(가) 암호화 키를 요청하고 있습니다.";
|
||||
"e2e_room_key_request_start_verification" = "확인 시작...";
|
||||
"e2e_room_key_request_share_without_verifying" = "확인없이 공유";
|
||||
"e2e_room_key_request_ignore_request" = "요청 무시";
|
||||
// GDPR
|
||||
"gdpr_consent_not_given_alert_message" = "%@ 홈서버를 계속 사용하려면 이용 약관을 검토하고 수락해야 합니다.";
|
||||
"gdpr_consent_not_given_alert_review_now_action" = "지금 검토";
|
||||
// Service terms
|
||||
"service_terms_modal_title" = "서비스 약관";
|
||||
"service_terms_modal_message" = "계속하려면 이 서비스 약관 (%@)에 동의해야 합니다.";
|
||||
"service_terms_modal_accept_button" = "수락";
|
||||
"service_terms_modal_description_for_identity_server" = "다른 사용자가 검색할 수 있음";
|
||||
"service_terms_modal_description_for_integration_manager" = "봇, 브릿지, 위젯과 스티커팩을 사용";
|
||||
"deactivate_account_title" = "계정 비활성화";
|
||||
"deactivate_account_informations_part1" = "이것으로 계정은 영구적으로 사용할 수 없게됩니다. 로그인할 수 없고 아무도 같은 사용자 ID로 로그인할 수 없게 돱니다. 참가한 모든 방에서 떠나게되고 계정 세부 사항도 ID 서버에서 지워집니다. ";
|
||||
"deactivate_account_informations_part2_emphasize" = "이 행동은 돌이킬 수 없습니다.";
|
||||
"deactivate_account_informations_part3" = "\n\n계정 비활성화하기 ";
|
||||
"deactivate_account_informations_part4_emphasize" = "우리는 보낸 메시지는 기본적으로 지우지 않습니다. ";
|
||||
"deactivate_account_informations_part5" = "메시지를 지우고 싶다면 아래 상자를 체크하시요\n\nMatrix에서 메시지 가시성은 이메일과 유사합니다. 메시지를 지운다는 것은 보낸 메시지를 더 이상 새로운 혹은 등록하지 않은 사용자와 공유하는 않는 다는 것입니다, 하지만 이미 이 메시지에 접근한 등록한 사용자라면 그 사본에 계속 접근할 수 있습니다.";
|
||||
"deactivate_account_forget_messages_information_part1" = "계정을 비활성화하면 보낸 모든 메시지를 지워주세요 (";
|
||||
"deactivate_account_forget_messages_information_part2_emphasize" = "경고";
|
||||
"deactivate_account_forget_messages_information_part3" = ": 이것은 이후 사용자가 불완전한 대화를 보게 됩니다)";
|
||||
"deactivate_account_validate_action" = "계정 비활성화";
|
||||
"deactivate_account_password_alert_title" = "계정 비활성화";
|
||||
"deactivate_account_password_alert_message" = "계속하려면, 비밀번호를 입력해주세요";
|
||||
// Re-request confirmation dialog
|
||||
"rerequest_keys_alert_title" = "요청을 보냈습니다";
|
||||
"rerequest_keys_alert_message" = "메시지를 해독해서 이 기기로 키를 보낼 수 있도록 Riot을 다른 기기에 설치해주세요.";
|
||||
"key_backup_setup_title" = "키 백업";
|
||||
"key_backup_setup_skip_alert_title" = "확신합니까?";
|
||||
"key_backup_setup_skip_alert_message" = "로그아웃하거나 기기를 잃어버리면 보안 메시지를 잃게 됩니다.";
|
||||
"key_backup_setup_skip_alert_skip_action" = "넘기기";
|
||||
"key_backup_setup_intro_title" = "절대 암호화된 메시지를 잃지 마세요";
|
||||
"key_backup_setup_intro_info" = "암호화된 방의 메시지는 종단간 암호화로 보호됩니다. 오직 당싱과 참가자만 키를 갖고 있어 메시지를 읽을 수 있습니다.\n\n키를 잃지 않도록 안전하게 백업하세요.";
|
||||
"key_backup_setup_intro_setup_action_without_existing_backup" = "키 백업 시작";
|
||||
"key_backup_setup_intro_setup_connect_action_with_existing_backup" = "이 기기를 키 백업에 연결";
|
||||
"key_backup_setup_intro_manual_export_info" = "(고급)";
|
||||
"key_backup_setup_intro_manual_export_action" = "수동으로 키 내보내기";
|
||||
"key_backup_setup_passphrase_title" = "백업을 암호로 보호하기";
|
||||
"key_backup_setup_passphrase_info" = "암호화된 키의 사본을 서버에 보관합니다. 암호로된 백업을 보호하며 안전하게 유지해줍니다.\n\n보안을 최대화하려면, 암호는 계정 비밀번호와 달라야 합니다.";
|
||||
"key_backup_setup_passphrase_passphrase_title" = "입력";
|
||||
"key_backup_setup_passphrase_passphrase_placeholder" = "암호 입력";
|
||||
"key_backup_setup_passphrase_passphrase_valid" = "좋아요!";
|
||||
"key_backup_setup_passphrase_passphrase_invalid" = "단어를 추가해보세요";
|
||||
"key_backup_setup_passphrase_confirm_passphrase_title" = "확인";
|
||||
"key_backup_setup_passphrase_confirm_passphrase_placeholder" = "암호 확인";
|
||||
"key_backup_setup_passphrase_confirm_passphrase_valid" = "좋아요!";
|
||||
"key_backup_setup_passphrase_confirm_passphrase_invalid" = "암호가 맞지 않습니다";
|
||||
"key_backup_setup_passphrase_set_passphrase_action" = "암호 설정";
|
||||
"key_backup_setup_passphrase_setup_recovery_key_info" = "또는, 안전한 곳에 저장해 둘 복구 키로 백업을 보호합니다.";
|
||||
"key_backup_setup_passphrase_setup_recovery_key_action" = "(고급) 복구 키로 설정";
|
||||
"key_backup_setup_success_title" = "성공!";
|
||||
// Success from passphrase
|
||||
"key_backup_setup_success_from_passphrase_info" = "키가 백업되었습니다.\n\n복구 키는 안전망입니다 - 이것으로 암호를 잊어버려도 암호화된 메시지에 접근할 수 있습니다.\n\n복구키를 비밀번호 관리자 (혹은 금고)같은 안전한 장소에 두세요.";
|
||||
"key_backup_setup_success_from_passphrase_save_recovery_key_action" = "복구 키 저장";
|
||||
"key_backup_setup_success_from_passphrase_done_action" = "끝";
|
||||
// Success from recovery key
|
||||
"key_backup_setup_success_from_recovery_key_info" = "키가 백업되었습니다.\n\n이 복구 키의 사본을 만들어 안전하게 보관하세요.";
|
||||
"key_backup_setup_success_from_recovery_key_recovery_key_title" = "복구 키";
|
||||
"key_backup_setup_success_from_recovery_key_make_copy_action" = "사본 만들기";
|
||||
"key_backup_setup_success_from_recovery_key_made_copy_action" = "사본을 만들었습니다";
|
||||
"key_backup_recover_title" = "보안 메시지";
|
||||
"key_backup_recover_invalid_passphrase_title" = "맞지 않는 복구 암호";
|
||||
"key_backup_recover_invalid_passphrase" = "이 암호로 백업을 해독할 수 없습니다: 올바른 복구 암호를 입력해서 확인해주세요.";
|
||||
"key_backup_recover_invalid_recovery_key_title" = "복구 키가 맞지 않음";
|
||||
"key_backup_recover_invalid_recovery_key" = "이 키로 백업을 해독할 수 없습니다: 올바른 복구 키를 입력해서 확인해주세요.";
|
||||
"key_backup_recover_from_passphrase_info" = "복구 암호를 사용해 보안 메시지 기록을 푸세요";
|
||||
"key_backup_recover_from_passphrase_passphrase_title" = "입력";
|
||||
"key_backup_recover_from_passphrase_passphrase_placeholder" = "암호 입력";
|
||||
"key_backup_recover_from_passphrase_recover_action" = "기록 풀기";
|
||||
"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "복구 암호가 기억나지 않나요? ";
|
||||
"key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "복구 키를 사용하세요";
|
||||
"key_backup_recover_from_passphrase_lost_passphrase_action_part3" = ".";
|
||||
"key_backup_recover_from_recovery_key_info" = "복구 키를 사용해 보안 메시지 기록을 풉니다";
|
||||
"key_backup_recover_from_recovery_key_recovery_key_title" = "입력";
|
||||
"key_backup_recover_from_recovery_key_recovery_key_placeholder" = "복구 키 입력";
|
||||
"key_backup_recover_from_recovery_key_recover_action" = "기록 풀기";
|
||||
"key_backup_recover_from_recovery_key_lost_recovery_key_action" = "복구 키를 잃어버렸나요? 설정에서 새 것을 설정할 수 있어요.";
|
||||
"key_backup_recover_success_info" = "백업이 복구되었습니다!";
|
||||
"key_backup_recover_done_action" = "끝";
|
||||
"key_backup_setup_banner_title" = "절대 암호화된 메시지를 잃지 마세요";
|
||||
"key_backup_setup_banner_subtitle" = "키 백업 시작";
|
||||
"key_backup_recover_banner_title" = "절대 암호화된 메시지를 잃지 마세요";
|
||||
"key_backup_recover_connent_banner_subtitle" = "이 기기를 키 백업에 연결";
|
||||
"sign_out_existing_key_backup_alert_title" = "로그아웃하겠습니까?";
|
||||
"sign_out_existing_key_backup_alert_sign_out_action" = "로그아웃";
|
||||
"sign_out_non_existing_key_backup_alert_title" = "지금 로그아웃하면 암호화된 메시지에 접근할 수 없게 됩니다";
|
||||
"sign_out_non_existing_key_backup_alert_setup_key_backup_action" = "키 백업 시작";
|
||||
"sign_out_non_existing_key_backup_alert_discard_key_backup_action" = "제 암호화된 메시지는 필요 없습니다";
|
||||
"sign_out_non_existing_key_backup_sign_out_confirmation_alert_title" = "암호화된 메시지를 잃게 됩니다";
|
||||
"sign_out_non_existing_key_backup_sign_out_confirmation_alert_message" = "로그아웃하기 전에 키를 백업하지 않으면 암호화된 메시지에 접근할 수 없게 됩니다.";
|
||||
"sign_out_non_existing_key_backup_sign_out_confirmation_alert_sign_out_action" = "로그아웃";
|
||||
"sign_out_non_existing_key_backup_sign_out_confirmation_alert_backup_action" = "백업";
|
||||
"sign_out_key_backup_in_progress_alert_title" = "키 백업이 진행 중입니다. 지금 로그아웃하면 암호화된 메시지에 접근할 수 없게 됩니다.";
|
||||
"sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "제 암호화된 메시지는 필요 없습니다";
|
||||
"sign_out_key_backup_in_progress_alert_cancel_action" = "기다릴게요";
|
||||
// MARK: - Device Verification
|
||||
"device_verification_title" = "기기 확인";
|
||||
"device_verification_security_advice" = "보안을 최대화하려면, 직접 또는 다른 신뢰할만한 통신 수단으로 확인하기를 추천합니다";
|
||||
"device_verification_cancelled" = "상대방이 확인을 취소했습니다.";
|
||||
"device_verification_cancelled_by_me" = "확인이 취소됬습니다. 이유: %@";
|
||||
"device_verification_error_cannot_load_device" = "기기 정보를 불러올 수 없습니다.";
|
||||
// Mark: Incoming
|
||||
"device_verification_incoming_title" = "오는 확인 요청";
|
||||
"device_verification_incoming_description_1" = "이 기기를 신뢰하도록 확인합니다. 상대방의 신뢰하는 기기는 종단간 암호화된 메시지를 사용할 때 더 마음에 안심을 줍니다.";
|
||||
"device_verification_incoming_description_2" = "이 기기를 신뢰하도록 확인합니다, 그리고 상대방도 당신의 기기를 신뢰하도록 합니다.";
|
||||
// MARK: Start
|
||||
"device_verification_start_title" = "짧은 문장을 비교하여 확인";
|
||||
"device_verification_start_wait_partner" = "상대방이 수락하기를 기다리는 중...";
|
||||
"device_verification_start_use_legacy" = "아무것도 안 나타나나요? 일부 클라이언트는 아직 상호작용 확인을 지원하지 않습니다. 예전 확인 방식을 사용하세요.";
|
||||
"device_verification_start_verify_button" = "확인 시작";
|
||||
"device_verification_start_use_legacy_action" = "예전 확인 방식 사용";
|
||||
// MARK: Verify
|
||||
"device_verification_verify_title_emoji" = "상대방의 화면에 나타나는 다음 이모지를 확인하는 것으로 이 기기를 확인합니다";
|
||||
"device_verification_verify_title_number" = "상대방의 화면에 나타나는 다음 숫자를 확인하는 것으로 이 기기를 확인합니다";
|
||||
"device_verification_verify_wait_partner" = "상대방이 확인하기를 기다리는 중...";
|
||||
// MARK: Verified
|
||||
"device_verification_verified_title" = "확인되었습니다!";
|
||||
"device_verification_verified_description_1" = "성공적으로 이 기기를 확인했습니다.";
|
||||
"device_verification_verified_description_2" = "이 사용자와의 보안 메시지는 종단간 암호화되며 제 3자가 읽을 수 없습니다.";
|
||||
"device_verification_verified_got_it_button" = "알겠습니다";
|
||||
// MARK: Emoji
|
||||
"device_verification_emoji_dog" = "개";
|
||||
"device_verification_emoji_cat" = "고양이";
|
||||
"device_verification_emoji_lion" = "사자";
|
||||
"device_verification_emoji_horse" = "말";
|
||||
"device_verification_emoji_unicorn" = "유니콘";
|
||||
"device_verification_emoji_pig" = "돼지";
|
||||
"device_verification_emoji_elephant" = "코끼리";
|
||||
"device_verification_emoji_rabbit" = "토끼";
|
||||
"device_verification_emoji_panda" = "판다";
|
||||
"device_verification_emoji_rooster" = "수탉";
|
||||
"device_verification_emoji_penguin" = "펭귄";
|
||||
"device_verification_emoji_turtle" = "거북";
|
||||
"device_verification_emoji_fish" = "물고기";
|
||||
"device_verification_emoji_octopus" = "문어";
|
||||
"device_verification_emoji_butterfly" = "나비";
|
||||
"device_verification_emoji_flower" = "꽃";
|
||||
"device_verification_emoji_tree" = "나무";
|
||||
"device_verification_emoji_cactus" = "선인장";
|
||||
"device_verification_emoji_mushroom" = "버섯";
|
||||
"device_verification_emoji_globe" = "지구본";
|
||||
"device_verification_emoji_moon" = "달";
|
||||
"device_verification_emoji_cloud" = "구름";
|
||||
"device_verification_emoji_fire" = "불";
|
||||
"device_verification_emoji_banana" = "바나나";
|
||||
"device_verification_emoji_apple" = "사과";
|
||||
"device_verification_emoji_strawberry" = "딸기";
|
||||
"device_verification_emoji_corn" = "옥수수";
|
||||
"device_verification_emoji_pizza" = "피자";
|
||||
"device_verification_emoji_cake" = "케이크";
|
||||
"device_verification_emoji_heart" = "하트";
|
||||
"device_verification_emoji_smiley" = "웃음";
|
||||
"device_verification_emoji_robot" = "로봇";
|
||||
"device_verification_emoji_hat" = "모자";
|
||||
"device_verification_emoji_glasses" = "안경";
|
||||
"device_verification_emoji_spanner" = "스패너";
|
||||
"device_verification_emoji_santa" = "산타클로스";
|
||||
"device_verification_emoji_thumbs up" = "좋아요";
|
||||
"device_verification_emoji_umbrella" = "우산";
|
||||
"device_verification_emoji_hourglass" = "모래시계";
|
||||
"device_verification_emoji_clock" = "시계";
|
||||
"device_verification_emoji_gift" = "선물";
|
||||
"device_verification_emoji_light bulb" = "전구";
|
||||
"device_verification_emoji_book" = "책";
|
||||
"device_verification_emoji_pencil" = "연필";
|
||||
"device_verification_emoji_paperclip" = "클립";
|
||||
"device_verification_emoji_scissors" = "가위";
|
||||
"device_verification_emoji_lock" = "자물쇠";
|
||||
"device_verification_emoji_key" = "열쇠";
|
||||
"device_verification_emoji_hammer" = "망치";
|
||||
"device_verification_emoji_telephone" = "전화기";
|
||||
"device_verification_emoji_flag" = "깃발";
|
||||
"device_verification_emoji_train" = "기차";
|
||||
"device_verification_emoji_bicycle" = "자전거";
|
||||
"device_verification_emoji_aeroplane" = "비행기";
|
||||
"device_verification_emoji_rocket" = "로켓";
|
||||
"device_verification_emoji_trophy" = "트로피";
|
||||
"device_verification_emoji_ball" = "공";
|
||||
"device_verification_emoji_guitar" = "기타";
|
||||
"device_verification_emoji_trumpet" = "트럼펫";
|
||||
"device_verification_emoji_bell" = "종";
|
||||
"device_verification_emoji_anchor" = "닻";
|
||||
"device_verification_emoji_headphones" = "헤드폰";
|
||||
"device_verification_emoji_folder" = "폴더";
|
||||
"device_verification_emoji_pin" = "핀";
|
||||
// MARK: File upload
|
||||
"file_upload_error_title" = "파일 업로드";
|
||||
"file_upload_error_unsupported_file_type_message" = "파일 형식을 지원하지 않습니다.";
|
||||
// MARK: Emoji picker
|
||||
"emoji_picker_title" = "리액션";
|
||||
"emoji_picker_people_category" = "표정 & 사람";
|
||||
"emoji_picker_nature_category" = "동물 & 자연";
|
||||
"emoji_picker_foods_category" = "음식 & 음료";
|
||||
"emoji_picker_activity_category" = "액티비티";
|
||||
"emoji_picker_places_category" = "여행 & 명소";
|
||||
"emoji_picker_objects_category" = "물건";
|
||||
"emoji_picker_symbols_category" = "기호";
|
||||
"emoji_picker_flags_category" = "깃발";
|
||||
// MARK: Reaction history
|
||||
"reaction_history_title" = "리액션";
|
||||
"room_participants_remove_third_party_invite_prompt_msg" = "이 초대를 취소하겠습니까?";
|
||||
// Errors
|
||||
"error_user_already_logged_in" = "다른 홈서버에 연결합니다. 로그아웃하겠습니까?";
|
||||
"room_accessiblity_scroll_to_bottom" = "아래로 스크롤";
|
||||
"room_accessibility_search" = "검색";
|
||||
"room_accessibility_integrations" = "통합";
|
||||
"room_accessibility_upload" = "업로드";
|
||||
"room_accessibility_call" = "전화";
|
||||
"room_accessibility_hangup" = "끊기";
|
||||
"media_type_accessibility_image" = "사진";
|
||||
"media_type_accessibility_audio" = "소리";
|
||||
"media_type_accessibility_video" = "영상";
|
||||
"media_type_accessibility_location" = "위치";
|
||||
"media_type_accessibility_file" = "파일";
|
||||
"media_type_accessibility_sticker" = "스티커";
|
||||
// Widget Picker
|
||||
"widget_picker_title" = "통합";
|
||||
"auth_add_email_message_2" = "계정 복구 용 이메일을 설정하세요, 이후 당신을 아는 사람들이 선택적으로 당신을 찾을 수 있도록 할 수 있습니다.";
|
||||
"auth_add_phone_message_2" = "전화를 설정하세요, 이후 당신을 아는 사람들이 선택적으로 당신을 찾을 수 있도록 할 수 있습니다.";
|
||||
"auth_add_email_phone_message_2" = "계정 복구 용 이메일을 설정하세요. 이후 당신을 아는 사람들이 선택적으로 당신을 찾을 수 있도록 이메일이나 전화를 사용할 수 있습니다.";
|
||||
"auth_email_is_required" = "설정된 ID 서버가 없어서 이후 비밀번호를 초기화할 이메일 주소를 추가할 수 없습니다.";
|
||||
"auth_phone_is_required" = "설정된 ID 서버가 없어서 이후 비밀번호를 초기화할 전화번호를 추가할 수 없습니다.";
|
||||
"auth_reset_password_error_is_required" = "설정된 ID 서버가 없음: 비밀번호를 초기화하려면 서버 설정에서 하나를 추가하세요.";
|
||||
"contacts_address_book_no_identity_server" = "설정된 ID 서버 없음";
|
||||
"settings_discovery_settings" = "탐색";
|
||||
"settings_identity_server_settings" = "ID 서버";
|
||||
"settings_three_pids_management_information_part1" = "여기서 로그인하거나 계정을 복구하는데 사용할 이메일 주소나 전화번호를 관리하세요. 어디서 당신을 찾을 수 있는지 제어하세요 ";
|
||||
"settings_three_pids_management_information_part2" = "탐색";
|
||||
"settings_three_pids_management_information_part3" = ".";
|
||||
"settings_calls_stun_server_fallback_button" = "대체 전화 지원 서버 허용";
|
||||
"settings_calls_stun_server_fallback_description" = "홈서버가 전화 서버를 지원하지 않는다면 대체 전화 지원 서버 %@를 허용합니다 (전화하는 동안 IP 주소가 공유됩니다).";
|
||||
"settings_devices_description" = "기기 공개 이름은 소통하는 사람들에게 보여집니다";
|
||||
"settings_discovery_no_identity_server" = "현재 ID 서버를 사용하고 있지 않습니다. 연락처에 알고 있는 사람들이 당신을 찾을 수 있도록 하려면 서버를 하나 추가하세요.";
|
||||
"settings_discovery_terms_not_signed" = "이메일이나 전화번호로 당신을 찾을 수 있도록 하려면 ID 서버 (%@)의 서비스 약관에 동의하세요.";
|
||||
"settings_discovery_three_pids_management_information_part1" = "무슨 이메일 주소나 전화번호로 다른 사용자가 당신을 찾고 방에 초대할 수 있는지 관리하세요. 이 목록에서 이메일 주소나 전화번호를 추가하거나 제거할 수 있습니다. ";
|
||||
"settings_discovery_three_pids_management_information_part2" = "사용자 설정";
|
||||
"settings_discovery_three_pids_management_information_part3" = ".";
|
||||
"settings_discovery_error_message" = "오류가 발생했습니다. 다시 시도해주세요.";
|
||||
"settings_discovery_three_pid_details_title_email" = "이메일 관리";
|
||||
"settings_discovery_three_pid_details_information_email" = "다른 사용자가 당신을 찾거나 방에 초대할 때 쓰이는 이메일 주소의 환경 설정을 관리합니다. 계정에 이메일 주소를 추가하거나 제거하세요.";
|
||||
"settings_discovery_three_pid_details_title_phone_number" = "전화번호 관리";
|
||||
"settings_discovery_three_pid_details_information_phone_number" = "다른 사용자가 당신을 찾거나 방에 초대할 때 쓰이는 전화번호의 환경 설정을 관리합니다. 계정에 전화번호를 추가하거나 제거하세요.";
|
||||
"settings_discovery_three_pid_details_share_action" = "공유";
|
||||
"settings_discovery_three_pid_details_revoke_action" = "취소";
|
||||
"settings_discovery_three_pid_details_cancel_email_validation_action" = "이메일 확인 취소";
|
||||
"settings_discovery_three_pid_details_enter_sms_code_action" = "SMS 활성 코드 입력";
|
||||
"settings_identity_server_description" = "위에 설정된 ID 서버를 사용하면, 알고 있는 연락처 사람들을 찾거나 연락처 사람들이 당신을 찾을 수 있습니다.";
|
||||
"settings_identity_server_no_is" = "설정된 ID 서버 없음";
|
||||
"settings_identity_server_no_is_description" = "현재 ID 서버를 사용하고 있지 않습니다. 알고 있는 연락처 사람들을 찾거나 연락처 사람들이 당신을 찾으려면 위의 서버 중 하나를 추가하세요.";
|
||||
// Identity server settings
|
||||
"identity_server_settings_title" = "ID 서버";
|
||||
"identity_server_settings_description" = "알고 있는 연락처 사람들을 찾거나 연락처 사람들이 당신을 찾도록 현재 %@을(를) 사용하고 있습니다.";
|
||||
"identity_server_settings_no_is_description" = "현재 ID 서버를 사용하고 있지 않습니다. 알고 있는 연락처 사람들을 찾거나 연락처 사람들이 당신을 찾도록 하려면, 위의 서버 중 하나를 추가하세요.";
|
||||
"identity_server_settings_place_holder" = "ID 서버 입력";
|
||||
"identity_server_settings_add" = "추가";
|
||||
"identity_server_settings_change" = "바꾸기";
|
||||
"identity_server_settings_disconnect_info" = "ID 서버와 연결을 해제하면 더 이상 다른 사용자가 당신을 찾을 수 없고, 다른 사용자를 이메일이나 전화번호로 초대할 수 없게 됩니다.";
|
||||
"identity_server_settings_disconnect" = "연결 해제";
|
||||
"identity_server_settings_alert_no_terms_title" = "ID 서버에 서비스 약관이 없습니다";
|
||||
"identity_server_settings_alert_no_terms" = "선택한 ID 서버에는 서비스 약관이 없습니다. 서버의 소유자를 신뢰하는 경우에만 계속하세요.";
|
||||
"identity_server_settings_alert_change_title" = "ID 서버 바꾸기";
|
||||
"identity_server_settings_alert_change" = "ID 서버 %1$@을(를) 연결 해제하고 %2$@을(를) 연결합니까?";
|
||||
"identity_server_settings_alert_disconnect_title" = "ID 서버 연결 해제";
|
||||
"identity_server_settings_alert_disconnect" = "ID 서버 %@을(를) 연결 해제합니까?";
|
||||
"identity_server_settings_alert_disconnect_button" = "연결 해제";
|
||||
"identity_server_settings_alert_disconnect_still_sharing_3pid" = "여전히 ID 서버 %@에 개인 정보를 공유하고 있습니다.\n\n연결을 해제하기 전에 ID 서버에서 이메일 주소와 전화번호를 제거하길 권합니다.";
|
||||
"identity_server_settings_alert_disconnect_still_sharing_3pid_button" = "무시하고 연결 해제";
|
||||
"identity_server_settings_alert_error_terms_not_accepted" = "ID 서버로 설정하려면 %@ 약관에 동의해야 합니다.";
|
||||
"identity_server_settings_alert_error_invalid_identity_server" = "%@은(는) 올바른 ID 서버가 아닙니다.";
|
||||
"call_no_stun_server_error_title" = "잘못 설정된 서버 때문에 전화에 실패했습니다";
|
||||
"call_no_stun_server_error_message_1" = "전화가 안정적으로 작동하게 하는 TURN 서버를 설정하려면 홈서버 %@의 관리자에게 연락하세요.";
|
||||
"call_no_stun_server_error_message_2" = "아니면 %@에서 공개 서버를 사용할 수 있습니다, 하지만 그렇게 신뢰할 수는 없고 서버와 IP 주소를 공유하게 됩니다. 설정에서 이것을 관리할 수도 있습니다";
|
||||
"call_no_stun_server_error_use_fallback_button" = "%@ 사용하기";
|
||||
// Generic errors
|
||||
"error_invite_3pid_with_no_identity_server" = "이메일로 초대하려면 설정에서 ID 서버를 추가하세요.";
|
||||
"service_terms_modal_decline_button" = "끊기";
|
||||
"service_terms_modal_description_for_identity_server_1" = "전화나 이메일로 다른 사람 찾기";
|
||||
"service_terms_modal_description_for_identity_server_2" = "전화나 이메일로 다른 사람들이 찾을 수 있도록 하기";
|
||||
// Service terms - Variant for identity server when displayed out of a context
|
||||
"service_terms_modal_title_identity_server" = "연락처 탐색";
|
||||
"service_terms_modal_message_identity_server" = "연락처를 탐색하려면 ID 서버 (%@)의 약관에 동의해야 합니다.";
|
||||
|
|
|
@ -18,4 +18,5 @@
|
|||
"NSCameraUsageDescription" = "De camera wordt gebruikt om foto’s en video’s te maken, en voor videogesprekken.";
|
||||
"NSPhotoLibraryUsageDescription" = "De fotogalerij wordt gebruikt om foto’s en video’s te versturen.";
|
||||
"NSMicrophoneUsageDescription" = "De microfoon wordt gebruikt om video’s te maken, en voor spraakoproepen.";
|
||||
"NSContactsUsageDescription" = "Om u te kunnen tonen welke van uw contacten reeds Riot of Matrix gebruiken, kunnen we de e-mailadressen en telefoonnummers in uw adresboek naar uw Matrix-identiteitsserver sturen. New Vector bewaart deze gegevens niet en gebruikt ze niet voor andere doeleinden. Bekijk voor meer informatie de privacybeleidspagina in de instellingen van de app.";
|
||||
"NSContactsUsageDescription" = "Om u te kunnen tonen welke van uw contacten reeds Matrix gebruiken, kan Riot de e-mailadressen en telefoonnummers in uw adresboek naar uw gekozen Matrix-identiteitsserver sturen. Waar mogelijk worden persoonlijke gegevens gehasht voor verzenden - bekijk het privacybeleid van uw identiteitsserver voor meer informatie.";
|
||||
"NSCalendarsUsageDescription" = "Bekijk uw geplande afspraken in de app.";
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"view" = "Weergeven";
|
||||
"next" = "Volgende";
|
||||
"back" = "Terug";
|
||||
"continue" = "Verder gaan";
|
||||
"continue" = "Verdergaan";
|
||||
"create" = "Aanmaken";
|
||||
"start" = "Starten";
|
||||
"leave" = "Verlaten";
|
||||
|
@ -42,8 +42,8 @@
|
|||
"camera" = "Camera";
|
||||
"voice" = "Spraak";
|
||||
"video" = "Video";
|
||||
"active_call" = "Actieve oproep";
|
||||
"active_call_details" = "Actieve oproep (%@)";
|
||||
"active_call" = "Oproep actief";
|
||||
"active_call_details" = "Oproep actief (%@)";
|
||||
"later" = "Later";
|
||||
"rename" = "Hernoemen";
|
||||
// Authentication
|
||||
|
@ -64,7 +64,7 @@
|
|||
"auth_repeat_password_placeholder" = "Wachtwoord herhalen";
|
||||
"auth_repeat_new_password_placeholder" = "Bevestig uw nieuwe wachtwoord";
|
||||
"auth_invalid_login_param" = "Onjuiste gebruikersnaam en/of wachtwoord";
|
||||
"auth_invalid_user_name" = "Gebruikersnamen mogen alleen letters, cijfers, punten, afbreek- en lage streepjes bevatten";
|
||||
"auth_invalid_user_name" = "Gebruikersnamen mogen alleen letters, cijfers, punten, koppeltekens en underscores bevatten";
|
||||
"auth_invalid_password" = "Het wachtwoord is te kort (min 6)";
|
||||
"auth_invalid_email" = "Dit ziet er niet uit als een geldig e-mailadres";
|
||||
"auth_invalid_phone" = "Dit ziet er niet uit als een geldig telefoonnummer";
|
||||
|
@ -441,7 +441,7 @@
|
|||
"event_formatter_member_updates" = "%tu lidmaatschapsaanpassingen";
|
||||
"bug_report_send" = "Versturen";
|
||||
"auth_home_server_placeholder" = "URL (bv. https://matrix.org)";
|
||||
"auth_identity_server_placeholder" = "URL (bv. https://matrix.org)";
|
||||
"auth_identity_server_placeholder" = "URL (bv. https://vector.im)";
|
||||
"room_ongoing_conference_call_with_close" = "Er is een vergadergesprek gaande. Neem deel met %@ of %@. %@ het.";
|
||||
"room_ongoing_conference_call_close" = "Sluiten";
|
||||
"room_conference_call_no_power" = "U heeft toestemming nodig om vergadergesprekken in dit groepsgesprek te beheren";
|
||||
|
@ -556,7 +556,7 @@
|
|||
"deactivate_account_informations_part1" = "Dit zal uw account voorgoed onbruikbaar maken. U zult zich niet meer kunnen aanmelden, en niemand anders zal zich met dezelfde gebruikers-ID kunnen registreren. Dit zal er voor zorgen dat uw account alle gesprekken verlaat waar deze momenteel lid van is, en het verwijdert uw accountgegevens van de identiteitsserver. ";
|
||||
"deactivate_account_informations_part2_emphasize" = "Deze actie is onomkeerbaar.";
|
||||
"deactivate_account_informations_part3" = "\n\nHet deactiveren van uw account ";
|
||||
"deactivate_account_informations_part4_emphasize" = "zal er niet standaard voor zorgen dat de berichten die u heeft verzonden worden vergeten. ";
|
||||
"deactivate_account_informations_part4_emphasize" = "zal er standaard niet voor zorgen dat de berichten die u heeft verzonden worden vergeten. ";
|
||||
"deactivate_account_informations_part5" = "Als u wilt dat wij de berichten vergeten, vinkt u het vakje hieronder aan.\n\nDe zichtbaarheid van berichten in Matrix is gelijkaardig aan e-mails. Het vergeten van uw berichten betekent dat berichten die u heeft verstuurd niet meer gedeeld worden met nieuwe of ongeregistreerde gebruikers, maar geregistreerde gebruikers die al toegang hebben tot deze berichten zullen alsnog toegang hebben tot hun eigen kopie ervan.";
|
||||
"deactivate_account_forget_messages_information_part1" = "Vergeet alle berichten die ik heb verstuurd wanneer mijn account gedeactiveerd is (";
|
||||
"deactivate_account_forget_messages_information_part3" = ": dit zal er voor zorgen dat toekomstige gebruikers een onvolledig beeld krijgen van gesprekken)";
|
||||
|
@ -829,3 +829,29 @@
|
|||
"emoji_picker_flags_category" = "Vlaggen";
|
||||
// MARK: Reaction history
|
||||
"reaction_history_title" = "Reacties";
|
||||
"auth_forgot_password_error_no_configured_identity_server" = "Er is geen identiteitsserver geconfigureerd: voeg er een toe om uw wachtwoord opnieuw in te stellen.";
|
||||
"room_creation_error_invite_user_by_email_without_identity_server" = "Er is geen identiteitsserver geconfigureerd, dus u kunt geen deelnemers toevoegen via e-mail.";
|
||||
"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Er is geen identiteitsserver geconfigureerd, dus u kunt geen gesprek beginnen met een contact via e-mail.";
|
||||
// Service terms
|
||||
"service_terms_modal_title" = "Dienstvoorwaarden";
|
||||
"service_terms_modal_message" = "Om door te gaan dient u de dienstvoorwaarden te aanvaarden.";
|
||||
"service_terms_modal_accept_button" = "Aanvaarden";
|
||||
"service_terms_modal_description_for_identity_server" = "Wees vindbaar voor anderen";
|
||||
"service_terms_modal_description_for_integration_manager" = "Gebruik bots, bruggen, widgets en stickerpakketten";
|
||||
// Errors
|
||||
"error_user_already_logged_in" = "Het lijkt alsof u probeert te verbinden met een andere thuisserver. Wilt u zich afmelden?";
|
||||
"room_participants_remove_third_party_invite_prompt_msg" = "Weet u zeker dat u deze uitnodiging wilt intrekken?";
|
||||
"room_accessiblity_scroll_to_bottom" = "Scrollen naar onderen";
|
||||
"room_accessibility_search" = "Zoeken";
|
||||
"room_accessibility_integrations" = "Integraties";
|
||||
"room_accessibility_upload" = "Uploaden";
|
||||
"room_accessibility_call" = "Bellen";
|
||||
"room_accessibility_hangup" = "Ophangen";
|
||||
"media_type_accessibility_image" = "Afbeelding";
|
||||
"media_type_accessibility_audio" = "Audio";
|
||||
"media_type_accessibility_video" = "Video";
|
||||
"media_type_accessibility_location" = "Locatie";
|
||||
"media_type_accessibility_file" = "Bestand";
|
||||
"media_type_accessibility_sticker" = "Sticker";
|
||||
// Widget Picker
|
||||
"widget_picker_title" = "Integraties";
|
||||
|
|
|
@ -2,3 +2,5 @@
|
|||
"NSCameraUsageDescription" = "Aparat służy do robienia zdjęć i nagrywania filmów, prowadzenia rozmów wideo.";
|
||||
"NSPhotoLibraryUsageDescription" = "Biblioteka zdjęć służy do wysyłania zdjęć i filmów.";
|
||||
"NSMicrophoneUsageDescription" = "Mikrofon służy do robienia filmów, wykonywania połączeń.";
|
||||
"NSContactsUsageDescription" = "Możemy pokazać Ci, które z Twoich kontaktów korzystają aktualnie z Riot, bądź Matrix. Możemy wysyłać adresy e-mail i numery telefonów z Twojej książki adresowej na Twój serwer Matrix. New Vector nie przechowuje Twoich danych, ani nie wykorzystuje ich w żadnym celu. Aby uzyskać dodatkowe informacje zajrzyj do zakładki \"polityka prywatności\" w ustawieniach aplikacji.";
|
||||
"NSCalendarsUsageDescription" = "Zobacz swoje zaplanowane spotkania w aplikacji.";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* New message from a specific person, not referencing a room */
|
||||
"MSG_FROM_USER" = "Wiadomość od %@";
|
||||
"MSG_FROM_USER" = "%@ wysłał(a) wiadomość";
|
||||
/* New message from a specific person, not referencing a room. Content included. */
|
||||
"MSG_FROM_USER_WITH_CONTENT" = "%@: %@";
|
||||
/* New message from a specific person in a named room. Content included. */
|
||||
|
@ -23,9 +23,9 @@
|
|||
/* Look, stuff's happened, alright? Just open the app. */
|
||||
"MSGS_IN_TWO_PLUS_ROOMS" = "%@ nowych wiadomości w %@, %@ i innych";
|
||||
/* New action message from a specific person, not referencing a room. */
|
||||
"IMAGE_FROM_USER" = "%@ wysłał(a) Tobie zdjęcie %@";
|
||||
"IMAGE_FROM_USER" = "%@ wysłał(a) zdjęcie %@";
|
||||
/* New action message from a specific person in a named room. */
|
||||
"IMAGE_FROM_USER_IN_ROOM" = "%@ wysłał(a) Tobie zdjęcie %@ w %@";
|
||||
"IMAGE_FROM_USER_IN_ROOM" = "%@ wysłał(a) zdjęcie %@ w %@";
|
||||
/* Multiple unread messages from a specific person, not referencing a room */
|
||||
"MSGS_FROM_USER" = "%@ nowych wiadomości w %@";
|
||||
/* Multiple messages in two rooms */
|
||||
|
@ -36,3 +36,21 @@
|
|||
"USER_INVITE_TO_CHAT_GROUP_CHAT" = "%@ zaprosił(a) Ciebie do rozmowy grupowej";
|
||||
/* A user has invited you to a chat */
|
||||
"USER_INVITE_TO_CHAT" = "%@ zaprosił(a) Ciebie do rozmowy";
|
||||
/* Message title for a specific person in a named room */
|
||||
"MSG_FROM_USER_IN_ROOM_TITLE" = "%@ w %@";
|
||||
/* New message from a specific person in a named room */
|
||||
"MSG_FROM_USER_IN_ROOM" = "%@ opublikowany w %@";
|
||||
/* Sticker from a specific person, not referencing a room. */
|
||||
"STICKER_FROM_USER" = "%@ wysłał(a) naklejkę";
|
||||
/* Incoming one-to-one voice call */
|
||||
"VOICE_CALL_FROM_USER" = "Zadzwonił do Ciebie z %@";
|
||||
/* Incoming one-to-one video call */
|
||||
"VIDEO_CALL_FROM_USER" = "Połączenie wideo z %@";
|
||||
/* Incoming unnamed voice conference invite from a specific person */
|
||||
"VOICE_CONF_FROM_USER" = "Połączenie grupowe z %@";
|
||||
/* Incoming unnamed video conference invite from a specific person */
|
||||
"VIDEO_CONF_FROM_USER" = "Grupowe połączenie wideo z %@";
|
||||
/* Incoming named voice conference invite from a specific person */
|
||||
"VOICE_CONF_NAMED_FROM_USER" = "Połączenie grupowe z %@: '%@'";
|
||||
/* Incoming named video conference invite from a specific person */
|
||||
"VIDEO_CONF_NAMED_FROM_USER" = "Grupowe połączenie wideo z %@: '%@'";
|
||||
|
|
|
@ -526,3 +526,283 @@
|
|||
"settings_key_backup_info_progress_done" = "Utworzono kopię zapasową wszystkich kluczy";
|
||||
"settings_key_backup_button_delete" = "Usuń kopię zapasową";
|
||||
"settings_key_backup_delete_confirmation_prompt_title" = "Usuń kopię zapasową";
|
||||
"auth_login_single_sign_on" = "Zaloguj się za pomocą pojedynczego logowania";
|
||||
"auth_autodiscover_invalid_response" = "Nieprawidłowa odpowiedź na wykrycie serwera domowego";
|
||||
"settings_key_backup_button_create" = "Rozpocznij z użyciem klucza kopii zapasowej";
|
||||
"settings_key_backup_button_restore" = "Przywróć z kopii zapasowej";
|
||||
"room_details_fail_to_update_avatar" = "Nie udało się zaaktualizować zdjęcia pokoju";
|
||||
"room_details_fail_to_update_room_name" = "Nie udało się zaaktualizować nazwy pokoju";
|
||||
"room_details_fail_to_update_topic" = "Nie udało się zaaktualizować tematu";
|
||||
"room_details_fail_to_update_room_guest_access" = "Nie udało się zaaktualizować dostępu gościa do pokoju";
|
||||
"room_details_fail_to_update_room_join_rule" = "Nie udało się zaaktualizować reguły dołączania";
|
||||
"room_details_fail_to_update_room_directory_visibility" = "Nie udało się zaaktualizować widoczności pokoju";
|
||||
"room_details_fail_to_update_history_visibility" = "Nie udało się zaaktualizować historii widoczności";
|
||||
"room_details_fail_to_add_room_aliases" = "Nie udało się dodać nowych adresów pokoi";
|
||||
"room_details_fail_to_remove_room_aliases" = "Nie udało się usunąć adresów pokoi";
|
||||
"room_details_fail_to_update_room_canonical_alias" = "Nie udało się zaaktualizować głównego adresu pokoju";
|
||||
"room_details_fail_to_update_room_communities" = "Nie udało się zaaktualizować powiązanych społeczności";
|
||||
"room_details_fail_to_update_room_direct" = "Nie udało się zaaktualizować flagi tego pokoju";
|
||||
"room_details_fail_to_enable_encryption" = "Nie udało się włączyć szyfrowania w tym pokoju";
|
||||
"group_details_home" = "Strona domowa";
|
||||
"key_backup_setup_intro_setup_action_without_existing_backup" = "Zacznij korzystać z klucza bezpieczeństwa";
|
||||
"key_backup_setup_intro_setup_connect_action_with_existing_backup" = "Podłącz to urządzenie do klucza bezpieczeństwa";
|
||||
"key_backup_setup_intro_manual_export_info" = "(Zaawansowany)";
|
||||
"key_backup_setup_intro_manual_export_action" = "Ręcznie eksportuj klucze";
|
||||
"key_backup_setup_passphrase_title" = "Zabezpiecz swoją kopię zapasową hasłem";
|
||||
"key_backup_setup_passphrase_info" = "Będziemy przechowywać zaszyfrowaną kopię Twoich kluczy na naszym serwerze. Zabezpiecz swoją kopię zapasową przy pomocy hasła, aby zapewnić jej bezpieczeństwo.\n\nDla maksymalnego bezpieczeństwa - to powinno być inne hasło, niż hasło do konta.";
|
||||
"key_backup_setup_passphrase_passphrase_title" = "Wejdź";
|
||||
"key_backup_setup_passphrase_passphrase_placeholder" = "Wprowadź hasło";
|
||||
"key_backup_setup_passphrase_passphrase_valid" = "Świetnie!";
|
||||
"key_backup_setup_passphrase_passphrase_invalid" = "Spróbuj dodać słowo";
|
||||
"key_backup_setup_passphrase_confirm_passphrase_title" = "Potwierdź";
|
||||
"key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Potwierdź hasło";
|
||||
"key_backup_setup_passphrase_confirm_passphrase_valid" = "Świetnie!";
|
||||
"key_backup_setup_passphrase_confirm_passphrase_invalid" = "Hasło nie pasuje";
|
||||
"key_backup_setup_passphrase_set_passphrase_action" = "Ustaw hasło";
|
||||
"key_backup_setup_passphrase_setup_recovery_key_info" = "Możesz też zabezpieczyć kopię zapasową przy pomocy klucza odzyskiwania, zapisując ją w bezpiecznym miejscu.";
|
||||
"key_backup_setup_passphrase_setup_recovery_key_action" = "(Zaawansowany) Konfiguruj za pomocą klucza odzyskiwania";
|
||||
"key_backup_setup_success_title" = "Sukces!";
|
||||
// Success from passphrase
|
||||
"key_backup_setup_success_from_passphrase_info" = "Tworzone są kopie zapasowe kluczy.\n\nTwój klucz odzyskiwania to gwarant bezpieczeństwa - możesz użyć go, aby odzyskać dostęp do zaszyfrowanych wiadomości, jeśli zapomnisz hasła.\n\nTrzymaj ten klucz w bezpiecznym miejscu (np. w menedżerze haseł).";
|
||||
"key_backup_setup_success_from_passphrase_save_recovery_key_action" = "Zapisz klucz odzyskiwania";
|
||||
"key_backup_setup_success_from_passphrase_done_action" = "Zrobione";
|
||||
// Success from recovery key
|
||||
"key_backup_setup_success_from_recovery_key_info" = "Tworzone są kopie zapasowe kluczy.\n\nZrób kopię tego klucza i przechowuj ją w bezpiecznym miejscu.";
|
||||
"key_backup_setup_success_from_recovery_key_recovery_key_title" = "Klucz odzyskiwania";
|
||||
"key_backup_setup_success_from_recovery_key_make_copy_action" = "Zrób kopię";
|
||||
"key_backup_setup_success_from_recovery_key_made_copy_action" = "Zrobiłem kopię";
|
||||
"key_backup_recover_title" = "Bezpieczne wiadomości";
|
||||
"key_backup_recover_invalid_passphrase_title" = "Niepoprawne hasło odzyskiwania";
|
||||
"key_backup_recover_invalid_passphrase" = "Nie można odszyfrować kopii zapasowej przy użyciu tego hasła: Proszę, sprawdź czy wprowadziłeś(aś) prawidłowe hasło odzyskiwania.";
|
||||
"key_backup_recover_invalid_recovery_key_title" = "Klucz odzyskiwania nie pasuje";
|
||||
"key_backup_recover_invalid_recovery_key" = "Nie można odszyfrować kopii zapasowej przy użycia tego klucza: Proszę, sprawdź czy wpisałeś go poprawnie.";
|
||||
"key_backup_recover_from_passphrase_info" = "Skorzystaj ze swojego hasła odzyskiwania, aby odblokować historię bezpiecznych wiadomości";
|
||||
"key_backup_recover_from_passphrase_passphrase_title" = "Wejdź";
|
||||
"key_backup_recover_from_passphrase_passphrase_placeholder" = "Wprowadź hasło";
|
||||
"key_backup_recover_from_passphrase_recover_action" = "Odblokuj historię";
|
||||
"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "Nie znasz hasła odzyskiwania? Możesz ";
|
||||
"key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "Użyj swojego klucza odzyskiwania";
|
||||
"key_backup_recover_from_passphrase_lost_passphrase_action_part3" = ".";
|
||||
"key_backup_recover_from_recovery_key_info" = "Skorzystaj z klucza odzyskiwania, aby odblokować historię bezpiecznych wiadomości";
|
||||
"key_backup_recover_from_recovery_key_recovery_key_title" = "Wejdź";
|
||||
"key_backup_recover_from_recovery_key_recovery_key_placeholder" = "Wpisz klucz odzyskiwania";
|
||||
"key_backup_recover_from_recovery_key_recover_action" = "Odblokuj historię";
|
||||
"key_backup_recover_from_recovery_key_lost_recovery_key_action" = "Zgubiłeś swój klucz odzyskiwania? Możesz ustawić nowy w ustawieniach.";
|
||||
"key_backup_recover_success_info" = "Kopia zapasowa została przywrócona!";
|
||||
"key_backup_recover_done_action" = "Zrobiono";
|
||||
"key_backup_setup_banner_title" = "Nigdy nie trać zaszyfrowanych wiadomości";
|
||||
"key_backup_setup_banner_subtitle" = "Zacznij korzystać z kopii zapasowej";
|
||||
"key_backup_recover_banner_title" = "Nigdy nie trać zaszyfrowanych wiadomości";
|
||||
"key_backup_recover_connent_banner_subtitle" = "Podłącz to urządzenie do kopii zapasowej";
|
||||
"sign_out_existing_key_backup_alert_title" = "Jesteś pewien, że chcesz się wylogować?";
|
||||
"sign_out_existing_key_backup_alert_sign_out_action" = "Wyloguj się";
|
||||
"sign_out_non_existing_key_backup_alert_title" = "Jeśli wylogujesz się teraz, stracisz dostęp do swoich zaszyfrowanych wiadomości";
|
||||
"sign_out_non_existing_key_backup_alert_setup_key_backup_action" = "Zacznij korzystać z kopii zapasowej";
|
||||
"sign_out_non_existing_key_backup_alert_discard_key_backup_action" = "Nie chcę swoich zaszyfrowanych wiadomości";
|
||||
"sign_out_non_existing_key_backup_sign_out_confirmation_alert_title" = "Utracisz zaszyfrowane wiadomości";
|
||||
"sign_out_non_existing_key_backup_sign_out_confirmation_alert_message" = "Utracisz dostęp do zaszyfrowanych wiadomości, jeżeli wylogujesz się przed utworzeniem kopii zapasowej.";
|
||||
"sign_out_non_existing_key_backup_sign_out_confirmation_alert_sign_out_action" = "Wylogowanie";
|
||||
"sign_out_non_existing_key_backup_sign_out_confirmation_alert_backup_action" = "Kopia zapasowa";
|
||||
"sign_out_key_backup_in_progress_alert_title" = "Trwa tworzenie kopii zapasowej. Jeżeli wylogujesz się teraz - Stracisz dostęp do swoich zaszyfrowanych wiadomości.";
|
||||
"sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "Nie chcę moich zaszyfrowanych wiadomości";
|
||||
"sign_out_key_backup_in_progress_alert_cancel_action" = "Poczekam";
|
||||
// MARK: - Device Verification
|
||||
"device_verification_title" = "Zweryfikuj urządzenie";
|
||||
"device_verification_security_advice" = "Dla zapewnienia maksymalnego bezpieczeństwa zalecamy zrobienie tego samemu, bądź skorzystanie z innego, zaufanego środka komunikacji";
|
||||
"device_verification_cancelled" = "Druga strona przerwała weryfikację.";
|
||||
"device_verification_cancelled_by_me" = "Weryfikacja została przerwana. Powód: %@";
|
||||
"device_verification_error_cannot_load_device" = "Nie można załadować informacji o urządzeniu.";
|
||||
// Mark: Incoming
|
||||
"device_verification_incoming_title" = "Przyszła prośba o weryfikację";
|
||||
"device_verification_incoming_description_1" = "Zweryfikuj to urządzenie, aby oznaczyć je jako zaufane. Zaufane urządzenia dają Twoim rozmówcom dodatkowe poczucie spokoju, podczas konwersacji z włączonymi szyfrowanymi wiadomościami end-to-end.";
|
||||
"device_verification_incoming_description_2" = "Weryfikacja tego urządzenia spowoduje oznaczenie go, jako zaufanego. Zostanie ono oznaczone jako zaufane również na urządzeniu Twojego rozmówcy.";
|
||||
// MARK: Start
|
||||
"device_verification_start_title" = "Zweryfikuj, porównując krótki tekst";
|
||||
"device_verification_start_wait_partner" = "Oczekiwanie na zaakceptowanie przez rozmówce...";
|
||||
"device_verification_start_use_legacy" = "Nic się nie pojawiło? Nie wszystkie wersje aplikacji obsługują jeszcze interaktywną weryfikację. Prosimy o skorzystanie ze starszej wersji.";
|
||||
"device_verification_start_verify_button" = "Rozpocznij weryfikację";
|
||||
"device_verification_start_use_legacy_action" = "Użyj starszej wersji weryfikacji";
|
||||
// MARK: Verify
|
||||
"device_verification_verify_title_emoji" = "Sprawdź to urządzenie potwierdzając, że następujące emotikony pojawiają się na ekranie rozmówcy";
|
||||
"device_verification_verify_title_number" = "Sprawdź to urządzenie potwierdzając, że następujące liczby pojawiają się na ekranie rozmówcy";
|
||||
"device_verification_verify_wait_partner" = "Oczekiwanie na rozmówce w celu potwierdzenia...";
|
||||
// MARK: Verified
|
||||
"device_verification_verified_title" = "Zweryfikowano!";
|
||||
"device_verification_verified_description_1" = "Pomyślnie zweryfikowano to urządzenie.";
|
||||
"device_verification_verified_description_2" = "Bezpieczne wiadomości z tym użytkownikiem są szyfrowane metodą end-to-end i nie mogą zostać odczytane przez osoby trzecie.";
|
||||
"device_verification_verified_got_it_button" = "Zrobione";
|
||||
// MARK: Emoji
|
||||
"device_verification_emoji_dog" = "Pies";
|
||||
"device_verification_emoji_cat" = "Kot";
|
||||
"device_verification_emoji_lion" = "Lew";
|
||||
"device_verification_emoji_horse" = "Koń";
|
||||
"device_verification_emoji_unicorn" = "Jednorożec";
|
||||
"device_verification_emoji_pig" = "Świnia";
|
||||
"device_verification_emoji_elephant" = "Słoń";
|
||||
"device_verification_emoji_rabbit" = "Królik";
|
||||
"device_verification_emoji_panda" = "Panda";
|
||||
"device_verification_emoji_rooster" = "Kogut";
|
||||
"device_verification_emoji_penguin" = "Pingwin";
|
||||
"device_verification_emoji_turtle" = "Żółw";
|
||||
"device_verification_emoji_fish" = "Ryba";
|
||||
"device_verification_emoji_octopus" = "Ośmiornica";
|
||||
"device_verification_emoji_butterfly" = "Motyl";
|
||||
"device_verification_emoji_flower" = "Kwiatek";
|
||||
"device_verification_emoji_tree" = "Drzewo";
|
||||
"device_verification_emoji_cactus" = "Kaktus";
|
||||
"device_verification_emoji_mushroom" = "Grzyb";
|
||||
"device_verification_emoji_globe" = "Kula ziemska";
|
||||
"device_verification_emoji_moon" = "Księżyc";
|
||||
"device_verification_emoji_cloud" = "Chmura";
|
||||
"device_verification_emoji_fire" = "Ogień";
|
||||
"device_verification_emoji_banana" = "Banan";
|
||||
"device_verification_emoji_apple" = "Jabłko";
|
||||
"device_verification_emoji_strawberry" = "Truskawka";
|
||||
"device_verification_emoji_corn" = "Kukurydza";
|
||||
"device_verification_emoji_pizza" = "Pizza";
|
||||
"device_verification_emoji_cake" = "Ciasto";
|
||||
"device_verification_emoji_heart" = "Serce";
|
||||
"device_verification_emoji_smiley" = "Uśmiech";
|
||||
"device_verification_emoji_robot" = "Robot";
|
||||
"device_verification_emoji_hat" = "Kapelusz";
|
||||
"device_verification_emoji_glasses" = "Okulary";
|
||||
"device_verification_emoji_spanner" = "Klucz";
|
||||
"device_verification_emoji_santa" = "Mikołaj";
|
||||
"device_verification_emoji_thumbs up" = "Kciuk w górę";
|
||||
"device_verification_emoji_umbrella" = "Parasolka";
|
||||
"device_verification_emoji_hourglass" = "Klepsydra";
|
||||
"device_verification_emoji_clock" = "Zegar";
|
||||
"device_verification_emoji_gift" = "Prezent";
|
||||
"device_verification_emoji_light bulb" = "Żarówka";
|
||||
"device_verification_emoji_book" = "Książka";
|
||||
"device_verification_emoji_pencil" = "Ołówek";
|
||||
"device_verification_emoji_paperclip" = "Spinacz";
|
||||
"device_verification_emoji_scissors" = "Nożyczki";
|
||||
"device_verification_emoji_lock" = "Zamek";
|
||||
"device_verification_emoji_key" = "Klucz";
|
||||
"device_verification_emoji_hammer" = "Młotek";
|
||||
"device_verification_emoji_telephone" = "Telefon";
|
||||
"device_verification_emoji_flag" = "Flaga";
|
||||
"device_verification_emoji_train" = "Pociąg";
|
||||
"device_verification_emoji_bicycle" = "Rower";
|
||||
"device_verification_emoji_aeroplane" = "Samolot";
|
||||
"device_verification_emoji_rocket" = "Rakieta";
|
||||
"device_verification_emoji_trophy" = "Trofeum";
|
||||
"device_verification_emoji_ball" = "Piłka";
|
||||
"device_verification_emoji_guitar" = "Gitara";
|
||||
"device_verification_emoji_trumpet" = "Trąbka";
|
||||
"device_verification_emoji_bell" = "Dzwon";
|
||||
"device_verification_emoji_anchor" = "Kotwica";
|
||||
"device_verification_emoji_headphones" = "Słuchawki";
|
||||
"device_verification_emoji_folder" = "Folder";
|
||||
"device_verification_emoji_pin" = "Przypnij";
|
||||
// MARK: File upload
|
||||
"file_upload_error_title" = "Wyślij plik";
|
||||
"file_upload_error_unsupported_file_type_message" = "Typ pliku nie jest wspierany.";
|
||||
// MARK: Emoji picker
|
||||
"emoji_picker_title" = "Reakcje";
|
||||
"emoji_picker_people_category" = "Emotikony i ludzie";
|
||||
"emoji_picker_nature_category" = "Zwierzęta i przyroda";
|
||||
"emoji_picker_foods_category" = "Jedzenie i picie";
|
||||
"emoji_picker_activity_category" = "Aktywności";
|
||||
"emoji_picker_places_category" = "Podróże i miejsca";
|
||||
"emoji_picker_objects_category" = "Obiekty";
|
||||
"emoji_picker_symbols_category" = "Symbole";
|
||||
"emoji_picker_flags_category" = "Flagi";
|
||||
// MARK: Reaction history
|
||||
"reaction_history_title" = "Reakcje";
|
||||
"auth_forgot_password_error_no_configured_identity_server" = "Brak skonfigurowanego serwera tożsamości: dodaj serwer tożsamości, aby zresetować hasło.";
|
||||
"auth_softlogout_signed_out" = "Zostałeś wylogowany";
|
||||
"auth_softlogout_reason" = "Administrator serwera domowego (%1$@) wylogował Cię z Twojego konta %2$@ (%3$@).";
|
||||
"auth_softlogout_recover_encryption_keys" = "Zaloguj się aby odzyskać klucze szyfrujące zapisane na tym urządzeniu. Potrzebujesz ich aby odczytać wszystkie swoje zaszyfrowane wiadomości na którymkolwiek z Twoich urządzeń.";
|
||||
"auth_softlogout_clear_data" = "Wyczyść prywatne dane";
|
||||
"auth_softlogout_clear_data_message_1" = "Uwaga: Twoje prywatne dane (z uwzględnieniem kluczy szyfrujących) nadal znajdują się na tym urządzeniu.";
|
||||
"auth_softlogout_clear_data_message_2" = "Wyczyść je, jeżeli nie będziesz już używać tego urządzenia, lub jeśli planujesz zalogować się na inne konto.";
|
||||
"auth_softlogout_clear_data_sign_out_title" = "Czy jesteś pewien?";
|
||||
"auth_softlogout_clear_data_sign_out_msg" = "Czy napewno chcesz wyczyścić wszystkie dane znajdujące się na tym urządzeniu? Zaloguj się ponownie, aby mieć dostęp do swojego konta, oraz wiadomości.";
|
||||
"room_creation_error_invite_user_by_email_without_identity_server" = "Serwer tożsamości nie został skonfigurowany, więc nie możesz dodać uczestnika przy użyciu adresu email.";
|
||||
"room_participants_remove_third_party_invite_msg" = "Usuwanie zaproszeń nie jest wspierane przez obecną wersję API";
|
||||
"room_participants_invited_section" = "ZAPROSZENI";
|
||||
"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Serwer tożsamości nie został skonfigurowany, więc nie możesz rozpocząć rozmowy używając adresu email.";
|
||||
"room_message_unable_open_link_error_message" = "Nie udało się otworzyć adresu.";
|
||||
"room_conference_call_no_power" = "Potrzebujesz uprawnień, aby zarządzać połączeniami konferencyjnymi w tym pokoju";
|
||||
"room_event_action_reaction_history" = "Historia reakcji";
|
||||
"room_action_camera" = "Zrób zdjęcie lub nagraj wideo";
|
||||
"settings_config_no_build_info" = "Brak informacji o buildzie";
|
||||
"settings_labs_message_reaction" = "Odpowiadaj na wiadomości używając emoji";
|
||||
"settings_key_backup_info" = "Zaszyfrowane wiadomości są zabezpieczone przy użyciu szyfrowania end-to-end. Tylko Ty oraz ich adresaci posiadają klucze do ich rozszyfrowania.";
|
||||
"settings_key_backup_info_none" = "Twoje klucze z tego urządzenia nie posiadają kopii zapasowej.";
|
||||
"settings_key_backup_info_signout_warning" = "Podłącz to urządzenie do klucza kopii zapasowej przed wylogowaniem się, aby nie utracić kluczy, które dostępne są tylko na tym urządzeniu.";
|
||||
"settings_key_backup_info_valid" = "Kopia zapasowa twoich kluczy jest tworzona.";
|
||||
"settings_key_backup_info_trust_signature_unknown" = "Kopia zapasowa posiada podpis urządzenia o ID: %@";
|
||||
"settings_key_backup_info_trust_signature_valid" = "Kopia zapasowa posiada prawidłowy podpis tego urządzenia";
|
||||
"settings_key_backup_info_trust_signature_valid_device_verified" = "Kopia zapasowa posiada prawidłowy podpis urządzenia %@";
|
||||
"settings_key_backup_info_trust_signature_valid_device_unverified" = "Kopia zapasowa posiada podpis urządzenia %@";
|
||||
"settings_key_backup_info_trust_signature_invalid_device_verified" = "Kopia zapasowa posiada nieprawidłowy podpis urządzenia %@";
|
||||
"settings_key_backup_info_trust_signature_invalid_device_unverified" = "Kopia zapasowa posiada nieprawidłowy podpis urządzenia %@";
|
||||
"settings_key_backup_button_connect" = "Podłącz to urządzenie do kopii zapasowej kluczy";
|
||||
"settings_key_backup_delete_confirmation_prompt_msg" = "Czy jesteś pewien? Stracisz dostęp do wszystkich swoich zaszyfrowanych wiadomości, jeżeli nie utworzyłeś poprawnej kopii zapasowej kluczy.";
|
||||
"room_details_access_section" = "Kto może dołączyć do pokoju?";
|
||||
"room_details_history_section_prompt_msg" = "Zmiany dostępu do historii będą miały zastosowanie tylko do przyszłych wiadomości w tym pokoju. Widoczność obecnych wiadomości pozostanie bez zmian.";
|
||||
"settings_key_backup_info_not_valid" = "To urządzenie nie tworzy kopii zapasowej Twoich kluczy. Ciągle jednak masz istniejącą kopię zapasową, którą możesz przywrócić i w przyszłości uzupełnić.";
|
||||
"room_details_addresses_disable_main_address_prompt_title" = "Główny adres ostrzega";
|
||||
"room_details_addresses_disable_main_address_prompt_msg" = "Nie masz adresu głównego. Domyślny główny adres zostanie wybrany losowo";
|
||||
"room_details_flair_section" = "Pokaż talent społecznościom";
|
||||
"room_details_flair_invalid_id_prompt_msg" = "%@ nie jest prawidłowym identyfikatorem społeczności";
|
||||
"group_participants_leave_prompt_msg" = "Czy jesteś pewien, że chcesz opuścić te grupę?";
|
||||
"group_participants_remove_prompt_msg" = "Czy jesteś pewien, że chcesz usunąć %@ z tej grupy?";
|
||||
"group_participants_invite_prompt_msg" = "Czy jesteś pewien, że chcesz zaprosić %@ do tej grupy?";
|
||||
"group_participants_invite_malformed_id_title" = "Błąd. Nie udało się zaprosić";
|
||||
"group_participants_invited_section" = "ZAPROSZONY";
|
||||
"receipt_status_read" = "Czytaj: ";
|
||||
// Media picker
|
||||
"media_picker_title" = "Selektor mediów";
|
||||
// Image picker
|
||||
"image_picker_action_camera" = "Zrób zdjęcie";
|
||||
"image_picker_action_library" = "Wybierz z biblioteki";
|
||||
"directory_server_all_native_rooms" = "Wszystkie rodzime pokoje Matrix";
|
||||
// Events formatter
|
||||
"event_formatter_member_updates" = "%tu zmiany członkostwa";
|
||||
"event_formatter_jitsi_widget_added" = "Konferencja VoIP dodana przez %@";
|
||||
"event_formatter_jitsi_widget_removed" = "Konferencja VoIP usunięta przez %@";
|
||||
"event_formatter_message_edited_mention" = "(edytowano)";
|
||||
"network_offline_prompt" = "Wygląda na to, że nie masz połączenia z internetem.";
|
||||
"homeserver_connection_lost" = "Nie można połączyć się z serwerem domowym.";
|
||||
"public_room_section_title" = "Pokoje Publiczne (na %@):";
|
||||
"bug_report_prompt" = "Poprzednio aplikacja uległa awarii. Czy chcesz wysłać raport?";
|
||||
"rage_shake_prompt" = "Zauważyliśmy, że potrząsasz telefonem (czyżby ze zdenerwowania?). Chciałbyś nam zgłosić jakiś problem?";
|
||||
"camera_access_not_granted" = "%@ nie ma uprawnień do korzystania z aparatu, zmień ustawienia w ustawieniach prywatności";
|
||||
"camera_unavailable" = "Aparat jest niedostępny na Twoim urządzeniu";
|
||||
"photo_library_access_not_granted" = "%@ nie ma uprawnień dostępu do biblioteki zdjęć, możesz to zmienić w ustawieniach prywatności";
|
||||
"room_does_not_exist" = "%@ nie istnieje";
|
||||
"call_already_displayed" = "Rozmowa tutaj już trwa.";
|
||||
"call_jitsi_error" = "Nie udało się dołączyć do rozmowy konferencyjnej.";
|
||||
"no_voip" = "%@ dzwoni do Ciebie ale %@ nie obsługuje jeszcze połączeń\nMożesz zignorować to powiadomienie i odebrać rozmowę na innym urządzeniu, bądź odrzucić je.";
|
||||
// Crash report
|
||||
"google_analytics_use_prompt" = "Chcesz pomóc nam w ulepszaniu %@ przez automatyczne wysyłanie anonimowych raportów o błędach i danych użytkowania?";
|
||||
// Key backup wrong version
|
||||
"e2e_key_backup_wrong_version_title" = "Nowy Klucz Kopii Zapasowej";
|
||||
"room_participants_remove_third_party_invite_prompt_msg" = "Czy jesteś pewien, że chcesz odrzucić to zaproszenie?";
|
||||
"e2e_key_backup_wrong_version" = "Wykryto nową wiadomość z kluczem zabezpieczeń. \nJeżeli to nie Ty - Prosimy, abyś zmienił swoje hasło w ustawieniach.";
|
||||
"e2e_key_backup_wrong_version_button_settings" = "Ustawienia";
|
||||
"e2e_key_backup_wrong_version_button_wasme" = "To ja";
|
||||
"bug_report_description" = "Proszę opisać błąd. Co zrobiłeś? Co miało się stać? Co się stało?";
|
||||
"bug_crash_report_description" = "Opisz, co zrobiłeś przed awarią:";
|
||||
// Widget
|
||||
"widget_no_integrations_server_configured" = "Nie skonfigurowano serwera integracji";
|
||||
"widget_integrations_server_failed_to_connect" = "Błąd łączenia z serwerem integracji";
|
||||
// Share extension
|
||||
"share_extension_auth_prompt" = "Zaloguj się do głównej aplikacji, aby udostępniać zawartość";
|
||||
"share_extension_failed_to_encrypt" = "Nie udało się wysłać. Sprawdź w głównej aplikacji ustawienia szyfrowania dla tego pokoju";
|
||||
// Service terms
|
||||
"service_terms_modal_title" = "Warunki usługi";
|
||||
"service_terms_modal_message" = "Aby kontynuować musisz zaakceptować Warunki Usługi.";
|
||||
"service_terms_modal_accept_button" = "Akceptuj";
|
||||
"service_terms_modal_description_for_identity_server" = "Być wykrywalnym dla innych";
|
||||
"service_terms_modal_description_for_integration_manager" = "Używaj Botów, mostków, widżetów i naklejek";
|
||||
"key_backup_setup_title" = "Klucz kopii zapasowej";
|
||||
"key_backup_setup_skip_alert_title" = "Jesteś pewien?";
|
||||
"key_backup_setup_skip_alert_message" = "Możesz stracić wiadomości bezpieczeństwa, jeżeli wylogujesz się z, bądź stracisz swoje urządzenie.";
|
||||
"key_backup_setup_skip_alert_skip_action" = "Pomiń";
|
||||
"key_backup_setup_intro_title" = "Nigdy nie trać zaszyfrowanych wiadomości";
|
||||
"key_backup_setup_intro_info" = "Wiadomości w szyfrowanym pokoju są zabezpieczone przez end-to-end. Tylko Ty i rozmówca macie klucze, aby odczytać te wiadomości.\nWykonaj kopię zapasową kluczy, aby ich nie zgubić.";
|
||||
|
|
|
@ -685,3 +685,146 @@
|
|||
"room_action_reply" = "Ответ";
|
||||
"settings_labs_message_reaction" = "Реагировать на сообщения с Emoji";
|
||||
"settings_key_backup_button_connect" = "Подключите это устройство к ключу резервного копирования";
|
||||
"close" = "Закрыть";
|
||||
"auth_forgot_password_error_no_configured_identity_server" = "Сервер идентификации не настроен: добавьте один для сброса пароля.";
|
||||
"auth_softlogout_signed_out" = "Вы вышли";
|
||||
"auth_softlogout_sign_in" = "Войти";
|
||||
"auth_softlogout_clear_data" = "Очистить личные данные";
|
||||
"auth_softlogout_clear_data_button" = "Очистить все данные";
|
||||
"auth_softlogout_clear_data_sign_out_title" = "Вы уверены?";
|
||||
"auth_softlogout_clear_data_sign_out" = "Выйти";
|
||||
"room_event_action_reaction_show_all" = "Показать все";
|
||||
"room_event_action_reaction_show_less" = "Свернуть";
|
||||
"room_event_action_reaction_history" = "История реакций";
|
||||
"room_action_camera" = "Записать фото или видео";
|
||||
"room_action_send_file" = "Отправить файл";
|
||||
"room_message_edits_history_title" = "Редактирование сообщений";
|
||||
// Media picker
|
||||
"media_picker_title" = "Медиатека";
|
||||
// Image picker
|
||||
"image_picker_action_camera" = "Сфотографировать";
|
||||
"image_picker_action_library" = "Выбрать из библиотеки";
|
||||
"event_formatter_message_edited_mention" = "(отредактированный)";
|
||||
"widget_integrations_server_failed_to_connect" = "Не удалось подключиться к серверу интеграции";
|
||||
// Service terms
|
||||
"service_terms_modal_title" = "Условия пользования";
|
||||
"service_terms_modal_message" = "Для продолжения Вам необходимо принять Условия данного сервиса.";
|
||||
"service_terms_modal_accept_button" = "Принять";
|
||||
"service_terms_modal_description_for_identity_server" = "Быть открытыми для других";
|
||||
"service_terms_modal_description_for_integration_manager" = "Используйте боты, мосты, виджеты и стикеры";
|
||||
"key_backup_setup_intro_setup_connect_action_with_existing_backup" = "Подключите это устройство к Key Backup";
|
||||
// MARK: - Device Verification
|
||||
"device_verification_title" = "Проверьте устройство";
|
||||
"auth_softlogout_reason" = "Ваш домашний сервер (%1$@) админ выписал вас из вашей учетной записи %2$@ (%3$@).";
|
||||
"auth_softlogout_recover_encryption_keys" = "Войдите, чтобы восстановить ключи шифрования, хранящиеся исключительно на этом устройстве. Они нужны вам для чтения всех ваших защищенных сообщений на любом устройстве.";
|
||||
"auth_softlogout_clear_data_message_1" = "Внимание: Ваши личные данные (включая ключи шифрования) все еще хранятся на этом устройстве.";
|
||||
"auth_softlogout_clear_data_message_2" = "Очистите его, если вы закончили использовать это устройство или хотите войти в другую учетную запись.";
|
||||
"auth_softlogout_clear_data_sign_out_msg" = "Вы уверены, что хотите удалить все данные, хранящиеся в данный момент на этом устройстве? Войдите снова, чтобы получить доступ к данным и сообщениям вашей учетной записи.";
|
||||
// Errors
|
||||
"error_user_already_logged_in" = "Похоже, вы пытаетесь подключиться к другому серверу. Вы хотите выйти?";
|
||||
"room_creation_error_invite_user_by_email_without_identity_server" = "Сервер идентификации не настроен, поэтому вы не можете добавить участника с электронной почтой.";
|
||||
"room_participants_remove_third_party_invite_prompt_msg" = "Вы уверены, что хотите отозвать это приглашение?";
|
||||
"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Сервер идентификации не настроен, поэтому вы не можете начать чат с контактом, используя электронную почту.";
|
||||
"camera_unavailable" = "Камера недоступна на вашем устройстве";
|
||||
"photo_library_access_not_granted" = "%@ не имеет доступа к библиотеке фотографий, измените настройки конфиденциальности";
|
||||
// Widget
|
||||
"widget_no_integrations_server_configured" = "Сервер интеграции не настроен";
|
||||
"key_backup_recover_connent_banner_subtitle" = "Подключите это устройство к функции резервного копирования ключей";
|
||||
"device_verification_security_advice" = "Для обеспечения максимальной безопасности мы рекомендуем делать это лично или использовать другие надежные средства связи";
|
||||
"device_verification_cancelled" = "Другая сторона отменила проверку.";
|
||||
"device_verification_cancelled_by_me" = "Проверка была отменена. Причина: %@";
|
||||
"device_verification_error_cannot_load_device" = "Невозможно загрузить информацию об устройстве.";
|
||||
// Mark: Incoming
|
||||
"device_verification_incoming_title" = "Входящий запрос на проверку";
|
||||
"device_verification_incoming_description_1" = "Проверьте это устройство, чтобы отметить его как доверенное. Доверительные устройства партнеров дают вам дополнительное спокойствие при использовании сообщений со сквозным шифрованием.";
|
||||
"device_verification_incoming_description_2" = "Убедитесь, что данное устройство является доверенным, а также проверьте, что оно доверено для вашего партнера.";
|
||||
// MARK: Start
|
||||
"device_verification_start_title" = "Проверьте, сравнив короткую текстовую строку";
|
||||
"device_verification_start_wait_partner" = "Ожидайте, пока партнер примет....";
|
||||
"device_verification_start_use_legacy" = "Ничего не появляется? Не все клиенты пока поддерживают интерактивную проверку. Используйте устаревшую проверку.";
|
||||
"device_verification_start_verify_button" = "Начать проверку";
|
||||
"device_verification_verify_wait_partner" = "Ожидайте, пока партнер подтвердит....";
|
||||
// MARK: Verified
|
||||
"device_verification_verified_title" = "Проверено!";
|
||||
"device_verification_verified_description_1" = "Вы успешно проверили это устройство.";
|
||||
"device_verification_verified_got_it_button" = "Понял";
|
||||
// MARK: Emoji
|
||||
"device_verification_emoji_dog" = "Собака";
|
||||
"device_verification_emoji_cat" = "Кот";
|
||||
"device_verification_emoji_lion" = "Лев";
|
||||
"device_verification_emoji_horse" = "Конь";
|
||||
"device_verification_emoji_unicorn" = "Единорог";
|
||||
"device_verification_emoji_pig" = "Хрюша";
|
||||
"device_verification_emoji_elephant" = "Слон";
|
||||
"device_verification_emoji_rabbit" = "Кролик";
|
||||
"device_verification_emoji_panda" = "Панда";
|
||||
"device_verification_emoji_rooster" = "Петух";
|
||||
"device_verification_emoji_penguin" = "Пингвин";
|
||||
"device_verification_emoji_turtle" = "Черепаха";
|
||||
"device_verification_emoji_fish" = "Рыба";
|
||||
"device_verification_emoji_octopus" = "Осьминог";
|
||||
"device_verification_emoji_butterfly" = "Бабочка";
|
||||
"device_verification_emoji_flower" = "Цветок";
|
||||
"device_verification_emoji_tree" = "Дерево";
|
||||
"device_verification_emoji_cactus" = "Кактус";
|
||||
"device_verification_emoji_mushroom" = "Гриб";
|
||||
"device_verification_emoji_globe" = "Глобус";
|
||||
"device_verification_emoji_moon" = "Луна";
|
||||
"device_verification_emoji_cloud" = "Облако";
|
||||
"device_verification_emoji_fire" = "Огонь";
|
||||
"device_verification_emoji_banana" = "Банан";
|
||||
"device_verification_emoji_apple" = "Яблоко";
|
||||
"device_verification_emoji_strawberry" = "Клубника";
|
||||
"device_verification_emoji_corn" = "Кукуруза";
|
||||
"device_verification_emoji_pizza" = "Пицца";
|
||||
"device_verification_emoji_cake" = "Печенье";
|
||||
"device_verification_emoji_heart" = "Сердце";
|
||||
"device_verification_emoji_smiley" = "Улыбка";
|
||||
"device_verification_emoji_robot" = "Робот";
|
||||
"device_verification_emoji_hat" = "Шапка";
|
||||
"device_verification_emoji_glasses" = "Очки";
|
||||
"device_verification_emoji_spanner" = "Ключ";
|
||||
"device_verification_emoji_santa" = "Морозко";
|
||||
"device_verification_emoji_thumbs up" = "Палец вверх";
|
||||
"device_verification_emoji_umbrella" = "Зонт";
|
||||
"device_verification_emoji_hourglass" = "Песочные часы";
|
||||
"device_verification_emoji_clock" = "Часы";
|
||||
"device_verification_emoji_gift" = "Подарок";
|
||||
"device_verification_emoji_light bulb" = "Лампочка";
|
||||
"device_verification_emoji_book" = "Книга";
|
||||
"device_verification_emoji_pencil" = "Карандаш";
|
||||
"device_verification_emoji_paperclip" = "Скрепка";
|
||||
"device_verification_emoji_scissors" = "Ножницы";
|
||||
"device_verification_emoji_lock" = "Замок";
|
||||
"device_verification_emoji_key" = "Ключ";
|
||||
"device_verification_emoji_hammer" = "Молоток";
|
||||
"device_verification_emoji_telephone" = "Телефон";
|
||||
"device_verification_emoji_flag" = "Флаг";
|
||||
"device_verification_emoji_train" = "Поезд";
|
||||
"device_verification_emoji_bicycle" = "Велосипед";
|
||||
"device_verification_emoji_aeroplane" = "Самолет";
|
||||
"device_verification_emoji_rocket" = "Ракета";
|
||||
"device_verification_emoji_trophy" = "Кубок";
|
||||
"device_verification_emoji_ball" = "Мяч";
|
||||
"device_verification_emoji_guitar" = "Гитара";
|
||||
"device_verification_emoji_trumpet" = "Труба";
|
||||
"device_verification_emoji_bell" = "Колокольчик";
|
||||
"device_verification_emoji_anchor" = "Якорь";
|
||||
"device_verification_emoji_headphones" = "Наушники";
|
||||
"device_verification_emoji_folder" = "Папка";
|
||||
"device_verification_emoji_pin" = "Ручка";
|
||||
// MARK: File upload
|
||||
"file_upload_error_title" = "Файл загрузить";
|
||||
"file_upload_error_unsupported_file_type_message" = "Тип файла не поддерживается.";
|
||||
// MARK: Emoji picker
|
||||
"emoji_picker_title" = "Реакция";
|
||||
"emoji_picker_people_category" = "Смайлики & люди";
|
||||
"emoji_picker_nature_category" = "Животные & Природа";
|
||||
"emoji_picker_foods_category" = "Еда & напитки";
|
||||
"emoji_picker_activity_category" = "Aктивность";
|
||||
"emoji_picker_places_category" = "Путешествия & Места";
|
||||
"emoji_picker_objects_category" = "Объекты";
|
||||
"emoji_picker_symbols_category" = "Символы";
|
||||
"emoji_picker_flags_category" = "Флаги";
|
||||
// MARK: Reaction history
|
||||
"reaction_history_title" = "Реакции";
|
||||
|
|
|
@ -2,4 +2,5 @@
|
|||
"NSCameraUsageDescription" = "Kamera përdoret për të bërë foto dhe regjistruar video, dhe për të bërë thirrje video.";
|
||||
"NSPhotoLibraryUsageDescription" = "Fototeka përdoret për të dërguar foto dhe video.";
|
||||
"NSMicrophoneUsageDescription" = "Mikrofoni përdoret për të regjistruar video, dhe për të bërë thirrje.";
|
||||
"NSContactsUsageDescription" = "Që të mund t’ju shfaqim se cilët prej kontakteve tuaj përdorin tashmë Riot ose Matrix, mund të dërgojmë adresat email dhe numrat e telefonave nga libri juaj i adresave te Shërbyesi Matrix i Identiteteve. Vektori i ri nuk i depoziton këto të dhëna, as i përdor për ndonjë qëllim tjetër. Për më tepër të dhëna, shihni faqen e rregullave të privatësisë, te rregullimet e aplikacionit.";
|
||||
"NSContactsUsageDescription" = "Që të mund t’ju shfaqim se cilët prej kontakteve tuaj përdorin tashmë Riot ose Matrix, mund të dërgojmë adresat email dhe numrat e telefonave nga libri juaj i adresave te shërbyesi Matrix i identiteteve. Vektori i ri nuk i depoziton këto të dhëna, as i përdor për ndonjë qëllim tjetër. Për më tepër të dhëna, shihni faqen e rregullave të privatësisë, te rregullimet e aplikacionit.";
|
||||
"NSCalendarsUsageDescription" = "Shihini te aplikacioni takimet tuaja të planifikuara.";
|
||||
|
|
|
@ -746,7 +746,7 @@
|
|||
"device_verification_emoji_santa" = "Babagjyshi i Vitit të Ri";
|
||||
"device_verification_emoji_umbrella" = "Ombrellë";
|
||||
"device_verification_emoji_hourglass" = "Klepsidër";
|
||||
"device_verification_emoji_clock" = "Klasë";
|
||||
"device_verification_emoji_clock" = "Orë";
|
||||
"device_verification_emoji_gift" = "Dhuratë";
|
||||
"device_verification_emoji_light bulb" = "Llambë";
|
||||
"device_verification_emoji_book" = "Libër";
|
||||
|
@ -770,7 +770,7 @@
|
|||
"device_verification_emoji_anchor" = "Spirancë";
|
||||
"device_verification_emoji_headphones" = "Kufje";
|
||||
"device_verification_emoji_folder" = "Dosje";
|
||||
"event_formatter_message_edited_mention" = "(U përpunua)";
|
||||
"event_formatter_message_edited_mention" = "(u përpunua)";
|
||||
// Widget
|
||||
"widget_no_integrations_server_configured" = "S’ka të formësuar shërbyes integrimesh";
|
||||
"widget_integrations_server_failed_to_connect" = "S’u arrit të lidhej me shërbyes integrimesh";
|
||||
|
@ -778,3 +778,66 @@
|
|||
"room_event_action_reaction_show_all" = "Shfaqi krejt";
|
||||
"room_event_action_reaction_show_less" = "Shfaq më pak";
|
||||
"room_message_edits_history_title" = "Përpunime mesazhi";
|
||||
"auth_softlogout_signed_out" = "Keni bërë dalje";
|
||||
"auth_softlogout_sign_in" = "Hyni";
|
||||
"auth_softlogout_reason" = "Përgjegjësi i shërbyesit tuaj Home (%1$@) ka bërë daljen tuaj nga llogaria juaj %2$@ (%3$@).";
|
||||
"auth_softlogout_recover_encryption_keys" = "Bëni hyrjen, që të rimerrni kyçe fshehtëzimi të depozituar përjashtimisht në këtë pajisje. Do t’ju duhen për të lexuar krejt mesazhet tuaj të siguruar në çfarëdo pajisje.";
|
||||
"auth_softlogout_clear_data" = "Spastro të dhëna personale";
|
||||
"auth_softlogout_clear_data_message_1" = "Kujdes: Të dhënat tuaja personale (përfshi kyçe fshehtëzimi) janë ende të depozituara në këtë pajisje.";
|
||||
"auth_softlogout_clear_data_message_2" = "Spastrojini, nëse keni përfunduar së përdoruri këtë pajisje, ose dëshironi të hyni në një llogari tjetër.";
|
||||
"auth_softlogout_clear_data_button" = "Spastro krejt të dhënat";
|
||||
"auth_softlogout_clear_data_sign_out_title" = "Jeni i sigurt?";
|
||||
"auth_softlogout_clear_data_sign_out_msg" = "Jeni i sigurt se doni të spastrohen krejt të dhënat e depozituara në këtë pajisje? Që të mund të hyni te të dhëna të llogarisë tuaj dhe te mesazhe, bëni sërish hyrjen.";
|
||||
"auth_softlogout_clear_data_sign_out" = "Dilni";
|
||||
"room_event_action_reaction_history" = "Historik reagimesh";
|
||||
"room_action_camera" = "Bëni foto ose video";
|
||||
"room_action_send_file" = "Dërgoni kartelë";
|
||||
// Media picker
|
||||
"media_picker_title" = "Mediatekë";
|
||||
// Image picker
|
||||
"image_picker_action_camera" = "Bëni një foto";
|
||||
"image_picker_action_library" = "Zgjidhni prej biblioteke";
|
||||
"camera_unavailable" = "Kamera në pajisjen tuaj s’është e përdorshme";
|
||||
"photo_library_access_not_granted" = "%@ s’ka leje të hyjë në fototekë, ju lutemi, ndryshoni rregullimet e privatësisë";
|
||||
"device_verification_emoji_spanner" = "Çelës";
|
||||
"device_verification_emoji_lock" = "Dry";
|
||||
"device_verification_emoji_pin" = "Fiksoje";
|
||||
// MARK: File upload
|
||||
"file_upload_error_title" = "Ngarkim kartele";
|
||||
"file_upload_error_unsupported_file_type_message" = "Lloj i pambuluar kartele.";
|
||||
// MARK: Emoji picker
|
||||
"emoji_picker_title" = "Reagime";
|
||||
"emoji_picker_people_category" = "Emotikone & Njerëz";
|
||||
"emoji_picker_nature_category" = "Kafshë & Natyrë";
|
||||
"emoji_picker_foods_category" = "Ushqim & Pije";
|
||||
"emoji_picker_activity_category" = "Veprimtari";
|
||||
"emoji_picker_places_category" = "Udhëtim & Vende";
|
||||
"emoji_picker_objects_category" = "Objekte";
|
||||
"emoji_picker_symbols_category" = "Simbole";
|
||||
"emoji_picker_flags_category" = "Flamuj";
|
||||
// MARK: Reaction history
|
||||
"reaction_history_title" = "Reagime";
|
||||
"auth_forgot_password_error_no_configured_identity_server" = "S’ka shërbyes identitetesh të formësuar: shtoni një të tillë që të ricaktoni fjalëkalimin tuaj.";
|
||||
"room_creation_error_invite_user_by_email_without_identity_server" = "S’ka shërbyes identitetesh të formësua, ndaj s’mund të shtoni një pjesëmarrës me një email.";
|
||||
"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "S’ka shërbyes identitetesh të formësuar, ndaj s’mund të nisni një fjalosje me një kontakt duke përdorur një email.";
|
||||
// Service terms
|
||||
"service_terms_modal_title" = "Kushte Shërbimi";
|
||||
"service_terms_modal_message" = "Që të vazhdohet, lypset të pranoni Kushtet e këtij shërbimi.";
|
||||
"service_terms_modal_accept_button" = "Pranoji";
|
||||
"service_terms_modal_description_for_identity_server" = "Jini i zbulueshëm nga të tjerët";
|
||||
"service_terms_modal_description_for_integration_manager" = "Përdorni Robotë, ura, widget-e dhe paketa ngjitësish";
|
||||
"room_participants_remove_third_party_invite_prompt_msg" = "Jeni i sigurt se doni të shfuqizohet kjo ftesë?";
|
||||
// Errors
|
||||
"error_user_already_logged_in" = "Duket se po rrekeni të lidheni me një tjetër shërbyes Home. Doni të dilet nga llogaria?";
|
||||
"room_accessiblity_scroll_to_bottom" = "Rrëshqitni drejt fundit";
|
||||
"room_accessibility_search" = "Kërko";
|
||||
"room_accessibility_integrations" = "Integrime";
|
||||
"room_accessibility_upload" = "Ngarkoni";
|
||||
"room_accessibility_call" = "Thirrje";
|
||||
"room_accessibility_hangup" = "Mbylle";
|
||||
"media_type_accessibility_image" = "Figurë";
|
||||
"media_type_accessibility_audio" = "Audio";
|
||||
"media_type_accessibility_video" = "Video";
|
||||
"media_type_accessibility_location" = "Vendndodhje";
|
||||
"media_type_accessibility_file" = "Kartelë";
|
||||
"media_type_accessibility_sticker" = "Ngjitës";
|
||||
|
|
1
Riot/Assets/th.lproj/Localizable.strings
Normal file
1
Riot/Assets/th.lproj/Localizable.strings
Normal file
|
@ -0,0 +1 @@
|
|||
|
|
@ -2,5 +2,5 @@
|
|||
"NSCameraUsageDescription" = "De camera wor gebruukt vo fotootjes te trekkn en filmtjes te moakn, en vo videogesprekkn.";
|
||||
"NSPhotoLibraryUsageDescription" = "De fotogalerie wor gebruukt vo fotootjes en filmtjes te versteurn.";
|
||||
"NSMicrophoneUsageDescription" = "De microfoon wor gebruukt vo filmtjes te maken, en vo sproakiproepn.";
|
||||
"NSContactsUsageDescription" = "Vo je te kunn toogn dewelkse van je contactn dat al Riot of Matrix gebruukn, kunn we d’e-mailadressn en telefongnumero’s in jen adresboek noa je Matrix-identiteitsserver steurn. New Vector bewoart deze gegevens nie en gebruukt ze ook nie voor andere doeleindn. Bekykt vo meer informoatie de privacybeleidspagina in d’instelliengn van den app.";
|
||||
"NSContactsUsageDescription" = "Vo je te kunn toogn dewelkse van je contactn dat al Matrix gebruukn, kun Riot d’e-mailadressn en telefongnumero’s in jen adresboek noa je gekoozn Matrix-identiteitsserver steurn. Woar meuglik worden persoonlike gegeevns gehasht vo dan ze worden verzonden - bekyk ’t privacybeleid van jen identiteitsserver vo meer informoasje.";
|
||||
"NSCalendarsUsageDescription" = "Bekykt je geplande afsproakn in den app.";
|
||||
|
|
|
@ -10,3 +10,88 @@
|
|||
// Actions
|
||||
"view" = "Toogn";
|
||||
"next" = "Volgende";
|
||||
"store_full_description" = "Communiceert ip joun manier.\n\nE chat-app, onder joun controle en zeer flexibel. Riot lat je communiceern lyk of da je wilt. Gemakt vo [matrix] - de standoard voor open, gedecentraliseerde communicoasje.\n\nMakt e gratis account aan ip matrix.org, verkrygt jen eigen server ip https://modular.im, of gebruukt een andere Matrix-server.\n\nVowa zoun ’kik vo Riot.im kiezn?\n\n• VOLLEDIGE COMMUNICOASJE: makt gesprekkn an rond je teams, je moats, je gemeenschap - gelyk of da je gy ’t mo wilt! Chat, deelt bestandn, voegt widgets toe en makt stem- en video-iproepn - ollemoale volledig gratis.\n\n• KRACHTIGE INTEGROASJE: gebruukt Riot.im met de hulpmiddeln woamee da je vertrouwd zyt. Me Riot.im ku je zelfst chattn me gebrukers en groepn ip andere chat-apps.\n\n• PRIVÉ EN VEILIG: houdt je gesprekkn geheim. End-tout-end-versleuterienge van de bovenste plank zorgt dervoorn da je privécommunicoasje ook privé bluuft.\n\n• OPEN, NIE GESLOOTN: vrye software, gebouwd ip Matrix. Zy den boas over jen eigen gegeevns deur jen eigen server te gebruukn, of te kiezn voor een andere server da je vertrouwt.\n\n• WOA DA J’OOK ZYT: houdt contact woa da j’ook zyt me volledig gesynchroniseerde berichtgeschiedenisse ip al je toestelln, en online ip https://riot.im.";
|
||||
"back" = "Weere";
|
||||
"continue" = "Verdergoan";
|
||||
"create" = "Anmoakn";
|
||||
"start" = "Beginn";
|
||||
"leave" = "Verloatn";
|
||||
"remove" = "Verwydern";
|
||||
"invite" = "Uutnodign";
|
||||
"retry" = "Herprobeern";
|
||||
"on" = "An";
|
||||
"off" = "Uut";
|
||||
"cancel" = "Annuleern";
|
||||
"save" = "Ipsloan";
|
||||
"join" = "Toetreedn";
|
||||
"decline" = "Afwyzn";
|
||||
"accept" = "Anveirdn";
|
||||
"preview" = "Voorvertoogn";
|
||||
"camera" = "Camera";
|
||||
"voice" = "Sproak";
|
||||
"video" = "Video";
|
||||
"active_call" = "Iproep actief";
|
||||
"active_call_details" = "Iproep actief (%@)";
|
||||
"later" = "Later";
|
||||
"rename" = "Hernoemn";
|
||||
"collapse" = "toeplooin";
|
||||
"send_to" = "Stuurt noa %@";
|
||||
"sending" = "Wor versteurd";
|
||||
"close" = "Sluutn";
|
||||
// Authentication
|
||||
"auth_login" = "Anmeldn";
|
||||
"auth_register" = "Registreern";
|
||||
"auth_submit" = "Versteurn";
|
||||
"auth_skip" = "Oversloan";
|
||||
"auth_login_single_sign_on" = "Anmeldn met enkele anmeldienge";
|
||||
"auth_send_reset_email" = "Herstelmail versteurn";
|
||||
"auth_return_to_login" = "Weere noa ’t anmeldiengsscherm";
|
||||
"auth_user_id_placeholder" = "E-mailadresse of gebrukersnoame";
|
||||
"auth_password_placeholder" = "Paswoord";
|
||||
"auth_new_password_placeholder" = "Nieuw paswoord";
|
||||
"auth_user_name_placeholder" = "Gebrukersnoame";
|
||||
"auth_optional_email_placeholder" = "E-mailadresse (optioneel)";
|
||||
"auth_email_placeholder" = "E-mailadresse";
|
||||
"auth_optional_phone_placeholder" = "Telefongnumero (optioneel)";
|
||||
"auth_phone_placeholder" = "Telefongnumero";
|
||||
"auth_repeat_password_placeholder" = "Paswoord herhoaln";
|
||||
"auth_repeat_new_password_placeholder" = "Bevestigt je nieuw paswoord";
|
||||
"auth_home_server_placeholder" = "URL (bv. https://matrix.org)";
|
||||
"auth_identity_server_placeholder" = "URL (bv. https://matrix.org)";
|
||||
"auth_invalid_login_param" = "Verkeerd(e) gebrukersnoame en/of paswoord";
|
||||
"auth_invalid_user_name" = "Gebrukersnoamn meugn alleene mo letters, cyfers, puntn, koppelteekns en underscores bevattn";
|
||||
"auth_invalid_password" = "’t Paswoord is te kort (min 6)";
|
||||
"auth_invalid_email" = "Da ziet der hier nie uut gelyk e geldig e-mailadresse";
|
||||
"auth_invalid_phone" = "Da ziet der hier nie uut gelyk e geldige telefongnumero";
|
||||
"auth_missing_password" = "Paswoord mankeert";
|
||||
"auth_add_email_message" = "Voegt een e-mailadresse toe an jen account zoda gebrukers je kunn viendn en zoda je je paswoord kut herstelln.";
|
||||
"auth_add_phone_message" = "Voegt e telefongnumero toe an jen account zoda gebrukers je kunn viendn.";
|
||||
"auth_add_email_phone_message" = "Voegt een e-mailadresse en/of e telefongnumero toe an jen account zoda gebrukers je kunn viendn. Jen e-mailadresse mak et ook meuglik van je paswoord t’herstelln.";
|
||||
"auth_add_email_and_phone_message" = "Voegt een e-mailadresse en e telefongnumero toe an jen account zoda gebrukers je kunn viendn. Jen e-mailadresse mak et ook meuglik van je paswoord t’herstelln.";
|
||||
"auth_missing_email" = "E-mailadresse mankeert";
|
||||
"auth_missing_phone" = "Telefongnumero mankeert";
|
||||
"auth_missing_email_or_phone" = "E-mailadresse of telefongnumero mankeert";
|
||||
"auth_email_in_use" = "Dat e-mailadresse hier is al in gebruuk";
|
||||
"auth_phone_in_use" = "Dien telefongnumero hier is al in gebruuk";
|
||||
"auth_untrusted_id_server" = "Den identiteitsserver is nie vertrouwd";
|
||||
"auth_password_dont_match" = "De paswoordn kommn nie overeen";
|
||||
"auth_username_in_use" = "De gebrukersnoame is al in gebruuk";
|
||||
"auth_forgot_password" = "Paswoord vergeetn?";
|
||||
"auth_forgot_password_error_no_configured_identity_server" = "’t Is genen identiteitsserver geconfigureerd gewist: voegt der enen toe vo je paswoord herin te stelln.";
|
||||
"auth_email_not_found" = "E-mail versteurn mislukt: dat e-mailadresse is hier nie gevoundn";
|
||||
"auth_use_server_options" = "Angepaste serverinstelliengn gebruukn (geavanceerd)";
|
||||
"auth_email_validation_message" = "Bekykt jen e-mail vo vorts te goan me de registroasje";
|
||||
"auth_msisdn_validation_title" = "Verificoasje in afwachtienge";
|
||||
"auth_msisdn_validation_message" = "M’èn een smse met een activoasjecode gesteurd ghed. Voert die code hieroundern in.";
|
||||
"auth_msisdn_validation_error" = "Kostege den telefongnumero nie verifieern.";
|
||||
"auth_recaptcha_message" = "Dezen thuusserver wilt der geern zeker van zyn da je gy geen robot zyt";
|
||||
"auth_reset_password_message" = "Gif ’t e-mailadresse da me jen account verbondn is in vo je paswoord herin te stelln:";
|
||||
"auth_reset_password_missing_email" = "’t E-mailadresse da men jen account verbondn is moet ingegeevn wordn.";
|
||||
"auth_reset_password_missing_password" = "’t Moet e nieuw paswoord ingegeevn wordn.";
|
||||
"auth_reset_password_email_validation_message" = "’t Is een e-mail noa %@ gesteurd gewist. Klikt hierounder van zodra da je de koppelienge derin geopend ghed èt.";
|
||||
"auth_reset_password_next_step_button" = "’k Èn ik m’n e-mailadresse geverifieerd";
|
||||
"auth_reset_password_error_unauthorized" = "Verifieern van ’t e-mailadresse is mislukt: zorgt da j’ip de koppelienge in den e-mail geklikt ghed èt";
|
||||
"auth_reset_password_error_not_found" = "’t Ziet der nie noar uut da jen e-mailadresse met e Matrix-ID ip dezen thuusserver is verboundn.";
|
||||
"auth_reset_password_success_message" = "Je paswoord is heringesteld gewist.\n\nJe zy nu ip alle toestelln afgemeld en je goa geen pushmeldiengn nie mi ontvangn. Vo meldiengn herin te schoakeln, meld je jen ip ieder toestel heran.";
|
||||
"auth_softlogout_signed_out" = "Je zyt afgemeld";
|
||||
"auth_softlogout_sign_in" = "Anmeldn";
|
||||
|
|
|
@ -39,6 +39,7 @@ internal enum RiotDefaults {
|
|||
internal static let showRedactionsInRoomHistory: Bool = _document["showRedactionsInRoomHistory"]
|
||||
internal static let showUnsupportedEventsInRoomHistory: Bool = _document["showUnsupportedEventsInRoomHistory"]
|
||||
internal static let sortRoomMembersUsingLastSeenTime: Bool = _document["sortRoomMembersUsingLastSeenTime"]
|
||||
internal static let stunServerFallback: String = _document["stunServerFallback"]
|
||||
internal static let syncLocalContacts: Bool = _document["syncLocalContacts"]
|
||||
internal static let webAppUrl: String = _document["webAppUrl"]
|
||||
internal static let webAppUrlBeta: String = _document["webAppUrlBeta"]
|
||||
|
|
|
@ -92,6 +92,21 @@ internal enum StoryboardScene {
|
|||
|
||||
internal static let initialScene = InitialSceneType<Riot.RoomContextualMenuViewController>(storyboard: RoomContextualMenuViewController.self)
|
||||
}
|
||||
internal enum ServiceTermsModalScreenViewController: StoryboardType {
|
||||
internal static let storyboardName = "ServiceTermsModalScreenViewController"
|
||||
|
||||
internal static let initialScene = InitialSceneType<Riot.ServiceTermsModalScreenViewController>(storyboard: ServiceTermsModalScreenViewController.self)
|
||||
}
|
||||
internal enum SettingsDiscoveryThreePidDetailsViewController: StoryboardType {
|
||||
internal static let storyboardName = "SettingsDiscoveryThreePidDetailsViewController"
|
||||
|
||||
internal static let initialScene = InitialSceneType<Riot.SettingsDiscoveryThreePidDetailsViewController>(storyboard: SettingsDiscoveryThreePidDetailsViewController.self)
|
||||
}
|
||||
internal enum SettingsIdentityServerViewController: StoryboardType {
|
||||
internal static let storyboardName = "SettingsIdentityServerViewController"
|
||||
|
||||
internal static let initialScene = InitialSceneType<Riot.SettingsIdentityServerViewController>(storyboard: SettingsIdentityServerViewController.self)
|
||||
}
|
||||
internal enum SimpleScreenTemplateViewController: StoryboardType {
|
||||
internal static let storyboardName = "SimpleScreenTemplateViewController"
|
||||
|
||||
|
|
|
@ -30,25 +30,21 @@ internal enum VectorL10n {
|
|||
internal static var authAcceptPolicies: String {
|
||||
return VectorL10n.tr("Vector", "auth_accept_policies")
|
||||
}
|
||||
/// Add an email address and a phone number to your account to let users discover you. Email address will also let you reset your password.
|
||||
internal static var authAddEmailAndPhoneMessage: String {
|
||||
return VectorL10n.tr("Vector", "auth_add_email_and_phone_message")
|
||||
}
|
||||
/// Registration with email and phone number at once is not supported yet until the api exists. Only the phone number will be taken into account. You may add your email to your profile in settings.
|
||||
internal static var authAddEmailAndPhoneWarning: String {
|
||||
return VectorL10n.tr("Vector", "auth_add_email_and_phone_warning")
|
||||
}
|
||||
/// Add an email address to your account to let users discover you, and to reset your password.
|
||||
internal static var authAddEmailMessage: String {
|
||||
return VectorL10n.tr("Vector", "auth_add_email_message")
|
||||
/// Set an email for account recovery, and later to be optionally discoverable by people who know you.
|
||||
internal static var authAddEmailMessage2: String {
|
||||
return VectorL10n.tr("Vector", "auth_add_email_message_2")
|
||||
}
|
||||
/// Add an email address and/or a phone number to your account to let users discover you. Email address will also let you reset your password.
|
||||
internal static var authAddEmailPhoneMessage: String {
|
||||
return VectorL10n.tr("Vector", "auth_add_email_phone_message")
|
||||
/// Set an email for account recovery. Use later email or phone to be optionally discoverable by people who know you.
|
||||
internal static var authAddEmailPhoneMessage2: String {
|
||||
return VectorL10n.tr("Vector", "auth_add_email_phone_message_2")
|
||||
}
|
||||
/// Add a phone number to your account to let users discover you.
|
||||
internal static var authAddPhoneMessage: String {
|
||||
return VectorL10n.tr("Vector", "auth_add_phone_message")
|
||||
/// Set a phone, and later to be optionally discoverable by people who know you.
|
||||
internal static var authAddPhoneMessage2: String {
|
||||
return VectorL10n.tr("Vector", "auth_add_phone_message_2")
|
||||
}
|
||||
/// Invalid homeserver discovery response
|
||||
internal static var authAutodiscoverInvalidResponse: String {
|
||||
|
@ -58,6 +54,10 @@ internal enum VectorL10n {
|
|||
internal static var authEmailInUse: String {
|
||||
return VectorL10n.tr("Vector", "auth_email_in_use")
|
||||
}
|
||||
/// No identity server is configured so you cannot add an email address in order to reset your password in the future.
|
||||
internal static var authEmailIsRequired: String {
|
||||
return VectorL10n.tr("Vector", "auth_email_is_required")
|
||||
}
|
||||
/// Failed to send email: This email address was not found
|
||||
internal static var authEmailNotFound: String {
|
||||
return VectorL10n.tr("Vector", "auth_email_not_found")
|
||||
|
@ -74,11 +74,15 @@ internal enum VectorL10n {
|
|||
internal static var authForgotPassword: String {
|
||||
return VectorL10n.tr("Vector", "auth_forgot_password")
|
||||
}
|
||||
/// No identity server is configured: add one to reset your password.
|
||||
internal static var authForgotPasswordErrorNoConfiguredIdentityServer: String {
|
||||
return VectorL10n.tr("Vector", "auth_forgot_password_error_no_configured_identity_server")
|
||||
}
|
||||
/// URL (e.g. https://matrix.org)
|
||||
internal static var authHomeServerPlaceholder: String {
|
||||
return VectorL10n.tr("Vector", "auth_home_server_placeholder")
|
||||
}
|
||||
/// URL (e.g. https://matrix.org)
|
||||
/// URL (e.g. https://vector.im)
|
||||
internal static var authIdentityServerPlaceholder: String {
|
||||
return VectorL10n.tr("Vector", "auth_identity_server_placeholder")
|
||||
}
|
||||
|
@ -162,6 +166,10 @@ internal enum VectorL10n {
|
|||
internal static var authPhoneInUse: String {
|
||||
return VectorL10n.tr("Vector", "auth_phone_in_use")
|
||||
}
|
||||
/// No identity server is configured so you cannot add a phone number in order to reset your password in the future.
|
||||
internal static var authPhoneIsRequired: String {
|
||||
return VectorL10n.tr("Vector", "auth_phone_is_required")
|
||||
}
|
||||
/// Phone number
|
||||
internal static var authPhonePlaceholder: String {
|
||||
return VectorL10n.tr("Vector", "auth_phone_placeholder")
|
||||
|
@ -186,6 +194,10 @@ internal enum VectorL10n {
|
|||
internal static func authResetPasswordEmailValidationMessage(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "auth_reset_password_email_validation_message", p1)
|
||||
}
|
||||
/// No identity server is configured: add one in server options to reset your password.
|
||||
internal static var authResetPasswordErrorIsRequired: String {
|
||||
return VectorL10n.tr("Vector", "auth_reset_password_error_is_required")
|
||||
}
|
||||
/// Your email address does not appear to be associated with a Matrix ID on this homeserver.
|
||||
internal static var authResetPasswordErrorNotFound: String {
|
||||
return VectorL10n.tr("Vector", "auth_reset_password_error_not_found")
|
||||
|
@ -366,6 +378,22 @@ internal enum VectorL10n {
|
|||
internal static var callJitsiError: String {
|
||||
return VectorL10n.tr("Vector", "call_jitsi_error")
|
||||
}
|
||||
/// Please ask the administrator of your homeserver %@ to configure a TURN server in order for calls to work reliably.
|
||||
internal static func callNoStunServerErrorMessage1(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "call_no_stun_server_error_message_1", p1)
|
||||
}
|
||||
/// Alternatively, you can try to use the public server at %@, but this will not be as reliable, and it will share your IP address with that server. You can also manage this in Settings
|
||||
internal static func callNoStunServerErrorMessage2(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "call_no_stun_server_error_message_2", p1)
|
||||
}
|
||||
/// Call failed due to misconfigured server
|
||||
internal static var callNoStunServerErrorTitle: String {
|
||||
return VectorL10n.tr("Vector", "call_no_stun_server_error_title")
|
||||
}
|
||||
/// Try using %@
|
||||
internal static func callNoStunServerErrorUseFallbackButton(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "call_no_stun_server_error_use_fallback_button", p1)
|
||||
}
|
||||
/// Camera
|
||||
internal static var camera: String {
|
||||
return VectorL10n.tr("Vector", "camera")
|
||||
|
@ -398,6 +426,10 @@ internal enum VectorL10n {
|
|||
internal static var contactsAddressBookNoContact: String {
|
||||
return VectorL10n.tr("Vector", "contacts_address_book_no_contact")
|
||||
}
|
||||
/// No identity server configured
|
||||
internal static var contactsAddressBookNoIdentityServer: String {
|
||||
return VectorL10n.tr("Vector", "contacts_address_book_no_identity_server")
|
||||
}
|
||||
/// You didn't allow Riot to access your local contacts
|
||||
internal static var contactsAddressBookPermissionDenied: String {
|
||||
return VectorL10n.tr("Vector", "contacts_address_book_permission_denied")
|
||||
|
@ -962,6 +994,10 @@ internal enum VectorL10n {
|
|||
internal static var encryptedRoomMessageReplyToPlaceholder: String {
|
||||
return VectorL10n.tr("Vector", "encrypted_room_message_reply_to_placeholder")
|
||||
}
|
||||
/// Add an identity server in your settings to invite by email.
|
||||
internal static var errorInvite3pidWithNoIdentityServer: String {
|
||||
return VectorL10n.tr("Vector", "error_invite_3pid_with_no_identity_server")
|
||||
}
|
||||
/// It looks like you’re trying to connect to another homeserver. Do you want to sign out?
|
||||
internal static var errorUserAlreadyLoggedIn: String {
|
||||
return VectorL10n.tr("Vector", "error_user_already_logged_in")
|
||||
|
@ -1118,6 +1154,82 @@ internal enum VectorL10n {
|
|||
internal static var homeserverConnectionLost: String {
|
||||
return VectorL10n.tr("Vector", "homeserver_connection_lost")
|
||||
}
|
||||
/// Add
|
||||
internal static var identityServerSettingsAdd: String {
|
||||
return VectorL10n.tr("Vector", "identity_server_settings_add")
|
||||
}
|
||||
/// Disconnect from the identity server %1$@ and connect to %2$@ instead?
|
||||
internal static func identityServerSettingsAlertChange(_ p1: String, _ p2: String) -> String {
|
||||
return VectorL10n.tr("Vector", "identity_server_settings_alert_change", p1, p2)
|
||||
}
|
||||
/// Change identity server
|
||||
internal static var identityServerSettingsAlertChangeTitle: String {
|
||||
return VectorL10n.tr("Vector", "identity_server_settings_alert_change_title")
|
||||
}
|
||||
/// Disconnect from the identity server %@?
|
||||
internal static func identityServerSettingsAlertDisconnect(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "identity_server_settings_alert_disconnect", p1)
|
||||
}
|
||||
/// Disconnect
|
||||
internal static var identityServerSettingsAlertDisconnectButton: String {
|
||||
return VectorL10n.tr("Vector", "identity_server_settings_alert_disconnect_button")
|
||||
}
|
||||
/// You are still sharing your personal data on the identity server %@.\n\nWe recommend that you remove your email addresses and phone numbers from the identity server before disconnecting.
|
||||
internal static func identityServerSettingsAlertDisconnectStillSharing3pid(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "identity_server_settings_alert_disconnect_still_sharing_3pid", p1)
|
||||
}
|
||||
/// Disconnect anyway
|
||||
internal static var identityServerSettingsAlertDisconnectStillSharing3pidButton: String {
|
||||
return VectorL10n.tr("Vector", "identity_server_settings_alert_disconnect_still_sharing_3pid_button")
|
||||
}
|
||||
/// Disconnect identity server
|
||||
internal static var identityServerSettingsAlertDisconnectTitle: String {
|
||||
return VectorL10n.tr("Vector", "identity_server_settings_alert_disconnect_title")
|
||||
}
|
||||
/// %@ is not a valid identity server.
|
||||
internal static func identityServerSettingsAlertErrorInvalidIdentityServer(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "identity_server_settings_alert_error_invalid_identity_server", p1)
|
||||
}
|
||||
/// You must accept terms of %@ to set it as identity server.
|
||||
internal static func identityServerSettingsAlertErrorTermsNotAccepted(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "identity_server_settings_alert_error_terms_not_accepted", p1)
|
||||
}
|
||||
/// The identity server you have chosen does not have any terms of service. Only continue if you trust the owner of the server.
|
||||
internal static var identityServerSettingsAlertNoTerms: String {
|
||||
return VectorL10n.tr("Vector", "identity_server_settings_alert_no_terms")
|
||||
}
|
||||
/// Identity server has no terms of services
|
||||
internal static var identityServerSettingsAlertNoTermsTitle: String {
|
||||
return VectorL10n.tr("Vector", "identity_server_settings_alert_no_terms_title")
|
||||
}
|
||||
/// Change
|
||||
internal static var identityServerSettingsChange: String {
|
||||
return VectorL10n.tr("Vector", "identity_server_settings_change")
|
||||
}
|
||||
/// You are currently using %@ to discover and be discoverable by existing contacts you know.
|
||||
internal static func identityServerSettingsDescription(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "identity_server_settings_description", p1)
|
||||
}
|
||||
/// Disconnect
|
||||
internal static var identityServerSettingsDisconnect: String {
|
||||
return VectorL10n.tr("Vector", "identity_server_settings_disconnect")
|
||||
}
|
||||
/// Disconnecting from your identity server will mean you won’t be discoverable by other users and be able to invite others by email or phone.
|
||||
internal static var identityServerSettingsDisconnectInfo: String {
|
||||
return VectorL10n.tr("Vector", "identity_server_settings_disconnect_info")
|
||||
}
|
||||
/// You are not currently using an identity server. To discover and be discoverable by existing contacts, add one above.
|
||||
internal static var identityServerSettingsNoIsDescription: String {
|
||||
return VectorL10n.tr("Vector", "identity_server_settings_no_is_description")
|
||||
}
|
||||
/// Enter an identity server
|
||||
internal static var identityServerSettingsPlaceHolder: String {
|
||||
return VectorL10n.tr("Vector", "identity_server_settings_place_holder")
|
||||
}
|
||||
/// Identity Server
|
||||
internal static var identityServerSettingsTitle: String {
|
||||
return VectorL10n.tr("Vector", "identity_server_settings_title")
|
||||
}
|
||||
/// Take photo
|
||||
internal static var imagePickerActionCamera: String {
|
||||
return VectorL10n.tr("Vector", "image_picker_action_camera")
|
||||
|
@ -1550,6 +1662,10 @@ internal enum VectorL10n {
|
|||
internal static var roomCreationAppearancePicture: String {
|
||||
return VectorL10n.tr("Vector", "room_creation_appearance_picture")
|
||||
}
|
||||
/// No identity server is configured so you cannot add a participant with an email.
|
||||
internal static var roomCreationErrorInviteUserByEmailWithoutIdentityServer: String {
|
||||
return VectorL10n.tr("Vector", "room_creation_error_invite_user_by_email_without_identity_server")
|
||||
}
|
||||
/// Search / invite by User ID, Name or email
|
||||
internal static var roomCreationInviteAnotherUser: String {
|
||||
return VectorL10n.tr("Vector", "room_creation_invite_another_user")
|
||||
|
@ -2166,9 +2282,13 @@ internal enum VectorL10n {
|
|||
internal static var roomParticipantsRemovePromptTitle: String {
|
||||
return VectorL10n.tr("Vector", "room_participants_remove_prompt_title")
|
||||
}
|
||||
/// Remove third-party invite is not supported yet until the api exists
|
||||
internal static var roomParticipantsRemoveThirdPartyInviteMsg: String {
|
||||
return VectorL10n.tr("Vector", "room_participants_remove_third_party_invite_msg")
|
||||
/// Are you sure you want to revoke this invite?
|
||||
internal static var roomParticipantsRemoveThirdPartyInvitePromptMsg: String {
|
||||
return VectorL10n.tr("Vector", "room_participants_remove_third_party_invite_prompt_msg")
|
||||
}
|
||||
/// No identity server is configured so you cannot start a chat with a contact using an email.
|
||||
internal static var roomParticipantsStartNewChatErrorUsingUserEmailWithoutIdentityServer: String {
|
||||
return VectorL10n.tr("Vector", "room_participants_start_new_chat_error_using_user_email_without_identity_server")
|
||||
}
|
||||
/// Participants
|
||||
internal static var roomParticipantsTitle: String {
|
||||
|
@ -2394,6 +2514,42 @@ internal enum VectorL10n {
|
|||
internal static var sending: String {
|
||||
return VectorL10n.tr("Vector", "sending")
|
||||
}
|
||||
/// Accept
|
||||
internal static var serviceTermsModalAcceptButton: String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_accept_button")
|
||||
}
|
||||
/// Decline
|
||||
internal static var serviceTermsModalDeclineButton: String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_decline_button")
|
||||
}
|
||||
/// Find others by phone or email
|
||||
internal static var serviceTermsModalDescriptionForIdentityServer1: String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_description_for_identity_server_1")
|
||||
}
|
||||
/// Be found by phone or email
|
||||
internal static var serviceTermsModalDescriptionForIdentityServer2: String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_description_for_identity_server_2")
|
||||
}
|
||||
/// Use Bots, bridges, widgets and sticker packs
|
||||
internal static var serviceTermsModalDescriptionForIntegrationManager: String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_description_for_integration_manager")
|
||||
}
|
||||
/// To continue you need to accept the terms of this service (%@).
|
||||
internal static func serviceTermsModalMessage(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_message", p1)
|
||||
}
|
||||
/// Accept the terms of the identity server (%@) to discover contacts.
|
||||
internal static func serviceTermsModalMessageIdentityServer(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_message_identity_server", p1)
|
||||
}
|
||||
/// Terms Of Service
|
||||
internal static var serviceTermsModalTitle: String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_title")
|
||||
}
|
||||
/// Contact discovery
|
||||
internal static var serviceTermsModalTitleIdentityServer: String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_title_identity_server")
|
||||
}
|
||||
/// Add email address
|
||||
internal static var settingsAddEmailAddress: String {
|
||||
return VectorL10n.tr("Vector", "settings_add_email_address")
|
||||
|
@ -2414,6 +2570,14 @@ internal enum VectorL10n {
|
|||
internal static var settingsCallsSettings: String {
|
||||
return VectorL10n.tr("Vector", "settings_calls_settings")
|
||||
}
|
||||
/// Allow fallback call assist server
|
||||
internal static var settingsCallsStunServerFallbackButton: String {
|
||||
return VectorL10n.tr("Vector", "settings_calls_stun_server_fallback_button")
|
||||
}
|
||||
/// Allow fallback call assist server %@ when your homeserver does not offer one (your IP address would be shared during a call).
|
||||
internal static func settingsCallsStunServerFallbackDescription(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "settings_calls_stun_server_fallback_description", p1)
|
||||
}
|
||||
/// Change password
|
||||
internal static var settingsChangePassword: String {
|
||||
return VectorL10n.tr("Vector", "settings_change_password")
|
||||
|
@ -2470,11 +2634,11 @@ internal enum VectorL10n {
|
|||
internal static var settingsCryptoDeviceId: String {
|
||||
return VectorL10n.tr("Vector", "settings_crypto_device_id")
|
||||
}
|
||||
/// \nDevice key:
|
||||
/// \nDevice key:\n
|
||||
internal static var settingsCryptoDeviceKey: String {
|
||||
return VectorL10n.tr("Vector", "settings_crypto_device_key")
|
||||
}
|
||||
/// Device name:
|
||||
/// Device Public Name:
|
||||
internal static var settingsCryptoDeviceName: String {
|
||||
return VectorL10n.tr("Vector", "settings_crypto_device_name")
|
||||
}
|
||||
|
@ -2498,6 +2662,70 @@ internal enum VectorL10n {
|
|||
internal static var settingsDevices: String {
|
||||
return VectorL10n.tr("Vector", "settings_devices")
|
||||
}
|
||||
/// A device's public name is visible to people you communicate with
|
||||
internal static var settingsDevicesDescription: String {
|
||||
return VectorL10n.tr("Vector", "settings_devices_description")
|
||||
}
|
||||
/// An error occured. Please retry.
|
||||
internal static var settingsDiscoveryErrorMessage: String {
|
||||
return VectorL10n.tr("Vector", "settings_discovery_error_message")
|
||||
}
|
||||
/// You are not currently using an identity server. To be discoverable by existing contacts you known, add one.
|
||||
internal static var settingsDiscoveryNoIdentityServer: String {
|
||||
return VectorL10n.tr("Vector", "settings_discovery_no_identity_server")
|
||||
}
|
||||
/// DISCOVERY
|
||||
internal static var settingsDiscoverySettings: String {
|
||||
return VectorL10n.tr("Vector", "settings_discovery_settings")
|
||||
}
|
||||
/// Agree to the Identity Server (%@) Terms of Service to allow yourself to be discoverable by email address or phone number.
|
||||
internal static func settingsDiscoveryTermsNotSigned(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "settings_discovery_terms_not_signed", p1)
|
||||
}
|
||||
/// Cancel email validation
|
||||
internal static var settingsDiscoveryThreePidDetailsCancelEmailValidationAction: String {
|
||||
return VectorL10n.tr("Vector", "settings_discovery_three_pid_details_cancel_email_validation_action")
|
||||
}
|
||||
/// Enter SMS activation code
|
||||
internal static var settingsDiscoveryThreePidDetailsEnterSmsCodeAction: String {
|
||||
return VectorL10n.tr("Vector", "settings_discovery_three_pid_details_enter_sms_code_action")
|
||||
}
|
||||
/// Manage preferences for this email address, which other users can use to discover you and use to invite you to rooms. Add or remove email addresses in Accounts.
|
||||
internal static var settingsDiscoveryThreePidDetailsInformationEmail: String {
|
||||
return VectorL10n.tr("Vector", "settings_discovery_three_pid_details_information_email")
|
||||
}
|
||||
/// Manage preferences for this phone number, which other users can use to discover you and use to invite you to rooms. Add or remove phone numbers in Accounts.
|
||||
internal static var settingsDiscoveryThreePidDetailsInformationPhoneNumber: String {
|
||||
return VectorL10n.tr("Vector", "settings_discovery_three_pid_details_information_phone_number")
|
||||
}
|
||||
/// Revoke
|
||||
internal static var settingsDiscoveryThreePidDetailsRevokeAction: String {
|
||||
return VectorL10n.tr("Vector", "settings_discovery_three_pid_details_revoke_action")
|
||||
}
|
||||
/// Share
|
||||
internal static var settingsDiscoveryThreePidDetailsShareAction: String {
|
||||
return VectorL10n.tr("Vector", "settings_discovery_three_pid_details_share_action")
|
||||
}
|
||||
/// Manage email
|
||||
internal static var settingsDiscoveryThreePidDetailsTitleEmail: String {
|
||||
return VectorL10n.tr("Vector", "settings_discovery_three_pid_details_title_email")
|
||||
}
|
||||
/// Manage phone number
|
||||
internal static var settingsDiscoveryThreePidDetailsTitlePhoneNumber: String {
|
||||
return VectorL10n.tr("Vector", "settings_discovery_three_pid_details_title_phone_number")
|
||||
}
|
||||
/// Manage which email addresses or phone numbers other users can use to discover you and use to invite you to rooms. Add or remove email addresses or phone numbers from this list in
|
||||
internal static var settingsDiscoveryThreePidsManagementInformationPart1: String {
|
||||
return VectorL10n.tr("Vector", "settings_discovery_three_pids_management_information_part1")
|
||||
}
|
||||
/// User Settings
|
||||
internal static var settingsDiscoveryThreePidsManagementInformationPart2: String {
|
||||
return VectorL10n.tr("Vector", "settings_discovery_three_pids_management_information_part2")
|
||||
}
|
||||
/// .
|
||||
internal static var settingsDiscoveryThreePidsManagementInformationPart3: String {
|
||||
return VectorL10n.tr("Vector", "settings_discovery_three_pids_management_information_part3")
|
||||
}
|
||||
/// Display Name
|
||||
internal static var settingsDisplayName: String {
|
||||
return VectorL10n.tr("Vector", "settings_display_name")
|
||||
|
@ -2542,6 +2770,22 @@ internal enum VectorL10n {
|
|||
internal static func settingsGlobalSettingsInfo(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "settings_global_settings_info", p1)
|
||||
}
|
||||
/// Using the identity server set above, you can discover and be discoverable by existing contacts you know.
|
||||
internal static var settingsIdentityServerDescription: String {
|
||||
return VectorL10n.tr("Vector", "settings_identity_server_description")
|
||||
}
|
||||
/// No identity server configured
|
||||
internal static var settingsIdentityServerNoIs: String {
|
||||
return VectorL10n.tr("Vector", "settings_identity_server_no_is")
|
||||
}
|
||||
/// You are not currently using an identity server. To discover and be discoverable by existing contacts you know, add one above.
|
||||
internal static var settingsIdentityServerNoIsDescription: String {
|
||||
return VectorL10n.tr("Vector", "settings_identity_server_no_is_description")
|
||||
}
|
||||
/// IDENTITY SERVER
|
||||
internal static var settingsIdentityServerSettings: String {
|
||||
return VectorL10n.tr("Vector", "settings_identity_server_settings")
|
||||
}
|
||||
/// IGNORED USERS
|
||||
internal static var settingsIgnoredUsers: String {
|
||||
return VectorL10n.tr("Vector", "settings_ignored_users")
|
||||
|
@ -2778,6 +3022,18 @@ internal enum VectorL10n {
|
|||
internal static var settingsThirdPartyNotices: String {
|
||||
return VectorL10n.tr("Vector", "settings_third_party_notices")
|
||||
}
|
||||
/// Manage which email addresses or phone numbers you can use to log in or recover your account here. Control who can find you in
|
||||
internal static var settingsThreePidsManagementInformationPart1: String {
|
||||
return VectorL10n.tr("Vector", "settings_three_pids_management_information_part1")
|
||||
}
|
||||
/// Discovery
|
||||
internal static var settingsThreePidsManagementInformationPart2: String {
|
||||
return VectorL10n.tr("Vector", "settings_three_pids_management_information_part2")
|
||||
}
|
||||
/// .
|
||||
internal static var settingsThreePidsManagementInformationPart3: String {
|
||||
return VectorL10n.tr("Vector", "settings_three_pids_management_information_part3")
|
||||
}
|
||||
/// Settings
|
||||
internal static var settingsTitle: String {
|
||||
return VectorL10n.tr("Vector", "settings_title")
|
||||
|
|
|
@ -30,6 +30,8 @@ final class RiotSettings: NSObject {
|
|||
static let notificationsShowDecryptedContent = "showDecryptedContent"
|
||||
static let pinRoomsWithMissedNotifications = "pinRoomsWithMissedNotif"
|
||||
static let pinRoomsWithUnreadMessages = "pinRoomsWithUnread"
|
||||
static let allowStunServerFallback = "allowStunServerFallback"
|
||||
static let stunServerFallback = "stunServerFallback"
|
||||
}
|
||||
|
||||
/// Riot Standard Room Member Power Level
|
||||
|
@ -119,4 +121,24 @@ final class RiotSettings: NSObject {
|
|||
UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.createConferenceCallsWithJitsi)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Calls
|
||||
|
||||
/// Indicate if `allowStunServerFallback` settings has been set once.
|
||||
var isAllowStunServerFallbackHasBeenSetOnce: Bool {
|
||||
return UserDefaults.standard.object(forKey: UserDefaultsKeys.allowStunServerFallback) != nil
|
||||
}
|
||||
|
||||
var allowStunServerFallback: Bool {
|
||||
get {
|
||||
return UserDefaults.standard.bool(forKey: UserDefaultsKeys.allowStunServerFallback)
|
||||
} set {
|
||||
UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.allowStunServerFallback)
|
||||
}
|
||||
}
|
||||
|
||||
var stunServerFallback: String? {
|
||||
return UserDefaults.standard.string(forKey: UserDefaultsKeys.stunServerFallback)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,5 +108,6 @@ class DarkTheme: NSObject, Theme {
|
|||
func applyStyle(onButton button: UIButton) {
|
||||
// NOTE: Tint color does nothing by default on button type `UIButtonType.custom`
|
||||
button.tintColor = self.tintColor
|
||||
button.setTitleColor(self.tintColor, for: .normal)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,5 +108,6 @@ class DefaultTheme: NSObject, Theme {
|
|||
func applyStyle(onButton button: UIButton) {
|
||||
// NOTE: Tint color does nothing by default on button type `UIButtonType.custom`
|
||||
button.tintColor = self.tintColor
|
||||
button.setTitleColor(self.tintColor, for: .normal)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,10 +56,12 @@ typedef enum : NSUInteger
|
|||
WidgetManagerErrorCodeNotEnoughPower,
|
||||
WidgetManagerErrorCodeCreationFailed,
|
||||
WidgetManagerErrorCodeNoIntegrationsServerConfigured,
|
||||
WidgetManagerErrorCodeFailedToConnectToIntegrationsServer
|
||||
WidgetManagerErrorCodeFailedToConnectToIntegrationsServer,
|
||||
WidgetManagerErrorCodeTermsNotSigned
|
||||
}
|
||||
WidgetManagerErrorCode;
|
||||
|
||||
FOUNDATION_EXPORT NSString *const WidgetManagerErrorOpenIdTokenKey;
|
||||
|
||||
/**
|
||||
The `WidgetManager` helps to handle modular widgets.
|
||||
|
|
|
@ -513,6 +513,8 @@ NSString *const WidgetManagerErrorDomain = @"WidgetManagerErrorDomain";
|
|||
MXHTTPOperation *operation;
|
||||
NSString *userId = mxSession.myUser.userId;
|
||||
|
||||
NSLog(@"[WidgetManager] registerForScalarToken");
|
||||
|
||||
WidgetManagerConfig *config = [self configForUser:userId];
|
||||
if (!config.hasUrls)
|
||||
{
|
||||
|
@ -537,15 +539,22 @@ NSString *const WidgetManagerErrorDomain = @"WidgetManagerErrorDomain";
|
|||
|
||||
NSString *scalarToken;
|
||||
MXJSONModelSetString(scalarToken, JSONResponse[@"scalar_token"])
|
||||
config.scalarToken = scalarToken;
|
||||
|
||||
config.scalarToken = scalarToken;
|
||||
self->configs[userId] = config;
|
||||
[self saveConfigs];
|
||||
|
||||
// Validate it (this mostly checks to see if the IM needs us to agree to some terms)
|
||||
MXHTTPOperation *operation3 = [self validateScalarToken:scalarToken forMXSession:mxSession complete:^(BOOL valid) {
|
||||
|
||||
if (success)
|
||||
{
|
||||
success(scalarToken);
|
||||
}
|
||||
if (success)
|
||||
{
|
||||
success(scalarToken);
|
||||
}
|
||||
|
||||
} failure:failure];
|
||||
|
||||
[operation mutateTo:operation3];
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
NSLog(@"[WidgetManager] registerForScalarToken: Failed to register. Error: %@", error);
|
||||
|
@ -622,7 +631,22 @@ NSString *const WidgetManagerErrorDomain = @"WidgetManagerErrorDomain";
|
|||
}
|
||||
else if (failure)
|
||||
{
|
||||
failure(error);
|
||||
MXError *mxError = [[MXError alloc] initWithNSError:error];
|
||||
if ([mxError.errcode isEqualToString:kMXErrCodeStringTermsNotSigned])
|
||||
{
|
||||
NSLog(@"[WidgetManager] validateScalarToke. Error: Need to accept terms");
|
||||
NSError *termsNotSignedError = [NSError errorWithDomain:WidgetManagerErrorDomain
|
||||
code:WidgetManagerErrorCodeTermsNotSigned
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey:error.userInfo[NSLocalizedDescriptionKey]
|
||||
}];
|
||||
|
||||
failure(termsNotSignedError);
|
||||
}
|
||||
else
|
||||
{
|
||||
failure(error);
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
|
|
@ -36,6 +36,38 @@ class WidgetManagerConfig: NSObject, NSCoding {
|
|||
}
|
||||
}
|
||||
|
||||
var baseUrl: NSString? {
|
||||
// Same comment as https://github.com/matrix-org/matrix-react-sdk/blob/1b0d8510a2ee93beddcd34c2d5770aa9fc76b1d9/src/ScalarAuthClient.js#L108
|
||||
// The terms endpoints are new and so live on standard _matrix prefixes,
|
||||
// but IM rest urls are currently configured with paths, so remove the
|
||||
// path from the base URL before passing it to the js-sdk
|
||||
|
||||
// We continue to use the full URL for the calls done by
|
||||
// Riot-iOS, but the standard terms API called
|
||||
// by the matrix-ios-sdk lives on the standard _matrix path. This means we
|
||||
// don't support running IMs on a non-root path, but it's the only
|
||||
// realistic way of transitioning to _matrix paths since configs in
|
||||
// the wild contain bits of the API path.
|
||||
|
||||
// Once we've fully transitioned to _matrix URLs, we can give people
|
||||
// a grace period to update their configs, then use the rest url as
|
||||
// a regular base url.
|
||||
guard let apiUrl = self.apiUrl as String?, let imApiUrl = URL(string: apiUrl) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
guard var baseUrl = URL(string: "/", relativeTo: imApiUrl)?.absoluteString else {
|
||||
return nil
|
||||
}
|
||||
|
||||
if baseUrl.hasSuffix("/") {
|
||||
// SDK doest not like trailing /
|
||||
baseUrl = String(baseUrl.dropLast())
|
||||
}
|
||||
|
||||
return baseUrl as NSString
|
||||
}
|
||||
|
||||
init(apiUrl: NSString?, uiUrl: NSString?) {
|
||||
self.apiUrl = apiUrl
|
||||
self.uiUrl = uiUrl
|
||||
|
|
|
@ -51,6 +51,8 @@
|
|||
AuthFallBackViewController *authFallBackViewController;
|
||||
}
|
||||
|
||||
@property (nonatomic, readonly) BOOL isIdentityServerConfigured;
|
||||
|
||||
@end
|
||||
|
||||
@implementation AuthenticationViewController
|
||||
|
@ -191,6 +193,11 @@
|
|||
[forgotPasswordTitle addAttribute:NSForegroundColorAttributeName value:ThemeService.shared.theme.tintColor range:NSMakeRange(0, forgotPasswordTitle.length)];
|
||||
[self.forgotPasswordButton setAttributedTitle:forgotPasswordTitle forState:UIControlStateNormal];
|
||||
[self.forgotPasswordButton setAttributedTitle:forgotPasswordTitle forState:UIControlStateHighlighted];
|
||||
|
||||
NSMutableAttributedString *forgotPasswordTitleDisabled = [[NSMutableAttributedString alloc] initWithAttributedString:forgotPasswordTitle];
|
||||
[forgotPasswordTitleDisabled addAttribute:NSForegroundColorAttributeName value:[ThemeService.shared.theme.tintColor colorWithAlphaComponent:0.3] range:NSMakeRange(0, forgotPasswordTitle.length)];
|
||||
[self.forgotPasswordButton setAttributedTitle:forgotPasswordTitleDisabled forState:UIControlStateDisabled];
|
||||
|
||||
[self updateForgotPwdButtonVisibility];
|
||||
|
||||
NSAttributedString *serverOptionsTitle = [[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"auth_use_server_options", @"Vector", nil) attributes:@{NSForegroundColorAttributeName : ThemeService.shared.theme.textSecondaryColor, NSFontAttributeName: [UIFont systemFontOfSize:14]}];
|
||||
|
@ -259,6 +266,11 @@
|
|||
autoDiscovery = nil;
|
||||
}
|
||||
|
||||
- (BOOL)isIdentityServerConfigured
|
||||
{
|
||||
return self.identityServerTextField.text.length > 0;
|
||||
}
|
||||
|
||||
- (void)setAuthType:(MXKAuthenticationType)authType
|
||||
{
|
||||
if (self.authType == MXKAuthenticationTypeRegister)
|
||||
|
@ -656,8 +668,21 @@
|
|||
}
|
||||
else if (sender == self.forgotPasswordButton)
|
||||
{
|
||||
// Update UI to reset password
|
||||
self.authType = MXKAuthenticationTypeForgotPassword;
|
||||
if (!self.isIdentityServerConfigured)
|
||||
{
|
||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSBundle mxk_localizedStringForKey:@"error"]
|
||||
message:NSLocalizedStringFromTable(@"auth_forgot_password_error_no_configured_identity_server", @"Vector", nil)
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
[alert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"ok"] style:UIAlertActionStyleDefault handler:nil]];
|
||||
[self presentViewController:alert animated:YES completion:nil];
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update UI to reset password
|
||||
self.authType = MXKAuthenticationTypeForgotPassword;
|
||||
}
|
||||
}
|
||||
else if (sender == self.rightBarButtonItem)
|
||||
{
|
||||
|
@ -735,7 +760,6 @@
|
|||
|
||||
// Show the supported 3rd party ids which may be added to the account
|
||||
authInputsview.thirdPartyIdentifiersHidden = NO;
|
||||
|
||||
[self updateRegistrationScreenWithThirdPartyIdentifiersHidden:NO];
|
||||
}
|
||||
}];
|
||||
|
@ -1013,6 +1037,10 @@
|
|||
{
|
||||
[self setHomeServerTextFieldText:customHomeServerURL];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self checkIdentityServer];
|
||||
}
|
||||
NSString *customIdentityServerURL = [[NSUserDefaults standardUserDefaults] objectForKey:@"customIdentityServerURL"];
|
||||
if (customIdentityServerURL.length)
|
||||
{
|
||||
|
|
|
@ -516,75 +516,94 @@
|
|||
|
||||
if (restClient)
|
||||
{
|
||||
// Check whether a second 3pid is available
|
||||
_isThirdPartyIdentifierPending = (!self.emailContainer.isHidden && self.emailTextField.text.length && ![self isFlowCompleted:kMXLoginFlowTypeEmailIdentity]);
|
||||
|
||||
// Launch msisdn validation
|
||||
NSString *e164 = [[NBPhoneNumberUtil sharedInstance] format:nbPhoneNumber numberFormat:NBEPhoneNumberFormatE164 error:nil];
|
||||
NSString *msisdn;
|
||||
if ([e164 hasPrefix:@"+"])
|
||||
{
|
||||
msisdn = [e164 substringFromIndex:1];
|
||||
}
|
||||
else if ([e164 hasPrefix:@"00"])
|
||||
{
|
||||
msisdn = [e164 substringFromIndex:2];
|
||||
}
|
||||
submittedMSISDN = [[MXK3PID alloc] initWithMedium:kMX3PIDMediumMSISDN andAddress:msisdn];
|
||||
|
||||
[submittedMSISDN requestValidationTokenWithMatrixRestClient:restClient
|
||||
isDuringRegistration:YES
|
||||
nextLink:nil
|
||||
success:^
|
||||
{
|
||||
|
||||
[self showValidationMSISDNDialogToPrepareParameters:callback];
|
||||
|
||||
}
|
||||
failure:^(NSError *error)
|
||||
{
|
||||
|
||||
NSLog(@"[AuthInputsView] Failed to request msisdn token");
|
||||
|
||||
// Ignore connection cancellation error
|
||||
if (([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorCancelled))
|
||||
MXWeakify(self);
|
||||
[self checkIdentityServerRequirement:restClient success:^(BOOL identityServerRequired) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
if (identityServerRequired && !restClient.identityServer)
|
||||
{
|
||||
callback(nil, [NSError errorWithDomain:MXKAuthErrorDomain
|
||||
code:0
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey:[NSBundle mxk_localizedStringForKey:@"auth_phone_is_required"]
|
||||
}]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check whether a second 3pid is available
|
||||
_isThirdPartyIdentifierPending = (!self.emailContainer.isHidden && self.emailTextField.text.length && ![self isFlowCompleted:kMXLoginFlowTypeEmailIdentity]);
|
||||
|
||||
// Launch msisdn validation
|
||||
NSString *e164 = [[NBPhoneNumberUtil sharedInstance] format:nbPhoneNumber numberFormat:NBEPhoneNumberFormatE164 error:nil];
|
||||
NSString *msisdn;
|
||||
if ([e164 hasPrefix:@"+"])
|
||||
{
|
||||
msisdn = [e164 substringFromIndex:1];
|
||||
}
|
||||
else if ([e164 hasPrefix:@"00"])
|
||||
{
|
||||
msisdn = [e164 substringFromIndex:2];
|
||||
}
|
||||
submittedMSISDN = [[MXK3PID alloc] initWithMedium:kMX3PIDMediumMSISDN andAddress:msisdn];
|
||||
|
||||
[submittedMSISDN requestValidationTokenWithMatrixRestClient:restClient
|
||||
isDuringRegistration:YES
|
||||
nextLink:nil
|
||||
success:^
|
||||
{
|
||||
return;
|
||||
|
||||
[self showValidationMSISDNDialogToPrepareParameters:callback];
|
||||
|
||||
}
|
||||
|
||||
// Translate the potential MX error.
|
||||
MXError *mxError = [[MXError alloc] initWithNSError:error];
|
||||
if (mxError && ([mxError.errcode isEqualToString:kMXErrCodeStringThreePIDInUse] || [mxError.errcode isEqualToString:kMXErrCodeStringServerNotTrusted]))
|
||||
failure:^(NSError *error)
|
||||
{
|
||||
NSMutableDictionary *userInfo;
|
||||
if (error.userInfo)
|
||||
|
||||
NSLog(@"[AuthInputsView] Failed to request msisdn token");
|
||||
|
||||
// Ignore connection cancellation error
|
||||
if (([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorCancelled))
|
||||
{
|
||||
userInfo = [NSMutableDictionary dictionaryWithDictionary:error.userInfo];
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
// Translate the potential MX error.
|
||||
MXError *mxError = [[MXError alloc] initWithNSError:error];
|
||||
if (mxError && ([mxError.errcode isEqualToString:kMXErrCodeStringThreePIDInUse] || [mxError.errcode isEqualToString:kMXErrCodeStringServerNotTrusted]))
|
||||
{
|
||||
userInfo = [NSMutableDictionary dictionary];
|
||||
NSMutableDictionary *userInfo;
|
||||
if (error.userInfo)
|
||||
{
|
||||
userInfo = [NSMutableDictionary dictionaryWithDictionary:error.userInfo];
|
||||
}
|
||||
else
|
||||
{
|
||||
userInfo = [NSMutableDictionary dictionary];
|
||||
}
|
||||
|
||||
userInfo[NSLocalizedFailureReasonErrorKey] = nil;
|
||||
|
||||
if ([mxError.errcode isEqualToString:kMXErrCodeStringThreePIDInUse])
|
||||
{
|
||||
userInfo[NSLocalizedDescriptionKey] = NSLocalizedStringFromTable(@"auth_phone_in_use", @"Vector", nil);
|
||||
userInfo[@"error"] = NSLocalizedStringFromTable(@"auth_phone_in_use", @"Vector", nil);
|
||||
}
|
||||
else
|
||||
{
|
||||
userInfo[NSLocalizedDescriptionKey] = NSLocalizedStringFromTable(@"auth_untrusted_id_server", @"Vector", nil);
|
||||
userInfo[@"error"] = NSLocalizedStringFromTable(@"auth_untrusted_id_server", @"Vector", nil);
|
||||
}
|
||||
|
||||
error = [NSError errorWithDomain:error.domain code:error.code userInfo:userInfo];
|
||||
}
|
||||
|
||||
userInfo[NSLocalizedFailureReasonErrorKey] = nil;
|
||||
|
||||
if ([mxError.errcode isEqualToString:kMXErrCodeStringThreePIDInUse])
|
||||
{
|
||||
userInfo[NSLocalizedDescriptionKey] = NSLocalizedStringFromTable(@"auth_phone_in_use", @"Vector", nil);
|
||||
userInfo[@"error"] = NSLocalizedStringFromTable(@"auth_phone_in_use", @"Vector", nil);
|
||||
}
|
||||
else
|
||||
{
|
||||
userInfo[NSLocalizedDescriptionKey] = NSLocalizedStringFromTable(@"auth_untrusted_id_server", @"Vector", nil);
|
||||
userInfo[@"error"] = NSLocalizedStringFromTable(@"auth_untrusted_id_server", @"Vector", nil);
|
||||
}
|
||||
|
||||
error = [NSError errorWithDomain:error.domain code:error.code userInfo:userInfo];
|
||||
}
|
||||
|
||||
callback(nil, error);
|
||||
|
||||
}];
|
||||
|
||||
callback(nil, error);
|
||||
|
||||
}];
|
||||
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
callback(nil, error);
|
||||
}];
|
||||
|
||||
// Async response
|
||||
return;
|
||||
|
@ -606,87 +625,121 @@
|
|||
|
||||
if (restClient)
|
||||
{
|
||||
// Check whether a second 3pid is available
|
||||
_isThirdPartyIdentifierPending = (nbPhoneNumber && ![self isFlowCompleted:kMXLoginFlowTypeMSISDN]);
|
||||
|
||||
// Launch email validation
|
||||
submittedEmail = [[MXK3PID alloc] initWithMedium:kMX3PIDMediumEmail andAddress:self.emailTextField.text];
|
||||
MXWeakify(self);
|
||||
[self checkIdentityServerRequirement:restClient success:^(BOOL identityServerRequired) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
// Create the next link that is common to all Vector.im clients
|
||||
NSString *nextLink = [NSString stringWithFormat:@"%@/#/register?client_secret=%@&hs_url=%@&is_url=%@&session_id=%@",
|
||||
[Tools webAppUrl],
|
||||
[submittedEmail.clientSecret stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]],
|
||||
[restClient.homeserver stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]],
|
||||
[restClient.identityServer stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]],
|
||||
[currentSession.session stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]];
|
||||
if (identityServerRequired && !restClient.identityServer)
|
||||
{
|
||||
callback(nil, [NSError errorWithDomain:MXKAuthErrorDomain
|
||||
code:0
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey:[NSBundle mxk_localizedStringForKey:@"auth_email_is_required"]
|
||||
}]);
|
||||
return;
|
||||
}
|
||||
|
||||
[submittedEmail requestValidationTokenWithMatrixRestClient:restClient
|
||||
isDuringRegistration:YES
|
||||
nextLink:nextLink
|
||||
success:^
|
||||
{
|
||||
|
||||
NSURL *identServerURL = [NSURL URLWithString:restClient.identityServer];
|
||||
NSDictionary *parameters;
|
||||
parameters = @{
|
||||
@"auth": @{@"session":currentSession.session, @"threepid_creds": @{@"client_secret": submittedEmail.clientSecret, @"id_server": identServerURL.host, @"sid": submittedEmail.sid}, @"type": kMXLoginFlowTypeEmailIdentity},
|
||||
@"username": self.userLoginTextField.text,
|
||||
@"password": self.passWordTextField.text,
|
||||
@"bind_msisdn": @([self isFlowCompleted:kMXLoginFlowTypeMSISDN]),
|
||||
@"bind_email": @(YES)
|
||||
};
|
||||
|
||||
[self hideInputsContainer];
|
||||
|
||||
self.messageLabel.text = NSLocalizedStringFromTable(@"auth_email_validation_message", @"Vector", nil);
|
||||
self.messageLabel.hidden = NO;
|
||||
|
||||
callback(parameters, nil);
|
||||
|
||||
}
|
||||
failure:^(NSError *error)
|
||||
{
|
||||
|
||||
NSLog(@"[AuthInputsView] Failed to request email token");
|
||||
|
||||
// Ignore connection cancellation error
|
||||
if (([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorCancelled))
|
||||
// Check whether a second 3pid is available
|
||||
self->_isThirdPartyIdentifierPending = (self->nbPhoneNumber && ![self isFlowCompleted:kMXLoginFlowTypeMSISDN]);
|
||||
|
||||
// Launch email validation
|
||||
self->submittedEmail = [[MXK3PID alloc] initWithMedium:kMX3PIDMediumEmail andAddress:self.emailTextField.text];
|
||||
|
||||
NSString *identityServer = restClient.identityServer;
|
||||
|
||||
// Create the next link that is common to all Vector.im clients
|
||||
NSString *nextLink = [NSString stringWithFormat:@"%@/#/register?client_secret=%@&hs_url=%@&session_id=%@",
|
||||
[Tools webAppUrl],
|
||||
[self->submittedEmail.clientSecret stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]],
|
||||
[restClient.homeserver stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]],
|
||||
[self->currentSession.session stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]];
|
||||
|
||||
if (identityServer)
|
||||
{
|
||||
nextLink = [NSString stringWithFormat:@"%@&is_url=%@", nextLink,
|
||||
[identityServer stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]];
|
||||
}
|
||||
|
||||
[self->submittedEmail requestValidationTokenWithMatrixRestClient:restClient
|
||||
isDuringRegistration:YES
|
||||
nextLink:nextLink
|
||||
success:^
|
||||
{
|
||||
return;
|
||||
NSMutableDictionary *threepidCreds = [NSMutableDictionary dictionaryWithDictionary:@{
|
||||
@"client_secret": self->submittedEmail.clientSecret,
|
||||
|
||||
@"sid": self->submittedEmail.sid
|
||||
}];
|
||||
if (identityServer)
|
||||
{
|
||||
NSURL *identServerURL = [NSURL URLWithString:identityServer];
|
||||
threepidCreds[@"id_server"] = identServerURL.host;
|
||||
}
|
||||
|
||||
NSDictionary *parameters;
|
||||
parameters = @{
|
||||
@"auth": @{
|
||||
@"session":self->currentSession.session,
|
||||
@"threepid_creds": threepidCreds,
|
||||
@"type": kMXLoginFlowTypeEmailIdentity},
|
||||
@"username": self.userLoginTextField.text,
|
||||
@"password": self.passWordTextField.text,
|
||||
};
|
||||
|
||||
[self hideInputsContainer];
|
||||
|
||||
self.messageLabel.text = NSLocalizedStringFromTable(@"auth_email_validation_message", @"Vector", nil);
|
||||
self.messageLabel.hidden = NO;
|
||||
|
||||
callback(parameters, nil);
|
||||
|
||||
}
|
||||
|
||||
// Translate the potential MX error.
|
||||
MXError *mxError = [[MXError alloc] initWithNSError:error];
|
||||
if (mxError && ([mxError.errcode isEqualToString:kMXErrCodeStringThreePIDInUse] || [mxError.errcode isEqualToString:kMXErrCodeStringServerNotTrusted]))
|
||||
failure:^(NSError *error)
|
||||
{
|
||||
NSMutableDictionary *userInfo;
|
||||
if (error.userInfo)
|
||||
|
||||
NSLog(@"[AuthInputsView] Failed to request email token");
|
||||
|
||||
// Ignore connection cancellation error
|
||||
if (([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorCancelled))
|
||||
{
|
||||
userInfo = [NSMutableDictionary dictionaryWithDictionary:error.userInfo];
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
// Translate the potential MX error.
|
||||
MXError *mxError = [[MXError alloc] initWithNSError:error];
|
||||
if (mxError && ([mxError.errcode isEqualToString:kMXErrCodeStringThreePIDInUse] || [mxError.errcode isEqualToString:kMXErrCodeStringServerNotTrusted]))
|
||||
{
|
||||
userInfo = [NSMutableDictionary dictionary];
|
||||
NSMutableDictionary *userInfo;
|
||||
if (error.userInfo)
|
||||
{
|
||||
userInfo = [NSMutableDictionary dictionaryWithDictionary:error.userInfo];
|
||||
}
|
||||
else
|
||||
{
|
||||
userInfo = [NSMutableDictionary dictionary];
|
||||
}
|
||||
|
||||
userInfo[NSLocalizedFailureReasonErrorKey] = nil;
|
||||
|
||||
if ([mxError.errcode isEqualToString:kMXErrCodeStringThreePIDInUse])
|
||||
{
|
||||
userInfo[NSLocalizedDescriptionKey] = NSLocalizedStringFromTable(@"auth_email_in_use", @"Vector", nil);
|
||||
userInfo[@"error"] = NSLocalizedStringFromTable(@"auth_email_in_use", @"Vector", nil);
|
||||
}
|
||||
else
|
||||
{
|
||||
userInfo[NSLocalizedDescriptionKey] = NSLocalizedStringFromTable(@"auth_untrusted_id_server", @"Vector", nil);
|
||||
userInfo[@"error"] = NSLocalizedStringFromTable(@"auth_untrusted_id_server", @"Vector", nil);
|
||||
}
|
||||
|
||||
error = [NSError errorWithDomain:error.domain code:error.code userInfo:userInfo];
|
||||
}
|
||||
|
||||
userInfo[NSLocalizedFailureReasonErrorKey] = nil;
|
||||
|
||||
if ([mxError.errcode isEqualToString:kMXErrCodeStringThreePIDInUse])
|
||||
{
|
||||
userInfo[NSLocalizedDescriptionKey] = NSLocalizedStringFromTable(@"auth_email_in_use", @"Vector", nil);
|
||||
userInfo[@"error"] = NSLocalizedStringFromTable(@"auth_email_in_use", @"Vector", nil);
|
||||
}
|
||||
else
|
||||
{
|
||||
userInfo[NSLocalizedDescriptionKey] = NSLocalizedStringFromTable(@"auth_untrusted_id_server", @"Vector", nil);
|
||||
userInfo[@"error"] = NSLocalizedStringFromTable(@"auth_untrusted_id_server", @"Vector", nil);
|
||||
}
|
||||
|
||||
error = [NSError errorWithDomain:error.domain code:error.code userInfo:userInfo];
|
||||
}
|
||||
callback(nil, error);
|
||||
|
||||
}];
|
||||
callback(nil, error);
|
||||
|
||||
}];
|
||||
} failure:^(NSError *error) {
|
||||
callback(nil, error);
|
||||
}];
|
||||
|
||||
// Async response
|
||||
return;
|
||||
|
@ -702,11 +755,13 @@
|
|||
if (response.length)
|
||||
{
|
||||
NSDictionary *parameters = @{
|
||||
@"auth": @{@"session":currentSession.session, @"response": response, @"type": kMXLoginFlowTypeRecaptcha},
|
||||
@"auth": @{
|
||||
@"session":currentSession.session,
|
||||
@"response": response,
|
||||
@"type": kMXLoginFlowTypeRecaptcha
|
||||
},
|
||||
@"username": self.userLoginTextField.text,
|
||||
@"password": self.passWordTextField.text,
|
||||
@"bind_msisdn": @([self isFlowCompleted:kMXLoginFlowTypeMSISDN]),
|
||||
@"bind_email": @([self isFlowCompleted:kMXLoginFlowTypeEmailIdentity])
|
||||
};
|
||||
|
||||
callback(parameters, nil);
|
||||
|
@ -725,11 +780,12 @@
|
|||
else if ([self isFlowSupported:kMXLoginFlowTypeDummy] && ![self isFlowCompleted:kMXLoginFlowTypeDummy])
|
||||
{
|
||||
parameters = @{
|
||||
@"auth": @{@"session":currentSession.session, @"type": kMXLoginFlowTypeDummy},
|
||||
@"auth": @{
|
||||
@"session":currentSession.session,
|
||||
@"type": kMXLoginFlowTypeDummy
|
||||
},
|
||||
@"username": self.userLoginTextField.text,
|
||||
@"password": self.passWordTextField.text,
|
||||
@"bind_msisdn": @(NO),
|
||||
@"bind_email": @(NO)
|
||||
};
|
||||
}
|
||||
else if ([self isFlowSupported:kMXLoginFlowTypePassword] && ![self isFlowCompleted:kMXLoginFlowTypePassword])
|
||||
|
@ -758,9 +814,7 @@
|
|||
@"type": kMXLoginFlowTypeTerms
|
||||
},
|
||||
@"username": self.userLoginTextField.text,
|
||||
@"password": self.passWordTextField.text,
|
||||
@"bind_msisdn": @([self isFlowCompleted:kMXLoginFlowTypeMSISDN]),
|
||||
@"bind_email": @([self isFlowCompleted:kMXLoginFlowTypeEmailIdentity])
|
||||
@"password": self.passWordTextField.text
|
||||
};
|
||||
callback(parameters, nil);
|
||||
}];
|
||||
|
@ -934,16 +988,31 @@
|
|||
}
|
||||
|
||||
// Check validity of the required parameters
|
||||
if (!homeserverURL.length || !identityURL.length || !clientSecret.length || !sid.length || !sessionId.length)
|
||||
if (!homeserverURL.length || !clientSecret.length || !sid.length || !sessionId.length)
|
||||
{
|
||||
NSLog(@"[AuthInputsView] setExternalRegistrationParameters failed: wrong parameters");
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
// Prepare the registration parameters (Ready to use)
|
||||
NSURL *identServerURL = [NSURL URLWithString:identityURL];
|
||||
|
||||
NSMutableDictionary *threepidCreds = [NSMutableDictionary dictionaryWithDictionary:@{
|
||||
@"client_secret": clientSecret,
|
||||
|
||||
@"sid": sid
|
||||
}];
|
||||
if (identityURL)
|
||||
{
|
||||
NSURL *identServerURL = [NSURL URLWithString:identityURL];
|
||||
threepidCreds[@"id_server"] = identServerURL.host;
|
||||
}
|
||||
|
||||
externalRegistrationParameters = @{
|
||||
@"auth": @{@"session": sessionId, @"threepid_creds": @{@"client_secret": clientSecret, @"id_server": identServerURL.host, @"sid": sid}, @"type": kMXLoginFlowTypeEmailIdentity},
|
||||
@"auth": @{
|
||||
@"session": sessionId,
|
||||
@"threepid_creds": threepidCreds,
|
||||
@"type": kMXLoginFlowTypeEmailIdentity
|
||||
},
|
||||
};
|
||||
|
||||
// Hide all inputs by default
|
||||
|
@ -1172,7 +1241,7 @@
|
|||
self.emailContainer.hidden = NO;
|
||||
|
||||
self.messageLabel.hidden = NO;
|
||||
self.messageLabel.text = NSLocalizedStringFromTable(@"auth_add_email_message", @"Vector", nil);
|
||||
self.messageLabel.text = NSLocalizedStringFromTable(@"auth_add_email_message_2", @"Vector", nil);
|
||||
|
||||
lastViewContainer = self.emailContainer;
|
||||
}
|
||||
|
@ -1201,22 +1270,14 @@
|
|||
self.emailTextField.returnKeyType = UIReturnKeyNext;
|
||||
|
||||
self.phoneContainerTopConstraint.constant = 50;
|
||||
|
||||
if (self.areAllThirdPartyIdentifiersRequired)
|
||||
{
|
||||
self.messageLabel.text = NSLocalizedStringFromTable(@"auth_add_email_and_phone_message", @"Vector", nil);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.messageLabel.text = NSLocalizedStringFromTable(@"auth_add_email_phone_message", @"Vector", nil);
|
||||
}
|
||||
self.messageLabel.text = NSLocalizedStringFromTable(@"auth_add_email_phone_message_2", @"Vector", nil);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.phoneContainerTopConstraint.constant = 0;
|
||||
|
||||
self.messageLabel.hidden = NO;
|
||||
self.messageLabel.text = NSLocalizedStringFromTable(@"auth_add_phone_message", @"Vector", nil);
|
||||
self.messageLabel.text = NSLocalizedStringFromTable(@"auth_add_phone_message_2", @"Vector", nil);
|
||||
}
|
||||
|
||||
lastViewContainer = self.phoneContainer;
|
||||
|
@ -1606,7 +1667,7 @@
|
|||
|
||||
inputsAlert = [UIAlertController alertControllerWithTitle:NSLocalizedStringFromTable(@"auth_msisdn_validation_title", @"Vector", nil) message:NSLocalizedStringFromTable(@"auth_msisdn_validation_message", @"Vector", nil) preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
[inputsAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"abort"]
|
||||
[inputsAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"]
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
|
@ -1646,25 +1707,40 @@
|
|||
{
|
||||
[self->submittedMSISDN submitValidationToken:smsCode success:^{
|
||||
|
||||
// Retrieve the REST client from delegate
|
||||
MXRestClient *restClient;
|
||||
// Retrieve the identity service from delegate
|
||||
MXIdentityService *identityService;
|
||||
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(authInputsViewThirdPartyIdValidationRestClient:)])
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(authInputsViewThirdPartyIdValidationIdentityService:)])
|
||||
{
|
||||
restClient = [self.delegate authInputsViewThirdPartyIdValidationRestClient:self];
|
||||
identityService = [self.delegate authInputsViewThirdPartyIdValidationIdentityService:self];
|
||||
}
|
||||
|
||||
NSURL *identServerURL = [NSURL URLWithString:restClient.identityServer];
|
||||
NSDictionary *parameters;
|
||||
parameters = @{
|
||||
@"auth": @{@"session":self->currentSession.session, @"threepid_creds": @{@"client_secret": self->submittedMSISDN.clientSecret, @"id_server": identServerURL.host, @"sid": self->submittedMSISDN.sid}, @"type": kMXLoginFlowTypeMSISDN},
|
||||
@"username": self.userLoginTextField.text,
|
||||
@"password": self.passWordTextField.text,
|
||||
@"bind_msisdn": @(YES),
|
||||
@"bind_email": @([self isFlowCompleted:kMXLoginFlowTypeEmailIdentity])
|
||||
};
|
||||
NSString *identityServer = identityService.identityServer;
|
||||
|
||||
callback(parameters, nil);
|
||||
if (identityServer)
|
||||
{
|
||||
NSURL *identServerURL = [NSURL URLWithString:identityServer];
|
||||
NSDictionary *parameters;
|
||||
parameters = @{
|
||||
@"auth": @{
|
||||
@"session":self->currentSession.session,
|
||||
@"threepid_creds": @{
|
||||
@"client_secret": self->submittedMSISDN.clientSecret,
|
||||
@"id_server": identServerURL.host,
|
||||
@"sid": self->submittedMSISDN.sid
|
||||
},
|
||||
@"type": kMXLoginFlowTypeMSISDN
|
||||
},
|
||||
@"username": self.userLoginTextField.text,
|
||||
@"password": self.passWordTextField.text
|
||||
};
|
||||
|
||||
callback(parameters, nil);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"[AuthInputsView] Failed to retrieve identity server URL");
|
||||
}
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
||||
|
@ -1790,4 +1866,16 @@
|
|||
return NO;
|
||||
}
|
||||
|
||||
- (void)checkIdentityServerRequirement:(MXRestClient*)mxRestClient
|
||||
success:(void (^)(BOOL identityServerRequired))success
|
||||
failure:(void (^)(NSError *error))failure
|
||||
{
|
||||
[mxRestClient supportedMatrixVersions:^(MXMatrixVersions *matrixVersions) {
|
||||
|
||||
NSLog(@"[AuthInputsView] checkIdentityServerRequirement: %@", matrixVersions.doesServerRequireIdentityServerParam ? @"YES": @"NO");
|
||||
success(matrixVersions.doesServerRequireIdentityServerParam);
|
||||
|
||||
} failure:failure];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -237,99 +237,109 @@
|
|||
|
||||
if (restClient)
|
||||
{
|
||||
// Launch email validation
|
||||
NSString *clientSecret = [MXTools generateSecret];
|
||||
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[restClient forgetPasswordForEmail:self.emailTextField.text
|
||||
clientSecret:clientSecret
|
||||
sendAttempt:1
|
||||
success:^(NSString *sid)
|
||||
{
|
||||
typeof(weakSelf) strongSelf = weakSelf;
|
||||
if (strongSelf) {
|
||||
strongSelf.didPrepareParametersCallback = callback;
|
||||
|
||||
NSURL *identServerURL = [NSURL URLWithString:restClient.identityServer];
|
||||
strongSelf.parameters = @{
|
||||
@"auth": @{
|
||||
@"threepid_creds": @{
|
||||
@"client_secret": clientSecret,
|
||||
@"id_server": identServerURL.host,
|
||||
@"sid": sid
|
||||
},
|
||||
@"type": kMXLoginFlowTypeEmailIdentity
|
||||
},
|
||||
@"new_password": strongSelf.passWordTextField.text
|
||||
};
|
||||
|
||||
[strongSelf hideInputsContainer];
|
||||
|
||||
strongSelf.messageLabel.text = [NSString stringWithFormat:NSLocalizedStringFromTable(@"auth_reset_password_email_validation_message", @"Vector", nil), strongSelf.emailTextField.text];
|
||||
|
||||
strongSelf.messageLabel.hidden = NO;
|
||||
|
||||
[strongSelf.nextStepButton addTarget:strongSelf
|
||||
action:@selector(didCheckEmail:)
|
||||
forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
strongSelf.nextStepButton.hidden = NO;
|
||||
}
|
||||
}
|
||||
failure:^(NSError *error)
|
||||
{
|
||||
NSLog(@"[ForgotPasswordInputsView] Failed to request email token");
|
||||
|
||||
// Ignore connection cancellation error
|
||||
if (([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorCancelled))
|
||||
[self checkIdentityServerRequirement:restClient success:^{
|
||||
|
||||
// Launch email validation
|
||||
NSString *clientSecret = [MXTools generateSecret];
|
||||
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[restClient forgetPasswordForEmail:self.emailTextField.text
|
||||
clientSecret:clientSecret
|
||||
sendAttempt:1
|
||||
success:^(NSString *sid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *errorMessage;
|
||||
|
||||
// Translate the potential MX error.
|
||||
MXError *mxError = [[MXError alloc] initWithNSError:error];
|
||||
if (mxError && [mxError.errcode isEqualToString:kMXErrCodeStringThreePIDNotFound])
|
||||
errorMessage = NSLocalizedStringFromTable(@"auth_email_not_found", @"Vector", nil);
|
||||
else if (mxError && [mxError.errcode isEqualToString:kMXErrCodeStringServerNotTrusted])
|
||||
errorMessage = NSLocalizedStringFromTable(@"auth_untrusted_id_server", @"Vector", nil);
|
||||
else if (error.userInfo[@"error"])
|
||||
errorMessage = error.userInfo[@"error"];
|
||||
else
|
||||
errorMessage = error.localizedDescription;
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
|
||||
if (self->inputsAlert)
|
||||
{
|
||||
[self->inputsAlert dismissViewControllerAnimated:NO completion:nil];
|
||||
typeof(weakSelf) strongSelf = weakSelf;
|
||||
if (strongSelf) {
|
||||
strongSelf.didPrepareParametersCallback = callback;
|
||||
|
||||
NSMutableDictionary *threepidCreds = [NSMutableDictionary dictionaryWithDictionary:@{
|
||||
@"client_secret": clientSecret,
|
||||
@"sid": sid
|
||||
}];
|
||||
if (restClient.identityServer)
|
||||
{
|
||||
NSURL *identServerURL = [NSURL URLWithString:restClient.identityServer];
|
||||
threepidCreds[@"id_server"] = identServerURL.host;
|
||||
}
|
||||
|
||||
strongSelf.parameters = @{
|
||||
@"auth": @{
|
||||
@"threepid_creds": threepidCreds,
|
||||
@"type": kMXLoginFlowTypeEmailIdentity
|
||||
},
|
||||
@"new_password": strongSelf.passWordTextField.text
|
||||
};
|
||||
|
||||
[strongSelf hideInputsContainer];
|
||||
|
||||
strongSelf.messageLabel.text = [NSString stringWithFormat:NSLocalizedStringFromTable(@"auth_reset_password_email_validation_message", @"Vector", nil), strongSelf.emailTextField.text];
|
||||
|
||||
strongSelf.messageLabel.hidden = NO;
|
||||
|
||||
[strongSelf.nextStepButton addTarget:strongSelf
|
||||
action:@selector(didCheckEmail:)
|
||||
forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
strongSelf.nextStepButton.hidden = NO;
|
||||
}
|
||||
|
||||
self->inputsAlert = [UIAlertController alertControllerWithTitle:[NSBundle mxk_localizedStringForKey:@"error"] message:errorMessage preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
[self->inputsAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"ok"]
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
self->inputsAlert = nil;
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(authInputsViewDidCancelOperation:)])
|
||||
{
|
||||
[self.delegate authInputsViewDidCancelOperation:self];
|
||||
}
|
||||
}
|
||||
|
||||
}]];
|
||||
|
||||
[self.delegate authInputsView:self presentAlertController:self->inputsAlert];
|
||||
}
|
||||
}];
|
||||
|
||||
failure:^(NSError *error)
|
||||
{
|
||||
NSLog(@"[ForgotPasswordInputsView] Failed to request email token");
|
||||
|
||||
// Ignore connection cancellation error
|
||||
if (([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorCancelled))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *errorMessage;
|
||||
|
||||
// Translate the potential MX error.
|
||||
MXError *mxError = [[MXError alloc] initWithNSError:error];
|
||||
if (mxError && [mxError.errcode isEqualToString:kMXErrCodeStringThreePIDNotFound])
|
||||
errorMessage = NSLocalizedStringFromTable(@"auth_email_not_found", @"Vector", nil);
|
||||
else if (mxError && [mxError.errcode isEqualToString:kMXErrCodeStringServerNotTrusted])
|
||||
errorMessage = NSLocalizedStringFromTable(@"auth_untrusted_id_server", @"Vector", nil);
|
||||
else if (error.userInfo[@"error"])
|
||||
errorMessage = error.userInfo[@"error"];
|
||||
else
|
||||
errorMessage = error.localizedDescription;
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
|
||||
if (self->inputsAlert)
|
||||
{
|
||||
[self->inputsAlert dismissViewControllerAnimated:NO completion:nil];
|
||||
}
|
||||
|
||||
self->inputsAlert = [UIAlertController alertControllerWithTitle:[NSBundle mxk_localizedStringForKey:@"error"] message:errorMessage preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
[self->inputsAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"ok"]
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
self->inputsAlert = nil;
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(authInputsViewDidCancelOperation:)])
|
||||
{
|
||||
[self.delegate authInputsViewDidCancelOperation:self];
|
||||
}
|
||||
}
|
||||
|
||||
}]];
|
||||
|
||||
[self.delegate authInputsView:self presentAlertController:self->inputsAlert];
|
||||
}
|
||||
}];
|
||||
} failure:^(NSError *error) {
|
||||
callback(nil, error);
|
||||
}];
|
||||
|
||||
// Async response
|
||||
return;
|
||||
}
|
||||
|
@ -400,6 +410,29 @@
|
|||
[self layoutIfNeeded];
|
||||
}
|
||||
|
||||
- (void)checkIdentityServerRequirement:(MXRestClient*)mxRestClient success:(void (^)(void))success failure:(void (^)(NSError *))failure
|
||||
{
|
||||
[mxRestClient supportedMatrixVersions:^(MXMatrixVersions *matrixVersions) {
|
||||
|
||||
NSLog(@"[ForgotPasswordInputsView] checkIdentityServerRequirement: %@", matrixVersions.doesServerRequireIdentityServerParam ? @"YES": @"NO");
|
||||
|
||||
if (matrixVersions.doesServerRequireIdentityServerParam
|
||||
&& !mxRestClient.identityServer)
|
||||
{
|
||||
failure([NSError errorWithDomain:MXKAuthErrorDomain
|
||||
code:0
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey:[NSBundle mxk_localizedStringForKey:@"auth_reset_password_error_is_required"]
|
||||
}]);
|
||||
}
|
||||
else
|
||||
{
|
||||
success();
|
||||
}
|
||||
|
||||
} failure:failure];
|
||||
}
|
||||
|
||||
#pragma mark - actions
|
||||
|
||||
- (void)didCheckEmail:(id)sender
|
||||
|
|
|
@ -26,4 +26,7 @@
|
|||
|
||||
@property (unsafe_unretained, nonatomic) IBOutlet NSLayoutConstraint *callerImageViewWidthConstraint;
|
||||
|
||||
// At the end of call, this flag indicates if the prompt to use the fallback should be displayed
|
||||
@property (nonatomic) BOOL shouldPromptForStunServerFallback;
|
||||
|
||||
@end
|
||||
|
|
|
@ -39,6 +39,9 @@
|
|||
|
||||
// Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change.
|
||||
id kThemeServiceDidChangeThemeNotificationObserver;
|
||||
|
||||
// Flag to compute self.shouldPromptForStunServerFallback
|
||||
BOOL promptForStunServerFallback;
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -52,6 +55,9 @@
|
|||
// Setup `MXKViewControllerHandling` properties
|
||||
self.enableBarTintColorStatusChange = NO;
|
||||
self.rageShakeManager = [RageShakeManager sharedManager];
|
||||
|
||||
promptForStunServerFallback = NO;
|
||||
_shouldPromptForStunServerFallback = NO;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
|
@ -229,6 +235,13 @@
|
|||
|
||||
#pragma mark - MXCallDelegate
|
||||
|
||||
- (void)call:(MXCall *)call stateDidChange:(MXCallState)state reason:(MXEvent *)event
|
||||
{
|
||||
[super call:call stateDidChange:state reason:event];
|
||||
|
||||
[self checkStunServerFallbackWithCallState:state];
|
||||
}
|
||||
|
||||
- (void)call:(MXCall *)call didEncounterError:(NSError *)error
|
||||
{
|
||||
if ([error.domain isEqualToString:MXEncryptingErrorDomain]
|
||||
|
@ -333,6 +346,41 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Fallback STUN server
|
||||
|
||||
- (void)checkStunServerFallbackWithCallState:(MXCallState)callState
|
||||
{
|
||||
// Detect if we should display the prompt to fallback to the STUN server defined
|
||||
// in the app plist if the homeserver does not provide STUN or TURN servers.
|
||||
// We should if the call ends while we were in connecting state
|
||||
if (!self.mainSession.callManager.turnServers
|
||||
&& !self.mainSession.callManager.fallbackSTUNServer
|
||||
&& !RiotSettings.shared.isAllowStunServerFallbackHasBeenSetOnce)
|
||||
{
|
||||
switch (callState)
|
||||
{
|
||||
case MXCallStateConnecting:
|
||||
promptForStunServerFallback = YES;
|
||||
break;
|
||||
|
||||
case MXCallStateConnected:
|
||||
promptForStunServerFallback = NO;
|
||||
break;
|
||||
|
||||
case MXCallStateEnded:
|
||||
if (promptForStunServerFallback)
|
||||
{
|
||||
_shouldPromptForStunServerFallback = YES;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Properties
|
||||
|
||||
- (UIImage*)picturePlaceholder
|
||||
|
|
|
@ -34,9 +34,20 @@ final class ActivityIndicatorPresenter: ActivityIndicatorPresenterType {
|
|||
private weak var activityIndicatorView: ActivityIndicatorView?
|
||||
private weak var presentingView: UIView?
|
||||
|
||||
var isPresenting: Bool {
|
||||
return self.activityIndicatorView != nil
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func presentActivityIndicator(on view: UIView, animated: Bool, completion: (() -> Void)? = nil) {
|
||||
if self.presentingView != nil {
|
||||
if let completion = completion {
|
||||
completion()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
self.presentingView = view
|
||||
|
||||
view.isUserInteractionEnabled = false
|
||||
|
@ -85,6 +96,7 @@ final class ActivityIndicatorPresenter: ActivityIndicatorPresenterType {
|
|||
}
|
||||
|
||||
presentingView.isUserInteractionEnabled = true
|
||||
self.presentingView = nil
|
||||
|
||||
let animationInstructions = {
|
||||
activityIndicatorView.alpha = 0
|
||||
|
|
|
@ -149,8 +149,10 @@
|
|||
// Screen tracking
|
||||
[[Analytics sharedInstance] trackScreen:_screenName];
|
||||
|
||||
// Check whether the access to the local contacts has not been already asked.
|
||||
if ([CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts] == CNAuthorizationStatusNotDetermined)
|
||||
// Check whether the access to the local contacts has not been already asked
|
||||
// and check that the user has decided to use or not to use an identity server
|
||||
if ([CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts] == CNAuthorizationStatusNotDetermined
|
||||
|| !contactsDataSource.mxSession.hasAccountDataIdentityServerValue)
|
||||
{
|
||||
// Allow by default the local contacts sync in order to discover matrix users.
|
||||
// This setting change will trigger the loading of the local contacts, which will automatically
|
||||
|
|
|
@ -86,13 +86,6 @@
|
|||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onContactManagerDidUpdate:) name:kMXKContactManagerDidUpdateMatrixContactsNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onContactManagerDidUpdate:) name:kMXKContactManagerDidUpdateLocalContactsNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onContactManagerDidUpdate:) name:kMXKContactManagerDidUpdateLocalContactMatrixIDsNotification object:nil];
|
||||
|
||||
// Refresh the matrix identifiers for all the local contacts.
|
||||
if ([CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts] != CNAuthorizationStatusNotDetermined)
|
||||
{
|
||||
// Refresh the matrix identifiers for all the local contacts.
|
||||
[[MXKContactManager sharedManager] updateMatrixIDsForAllLocalContacts];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -622,8 +615,16 @@
|
|||
switch ([CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts])
|
||||
{
|
||||
case CNAuthorizationStatusAuthorized:
|
||||
// Because there is no contacts on the device
|
||||
tableViewCell.textLabel.text = NSLocalizedStringFromTable(@"contacts_address_book_no_contact", @"Vector", nil);
|
||||
if (hideNonMatrixEnabledContacts && !self.mxSession.identityService)
|
||||
{
|
||||
// Because we cannot make lookups with no IS
|
||||
tableViewCell.textLabel.text = NSLocalizedStringFromTable(@"contacts_address_book_no_identity_server", @"Vector", nil);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Because there is no contacts on the device
|
||||
tableViewCell.textLabel.text = NSLocalizedStringFromTable(@"contacts_address_book_no_contact", @"Vector", nil);
|
||||
}
|
||||
break;
|
||||
|
||||
case CNAuthorizationStatusNotDetermined:
|
||||
|
|
|
@ -1011,10 +1011,13 @@
|
|||
// The identity server must be defined
|
||||
if (!self.mainSession.matrixRestClient.identityServer)
|
||||
{
|
||||
MXError *error = [[MXError alloc] initWithErrorCode:kMXSDKErrCodeStringMissingParameters error:@"No supplied identity server URL"];
|
||||
NSLog(@"[ContactDetailsViewController] Invite %@ failed", participantId);
|
||||
// Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:[error createNSError]];
|
||||
[self removePendingActionMask];
|
||||
|
||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSBundle mxk_localizedStringForKey:@"error"]
|
||||
message:NSLocalizedStringFromTable(@"room_participants_start_new_chat_error_using_user_email_without_identity_server", @"Vector", nil)
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
[alert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"ok"] style:UIAlertActionStyleDefault handler:nil]];
|
||||
[self presentViewController:alert animated:YES completion:nil];
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ NSString *const kIntegrationManagerMainScreen = nil;
|
|||
NSString *const kIntegrationManagerAddIntegrationScreen = @"add_integ";
|
||||
|
||||
|
||||
@interface IntegrationManagerViewController ()
|
||||
@interface IntegrationManagerViewController () <ServiceTermsModalCoordinatorBridgePresenterDelegate>
|
||||
{
|
||||
MXSession *mxSession;
|
||||
NSString *roomId;
|
||||
|
@ -37,6 +37,8 @@ NSString *const kIntegrationManagerAddIntegrationScreen = @"add_integ";
|
|||
MXHTTPOperation *operation;
|
||||
}
|
||||
|
||||
@property (nonatomic, strong) ServiceTermsModalCoordinatorBridgePresenter *serviceTermsModalCoordinatorBridgePresenter;
|
||||
|
||||
@end
|
||||
|
||||
@implementation IntegrationManagerViewController
|
||||
|
@ -67,10 +69,15 @@ NSString *const kIntegrationManagerAddIntegrationScreen = @"add_integ";
|
|||
operation = nil;
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewWillAppear:animated];
|
||||
[super viewDidLoad];
|
||||
|
||||
[self loadData];
|
||||
}
|
||||
|
||||
- (void)loadData
|
||||
{
|
||||
if (!self.URL && !operation)
|
||||
{
|
||||
[self startActivityIndicator];
|
||||
|
@ -94,9 +101,17 @@ NSString *const kIntegrationManagerAddIntegrationScreen = @"add_integ";
|
|||
self->operation = nil;
|
||||
[self stopActivityIndicator];
|
||||
|
||||
[self withdrawViewControllerAnimated:YES completion:^{
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
}];
|
||||
if ([error.domain isEqualToString:WidgetManagerErrorDomain]
|
||||
&& error.code == WidgetManagerErrorCodeTermsNotSigned)
|
||||
{
|
||||
[self presentTerms];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self withdrawViewControllerAnimated:YES completion:^{
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
}];
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
@ -681,4 +696,40 @@ NSString *const kIntegrationManagerAddIntegrationScreen = @"add_integ";
|
|||
}];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Service terms
|
||||
|
||||
- (void)presentTerms
|
||||
{
|
||||
WidgetManagerConfig *config = [[WidgetManager sharedManager] configForUser:mxSession.myUser.userId];
|
||||
|
||||
NSLog(@"[IntegrationManagerVC] presentTerms for %@", config.baseUrl);
|
||||
|
||||
ServiceTermsModalCoordinatorBridgePresenter *serviceTermsModalCoordinatorBridgePresenter = [[ServiceTermsModalCoordinatorBridgePresenter alloc] initWithSession:mxSession baseUrl:config.baseUrl
|
||||
serviceType:MXServiceTypeIntegrationManager
|
||||
outOfContext:NO
|
||||
accessToken:config.scalarToken];
|
||||
|
||||
serviceTermsModalCoordinatorBridgePresenter.delegate = self;
|
||||
|
||||
[serviceTermsModalCoordinatorBridgePresenter presentFrom:self animated:YES];
|
||||
self.serviceTermsModalCoordinatorBridgePresenter = serviceTermsModalCoordinatorBridgePresenter;
|
||||
}
|
||||
|
||||
- (void)serviceTermsModalCoordinatorBridgePresenterDelegateDidAccept:(ServiceTermsModalCoordinatorBridgePresenter * _Nonnull)coordinatorBridgePresenter
|
||||
{
|
||||
[coordinatorBridgePresenter dismissWithAnimated:YES completion:^{
|
||||
[self loadData];
|
||||
}];
|
||||
self.serviceTermsModalCoordinatorBridgePresenter = nil;
|
||||
}
|
||||
|
||||
- (void)serviceTermsModalCoordinatorBridgePresenterDelegateDidCancel:(ServiceTermsModalCoordinatorBridgePresenter * _Nonnull)coordinatorBridgePresenter
|
||||
{
|
||||
[coordinatorBridgePresenter dismissWithAnimated:YES completion:^{
|
||||
[self withdrawViewControllerAnimated:YES completion:nil];
|
||||
}];
|
||||
self.serviceTermsModalCoordinatorBridgePresenter = nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -19,10 +19,13 @@
|
|||
|
||||
#import "AppDelegate.h"
|
||||
#import "IntegrationManagerViewController.h"
|
||||
#import "Riot-Swift.h"
|
||||
|
||||
NSString *const kJavascriptSendResponseToPostMessageAPI = @"riotIOS.sendResponse('%@', %@);";
|
||||
|
||||
@interface WidgetViewController ()
|
||||
@interface WidgetViewController () <ServiceTermsModalCoordinatorBridgePresenterDelegate>
|
||||
|
||||
@property (nonatomic, strong) ServiceTermsModalCoordinatorBridgePresenter *serviceTermsModalCoordinatorBridgePresenter;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -363,15 +366,73 @@ NSString *const kJavascriptSendResponseToPostMessageAPI = @"riotIOS.sendResponse
|
|||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
NSLog(@"[WidgetVC] fixScalarToken: DONE");
|
||||
|
||||
self.URL = [self stringByReplacingScalarTokenInString:self.URL byScalarToken:scalarToken];
|
||||
|
||||
self->webView.hidden = NO;
|
||||
[self loadDataWithScalarToken:scalarToken];
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
NSLog(@"[WidgetVC] fixScalarToken: Error: %@", error);
|
||||
[self showErrorAsAlert:error];
|
||||
|
||||
if ([error.domain isEqualToString:WidgetManagerErrorDomain]
|
||||
&& error.code == WidgetManagerErrorCodeTermsNotSigned)
|
||||
{
|
||||
[self presentTerms];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self showErrorAsAlert:error];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)loadDataWithScalarToken:(NSString*)scalarToken
|
||||
{
|
||||
self.URL = [self stringByReplacingScalarTokenInString:self.URL byScalarToken:scalarToken];
|
||||
|
||||
self->webView.hidden = NO;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma mark - Service terms
|
||||
|
||||
- (void)presentTerms
|
||||
{
|
||||
if (self.serviceTermsModalCoordinatorBridgePresenter)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
WidgetManagerConfig *config = [[WidgetManager sharedManager] configForUser:widget.mxSession.myUser.userId];
|
||||
|
||||
NSLog(@"[WidgetVC] presentTerms for %@", config.baseUrl);
|
||||
|
||||
ServiceTermsModalCoordinatorBridgePresenter *serviceTermsModalCoordinatorBridgePresenter = [[ServiceTermsModalCoordinatorBridgePresenter alloc] initWithSession:widget.mxSession baseUrl:config.baseUrl
|
||||
serviceType:MXServiceTypeIntegrationManager
|
||||
outOfContext:NO
|
||||
accessToken:config.scalarToken];
|
||||
serviceTermsModalCoordinatorBridgePresenter.delegate = self;
|
||||
|
||||
[serviceTermsModalCoordinatorBridgePresenter presentFrom:self animated:YES];
|
||||
self.serviceTermsModalCoordinatorBridgePresenter = serviceTermsModalCoordinatorBridgePresenter;
|
||||
}
|
||||
|
||||
- (void)serviceTermsModalCoordinatorBridgePresenterDelegateDidAccept:(ServiceTermsModalCoordinatorBridgePresenter * _Nonnull)coordinatorBridgePresenter
|
||||
{
|
||||
MXWeakify(self);
|
||||
[coordinatorBridgePresenter dismissWithAnimated:YES completion:^{
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
WidgetManagerConfig *config = [[WidgetManager sharedManager] configForUser:self->widget.mxSession.myUser.userId];
|
||||
[self loadDataWithScalarToken:config.scalarToken];
|
||||
}];
|
||||
self.serviceTermsModalCoordinatorBridgePresenter = nil;
|
||||
}
|
||||
|
||||
- (void)serviceTermsModalCoordinatorBridgePresenterDelegateDidCancel:(ServiceTermsModalCoordinatorBridgePresenter * _Nonnull)coordinatorBridgePresenter
|
||||
{
|
||||
[coordinatorBridgePresenter dismissWithAnimated:YES completion:^{
|
||||
[self withdrawViewControllerAnimated:YES completion:nil];
|
||||
}];
|
||||
self.serviceTermsModalCoordinatorBridgePresenter = nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -99,8 +99,10 @@
|
|||
{
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Check whether the access to the local contacts has not been already asked.
|
||||
if ([CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts] == CNAuthorizationStatusNotDetermined)
|
||||
// Check whether the access to the local contacts has not been already asked
|
||||
// and check that the user has decided to use or not to use an identity server
|
||||
if ([CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts] == CNAuthorizationStatusNotDetermined
|
||||
|| !contactsDataSource.mxSession.hasAccountDataIdentityServerValue)
|
||||
{
|
||||
// Allow by default the local contacts sync in order to discover matrix users.
|
||||
// This setting change will trigger the loading of the local contacts, which will automatically
|
||||
|
@ -108,6 +110,9 @@
|
|||
[MXKAppSettings standardAppSettings].syncLocalContacts = YES;
|
||||
}
|
||||
|
||||
// Refresh the local contacts list.
|
||||
[[MXKContactManager sharedManager] refreshLocalContacts];
|
||||
|
||||
[AppDelegate theDelegate].masterTabBarController.navigationItem.title = NSLocalizedStringFromTable(@"title_people", @"Vector", nil);
|
||||
[AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = ThemeService.shared.riotColorOrange;
|
||||
|
||||
|
|
|
@ -798,7 +798,9 @@
|
|||
- (void)addRoomThirdPartyInviteToParticipants:(MXRoomThirdPartyInvite*)roomThirdPartyInvite roomState:(MXRoomState*)roomState
|
||||
{
|
||||
// If the homeserver has converted the 3pid invite into a room member, do no show it
|
||||
if (![roomState memberWithThirdPartyInviteToken:roomThirdPartyInvite.token])
|
||||
// If the invite has been revoked (null display name), do not show it too.
|
||||
if (![roomState memberWithThirdPartyInviteToken:roomThirdPartyInvite.token]
|
||||
&& roomThirdPartyInvite.displayname)
|
||||
{
|
||||
Contact *contact = [[Contact alloc] initMatrixContactWithDisplayName:roomThirdPartyInvite.displayname andMatrixID:nil];
|
||||
contact.isThirdPartyInvite = YES;
|
||||
|
@ -1373,8 +1375,6 @@
|
|||
|
||||
if (section == participantsSection || section == invitedSection)
|
||||
{
|
||||
__weak typeof(self) weakSelf = self;
|
||||
|
||||
if (currentAlert)
|
||||
{
|
||||
[currentAlert dismissViewControllerAnimated:NO completion:nil];
|
||||
|
@ -1384,6 +1384,7 @@
|
|||
if (section == participantsSection && userParticipant && (0 == row) && !currentSearchText.length)
|
||||
{
|
||||
// Leave ?
|
||||
MXWeakify(self);
|
||||
currentAlert = [UIAlertController alertControllerWithTitle:NSLocalizedStringFromTable(@"room_participants_leave_prompt_title", @"Vector", nil)
|
||||
message:NSLocalizedStringFromTable(@"room_participants_leave_prompt_msg", @"Vector", nil)
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
@ -1392,11 +1393,8 @@
|
|||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
self->currentAlert = nil;
|
||||
}
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
self->currentAlert = nil;
|
||||
|
||||
}]];
|
||||
|
||||
|
@ -1404,25 +1402,25 @@
|
|||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
self->currentAlert = nil;
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
self->currentAlert = nil;
|
||||
|
||||
[self addPendingActionMask];
|
||||
MXWeakify(self);
|
||||
[self.mxRoom leave:^{
|
||||
|
||||
[self addPendingActionMask];
|
||||
[self.mxRoom leave:^{
|
||||
|
||||
[self withdrawViewControllerAnimated:YES completion:nil];
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
||||
[self removePendingActionMask];
|
||||
NSLog(@"[RoomParticipantsVC] Leave room %@ failed", self.mxRoom.roomId);
|
||||
// Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
|
||||
}];
|
||||
}
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
[self withdrawViewControllerAnimated:YES completion:nil];
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
[self removePendingActionMask];
|
||||
NSLog(@"[RoomParticipantsVC] Leave room %@ failed", self.mxRoom.roomId);
|
||||
// Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
|
||||
}];
|
||||
|
||||
}]];
|
||||
|
||||
|
@ -1464,6 +1462,7 @@
|
|||
if (row < participants.count)
|
||||
{
|
||||
Contact *contact = participants[row];
|
||||
MXWeakify(self);
|
||||
|
||||
if (contact.mxMember)
|
||||
{
|
||||
|
@ -1479,11 +1478,8 @@
|
|||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
self->currentAlert = nil;
|
||||
}
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
self->currentAlert = nil;
|
||||
|
||||
}]];
|
||||
|
||||
|
@ -1491,51 +1487,80 @@
|
|||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
self->currentAlert = nil;
|
||||
|
||||
[self addPendingActionMask];
|
||||
[self.mxRoom kickUser:memberUserId
|
||||
reason:nil
|
||||
success:^{
|
||||
|
||||
[self removePendingActionMask];
|
||||
|
||||
[participants removeObjectAtIndex:row];
|
||||
|
||||
// Refresh display
|
||||
[self.tableView reloadData];
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
||||
[self removePendingActionMask];
|
||||
NSLog(@"[RoomParticipantsVC] Kick %@ failed", memberUserId);
|
||||
// Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
|
||||
}];
|
||||
}
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
self->currentAlert = nil;
|
||||
|
||||
[self addPendingActionMask];
|
||||
MXWeakify(self);
|
||||
[self.mxRoom kickUser:memberUserId
|
||||
reason:nil
|
||||
success:^{
|
||||
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
[self removePendingActionMask];
|
||||
|
||||
[participants removeObjectAtIndex:row];
|
||||
|
||||
// Refresh display
|
||||
[self.tableView reloadData];
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
[self removePendingActionMask];
|
||||
NSLog(@"[RoomParticipantsVC] Kick %@ failed", memberUserId);
|
||||
// Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
|
||||
}];
|
||||
|
||||
}]];
|
||||
}
|
||||
else
|
||||
else if (contact.mxThirdPartyInvite)
|
||||
{
|
||||
// This is a third-party invite, it could not be removed until the api exists
|
||||
// This is a third-party invite
|
||||
currentAlert = [UIAlertController alertControllerWithTitle:nil
|
||||
message:NSLocalizedStringFromTable(@"room_participants_remove_third_party_invite_msg", @"Vector", nil)
|
||||
message:NSLocalizedStringFromTable(@"room_participants_remove_third_party_invite_prompt_msg", @"Vector", nil)
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
[currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"]
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
self->currentAlert = nil;
|
||||
}
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
self->currentAlert = nil;
|
||||
|
||||
}]];
|
||||
|
||||
[currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"remove", @"Vector", nil)
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
self->currentAlert = nil;
|
||||
|
||||
[self addPendingActionMask];
|
||||
MXWeakify(self);
|
||||
[self.mxRoom sendStateEventOfType:kMXEventTypeStringRoomThirdPartyInvite
|
||||
content:@{} stateKey:contact.mxThirdPartyInvite.token success:^(NSString *eventId) {
|
||||
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
[self removePendingActionMask];
|
||||
|
||||
[participants removeObjectAtIndex:row];
|
||||
|
||||
// Refresh display
|
||||
[self.tableView reloadData];
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
[self removePendingActionMask];
|
||||
NSLog(@"[RoomParticipantsVC] Revoke 3pid invite failed");
|
||||
// Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
|
||||
}];
|
||||
|
||||
}]];
|
||||
}
|
||||
|
@ -1646,8 +1671,18 @@
|
|||
[self removePendingActionMask];
|
||||
|
||||
NSLog(@"[RoomParticipantsVC] Invite be email %@ failed", participantId);
|
||||
|
||||
// Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
if ([error.domain isEqualToString:kMXRestClientErrorDomain]
|
||||
&& error.code == MXRestClientErrorMissingIdentityServer)
|
||||
{
|
||||
NSString *message = [NSBundle mxk_localizedStringForKey:@"error_invite_3pid_with_no_identity_server"];
|
||||
[[AppDelegate theDelegate] showAlertWithTitle:message message:nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
}
|
||||
}];
|
||||
}
|
||||
else //if ([MXTools isMatrixUserIdentifier:participantId])
|
||||
|
|
|
@ -5098,8 +5098,16 @@
|
|||
|
||||
NSLog(@"[RoomVC] Invite be email %@ failed", participantId);
|
||||
// Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
|
||||
if ([error.domain isEqualToString:kMXRestClientErrorDomain]
|
||||
&& error.code == MXRestClientErrorMissingIdentityServer)
|
||||
{
|
||||
NSString *message = [NSBundle mxk_localizedStringForKey:@"error_invite_3pid_with_no_identity_server"];
|
||||
[[AppDelegate theDelegate] showAlertWithTitle:message message:nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
}
|
||||
}];
|
||||
}
|
||||
else //if ([MXTools isMatrixUserIdentifier:participantId])
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Modal/Show ServiceTermsModalScreen
|
||||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
import UIKit
|
||||
|
||||
final class ServiceTermsModalScreenCoordinator: ServiceTermsModalScreenCoordinatorType {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private var serviceTermsModalScreenViewModel: ServiceTermsModalScreenViewModelType
|
||||
private let serviceTermsModalScreenViewController: ServiceTermsModalScreenViewController
|
||||
|
||||
// Must be used only internally
|
||||
var childCoordinators: [Coordinator] = []
|
||||
|
||||
// MARK: Public
|
||||
|
||||
weak var delegate: ServiceTermsModalScreenCoordinatorDelegate?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(serviceTerms: MXServiceTerms, outOfContext: Bool = false) {
|
||||
|
||||
let serviceTermsModalScreenViewModel = ServiceTermsModalScreenViewModel(serviceTerms: serviceTerms, outOfContext: outOfContext)
|
||||
let serviceTermsModalScreenViewController = ServiceTermsModalScreenViewController.instantiate(with: serviceTermsModalScreenViewModel)
|
||||
self.serviceTermsModalScreenViewModel = serviceTermsModalScreenViewModel
|
||||
self.serviceTermsModalScreenViewController = serviceTermsModalScreenViewController
|
||||
}
|
||||
|
||||
// MARK: - Public methods
|
||||
|
||||
func start() {
|
||||
self.serviceTermsModalScreenViewModel.coordinatorDelegate = self
|
||||
}
|
||||
|
||||
func toPresentable() -> UIViewController {
|
||||
return self.serviceTermsModalScreenViewController
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - ServiceTermsModalScreenViewModelCoordinatorDelegate
|
||||
extension ServiceTermsModalScreenCoordinator: ServiceTermsModalScreenViewModelCoordinatorDelegate {
|
||||
|
||||
func serviceTermsModalScreenViewModelDidAccept(_ viewModel: ServiceTermsModalScreenViewModelType) {
|
||||
self.delegate?.serviceTermsModalScreenCoordinatorDidAccept(self)
|
||||
}
|
||||
|
||||
func serviceTermsModalScreenViewModel(_ coordinator: ServiceTermsModalScreenViewModelType, displayPolicy policy: MXLoginPolicyData) {
|
||||
self.delegate?.serviceTermsModalScreenCoordinator(self, displayPolicy: policy)
|
||||
}
|
||||
|
||||
func serviceTermsModalScreenViewModelDidDecline(_ viewModel: ServiceTermsModalScreenViewModelType) {
|
||||
self.delegate?.serviceTermsModalScreenCoordinatorDidDecline(self)
|
||||
}
|
||||
|
||||
func serviceTermsModalScreenViewModelDidCancel(_ viewModel: ServiceTermsModalScreenViewModelType) {
|
||||
self.delegate?.serviceTermsModalScreenCoordinatorDidCancel(self)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Modal/Show ServiceTermsModalScreen
|
||||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
protocol ServiceTermsModalScreenCoordinatorDelegate: class {
|
||||
func serviceTermsModalScreenCoordinatorDidAccept(_ coordinator: ServiceTermsModalScreenCoordinatorType)
|
||||
func serviceTermsModalScreenCoordinator(_ coordinator: ServiceTermsModalScreenCoordinatorType, displayPolicy policy: MXLoginPolicyData)
|
||||
func serviceTermsModalScreenCoordinatorDidDecline(_ coordinator: ServiceTermsModalScreenCoordinatorType)
|
||||
func serviceTermsModalScreenCoordinatorDidCancel(_ coordinator: ServiceTermsModalScreenCoordinatorType)
|
||||
}
|
||||
|
||||
/// `ServiceTermsModalScreenCoordinatorType` is a protocol describing a Coordinator that handle key backup setup passphrase navigation flow.
|
||||
protocol ServiceTermsModalScreenCoordinatorType: Coordinator, Presentable {
|
||||
var delegate: ServiceTermsModalScreenCoordinatorDelegate? { get }
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Modal/Show ServiceTermsModalScreen
|
||||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
/// ServiceTermsModalScreenViewController view actions exposed to view model
|
||||
enum ServiceTermsModalScreenViewAction {
|
||||
case load
|
||||
case display(MXLoginPolicyData)
|
||||
case accept
|
||||
case decline
|
||||
case cancel
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="V8j-Lb-PgC">
|
||||
<device id="retina6_1" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Service Terms Modal Screen View Controller-->
|
||||
<scene sceneID="mt5-wz-YKA">
|
||||
<objects>
|
||||
<viewController extendedLayoutIncludesOpaqueBars="YES" automaticallyAdjustsScrollViewInsets="NO" id="V8j-Lb-PgC" customClass="ServiceTermsModalScreenViewController" customModule="Riot" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="EL9-GA-lwo">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="9U2-KL-ZVA">
|
||||
<rect key="frame" x="0.0" y="44" width="414" height="852"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="e7g-um-WO4">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="852"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="voD-3Q-ryt">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="852"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="To continue you need to accept the Terms of this service." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bxI-mu-qng">
|
||||
<rect key="frame" x="20" y="20" width="374" height="100"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="100" id="1bP-8m-xrd"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="swq-xw-ItG">
|
||||
<rect key="frame" x="20" y="128" width="374" height="600"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</tableView>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="dcx-ju-f0Q">
|
||||
<rect key="frame" x="20" y="736" width="374" height="96"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DOt-5E-FjF">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="44"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="44" id="d2a-Dw-Pu5"/>
|
||||
</constraints>
|
||||
<state key="normal" title="Accept"/>
|
||||
<connections>
|
||||
<action selector="acceptButtonAction:" destination="V8j-Lb-PgC" eventType="touchUpInside" id="uvI-tt-Nfj"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="QHr-gh-dAD">
|
||||
<rect key="frame" x="0.0" y="52" width="374" height="44"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="44" id="y6d-Vg-5PP"/>
|
||||
</constraints>
|
||||
<state key="normal" title="Decline">
|
||||
<color key="titleColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="declineButtonAction:" destination="V8j-Lb-PgC" eventType="touchUpInside" id="MTU-9k-8yo"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="bxI-mu-qng" firstAttribute="leading" secondItem="voD-3Q-ryt" secondAttribute="leading" constant="20" symbolic="YES" id="1K2-u8-QsL"/>
|
||||
<constraint firstAttribute="trailing" secondItem="bxI-mu-qng" secondAttribute="trailing" constant="20" symbolic="YES" id="41D-TP-69f"/>
|
||||
<constraint firstItem="swq-xw-ItG" firstAttribute="top" secondItem="bxI-mu-qng" secondAttribute="bottom" constant="8" symbolic="YES" id="9Gg-Xb-o2W"/>
|
||||
<constraint firstItem="bxI-mu-qng" firstAttribute="top" secondItem="voD-3Q-ryt" secondAttribute="top" constant="20" symbolic="YES" id="W1m-x0-TyS"/>
|
||||
<constraint firstItem="dcx-ju-f0Q" firstAttribute="leading" secondItem="voD-3Q-ryt" secondAttribute="leading" constant="20" symbolic="YES" id="Wcx-d6-M14"/>
|
||||
<constraint firstAttribute="trailing" secondItem="swq-xw-ItG" secondAttribute="trailing" constant="20" symbolic="YES" id="Y5v-Gg-xkM"/>
|
||||
<constraint firstAttribute="bottom" secondItem="dcx-ju-f0Q" secondAttribute="bottom" constant="20" symbolic="YES" id="cpa-Lq-Mvs"/>
|
||||
<constraint firstAttribute="trailing" secondItem="dcx-ju-f0Q" secondAttribute="trailing" constant="20" symbolic="YES" id="eGO-kM-neh"/>
|
||||
<constraint firstAttribute="width" priority="750" constant="500" id="glD-Sz-73O"/>
|
||||
<constraint firstItem="dcx-ju-f0Q" firstAttribute="top" secondItem="swq-xw-ItG" secondAttribute="bottom" constant="8" symbolic="YES" id="zYm-2k-kvi"/>
|
||||
<constraint firstItem="swq-xw-ItG" firstAttribute="leading" secondItem="voD-3Q-ryt" secondAttribute="leading" constant="20" symbolic="YES" id="ze1-Iw-v9U"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="voD-3Q-ryt" secondAttribute="bottom" id="63a-5e-ptU"/>
|
||||
<constraint firstItem="voD-3Q-ryt" firstAttribute="centerX" secondItem="e7g-um-WO4" secondAttribute="centerX" id="P2G-mq-gQW"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="voD-3Q-ryt" secondAttribute="trailing" id="QgV-SO-5yf"/>
|
||||
<constraint firstItem="voD-3Q-ryt" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="e7g-um-WO4" secondAttribute="leading" id="YPo-u1-PtT"/>
|
||||
<constraint firstItem="voD-3Q-ryt" firstAttribute="top" secondItem="e7g-um-WO4" secondAttribute="top" id="rhQ-96-szL"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="e7g-um-WO4" firstAttribute="height" secondItem="9U2-KL-ZVA" secondAttribute="height" priority="500" id="GP8-i4-Fqh"/>
|
||||
<constraint firstAttribute="trailing" secondItem="e7g-um-WO4" secondAttribute="trailing" id="GyG-Fh-PME"/>
|
||||
<constraint firstItem="e7g-um-WO4" firstAttribute="width" secondItem="9U2-KL-ZVA" secondAttribute="width" id="Ok2-WQ-Zgc"/>
|
||||
<constraint firstAttribute="bottom" secondItem="e7g-um-WO4" secondAttribute="bottom" id="Y46-NP-zAc"/>
|
||||
<constraint firstItem="e7g-um-WO4" firstAttribute="leading" secondItem="9U2-KL-ZVA" secondAttribute="leading" id="aoV-Yh-AcD"/>
|
||||
<constraint firstItem="e7g-um-WO4" firstAttribute="top" secondItem="9U2-KL-ZVA" secondAttribute="top" id="pFN-bA-SHw"/>
|
||||
</constraints>
|
||||
</scrollView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.94509803921568625" green="0.96078431372549022" blue="0.97254901960784312" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="9U2-KL-ZVA" secondAttribute="bottom" id="7Cb-nY-CsO"/>
|
||||
<constraint firstItem="9U2-KL-ZVA" firstAttribute="leading" secondItem="bFg-jh-JZB" secondAttribute="leading" id="GdQ-hK-muG"/>
|
||||
<constraint firstItem="bFg-jh-JZB" firstAttribute="trailing" secondItem="9U2-KL-ZVA" secondAttribute="trailing" id="sbD-ek-vGJ"/>
|
||||
<constraint firstItem="bFg-jh-JZB" firstAttribute="top" secondItem="9U2-KL-ZVA" secondAttribute="top" id="wTB-V6-IHV"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="bFg-jh-JZB"/>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="acceptButton" destination="DOt-5E-FjF" id="ktw-U4-efQ"/>
|
||||
<outlet property="declineButton" destination="QHr-gh-dAD" id="QOS-rE-4SP"/>
|
||||
<outlet property="messageLabel" destination="bxI-mu-qng" id="pbX-aZ-inC"/>
|
||||
<outlet property="scrollView" destination="9U2-KL-ZVA" id="ojG-2y-X7b"/>
|
||||
<outlet property="tableView" destination="swq-xw-ItG" id="Fwb-Sc-bec"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="zK0-v6-7Wt" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-3198" y="-647"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,313 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Modal/Show ServiceTermsModalScreen
|
||||
/*
|
||||
Copyright 2019 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 UIKit
|
||||
|
||||
final class ServiceTermsModalScreenViewController: UIViewController {
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Outlets
|
||||
|
||||
@IBOutlet private weak var scrollView: UIScrollView!
|
||||
|
||||
@IBOutlet private weak var messageLabel: UILabel!
|
||||
@IBOutlet private weak var tableView: UITableView!
|
||||
@IBOutlet private weak var acceptButton: UIButton!
|
||||
@IBOutlet private weak var declineButton: UIButton!
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private var viewModel: ServiceTermsModalScreenViewModelType!
|
||||
private var theme: Theme!
|
||||
private var errorPresenter: MXKErrorPresentation!
|
||||
private var activityPresenter: ActivityIndicatorPresenter!
|
||||
|
||||
private var policies: [MXLoginPolicyData] = []
|
||||
|
||||
/// Policies checked by the end user
|
||||
private var checkedPolicies: Set<Int> = []
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
class func instantiate(with viewModel: ServiceTermsModalScreenViewModelType) -> ServiceTermsModalScreenViewController {
|
||||
let viewController = StoryboardScene.ServiceTermsModalScreenViewController.initialScene.instantiate()
|
||||
viewController.viewModel = viewModel
|
||||
viewController.theme = ThemeService.shared().theme
|
||||
return viewController
|
||||
}
|
||||
|
||||
// MARK: - Life cycle
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
|
||||
self.title = VectorL10n.serviceTermsModalTitle
|
||||
|
||||
self.setupViews()
|
||||
self.activityPresenter = ActivityIndicatorPresenter()
|
||||
self.errorPresenter = MXKErrorAlertPresentation()
|
||||
|
||||
self.registerThemeServiceDidChangeThemeNotification()
|
||||
self.update(theme: self.theme)
|
||||
|
||||
self.viewModel.viewDelegate = self
|
||||
|
||||
self.viewModel.process(viewAction: .load)
|
||||
}
|
||||
|
||||
override var preferredStatusBarStyle: UIStatusBarStyle {
|
||||
return self.theme.statusBarStyle
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func update(theme: Theme) {
|
||||
self.theme = theme
|
||||
|
||||
self.view.backgroundColor = theme.headerBackgroundColor
|
||||
|
||||
if let navigationBar = self.navigationController?.navigationBar {
|
||||
theme.applyStyle(onNavigationBar: navigationBar)
|
||||
}
|
||||
|
||||
self.messageLabel.textColor = theme.textPrimaryColor
|
||||
|
||||
self.acceptButton.backgroundColor = theme.backgroundColor
|
||||
theme.applyStyle(onButton: self.acceptButton)
|
||||
|
||||
theme.applyStyle(onButton: self.declineButton)
|
||||
self.declineButton.setTitleColor(self.theme.warningColor, for: .normal)
|
||||
|
||||
self.refreshViews()
|
||||
}
|
||||
|
||||
private func registerThemeServiceDidChangeThemeNotification() {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil)
|
||||
}
|
||||
|
||||
@objc private func themeDidChange() {
|
||||
self.update(theme: ThemeService.shared().theme)
|
||||
}
|
||||
|
||||
private func setupViews() {
|
||||
let cancelBarButtonItem = MXKBarButtonItem(title: VectorL10n.cancel, style: .plain) { [weak self] in
|
||||
self?.cancelButtonAction()
|
||||
}
|
||||
|
||||
self.navigationItem.rightBarButtonItem = cancelBarButtonItem
|
||||
|
||||
self.setupTableView()
|
||||
self.scrollView.keyboardDismissMode = .interactive
|
||||
|
||||
self.messageLabel.text = VectorL10n.serviceTermsModalMessage(self.viewModel.serviceUrl)
|
||||
|
||||
self.acceptButton.setTitle(VectorL10n.serviceTermsModalAcceptButton, for: .normal)
|
||||
self.acceptButton.setTitle(VectorL10n.serviceTermsModalAcceptButton, for: .highlighted)
|
||||
self.refreshAcceptButton()
|
||||
|
||||
if self.viewModel.outOfContext
|
||||
&& self.viewModel.serviceType == MXServiceTypeIdentityService {
|
||||
self.title = VectorL10n.serviceTermsModalTitleIdentityServer
|
||||
self.messageLabel.text = VectorL10n.serviceTermsModalMessageIdentityServer(self.viewModel.serviceUrl)
|
||||
|
||||
self.declineButton.setTitle(VectorL10n.serviceTermsModalDeclineButton, for: .normal)
|
||||
self.declineButton.setTitle(VectorL10n.serviceTermsModalDeclineButton, for: .highlighted)
|
||||
} else {
|
||||
self.declineButton.isHidden = true
|
||||
}
|
||||
}
|
||||
|
||||
private func setupTableView() {
|
||||
self.tableView.delegate = self
|
||||
self.tableView.dataSource = self
|
||||
self.tableView.separatorStyle = .none
|
||||
self.tableView.alwaysBounceVertical = false
|
||||
self.tableView.backgroundColor = .clear
|
||||
self.tableView.register(TableViewCellWithCheckBoxAndLabel.nib(), forCellReuseIdentifier: TableViewCellWithCheckBoxAndLabel.defaultReuseIdentifier())
|
||||
}
|
||||
|
||||
private func render(viewState: ServiceTermsModalScreenViewState) {
|
||||
switch viewState {
|
||||
case .loading:
|
||||
self.renderLoading()
|
||||
case .loaded(let policies, let alreadyAcceptedPoliciesUrls):
|
||||
self.renderLoaded(policies: policies, alreadyAcceptedPoliciesUrls: alreadyAcceptedPoliciesUrls)
|
||||
case .accepted:
|
||||
self.renderAccepted()
|
||||
case .error(let error):
|
||||
self.render(error: error)
|
||||
}
|
||||
}
|
||||
|
||||
private func renderLoading() {
|
||||
self.activityPresenter.presentActivityIndicator(on: self.view, animated: true)
|
||||
}
|
||||
|
||||
private func renderLoaded(policies: [MXLoginPolicyData], alreadyAcceptedPoliciesUrls: [String]) {
|
||||
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
|
||||
|
||||
self.policies = policies
|
||||
self.updateCheckedPolicies(with: alreadyAcceptedPoliciesUrls)
|
||||
|
||||
self.refreshViews()
|
||||
}
|
||||
|
||||
private func renderAccepting() {
|
||||
self.activityPresenter.presentActivityIndicator(on: self.view, animated: true)
|
||||
}
|
||||
|
||||
private func renderAccepted() {
|
||||
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
|
||||
}
|
||||
|
||||
private func render(error: Error) {
|
||||
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
|
||||
self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: nil)
|
||||
}
|
||||
|
||||
private func refreshViews() {
|
||||
self.tableView.reloadData()
|
||||
self.refreshAcceptButton()
|
||||
}
|
||||
|
||||
private func refreshAcceptButton() {
|
||||
// Enable the button only if the user has accepted all policies
|
||||
self.acceptButton.isEnabled = (self.policies.count == self.checkedPolicies.count)
|
||||
}
|
||||
|
||||
// Pre-check policies already accepted by the user
|
||||
private func updateCheckedPolicies(with acceptedPoliciesUrls: [String]) {
|
||||
for url in acceptedPoliciesUrls {
|
||||
if let policyIndex = self.policies.firstIndex(where: { $0.url == url }) {
|
||||
checkedPolicies.insert(policyIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@IBAction private func acceptButtonAction(_ sender: Any) {
|
||||
self.viewModel.process(viewAction: .accept)
|
||||
}
|
||||
|
||||
@IBAction private func declineButtonAction(_ sender: Any) {
|
||||
self.viewModel.process(viewAction: .decline)
|
||||
}
|
||||
|
||||
private func cancelButtonAction() {
|
||||
self.viewModel.process(viewAction: .cancel)
|
||||
}
|
||||
|
||||
@objc private func didTapCheckbox(sender: UITapGestureRecognizer) {
|
||||
|
||||
guard let policyIndex = sender.view?.tag else {
|
||||
return
|
||||
}
|
||||
|
||||
if self.checkedPolicies.contains(policyIndex) {
|
||||
self.checkedPolicies.remove(policyIndex)
|
||||
} else {
|
||||
checkedPolicies.insert(policyIndex)
|
||||
}
|
||||
|
||||
self.refreshViews()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - ServiceTermsModalScreenViewModelViewDelegate
|
||||
extension ServiceTermsModalScreenViewController: ServiceTermsModalScreenViewModelViewDelegate {
|
||||
|
||||
func serviceTermsModalScreenViewModel(_ viewModel: ServiceTermsModalScreenViewModelType, didUpdateViewState viewSate: ServiceTermsModalScreenViewState) {
|
||||
self.render(viewState: viewSate)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - UITableViewDataSource
|
||||
|
||||
extension ServiceTermsModalScreenViewController: UITableViewDataSource {
|
||||
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return self.policies.count
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
|
||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: TableViewCellWithCheckBoxAndLabel.defaultReuseIdentifier(), for: indexPath) as? TableViewCellWithCheckBoxAndLabel else {
|
||||
fatalError("\(String(describing: TableViewCellWithCheckBoxAndLabel.self)) should be registered")
|
||||
}
|
||||
|
||||
let policy = policies[indexPath.row]
|
||||
let checked = checkedPolicies.contains(indexPath.row)
|
||||
|
||||
cell.label.attributedText = self.cellLabel(for: policy)
|
||||
cell.label.font = .systemFont(ofSize: 15)
|
||||
cell.isEnabled = checked
|
||||
cell.accessoryType = .disclosureIndicator
|
||||
cell.backgroundColor = self.theme.backgroundColor
|
||||
|
||||
if let checkBox = cell.checkBox, checkBox.gestureRecognizers?.isEmpty ?? true {
|
||||
let gesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didTapCheckbox))
|
||||
gesture.numberOfTapsRequired = 1
|
||||
gesture.numberOfTouchesRequired = 1
|
||||
|
||||
checkBox.isUserInteractionEnabled = true
|
||||
checkBox.tag = indexPath.row
|
||||
checkBox.addGestureRecognizer(gesture)
|
||||
}
|
||||
|
||||
return cell
|
||||
}
|
||||
|
||||
func cellLabel(for policy: MXLoginPolicyData) -> NSAttributedString {
|
||||
|
||||
// TableViewCellWithCheckBoxAndLabel does not have a detailTextLabel
|
||||
// Do it by hand
|
||||
|
||||
var labelDetail: String = ""
|
||||
switch self.viewModel.serviceType {
|
||||
case MXServiceTypeIdentityService:
|
||||
labelDetail = VectorL10n.serviceTermsModalDescriptionForIdentityServer1
|
||||
+ "\n"
|
||||
+ VectorL10n.serviceTermsModalDescriptionForIdentityServer2
|
||||
case MXServiceTypeIntegrationManager:
|
||||
labelDetail = VectorL10n.serviceTermsModalDescriptionForIntegrationManager
|
||||
default: break
|
||||
}
|
||||
|
||||
let label = NSMutableAttributedString(string: policy.name,
|
||||
attributes: [.foregroundColor: theme.textPrimaryColor])
|
||||
label.append(NSAttributedString(string: "\n"))
|
||||
label.append(NSAttributedString(string: labelDetail,
|
||||
attributes: [.foregroundColor: theme.textSecondaryColor]))
|
||||
return label
|
||||
}
|
||||
}
|
||||
|
||||
extension ServiceTermsModalScreenViewController: UITableViewDelegate {
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
let policy = policies[indexPath.row]
|
||||
self.viewModel.process(viewAction: .display(policy))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Modal/Show ServiceTermsModalScreen
|
||||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
final class ServiceTermsModalScreenViewModel: ServiceTermsModalScreenViewModelType {
|
||||
|
||||
// MARK: - Properties
|
||||
let outOfContext: Bool
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let serviceTerms: MXServiceTerms
|
||||
|
||||
// MARK: Public
|
||||
|
||||
var serviceUrl: String {
|
||||
return serviceTerms.baseUrl
|
||||
}
|
||||
var serviceType: MXServiceType {
|
||||
return serviceTerms.serviceType
|
||||
}
|
||||
var policies: [MXLoginPolicyData]?
|
||||
var alreadyAcceptedPoliciesUrls: [String] = []
|
||||
|
||||
weak var viewDelegate: ServiceTermsModalScreenViewModelViewDelegate?
|
||||
weak var coordinatorDelegate: ServiceTermsModalScreenViewModelCoordinatorDelegate?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(serviceTerms: MXServiceTerms, outOfContext: Bool) {
|
||||
self.serviceTerms = serviceTerms
|
||||
self.outOfContext = outOfContext
|
||||
}
|
||||
|
||||
deinit {
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func process(viewAction: ServiceTermsModalScreenViewAction) {
|
||||
switch viewAction {
|
||||
case .load:
|
||||
self.loadTerms()
|
||||
case .display(let policy):
|
||||
self.coordinatorDelegate?.serviceTermsModalScreenViewModel(self, displayPolicy: policy)
|
||||
case .accept:
|
||||
self.acceptTerms()
|
||||
case .decline:
|
||||
self.coordinatorDelegate?.serviceTermsModalScreenViewModelDidDecline(self)
|
||||
case .cancel:
|
||||
self.coordinatorDelegate?.serviceTermsModalScreenViewModelDidCancel(self)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func loadTerms() {
|
||||
|
||||
self.update(viewState: .loading)
|
||||
|
||||
self.serviceTerms.terms({ [weak self] (terms, alreadyAcceptedTermsUrls) in
|
||||
guard let self = self else {
|
||||
return
|
||||
}
|
||||
|
||||
let policies = self.processTerms(terms: terms)
|
||||
self.policies = policies
|
||||
self.alreadyAcceptedPoliciesUrls = alreadyAcceptedTermsUrls ?? []
|
||||
self.update(viewState: .loaded(policies: policies, alreadyAcceptedPoliciesUrls: self.alreadyAcceptedPoliciesUrls))
|
||||
|
||||
}, failure: { [weak self] error in
|
||||
guard let self = self else {
|
||||
return
|
||||
}
|
||||
|
||||
self.update(viewState: .error(error))
|
||||
})
|
||||
}
|
||||
|
||||
private func acceptTerms() {
|
||||
|
||||
self.update(viewState: .loading)
|
||||
|
||||
self.serviceTerms.agree(toTerms: self.termsUrls, success: { [weak self] in
|
||||
guard let self = self else {
|
||||
return
|
||||
}
|
||||
self.update(viewState: .accepted)
|
||||
self.coordinatorDelegate?.serviceTermsModalScreenViewModelDidAccept(self)
|
||||
|
||||
}, failure: { [weak self] (error) in
|
||||
guard let self = self else {
|
||||
return
|
||||
}
|
||||
|
||||
self.update(viewState: .error(error))
|
||||
})
|
||||
}
|
||||
|
||||
private func processTerms(terms: MXLoginTerms?) -> [MXLoginPolicyData] {
|
||||
if let policies = terms?.policiesData(forLanguage: Bundle.mxk_language(), defaultLanguage: Bundle.mxk_fallbackLanguage()) {
|
||||
return policies
|
||||
} else {
|
||||
print("[ServiceTermsModalScreenViewModel] processTerms: Error: No terms for \(String(describing: terms))")
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
private var termsUrls: [String] {
|
||||
guard let policies = self.policies else {
|
||||
return []
|
||||
}
|
||||
return policies.map({ return $0.url })
|
||||
}
|
||||
|
||||
private func update(viewState: ServiceTermsModalScreenViewState) {
|
||||
self.viewDelegate?.serviceTermsModalScreenViewModel(self, didUpdateViewState: viewState)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Modal/Show ServiceTermsModalScreen
|
||||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
protocol ServiceTermsModalScreenViewModelViewDelegate: class {
|
||||
func serviceTermsModalScreenViewModel(_ viewModel: ServiceTermsModalScreenViewModelType, didUpdateViewState viewSate: ServiceTermsModalScreenViewState)
|
||||
}
|
||||
|
||||
protocol ServiceTermsModalScreenViewModelCoordinatorDelegate: class {
|
||||
func serviceTermsModalScreenViewModel(_ coordinator: ServiceTermsModalScreenViewModelType, displayPolicy policy: MXLoginPolicyData)
|
||||
func serviceTermsModalScreenViewModelDidAccept(_ viewModel: ServiceTermsModalScreenViewModelType)
|
||||
func serviceTermsModalScreenViewModelDidDecline(_ viewModel: ServiceTermsModalScreenViewModelType)
|
||||
func serviceTermsModalScreenViewModelDidCancel(_ viewModel: ServiceTermsModalScreenViewModelType)
|
||||
}
|
||||
|
||||
/// Protocol describing the view model used by `ServiceTermsModalScreenViewController`
|
||||
protocol ServiceTermsModalScreenViewModelType {
|
||||
|
||||
var serviceUrl: String { get }
|
||||
var serviceType: MXServiceType { get }
|
||||
/// If true, terms are displayed out of a context of a flow (like a background 3pids lookup)
|
||||
/// In this case, the wording needs to provide more information about the intent
|
||||
var outOfContext: Bool { get }
|
||||
var policies: [MXLoginPolicyData]? { get set }
|
||||
var alreadyAcceptedPoliciesUrls: [String] { get set }
|
||||
|
||||
var viewDelegate: ServiceTermsModalScreenViewModelViewDelegate? { get set }
|
||||
var coordinatorDelegate: ServiceTermsModalScreenViewModelCoordinatorDelegate? { get set }
|
||||
|
||||
func process(viewAction: ServiceTermsModalScreenViewAction)
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Modal/Show ServiceTermsModalScreen
|
||||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
/// ServiceTermsModalScreenViewController view state
|
||||
enum ServiceTermsModalScreenViewState {
|
||||
case loading
|
||||
case loaded(policies: [MXLoginPolicyData], alreadyAcceptedPoliciesUrls: [String])
|
||||
case accepted
|
||||
case error(Error)
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
// File created from FlowTemplate
|
||||
// $ createRootCoordinator.sh Modal ServiceTermsModal ServiceTermsModalScreen
|
||||
/*
|
||||
Copyright 2019 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 UIKit
|
||||
|
||||
@objcMembers
|
||||
final class ServiceTermsModalCoordinator: ServiceTermsModalCoordinatorType {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let navigationRouter: NavigationRouterType
|
||||
private let session: MXSession
|
||||
private let serviceTerms: MXServiceTerms
|
||||
private let outOfContext: Bool
|
||||
|
||||
// MARK: Public
|
||||
|
||||
// Must be used only internally
|
||||
var childCoordinators: [Coordinator] = []
|
||||
|
||||
weak var delegate: ServiceTermsModalCoordinatorDelegate?
|
||||
|
||||
// MARK: - Setup
|
||||
init(session: MXSession, baseUrl: String, serviceType: MXServiceType, outOfContext: Bool, accessToken: String) {
|
||||
self.navigationRouter = NavigationRouter(navigationController: RiotNavigationController())
|
||||
self.session = session
|
||||
self.serviceTerms = MXServiceTerms(baseUrl: baseUrl, serviceType: serviceType, matrixSession: session, accessToken: accessToken)
|
||||
self.outOfContext = outOfContext
|
||||
}
|
||||
|
||||
// MARK: - Public methods
|
||||
|
||||
func start() {
|
||||
let rootCoordinator = self.createServiceTermsModalLoadTermsScreenCoordinator()
|
||||
|
||||
rootCoordinator.start()
|
||||
|
||||
self.add(childCoordinator: rootCoordinator)
|
||||
|
||||
self.navigationRouter.setRootModule(rootCoordinator)
|
||||
}
|
||||
|
||||
func toPresentable() -> UIViewController {
|
||||
return self.navigationRouter.toPresentable()
|
||||
}
|
||||
|
||||
// MARK: - Private methods
|
||||
|
||||
private func createServiceTermsModalLoadTermsScreenCoordinator() -> ServiceTermsModalScreenCoordinator {
|
||||
let coordinator = ServiceTermsModalScreenCoordinator(serviceTerms: self.serviceTerms, outOfContext: self.outOfContext)
|
||||
coordinator.delegate = self
|
||||
return coordinator
|
||||
}
|
||||
|
||||
private func showPolicy(policy: MXLoginPolicyData) {
|
||||
// Display the policy webpage into our webview
|
||||
let webViewViewController: WebViewViewController = WebViewViewController(url: policy.url)
|
||||
webViewViewController.title = policy.name
|
||||
|
||||
let leftBarButtonItem: UIBarButtonItem = UIBarButtonItem(image: UIImage(named: "back_icon"), style: .plain, target: self, action: #selector(didTapCancelOnPolicyScreen))
|
||||
webViewViewController.navigationItem.leftBarButtonItem = leftBarButtonItem
|
||||
|
||||
self.navigationRouter.push(webViewViewController, animated: true, popCompletion: nil)
|
||||
}
|
||||
|
||||
private func removePolicyScreen() {
|
||||
self.navigationRouter.popModule(animated: true)
|
||||
}
|
||||
|
||||
@objc private func didTapCancelOnPolicyScreen() {
|
||||
self.removePolicyScreen()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - ServiceTermsModalLoadTermsScreenCoordinatorDelegate
|
||||
extension ServiceTermsModalCoordinator: ServiceTermsModalScreenCoordinatorDelegate {
|
||||
|
||||
func serviceTermsModalScreenCoordinatorDidAccept(_ coordinator: ServiceTermsModalScreenCoordinatorType) {
|
||||
self.delegate?.serviceTermsModalCoordinatorDidAccept(self)
|
||||
}
|
||||
|
||||
func serviceTermsModalScreenCoordinator(_ coordinator: ServiceTermsModalScreenCoordinatorType, displayPolicy policy: MXLoginPolicyData) {
|
||||
self.showPolicy(policy: policy)
|
||||
}
|
||||
|
||||
func serviceTermsModalScreenCoordinatorDidDecline(_ coordinator: ServiceTermsModalScreenCoordinatorType) {
|
||||
self.delegate?.serviceTermsModalCoordinatorDidDecline(self)
|
||||
}
|
||||
|
||||
func serviceTermsModalScreenCoordinatorDidCancel(_ coordinator: ServiceTermsModalScreenCoordinatorType) {
|
||||
self.delegate?.serviceTermsModalCoordinatorDidCancel(self)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
// File created from FlowTemplate
|
||||
// $ createRootCoordinator.sh Modal ServiceTermsModal ServiceTermsModalLoadTermsScreen
|
||||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
@objc protocol ServiceTermsModalCoordinatorBridgePresenterDelegate {
|
||||
func serviceTermsModalCoordinatorBridgePresenterDelegateDidAccept(_ coordinatorBridgePresenter: ServiceTermsModalCoordinatorBridgePresenter)
|
||||
func serviceTermsModalCoordinatorBridgePresenterDelegateDidDecline(_ coordinatorBridgePresenter: ServiceTermsModalCoordinatorBridgePresenter, session: MXSession)
|
||||
func serviceTermsModalCoordinatorBridgePresenterDelegateDidCancel(_ coordinatorBridgePresenter: ServiceTermsModalCoordinatorBridgePresenter)
|
||||
}
|
||||
|
||||
/// ServiceTermsModalCoordinatorBridgePresenter enables to start ServiceTermsModalCoordinator from a view controller.
|
||||
/// This bridge is used while waiting for global usage of coordinator pattern.
|
||||
@objcMembers
|
||||
final class ServiceTermsModalCoordinatorBridgePresenter: NSObject {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let session: MXSession
|
||||
private let baseUrl: String
|
||||
private let serviceType: MXServiceType
|
||||
private let outOfContext: Bool
|
||||
private let accessToken: String
|
||||
private var coordinator: ServiceTermsModalCoordinator?
|
||||
|
||||
// MARK: Public
|
||||
|
||||
weak var delegate: ServiceTermsModalCoordinatorBridgePresenterDelegate?
|
||||
|
||||
var isPresenting: Bool {
|
||||
return self.coordinator != nil
|
||||
}
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(session: MXSession, baseUrl: String, serviceType: MXServiceType, outOfContext: Bool = false, accessToken: String) {
|
||||
self.session = session
|
||||
self.baseUrl = baseUrl
|
||||
self.serviceType = serviceType
|
||||
self.outOfContext = outOfContext
|
||||
self.accessToken = accessToken
|
||||
super.init()
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
// NOTE: Default value feature is not compatible with Objective-C.
|
||||
// func present(from viewController: UIViewController, animated: Bool) {
|
||||
// self.present(from: viewController, animated: animated)
|
||||
// }
|
||||
|
||||
func present(from viewController: UIViewController, animated: Bool) {
|
||||
let serviceTermsModalCoordinator = ServiceTermsModalCoordinator(session: self.session, baseUrl: self.baseUrl, serviceType: self.serviceType, outOfContext: self.outOfContext, accessToken: accessToken)
|
||||
serviceTermsModalCoordinator.delegate = self
|
||||
viewController.present(serviceTermsModalCoordinator.toPresentable(), animated: animated, completion: nil)
|
||||
serviceTermsModalCoordinator.start()
|
||||
|
||||
if let coordinator = self.coordinator {
|
||||
coordinator.toPresentable().dismiss(animated: false, completion: nil)
|
||||
}
|
||||
|
||||
self.coordinator = serviceTermsModalCoordinator
|
||||
}
|
||||
|
||||
func dismiss(animated: Bool, completion: (() -> Void)?) {
|
||||
guard let coordinator = self.coordinator else {
|
||||
return
|
||||
}
|
||||
coordinator.toPresentable().dismiss(animated: animated) {
|
||||
self.coordinator = nil
|
||||
|
||||
if let completion = completion {
|
||||
completion()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - ServiceTermsModalCoordinatorDelegate
|
||||
extension ServiceTermsModalCoordinatorBridgePresenter: ServiceTermsModalCoordinatorDelegate {
|
||||
|
||||
func serviceTermsModalCoordinatorDidAccept(_ coordinator: ServiceTermsModalCoordinatorType) {
|
||||
self.delegate?.serviceTermsModalCoordinatorBridgePresenterDelegateDidAccept(self)
|
||||
}
|
||||
|
||||
func serviceTermsModalCoordinatorDidDecline(_ coordinator: ServiceTermsModalCoordinatorType) {
|
||||
self.delegate?.serviceTermsModalCoordinatorBridgePresenterDelegateDidDecline(self, session: self.session)
|
||||
}
|
||||
|
||||
func serviceTermsModalCoordinatorDidCancel(_ coordinator: ServiceTermsModalCoordinatorType) {
|
||||
self.delegate?.serviceTermsModalCoordinatorBridgePresenterDelegateDidCancel(self)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
// File created from FlowTemplate
|
||||
// $ createRootCoordinator.sh Modal ServiceTermsModal ServiceTermsModalLoadTermsScreen
|
||||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
protocol ServiceTermsModalCoordinatorDelegate: class {
|
||||
func serviceTermsModalCoordinatorDidAccept(_ coordinator: ServiceTermsModalCoordinatorType)
|
||||
func serviceTermsModalCoordinatorDidDecline(_ coordinator: ServiceTermsModalCoordinatorType)
|
||||
func serviceTermsModalCoordinatorDidCancel(_ coordinator: ServiceTermsModalCoordinatorType)
|
||||
}
|
||||
|
||||
/// `ServiceTermsModalCoordinatorType` is a protocol describing a Coordinator that handle keybackup setup navigation flow.
|
||||
protocol ServiceTermsModalCoordinatorType: Coordinator, Presentable {
|
||||
var delegate: ServiceTermsModalCoordinatorDelegate? { get }
|
||||
}
|
|
@ -0,0 +1,257 @@
|
|||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
@objc protocol SettingsDiscoveryTableViewSectionDelegate: class {
|
||||
|
||||
func settingsDiscoveryTableViewSection(_ settingsDiscoveryTableViewSection: SettingsDiscoveryTableViewSection, tableViewCellClass: MXKTableViewCell.Type, forRow: Int) -> MXKTableViewCell
|
||||
func settingsDiscoveryTableViewSectionDidUpdate(_ settingsDiscoveryTableViewSection: SettingsDiscoveryTableViewSection)
|
||||
}
|
||||
|
||||
private enum DiscoverySectionRows {
|
||||
case info(text: String)
|
||||
case attributedInfo(attributedText: NSAttributedString)
|
||||
case button(title: String, action: () -> Void)
|
||||
case threePid(threePid: MX3PID)
|
||||
}
|
||||
|
||||
@objc final class SettingsDiscoveryTableViewSection: NSObject, Themable {
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
private enum Constants {
|
||||
static let defaultFont = UIFont.systemFont(ofSize: 17.0)
|
||||
}
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
@objc weak var delegate: SettingsDiscoveryTableViewSectionDelegate?
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private var theme: Theme!
|
||||
private var viewModel: SettingsDiscoveryViewModel
|
||||
|
||||
// Need to know the state to make `cellForRow` deliver cells accordingly
|
||||
private var viewState: SettingsDiscoveryViewState = .loading {
|
||||
didSet {
|
||||
self.updateRows()
|
||||
}
|
||||
}
|
||||
|
||||
private var discoveryRows: [DiscoverySectionRows] = []
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
@objc init(viewModel: SettingsDiscoveryViewModel) {
|
||||
self.theme = ThemeService.shared().theme
|
||||
self.viewModel = viewModel
|
||||
super.init()
|
||||
self.viewModel.viewDelegate = self
|
||||
|
||||
self.viewModel.process(viewAction: .load)
|
||||
|
||||
self.registerThemeServiceDidChangeThemeNotification()
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
@objc func numberOfRows() -> Int {
|
||||
return self.discoveryRows.count
|
||||
}
|
||||
|
||||
@objc func cellForRow(atRow row: Int) -> UITableViewCell {
|
||||
|
||||
let discoveryRow = self.discoveryRows[row]
|
||||
|
||||
var cell: UITableViewCell?
|
||||
|
||||
let enableInteraction: Bool
|
||||
|
||||
if case .loading = self.viewState {
|
||||
enableInteraction = false
|
||||
} else {
|
||||
enableInteraction = true
|
||||
}
|
||||
|
||||
switch discoveryRow {
|
||||
case .info(let infoText):
|
||||
if let infoCell: MXKTableViewCell = self.cellType(at: row) {
|
||||
infoCell.textLabel?.numberOfLines = 0
|
||||
infoCell.textLabel?.text = infoText
|
||||
infoCell.selectionStyle = .none
|
||||
cell = infoCell
|
||||
}
|
||||
case .attributedInfo(attributedText: let infoText):
|
||||
if let infoCell: MXKTableViewCell = self.cellType(at: row) {
|
||||
infoCell.textLabel?.numberOfLines = 0
|
||||
infoCell.textLabel?.attributedText = infoText
|
||||
infoCell.selectionStyle = .none
|
||||
cell = infoCell
|
||||
}
|
||||
case .button(title: let title, action: let action):
|
||||
if let buttonCell: MXKTableViewCellWithButton = self.cellType(at: row) {
|
||||
buttonCell.mxkButton.setTitle(title, for: .normal)
|
||||
buttonCell.mxkButton.setTitle(title, for: .highlighted)
|
||||
buttonCell.mxkButton.vc_addAction(action: action)
|
||||
buttonCell.mxkButton.isEnabled = enableInteraction
|
||||
cell = buttonCell
|
||||
}
|
||||
case .threePid(let threePid):
|
||||
if let detailCell: MXKTableViewCell = self.cellType(at: row) {
|
||||
detailCell.accessoryType = .disclosureIndicator
|
||||
|
||||
let formattedThreePid: String?
|
||||
|
||||
switch threePid.medium {
|
||||
case .email:
|
||||
formattedThreePid = threePid.address
|
||||
case .msisdn:
|
||||
formattedThreePid = MXKTools.readableMSISDN(threePid.address)
|
||||
default:
|
||||
formattedThreePid = nil
|
||||
}
|
||||
|
||||
detailCell.textLabel?.text = formattedThreePid
|
||||
detailCell.isUserInteractionEnabled = enableInteraction
|
||||
cell = detailCell
|
||||
}
|
||||
}
|
||||
|
||||
return cell ?? UITableViewCell()
|
||||
}
|
||||
|
||||
@objc func reload() {
|
||||
self.viewModel.process(viewAction: .load)
|
||||
}
|
||||
|
||||
@objc func selectRow(_ row: Int) {
|
||||
let discoveryRow = self.discoveryRows[row]
|
||||
|
||||
switch discoveryRow {
|
||||
case .threePid(threePid: let threePid):
|
||||
self.viewModel.process(viewAction: .select(threePid: threePid))
|
||||
case .attributedInfo(attributedText: _):
|
||||
if case let .loaded(displayMode) = self.viewState {
|
||||
switch displayMode {
|
||||
case .noThreePidsAdded, .threePidsAdded:
|
||||
self.viewModel.process(viewAction: .tapUserSettingsLink)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func update(theme: Theme) {
|
||||
self.theme = theme
|
||||
|
||||
self.updateRows()
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func registerThemeServiceDidChangeThemeNotification() {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil)
|
||||
}
|
||||
|
||||
@objc private func themeDidChange() {
|
||||
self.update(theme: ThemeService.shared().theme)
|
||||
}
|
||||
|
||||
private func cellType<T: MXKTableViewCell>(at row: Int) -> T? {
|
||||
let klass: T.Type = T.self
|
||||
let tableViewCell = delegate?.settingsDiscoveryTableViewSection(self, tableViewCellClass: klass, forRow: row)
|
||||
return tableViewCell as? T
|
||||
}
|
||||
|
||||
private func updateRows() {
|
||||
|
||||
let discoveryRows: [DiscoverySectionRows]
|
||||
|
||||
switch self.viewState {
|
||||
case .loading:
|
||||
discoveryRows = self.discoveryRows
|
||||
case .loaded(let displayMode):
|
||||
switch displayMode {
|
||||
case .noIdentityServer:
|
||||
discoveryRows = [
|
||||
.info(text: VectorL10n.settingsDiscoveryNoIdentityServer)
|
||||
]
|
||||
case .termsNotSigned(let host):
|
||||
discoveryRows = [
|
||||
.info(text: VectorL10n.settingsDiscoveryTermsNotSigned(host)),
|
||||
.button(title: VectorL10n.accept, action: { [weak self] in
|
||||
self?.viewModel.process(viewAction: .acceptTerms)
|
||||
})
|
||||
]
|
||||
case .noThreePidsAdded:
|
||||
discoveryRows = [
|
||||
.attributedInfo(attributedText: self.threePidsManagementInfoAttributedString())
|
||||
]
|
||||
case .threePidsAdded(let emails, let phoneNumbers):
|
||||
|
||||
let emailThreePids = emails.map { (email) -> DiscoverySectionRows in
|
||||
return .threePid(threePid: email)
|
||||
}
|
||||
|
||||
let phoneNumbersThreePids = phoneNumbers.map { (phoneNumber) -> DiscoverySectionRows in
|
||||
return .threePid(threePid: phoneNumber)
|
||||
}
|
||||
|
||||
var threePidsRows: [DiscoverySectionRows] = []
|
||||
threePidsRows.append(contentsOf: emailThreePids)
|
||||
threePidsRows.append(contentsOf: phoneNumbersThreePids)
|
||||
threePidsRows.append(.attributedInfo(attributedText: self.threePidsManagementInfoAttributedString()))
|
||||
|
||||
discoveryRows = threePidsRows
|
||||
}
|
||||
case .error:
|
||||
discoveryRows = [
|
||||
.info(text: VectorL10n.settingsDiscoveryErrorMessage),
|
||||
.button(title: VectorL10n.retry, action: { [weak self] in
|
||||
self?.viewModel.process(viewAction: .load)
|
||||
})
|
||||
]
|
||||
}
|
||||
|
||||
self.discoveryRows = discoveryRows
|
||||
}
|
||||
|
||||
private func threePidsManagementInfoAttributedString() -> NSAttributedString {
|
||||
let attributedInfoString = NSMutableAttributedString(string: VectorL10n.settingsDiscoveryThreePidsManagementInformationPart1,
|
||||
attributes: [.foregroundColor: self.theme.textPrimaryColor, .font: Constants.defaultFont])
|
||||
attributedInfoString.append(NSAttributedString(string: VectorL10n.settingsDiscoveryThreePidsManagementInformationPart2,
|
||||
attributes: [.foregroundColor: self.theme.tintColor, .font: Constants.defaultFont]))
|
||||
attributedInfoString.append(NSAttributedString(string: VectorL10n.settingsDiscoveryThreePidsManagementInformationPart3,
|
||||
attributes: [.foregroundColor: self.theme.tintColor, .font: Constants.defaultFont]))
|
||||
return attributedInfoString
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - SettingsDiscoveryViewModelViewDelegate
|
||||
extension SettingsDiscoveryTableViewSection: SettingsDiscoveryViewModelViewDelegate {
|
||||
|
||||
func settingsDiscoveryViewModel(_ viewModel: SettingsDiscoveryViewModelType, didUpdateViewState viewState: SettingsDiscoveryViewState) {
|
||||
self.viewState = viewState
|
||||
|
||||
// The tableview datasource will call `self.cellForRow()`
|
||||
self.delegate?.settingsDiscoveryTableViewSectionDidUpdate(self)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
/// SettingsDiscoveryTableViewSection view actions exposed to view model
|
||||
enum SettingsDiscoveryViewAction {
|
||||
case load
|
||||
case acceptTerms
|
||||
case select(threePid: MX3PID)
|
||||
case tapUserSettingsLink
|
||||
}
|
200
Riot/Modules/Settings/Discovery/SettingsDiscoveryViewModel.swift
Normal file
200
Riot/Modules/Settings/Discovery/SettingsDiscoveryViewModel.swift
Normal file
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
@objc final class SettingsDiscoveryViewModel: NSObject, SettingsDiscoveryViewModelType {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let session: MXSession
|
||||
private var identityService: MXIdentityService?
|
||||
private var serviceTerms: MXServiceTerms?
|
||||
private var viewState: SettingsDiscoveryViewState?
|
||||
private var threePIDs: [MX3PID] = []
|
||||
|
||||
// MARK: Public
|
||||
|
||||
weak var viewDelegate: SettingsDiscoveryViewModelViewDelegate?
|
||||
@objc weak var coordinatorDelegate: SettingsDiscoveryViewModelCoordinatorDelegate?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
@objc init(session: MXSession, thirdPartyIdentifiers: [MXThirdPartyIdentifier]) {
|
||||
self.session = session
|
||||
|
||||
let identityService = session.identityService
|
||||
|
||||
if let identityService = identityService {
|
||||
self.serviceTerms = MXServiceTerms(baseUrl: identityService.identityServer, serviceType: MXServiceTypeIdentityService, matrixSession: session, accessToken: nil)
|
||||
}
|
||||
|
||||
self.identityService = identityService
|
||||
self.threePIDs = SettingsDiscoveryViewModel.threePids(from: thirdPartyIdentifiers)
|
||||
super.init()
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func process(viewAction: SettingsDiscoveryViewAction) {
|
||||
switch viewAction {
|
||||
case .load:
|
||||
self.checkTerms()
|
||||
case .acceptTerms:
|
||||
self.acceptTerms()
|
||||
case .select(threePid: let threePid):
|
||||
self.coordinatorDelegate?.settingsDiscoveryViewModel(self, didSelectThreePidWith: threePid.medium.identifier, and: threePid.address)
|
||||
case .tapUserSettingsLink:
|
||||
self.coordinatorDelegate?.settingsDiscoveryViewModelDidTapUserSettingsLink(self)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func update(thirdPartyIdentifiers: [MXThirdPartyIdentifier]) {
|
||||
self.threePIDs = SettingsDiscoveryViewModel.threePids(from: thirdPartyIdentifiers)
|
||||
|
||||
// Update view state only if three3pids was previously
|
||||
guard let viewState = self.viewState,
|
||||
case let .loaded(displayMode: displayMode) = viewState else {
|
||||
return
|
||||
}
|
||||
|
||||
let canDisplayThreePids: Bool
|
||||
|
||||
switch displayMode {
|
||||
case .threePidsAdded, .noThreePidsAdded:
|
||||
canDisplayThreePids = true
|
||||
default:
|
||||
canDisplayThreePids = false
|
||||
}
|
||||
|
||||
if canDisplayThreePids {
|
||||
self.updateViewStateFromCurrentThreePids()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func checkTerms() {
|
||||
guard let identityService = self.identityService, let serviceTerms = self.serviceTerms else {
|
||||
self.update(viewState: .loaded(displayMode: .noIdentityServer))
|
||||
return
|
||||
}
|
||||
|
||||
guard self.canCheckTerms() else {
|
||||
return
|
||||
}
|
||||
|
||||
self.update(viewState: .loading)
|
||||
|
||||
serviceTerms.areAllTermsAgreed({ (agreedTermsProgress) in
|
||||
if agreedTermsProgress.isFinished || agreedTermsProgress.totalUnitCount == 0 {
|
||||
// Display three pids if presents
|
||||
self.updateViewStateFromCurrentThreePids()
|
||||
} else {
|
||||
let identityServer = identityService.identityServer
|
||||
let identityServerHost = URL(string: identityServer)?.host ?? identityServer
|
||||
|
||||
self.update(viewState: .loaded(displayMode: .termsNotSigned(host: identityServerHost)))
|
||||
}
|
||||
}, failure: { (error) in
|
||||
self.update(viewState: .error(error))
|
||||
})
|
||||
}
|
||||
|
||||
private func acceptTerms() {
|
||||
guard let identityService = self.identityService else {
|
||||
self.update(viewState: .loaded(displayMode: .noIdentityServer))
|
||||
return
|
||||
}
|
||||
|
||||
// Launch an identity server request to trigger terms modal apparition
|
||||
identityService.account { (response) in
|
||||
switch response {
|
||||
case .success:
|
||||
// Display three pids if presents
|
||||
self.updateViewStateFromCurrentThreePids()
|
||||
case .failure(let error):
|
||||
if MXError(nsError: error)?.errcode == kMXErrCodeStringTermsNotSigned {
|
||||
// Identity terms modal should appear
|
||||
} else {
|
||||
self.update(viewState: .error(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func canCheckTerms() -> Bool {
|
||||
guard let viewState = self.viewState else {
|
||||
return true
|
||||
}
|
||||
|
||||
let canCheckTerms: Bool
|
||||
|
||||
if case .loading = viewState {
|
||||
canCheckTerms = false
|
||||
} else {
|
||||
canCheckTerms = true
|
||||
}
|
||||
|
||||
return canCheckTerms
|
||||
}
|
||||
|
||||
private func updateViewStateFromCurrentThreePids() {
|
||||
self.updateViewState(with: self.threePIDs)
|
||||
}
|
||||
|
||||
private func updateViewState(with threePids: [MX3PID]) {
|
||||
|
||||
let viewState: SettingsDiscoveryViewState
|
||||
|
||||
if threePids.isEmpty {
|
||||
viewState = .loaded(displayMode: .noThreePidsAdded)
|
||||
} else {
|
||||
let emails = threePids.compactMap { (threePid) -> MX3PID? in
|
||||
if case .email = threePid.medium {
|
||||
return threePid
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
let phoneNumbers = threePids.compactMap { (threePid) -> MX3PID? in
|
||||
if case .msisdn = threePid.medium {
|
||||
return threePid
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
viewState = .loaded(displayMode: .threePidsAdded(emails: emails, phoneNumbers: phoneNumbers))
|
||||
}
|
||||
|
||||
self.update(viewState: viewState)
|
||||
}
|
||||
|
||||
private func update(viewState: SettingsDiscoveryViewState) {
|
||||
self.viewState = viewState
|
||||
self.viewDelegate?.settingsDiscoveryViewModel(self, didUpdateViewState: viewState)
|
||||
}
|
||||
|
||||
private class func threePids(from thirdPartyIdentifiers: [MXThirdPartyIdentifier]) -> [MX3PID] {
|
||||
return thirdPartyIdentifiers.map({ (thirdPartyIdentifier) -> MX3PID in
|
||||
return MX3PID(medium: MX3PID.Medium(identifier: thirdPartyIdentifier.medium), address: thirdPartyIdentifier.address)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
protocol SettingsDiscoveryViewModelViewDelegate: class {
|
||||
func settingsDiscoveryViewModel(_ viewModel: SettingsDiscoveryViewModelType, didUpdateViewState viewState: SettingsDiscoveryViewState)
|
||||
}
|
||||
|
||||
@objc protocol SettingsDiscoveryViewModelCoordinatorDelegate: class {
|
||||
func settingsDiscoveryViewModel(_ viewModel: SettingsDiscoveryViewModel, didSelectThreePidWith medium: String, and address: String)
|
||||
func settingsDiscoveryViewModelDidTapUserSettingsLink(_ viewModel: SettingsDiscoveryViewModel)
|
||||
}
|
||||
|
||||
protocol SettingsDiscoveryViewModelType {
|
||||
|
||||
var viewDelegate: SettingsDiscoveryViewModelViewDelegate? { get set }
|
||||
|
||||
var coordinatorDelegate: SettingsDiscoveryViewModelCoordinatorDelegate? { get set }
|
||||
|
||||
func process(viewAction: SettingsDiscoveryViewAction)
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
/// SettingsDiscoveryTableViewSection view state
|
||||
enum SettingsDiscoveryViewState {
|
||||
case loading
|
||||
case loaded(displayMode: SettingsDiscoveryDisplayMode)
|
||||
case error(Error)
|
||||
}
|
||||
|
||||
/// SettingsDiscoveryTableViewSection `loaded` view state dipslay modes
|
||||
///
|
||||
/// - noIdentityServer: No identity server configured.
|
||||
/// - termsNotSigned: Identity server terms are not signed.
|
||||
/// - noThreePidsAdded: No three pids added to the user HS account.
|
||||
/// - threePidsAdded: Three pids added to the user HS account.
|
||||
enum SettingsDiscoveryDisplayMode {
|
||||
case noIdentityServer
|
||||
case termsNotSigned(host: String)
|
||||
case noThreePidsAdded
|
||||
case threePidsAdded(emails: [MX3PID], phoneNumbers: [MX3PID])
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Details SettingsDiscoveryThreePidDetails
|
||||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
import UIKit
|
||||
|
||||
final class SettingsDiscoveryThreePidDetailsCoordinator: SettingsDiscoveryThreePidDetailsCoordinatorType {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let session: MXSession
|
||||
private var settingsDiscoveryThreePidDetailsViewModel: SettingsDiscoveryThreePidDetailsViewModelType
|
||||
private let settingsDiscoveryThreePidDetailsViewController: SettingsDiscoveryThreePidDetailsViewController
|
||||
|
||||
// MARK: Public
|
||||
|
||||
// Must be used only internally
|
||||
var childCoordinators: [Coordinator] = []
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(session: MXSession, threePid: MX3PID) {
|
||||
self.session = session
|
||||
|
||||
let settingsDiscoveryThreePidDetailsViewModel = SettingsDiscoveryThreePidDetailsViewModel(session: self.session, threePid: threePid)
|
||||
let settingsDiscoveryThreePidDetailsViewController = SettingsDiscoveryThreePidDetailsViewController.instantiate(with: settingsDiscoveryThreePidDetailsViewModel)
|
||||
self.settingsDiscoveryThreePidDetailsViewModel = settingsDiscoveryThreePidDetailsViewModel
|
||||
self.settingsDiscoveryThreePidDetailsViewController = settingsDiscoveryThreePidDetailsViewController
|
||||
}
|
||||
|
||||
// MARK: - Public methods
|
||||
|
||||
func start() {
|
||||
}
|
||||
|
||||
func toPresentable() -> UIViewController {
|
||||
return self.settingsDiscoveryThreePidDetailsViewController
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
// File created from FlowTemplate
|
||||
// $ createRootCoordinator.sh Details SettingsDiscoveryThreePidDetails
|
||||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
/// SettingsDiscoveryThreePidDetailsCoordinatorBridgePresenter enables to start SettingsDiscoveryThreePidDetailsCoordinator from a view controller.
|
||||
/// This bridge is used while waiting for global usage of coordinator pattern.
|
||||
@objcMembers
|
||||
final class SettingsDiscoveryThreePidDetailsCoordinatorBridgePresenter: NSObject {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let session: MXSession
|
||||
private let threePid: MX3PID
|
||||
|
||||
private var coordinator: SettingsDiscoveryThreePidDetailsCoordinator?
|
||||
private var router: NavigationRouter?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(session: MXSession, medium: String, adress: String) {
|
||||
self.session = session
|
||||
self.threePid = MX3PID(medium: MX3PID.Medium(identifier: medium), address: adress)
|
||||
super.init()
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func push(from navigationController: UINavigationController, animated: Bool, popCompletion: (() -> Void)?) {
|
||||
|
||||
let router = NavigationRouter(navigationController: navigationController)
|
||||
|
||||
let settingsDiscoveryThreePidDetailsCoordinator = SettingsDiscoveryThreePidDetailsCoordinator(session: self.session, threePid: self.threePid)
|
||||
|
||||
router.push(settingsDiscoveryThreePidDetailsCoordinator, animated: animated) { [weak self] in
|
||||
self?.coordinator = nil
|
||||
self?.router = nil
|
||||
popCompletion?()
|
||||
}
|
||||
|
||||
settingsDiscoveryThreePidDetailsCoordinator.start()
|
||||
|
||||
self.coordinator = settingsDiscoveryThreePidDetailsCoordinator
|
||||
self.router = router
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Details SettingsDiscoveryThreePidDetails
|
||||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
/// `SettingsDiscoveryThreePidDetailsCoordinatorType` is a protocol describing a Coordinator that handle key backup setup passphrase navigation flow.
|
||||
protocol SettingsDiscoveryThreePidDetailsCoordinatorType: Coordinator, Presentable {
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Details SettingsDiscoveryThreePidDetails
|
||||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
/// SettingsDiscoveryThreePidDetailsViewController view actions exposed to view model
|
||||
enum SettingsDiscoveryThreePidDetailsViewAction {
|
||||
case load
|
||||
case share
|
||||
case revoke
|
||||
case cancelThreePidValidation
|
||||
case confirmEmailValidation
|
||||
case confirmMSISDNValidation(code: String)
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="ezK-Hg-0xv">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Settings Discovery Three Pid Details View Controller-->
|
||||
<scene sceneID="3dE-H2-gcP">
|
||||
<objects>
|
||||
<viewController extendedLayoutIncludesOpaqueBars="YES" automaticallyAdjustsScrollViewInsets="NO" id="ezK-Hg-0xv" customClass="SettingsDiscoveryThreePidDetailsViewController" customModule="Riot" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="R2r-2G-yM5">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="q1k-fN-38j">
|
||||
<rect key="frame" x="0.0" y="20" width="375" height="647"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="aP2-lr-60e">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="277"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="1h7-ek-3CO">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="277"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="H6I-jF-SbB">
|
||||
<rect key="frame" x="0.0" y="40" width="375" height="50"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" text="email" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vPl-rf-DWf">
|
||||
<rect key="frame" x="20" y="16" width="36.5" height="18"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="foo@matrix.org" textAlignment="right" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="SP5-xI-3zJ">
|
||||
<rect key="frame" x="66.5" y="16" width="288.5" height="18"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="SP5-xI-3zJ" firstAttribute="top" secondItem="vPl-rf-DWf" secondAttribute="top" id="5Mc-1w-3Qy"/>
|
||||
<constraint firstAttribute="trailing" secondItem="SP5-xI-3zJ" secondAttribute="trailing" constant="20" id="9CG-58-qE1"/>
|
||||
<constraint firstItem="vPl-rf-DWf" firstAttribute="leading" secondItem="H6I-jF-SbB" secondAttribute="leading" constant="20" id="Ngy-Un-QjA"/>
|
||||
<constraint firstItem="vPl-rf-DWf" firstAttribute="top" secondItem="H6I-jF-SbB" secondAttribute="top" constant="16" id="eoq-0N-Ka3"/>
|
||||
<constraint firstItem="SP5-xI-3zJ" firstAttribute="leading" secondItem="vPl-rf-DWf" secondAttribute="trailing" constant="10" id="gWa-Bh-BGZ"/>
|
||||
<constraint firstAttribute="bottom" secondItem="vPl-rf-DWf" secondAttribute="bottom" constant="16" id="kmG-LA-aJL"/>
|
||||
<constraint firstItem="SP5-xI-3zJ" firstAttribute="bottom" secondItem="vPl-rf-DWf" secondAttribute="bottom" id="tt6-jQ-Gtv"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="PNH-63-Z3c">
|
||||
<rect key="frame" x="0.0" y="115" width="375" height="50"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="GnW-2q-pSU">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="50"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="8qU-Gg-4dL"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<inset key="contentEdgeInsets" minX="10" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="Share">
|
||||
<color key="titleColor" red="0.47843137250000001" green="0.78823529410000004" blue="0.63137254899999995" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</state>
|
||||
<state key="disabled">
|
||||
<color key="titleColor" red="0.47843137250000001" green="0.78823529410000004" blue="0.63137254899999995" alpha="0.5" colorSpace="calibratedRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="operationButtonAction:" destination="ezK-Hg-0xv" eventType="touchUpInside" id="uLq-yW-mh2"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="GnW-2q-pSU" firstAttribute="leading" secondItem="PNH-63-Z3c" secondAttribute="leading" id="45P-d7-TNc"/>
|
||||
<constraint firstItem="GnW-2q-pSU" firstAttribute="top" secondItem="PNH-63-Z3c" secondAttribute="top" id="6w9-y9-Cic"/>
|
||||
<constraint firstAttribute="bottom" secondItem="GnW-2q-pSU" secondAttribute="bottom" id="K0b-tM-nlb"/>
|
||||
<constraint firstAttribute="trailing" secondItem="GnW-2q-pSU" secondAttribute="trailing" id="fvC-FK-JJE"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fYa-31-Xfd">
|
||||
<rect key="frame" x="20" y="185" width="335" height="72"/>
|
||||
<string key="text">Manage preferences for this email address, which other users can use to discover you and use to invite you to rooms. Add or remove email addresses in Accounts.</string>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<color key="textColor" white="1" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="H6I-jF-SbB" secondAttribute="trailing" id="2eD-FF-4pI"/>
|
||||
<constraint firstItem="fYa-31-Xfd" firstAttribute="top" secondItem="PNH-63-Z3c" secondAttribute="bottom" constant="20" id="7m2-AA-5BM"/>
|
||||
<constraint firstItem="H6I-jF-SbB" firstAttribute="top" secondItem="1h7-ek-3CO" secondAttribute="top" constant="40" id="9nH-V1-qst"/>
|
||||
<constraint firstItem="PNH-63-Z3c" firstAttribute="top" secondItem="H6I-jF-SbB" secondAttribute="bottom" constant="25" id="JJC-gO-Yl3"/>
|
||||
<constraint firstAttribute="bottom" secondItem="fYa-31-Xfd" secondAttribute="bottom" constant="20" id="LMW-Qk-Dv4"/>
|
||||
<constraint firstItem="fYa-31-Xfd" firstAttribute="leading" secondItem="1h7-ek-3CO" secondAttribute="leading" constant="20" id="PlF-wq-3sl"/>
|
||||
<constraint firstItem="PNH-63-Z3c" firstAttribute="leading" secondItem="1h7-ek-3CO" secondAttribute="leading" id="alO-Yb-wVp"/>
|
||||
<constraint firstAttribute="trailing" secondItem="PNH-63-Z3c" secondAttribute="trailing" id="brL-L8-ch1"/>
|
||||
<constraint firstAttribute="width" priority="750" constant="500" id="l3L-bE-s7u"/>
|
||||
<constraint firstItem="H6I-jF-SbB" firstAttribute="leading" secondItem="1h7-ek-3CO" secondAttribute="leading" id="nAN-0L-p44"/>
|
||||
<constraint firstAttribute="trailing" secondItem="fYa-31-Xfd" secondAttribute="trailing" constant="20" id="pTH-Uc-hX7"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="1h7-ek-3CO" firstAttribute="centerX" secondItem="aP2-lr-60e" secondAttribute="centerX" id="CV4-kX-dzd"/>
|
||||
<constraint firstItem="1h7-ek-3CO" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="aP2-lr-60e" secondAttribute="leading" id="F1Q-cV-TEV"/>
|
||||
<constraint firstAttribute="bottom" secondItem="1h7-ek-3CO" secondAttribute="bottom" id="Hyc-7c-jZe"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="1h7-ek-3CO" secondAttribute="trailing" id="MPu-qV-x2a"/>
|
||||
<constraint firstItem="1h7-ek-3CO" firstAttribute="top" secondItem="aP2-lr-60e" secondAttribute="top" id="Ol3-Vk-aV2"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="aP2-lr-60e" firstAttribute="top" secondItem="q1k-fN-38j" secondAttribute="top" id="52d-aL-BvB"/>
|
||||
<constraint firstAttribute="trailing" secondItem="aP2-lr-60e" secondAttribute="trailing" id="E3H-IS-rRu"/>
|
||||
<constraint firstItem="aP2-lr-60e" firstAttribute="width" secondItem="q1k-fN-38j" secondAttribute="width" id="JlK-tw-JnA"/>
|
||||
<constraint firstAttribute="bottom" secondItem="aP2-lr-60e" secondAttribute="bottom" id="dYG-fE-MEt"/>
|
||||
<constraint firstItem="aP2-lr-60e" firstAttribute="leading" secondItem="q1k-fN-38j" secondAttribute="leading" id="whl-EE-953"/>
|
||||
</constraints>
|
||||
</scrollView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.94509803920000002" green="0.96078431369999995" blue="0.97254901959999995" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="juo-3g-nXq" firstAttribute="top" secondItem="q1k-fN-38j" secondAttribute="top" id="9hw-K8-RPD"/>
|
||||
<constraint firstAttribute="bottom" secondItem="q1k-fN-38j" secondAttribute="bottom" id="Fad-dA-ZfQ"/>
|
||||
<constraint firstItem="juo-3g-nXq" firstAttribute="trailing" secondItem="q1k-fN-38j" secondAttribute="trailing" id="JhW-Hh-xAm"/>
|
||||
<constraint firstItem="q1k-fN-38j" firstAttribute="leading" secondItem="juo-3g-nXq" secondAttribute="leading" id="iYf-jl-9Jd"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="juo-3g-nXq"/>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="informationLabel" destination="fYa-31-Xfd" id="pgq-O8-lEO"/>
|
||||
<outlet property="operationButton" destination="GnW-2q-pSU" id="7iB-Gx-ppD"/>
|
||||
<outlet property="scrollView" destination="q1k-fN-38j" id="hkr-ze-2Ht"/>
|
||||
<outlet property="threePidAdressLabel" destination="SP5-xI-3zJ" id="q5X-AN-eed"/>
|
||||
<outlet property="threePidBackgroundView" destination="H6I-jF-SbB" id="s57-Tg-UUJ"/>
|
||||
<outlet property="threePidTitleLabel" destination="vPl-rf-DWf" id="SMX-J1-71T"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Pf0-Pr-ZvT" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-3772" y="-774"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,303 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Details SettingsDiscoveryThreePidDetails
|
||||
/*
|
||||
Copyright 2019 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 UIKit
|
||||
|
||||
final class SettingsDiscoveryThreePidDetailsViewController: UIViewController {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Outlets
|
||||
|
||||
@IBOutlet private weak var scrollView: UIScrollView!
|
||||
|
||||
@IBOutlet private weak var threePidBackgroundView: UIView!
|
||||
@IBOutlet private weak var threePidTitleLabel: UILabel!
|
||||
@IBOutlet private weak var threePidAdressLabel: UILabel!
|
||||
@IBOutlet private weak var operationButton: UIButton!
|
||||
@IBOutlet private weak var informationLabel: UILabel!
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private var viewModel: SettingsDiscoveryThreePidDetailsViewModelType!
|
||||
private var theme: Theme!
|
||||
private var keyboardAvoider: KeyboardAvoider?
|
||||
private var errorPresenter: MXKErrorPresentation!
|
||||
private var activityPresenter: ActivityIndicatorPresenter!
|
||||
private weak var presentedAlertController: UIAlertController?
|
||||
|
||||
private var displayMode: SettingsDiscoveryThreePidDetailsDisplayMode?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
class func instantiate(with viewModel: SettingsDiscoveryThreePidDetailsViewModelType) -> SettingsDiscoveryThreePidDetailsViewController {
|
||||
let viewController = StoryboardScene.SettingsDiscoveryThreePidDetailsViewController.initialScene.instantiate()
|
||||
viewController.viewModel = viewModel
|
||||
viewController.theme = ThemeService.shared().theme
|
||||
return viewController
|
||||
}
|
||||
|
||||
// MARK: - Life cycle
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
|
||||
self.setupViews()
|
||||
self.keyboardAvoider = KeyboardAvoider(scrollViewContainerView: self.view, scrollView: self.scrollView)
|
||||
self.activityPresenter = ActivityIndicatorPresenter()
|
||||
self.errorPresenter = MXKErrorAlertPresentation()
|
||||
|
||||
self.registerThemeServiceDidChangeThemeNotification()
|
||||
self.update(theme: self.theme)
|
||||
|
||||
self.viewModel.viewDelegate = self
|
||||
|
||||
self.viewModel.process(viewAction: .load)
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
self.keyboardAvoider?.startAvoiding()
|
||||
}
|
||||
|
||||
override func viewDidDisappear(_ animated: Bool) {
|
||||
super.viewDidDisappear(animated)
|
||||
|
||||
self.keyboardAvoider?.stopAvoiding()
|
||||
}
|
||||
|
||||
override var preferredStatusBarStyle: UIStatusBarStyle {
|
||||
return self.theme.statusBarStyle
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func update(theme: Theme) {
|
||||
self.theme = theme
|
||||
|
||||
self.view.backgroundColor = theme.headerBackgroundColor
|
||||
|
||||
if let navigationBar = self.navigationController?.navigationBar {
|
||||
theme.applyStyle(onNavigationBar: navigationBar)
|
||||
}
|
||||
|
||||
self.threePidBackgroundView.backgroundColor = theme.backgroundColor
|
||||
self.threePidTitleLabel.textColor = theme.textPrimaryColor
|
||||
self.threePidAdressLabel.textColor = theme.textSecondaryColor
|
||||
|
||||
self.informationLabel.textColor = theme.textSecondaryColor
|
||||
self.operationButton.backgroundColor = theme.backgroundColor
|
||||
theme.applyStyle(onButton: self.operationButton)
|
||||
}
|
||||
|
||||
private func registerThemeServiceDidChangeThemeNotification() {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil)
|
||||
}
|
||||
|
||||
@objc private func themeDidChange() {
|
||||
self.update(theme: ThemeService.shared().theme)
|
||||
}
|
||||
|
||||
private func setupViews() {
|
||||
|
||||
self.scrollView.keyboardDismissMode = .interactive
|
||||
|
||||
self.render(threePid: self.viewModel.threePid)
|
||||
}
|
||||
|
||||
private func render(threePid: MX3PID) {
|
||||
|
||||
let title: String
|
||||
let threePidTitle: String
|
||||
let informationText: String
|
||||
let formattedThreePid: String
|
||||
|
||||
switch threePid.medium {
|
||||
case .email:
|
||||
title = VectorL10n.settingsDiscoveryThreePidDetailsTitleEmail
|
||||
threePidTitle = VectorL10n.settingsEmailAddress
|
||||
informationText = VectorL10n.settingsDiscoveryThreePidDetailsInformationEmail
|
||||
formattedThreePid = threePid.address
|
||||
case .msisdn:
|
||||
title = VectorL10n.settingsDiscoveryThreePidDetailsTitlePhoneNumber
|
||||
threePidTitle = VectorL10n.settingsPhoneNumber
|
||||
informationText = VectorL10n.settingsDiscoveryThreePidDetailsInformationPhoneNumber
|
||||
formattedThreePid = MXKTools.readableMSISDN(threePid.address)
|
||||
default:
|
||||
title = ""
|
||||
threePidTitle = ""
|
||||
informationText = ""
|
||||
formattedThreePid = ""
|
||||
}
|
||||
|
||||
self.title = title
|
||||
self.threePidTitleLabel.text = threePidTitle
|
||||
self.threePidAdressLabel.text = formattedThreePid
|
||||
self.informationLabel.text = informationText
|
||||
}
|
||||
|
||||
private func render(viewState: SettingsDiscoveryThreePidDetailsViewState) {
|
||||
switch viewState {
|
||||
case .loading:
|
||||
self.renderLoading()
|
||||
case .loaded(displayMode: let displayMode):
|
||||
self.renderLoaded(displayMode: displayMode)
|
||||
case .error(let error):
|
||||
self.render(error: error)
|
||||
}
|
||||
}
|
||||
|
||||
private func renderLoaded(displayMode: SettingsDiscoveryThreePidDetailsDisplayMode) {
|
||||
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
|
||||
|
||||
let operationButtonTitle: String?
|
||||
let operationButtonColor: UIColor?
|
||||
let operationButtonEnabled: Bool
|
||||
|
||||
self.presentedAlertController?.dismiss(animated: false, completion: nil)
|
||||
|
||||
switch displayMode {
|
||||
case .share:
|
||||
operationButtonTitle = VectorL10n.settingsDiscoveryThreePidDetailsShareAction
|
||||
operationButtonColor = self.theme.tintColor
|
||||
operationButtonEnabled = true
|
||||
case .revoke:
|
||||
operationButtonTitle = VectorL10n.settingsDiscoveryThreePidDetailsRevokeAction
|
||||
operationButtonColor = self.theme.warningColor
|
||||
operationButtonEnabled = true
|
||||
case .pendingThreePidVerification:
|
||||
switch self.viewModel.threePid.medium {
|
||||
case .email:
|
||||
self.presentPendingEmailVerificationAlert()
|
||||
case .msisdn:
|
||||
self.presentPendingMSISDNVerificationAlert()
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
operationButtonTitle = nil
|
||||
operationButtonColor = nil
|
||||
operationButtonEnabled = false
|
||||
}
|
||||
|
||||
if let operationButtonTitle = operationButtonTitle {
|
||||
self.operationButton.setTitle(operationButtonTitle, for: .normal)
|
||||
}
|
||||
|
||||
if let operationButtonColor = operationButtonColor {
|
||||
self.operationButton.setTitleColor(operationButtonColor, for: .normal)
|
||||
}
|
||||
|
||||
self.operationButton.isEnabled = operationButtonEnabled
|
||||
|
||||
self.displayMode = displayMode
|
||||
}
|
||||
|
||||
private func renderLoading() {
|
||||
if self.activityPresenter.isPresenting == false {
|
||||
self.activityPresenter.presentActivityIndicator(on: self.view, animated: true)
|
||||
}
|
||||
self.operationButton.isEnabled = false
|
||||
}
|
||||
|
||||
private func render(error: Error) {
|
||||
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
|
||||
self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: {
|
||||
self.viewModel.process(viewAction: .cancelThreePidValidation)
|
||||
})
|
||||
self.operationButton.isEnabled = true
|
||||
}
|
||||
|
||||
private func presentPendingEmailVerificationAlert() {
|
||||
|
||||
let alert = UIAlertController(title: Bundle.mxk_localizedString(forKey: "account_email_validation_title"),
|
||||
message: Bundle.mxk_localizedString(forKey: "account_email_validation_message"),
|
||||
preferredStyle: .alert)
|
||||
|
||||
alert.addAction(UIAlertAction(title: VectorL10n.continue, style: .default, handler: { _ in
|
||||
self.viewModel.process(viewAction: .confirmEmailValidation)
|
||||
}))
|
||||
|
||||
alert.addAction(UIAlertAction(title: Bundle.mxk_localizedString(forKey: "cancel"), style: .cancel, handler: { _ in
|
||||
self.viewModel.process(viewAction: .cancelThreePidValidation)
|
||||
}))
|
||||
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
self.presentedAlertController = alert
|
||||
}
|
||||
|
||||
private func presentPendingMSISDNVerificationAlert() {
|
||||
|
||||
let alert = UIAlertController(title: Bundle.mxk_localizedString(forKey: "account_msisdn_validation_title"),
|
||||
message: Bundle.mxk_localizedString(forKey: "account_msisdn_validation_message"),
|
||||
preferredStyle: .alert)
|
||||
|
||||
alert.addTextField { (textField) in
|
||||
textField.placeholder = nil
|
||||
textField.keyboardType = .phonePad
|
||||
}
|
||||
|
||||
alert.addAction(UIAlertAction(title: VectorL10n.continue, style: .default, handler: { _ in
|
||||
guard let textField = alert.textFields?.first, let smsCode = textField.text, smsCode.isEmpty == false else {
|
||||
return
|
||||
}
|
||||
self.viewModel.process(viewAction: .confirmMSISDNValidation(code: smsCode))
|
||||
}))
|
||||
|
||||
alert.addAction(UIAlertAction(title: Bundle.mxk_localizedString(forKey: "cancel"), style: .cancel, handler: { _ in
|
||||
self.viewModel.process(viewAction: .cancelThreePidValidation)
|
||||
}))
|
||||
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
self.presentedAlertController = alert
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@IBAction private func operationButtonAction(_ sender: Any) {
|
||||
guard let displayMode = self.displayMode else {
|
||||
return
|
||||
}
|
||||
|
||||
let viewAction: SettingsDiscoveryThreePidDetailsViewAction?
|
||||
|
||||
switch displayMode {
|
||||
case .share:
|
||||
viewAction = .share
|
||||
case .revoke:
|
||||
viewAction = .revoke
|
||||
default:
|
||||
viewAction = nil
|
||||
}
|
||||
|
||||
if let viewAction = viewAction {
|
||||
self.viewModel.process(viewAction: viewAction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - SettingsDiscoveryThreePidDetailsViewModelViewDelegate
|
||||
extension SettingsDiscoveryThreePidDetailsViewController: SettingsDiscoveryThreePidDetailsViewModelViewDelegate {
|
||||
|
||||
func settingsDiscoveryThreePidDetailsViewModel(_ viewModel: SettingsDiscoveryThreePidDetailsViewModelType, didUpdateViewState viewSate: SettingsDiscoveryThreePidDetailsViewState) {
|
||||
self.render(viewState: viewSate)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,257 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Details SettingsDiscoveryThreePidDetails
|
||||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
enum SettingsDiscoveryThreePidDetailsViewModelError: Error {
|
||||
case unknown
|
||||
}
|
||||
|
||||
private struct ThreePidRequestTokenInfo {
|
||||
let clientSecret: String
|
||||
let sid: String
|
||||
let bind: Bool
|
||||
}
|
||||
|
||||
final class SettingsDiscoveryThreePidDetailsViewModel: SettingsDiscoveryThreePidDetailsViewModelType {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private var viewState: SettingsDiscoveryThreePidDetailsViewState?
|
||||
|
||||
private let threePidAddManager: MX3PidAddManager
|
||||
private let identityService: MXIdentityService?
|
||||
private var currentThreePidAddSession: MX3PidAddSession?
|
||||
|
||||
// MARK: Public
|
||||
|
||||
let threePid: MX3PID
|
||||
|
||||
weak var viewDelegate: SettingsDiscoveryThreePidDetailsViewModelViewDelegate?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(session: MXSession, threePid: MX3PID) {
|
||||
self.threePidAddManager = session.threePidAddManager
|
||||
self.identityService = session.identityService
|
||||
self.threePid = threePid
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func process(viewAction: SettingsDiscoveryThreePidDetailsViewAction) {
|
||||
switch viewAction {
|
||||
case .load:
|
||||
self.load()
|
||||
case .share:
|
||||
self.share()
|
||||
case .revoke:
|
||||
self.revoke()
|
||||
case .cancelThreePidValidation:
|
||||
self.cancelThreePidValidation()
|
||||
case .confirmEmailValidation:
|
||||
self.confirmEmailValidation()
|
||||
case .confirmMSISDNValidation(code: let code):
|
||||
self.validatePhoneNumber(with: code)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func load() {
|
||||
self.update(viewState: .loading)
|
||||
|
||||
self.checkThreePidDiscoverability()
|
||||
}
|
||||
|
||||
private func checkThreePidDiscoverability() {
|
||||
self.isThreePidDiscoverable(self.threePid) { (response) in
|
||||
switch response {
|
||||
case .success(let isDiscoverable):
|
||||
if isDiscoverable {
|
||||
self.update(viewState: .loaded(displayMode: .revoke))
|
||||
} else {
|
||||
self.update(viewState: .loaded(displayMode: .share))
|
||||
}
|
||||
case .failure(let error):
|
||||
self.update(viewState: .error(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func share() {
|
||||
self.bind(bind: true)
|
||||
}
|
||||
|
||||
private func revoke() {
|
||||
self.bind(bind: false)
|
||||
}
|
||||
|
||||
private func bind(bind: Bool) {
|
||||
self.update(viewState: .loading)
|
||||
|
||||
let completion: ((MXResponse<Bool>) -> Void) = { (response) in
|
||||
switch response {
|
||||
case .success(let needValidation):
|
||||
if needValidation {
|
||||
self.update(viewState: .loaded(displayMode: .pendingThreePidVerification))
|
||||
|
||||
if case .email = self.threePid.medium {
|
||||
self.registerEmailValidationNotification()
|
||||
}
|
||||
} else {
|
||||
self.checkThreePidDiscoverability()
|
||||
}
|
||||
|
||||
case .failure(let error):
|
||||
self.update(viewState: .error(error))
|
||||
}
|
||||
}
|
||||
|
||||
switch self.threePid.medium {
|
||||
case .email:
|
||||
self.currentThreePidAddSession = self.threePidAddManager.startIdentityServerSession(withEmail: self.threePid.address, bind: bind, completion: completion)
|
||||
case .msisdn:
|
||||
let formattedPhoneNumber = self.formattedPhoneNumber(from: threePid.address)
|
||||
self.currentThreePidAddSession = self.threePidAddManager.startIdentityServerSession(withPhoneNumber: formattedPhoneNumber, countryCode: nil, bind: bind, completion: completion)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@discardableResult
|
||||
private func isThreePidDiscoverable(_ threePid: MX3PID, completion: @escaping (_ response: MXResponse<Bool>) -> Void) -> MXHTTPOperation? {
|
||||
guard let identityService = self.identityService else {
|
||||
completion(.failure(SettingsDiscoveryThreePidDetailsViewModelError.unknown))
|
||||
return nil
|
||||
}
|
||||
|
||||
return identityService.lookup3PIDs([threePid]) { lookupResponse in
|
||||
switch lookupResponse {
|
||||
case .success(let threePids):
|
||||
completion(.success(threePids.isEmpty == false))
|
||||
case .failure(let error):
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func update(viewState: SettingsDiscoveryThreePidDetailsViewState) {
|
||||
self.viewDelegate?.settingsDiscoveryThreePidDetailsViewModel(self, didUpdateViewState: viewState)
|
||||
}
|
||||
|
||||
// MARK: Email
|
||||
|
||||
private func cancelThreePidValidation() {
|
||||
|
||||
if case .email = threePid.medium {
|
||||
self.unregisterEmailValidationNotification()
|
||||
}
|
||||
|
||||
if let currentThreePidAddSession = self.currentThreePidAddSession {
|
||||
self.threePidAddManager.cancel(session: currentThreePidAddSession)
|
||||
self.currentThreePidAddSession = nil
|
||||
}
|
||||
|
||||
self.checkThreePidDiscoverability()
|
||||
}
|
||||
|
||||
private func confirmEmailValidation() {
|
||||
guard let threePidAddSession = self.currentThreePidAddSession else {
|
||||
return
|
||||
}
|
||||
self.update(viewState: .loading)
|
||||
|
||||
self.threePidAddManager.tryFinaliseIdentityServerEmailSession(threePidAddSession) { response in
|
||||
switch response {
|
||||
case .success:
|
||||
|
||||
if threePidAddSession.medium == kMX3PIDMediumEmail {
|
||||
self.unregisterEmailValidationNotification()
|
||||
}
|
||||
|
||||
self.checkThreePidDiscoverability()
|
||||
case .failure(let error):
|
||||
if let mxError = MXError(nsError: error),
|
||||
(mxError.errcode == kMXErrCodeStringThreePIDAuthFailed
|
||||
|| mxError.errcode == kMXErrCodeStringUnknown) {
|
||||
self.update(viewState: .loaded(displayMode: .pendingThreePidVerification))
|
||||
} else {
|
||||
if threePidAddSession.medium == kMX3PIDMediumEmail {
|
||||
self.unregisterEmailValidationNotification()
|
||||
}
|
||||
|
||||
self.update(viewState: .error(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func registerEmailValidationNotification() {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(handleEmailValidationNotification(notification:)), name: .AppDelegateDidValidateEmail, object: nil)
|
||||
}
|
||||
|
||||
private func unregisterEmailValidationNotification() {
|
||||
NotificationCenter.default.removeObserver(self, name: .AppDelegateDidValidateEmail, object: nil)
|
||||
}
|
||||
|
||||
@objc private func handleEmailValidationNotification(notification: Notification) {
|
||||
guard let userInfo = notification.userInfo,
|
||||
let clientSecret = userInfo[AppDelegateDidValidateEmailNotificationClientSecretKey] as? String,
|
||||
let sid = userInfo[AppDelegateDidValidateEmailNotificationSIDKey] as? String,
|
||||
let threePidAddSession = self.currentThreePidAddSession,
|
||||
threePidAddSession.clientSecret == clientSecret,
|
||||
threePidAddSession.sid == sid else {
|
||||
return
|
||||
}
|
||||
|
||||
self.confirmEmailValidation()
|
||||
}
|
||||
|
||||
// MARK: Phone number
|
||||
|
||||
private func formattedPhoneNumber(from phoneNumber: String) -> String {
|
||||
guard phoneNumber.starts(with: "+") == false else {
|
||||
return phoneNumber
|
||||
}
|
||||
return "+\(phoneNumber)"
|
||||
}
|
||||
|
||||
private func validatePhoneNumber(with activationCode: String) {
|
||||
guard let threePidAddSession = self.currentThreePidAddSession else {
|
||||
return
|
||||
}
|
||||
self.update(viewState: .loading)
|
||||
|
||||
self.threePidAddManager.finaliseIdentityServerPhoneNumberSession(threePidAddSession, token: activationCode) { (response) in
|
||||
switch response {
|
||||
case .success:
|
||||
self.checkThreePidDiscoverability()
|
||||
case .failure(let error):
|
||||
if let mxError = MXError(nsError: error), mxError.errcode == kMXErrCodeStringUnknownToken {
|
||||
self.update(viewState: .loaded(displayMode: .pendingThreePidVerification))
|
||||
} else {
|
||||
self.update(viewState: .error(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Details SettingsDiscoveryThreePidDetails
|
||||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
protocol SettingsDiscoveryThreePidDetailsViewModelViewDelegate: class {
|
||||
func settingsDiscoveryThreePidDetailsViewModel(_ viewModel: SettingsDiscoveryThreePidDetailsViewModelType, didUpdateViewState viewSate: SettingsDiscoveryThreePidDetailsViewState)
|
||||
}
|
||||
|
||||
/// Protocol describing the view model used by `SettingsDiscoveryThreePidDetailsViewController`
|
||||
protocol SettingsDiscoveryThreePidDetailsViewModelType {
|
||||
|
||||
var threePid: MX3PID { get }
|
||||
|
||||
var viewDelegate: SettingsDiscoveryThreePidDetailsViewModelViewDelegate? { get set }
|
||||
|
||||
func process(viewAction: SettingsDiscoveryThreePidDetailsViewAction)
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Details SettingsDiscoveryThreePidDetails
|
||||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
/// SettingsDiscoveryThreePidDetailsViewController view state
|
||||
enum SettingsDiscoveryThreePidDetailsViewState {
|
||||
case loading
|
||||
case loaded(displayMode: SettingsDiscoveryThreePidDetailsDisplayMode)
|
||||
case error(Error)
|
||||
}
|
||||
|
||||
enum SettingsDiscoveryThreePidDetailsDisplayMode {
|
||||
case share
|
||||
case revoke
|
||||
case pendingThreePidVerification
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
// File created from FlowTemplate
|
||||
// $ createRootCoordinator.sh Test SettingsIdentityServer
|
||||
/*
|
||||
Copyright 2019 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 UIKit
|
||||
|
||||
@objcMembers
|
||||
final class SettingsIdentityServerCoordinator: SettingsIdentityServerCoordinatorType {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let session: MXSession
|
||||
private let settingsIdentityServerViewController: SettingsIdentityServerViewController
|
||||
|
||||
// MARK: Public
|
||||
|
||||
// Must be used only internally
|
||||
var childCoordinators: [Coordinator] = []
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(session: MXSession) {
|
||||
self.session = session
|
||||
|
||||
let settingsIdentityServerViewModel = SettingsIdentityServerViewModel(session: self.session)
|
||||
let settingsIdentityServerViewController = SettingsIdentityServerViewController.instantiate(with: settingsIdentityServerViewModel)
|
||||
self.settingsIdentityServerViewController = settingsIdentityServerViewController
|
||||
}
|
||||
|
||||
// MARK: - Public methods
|
||||
|
||||
func start() {
|
||||
}
|
||||
|
||||
func toPresentable() -> UIViewController {
|
||||
return self.settingsIdentityServerViewController
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
// File created from FlowTemplate
|
||||
// $ createRootCoordinator.sh Test SettingsIdentityServer
|
||||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
@objc protocol SettingsIdentityServerCoordinatorBridgePresenterDelegate {
|
||||
func settingsIdentityServerCoordinatorBridgePresenterDelegateDidComplete(_ coordinatorBridgePresenter: SettingsIdentityServerCoordinatorBridgePresenter)
|
||||
}
|
||||
|
||||
/// SettingsIdentityServerCoordinatorBridgePresenter enables to start SettingsIdentityServerCoordinator from a view controller.
|
||||
/// This bridge is used while waiting for global usage of coordinator pattern.
|
||||
@objcMembers
|
||||
final class SettingsIdentityServerCoordinatorBridgePresenter: NSObject {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let session: MXSession
|
||||
private var router: NavigationRouter?
|
||||
private var coordinator: SettingsIdentityServerCoordinator?
|
||||
|
||||
// MARK: Public
|
||||
|
||||
weak var delegate: SettingsIdentityServerCoordinatorBridgePresenterDelegate?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(session: MXSession) {
|
||||
self.session = session
|
||||
super.init()
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func push(from navigationController: UINavigationController, animated: Bool, popCompletion: (() -> Void)?) {
|
||||
|
||||
let router = NavigationRouter(navigationController: navigationController)
|
||||
|
||||
let settingsIdentityServerCoordinator = SettingsIdentityServerCoordinator(session: self.session)
|
||||
|
||||
router.push(settingsIdentityServerCoordinator, animated: animated) { [weak self] in
|
||||
self?.coordinator = nil
|
||||
self?.router = nil
|
||||
popCompletion?()
|
||||
}
|
||||
|
||||
settingsIdentityServerCoordinator.start()
|
||||
|
||||
self.coordinator = settingsIdentityServerCoordinator
|
||||
self.router = router
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
// File created from FlowTemplate
|
||||
// $ createRootCoordinator.sh Test SettingsIdentityServer
|
||||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
/// `SettingsIdentityServerCoordinatorType` is a protocol describing a Coordinator that handle keybackup setup navigation flow.
|
||||
protocol SettingsIdentityServerCoordinatorType: Coordinator, Presentable {
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Test SettingsIdentityServer
|
||||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
/// SettingsIdentityServerViewController view actions exposed to view model
|
||||
enum SettingsIdentityServerViewAction {
|
||||
case load
|
||||
case add(identityServer: String)
|
||||
case change(identityServer: String)
|
||||
case disconnect
|
||||
}
|
|
@ -0,0 +1,200 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="YCb-yR-1Km">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Settings Identity Server View Controller-->
|
||||
<scene sceneID="CLh-Ql-FIE">
|
||||
<objects>
|
||||
<viewController extendedLayoutIncludesOpaqueBars="YES" automaticallyAdjustsScrollViewInsets="NO" id="YCb-yR-1Km" customClass="SettingsIdentityServerViewController" customModule="Riot" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="trm-G2-fZS">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="8Oz-k6-Zyh">
|
||||
<rect key="frame" x="0.0" y="20" width="375" height="647"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="lG2-Xw-KPE">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="500"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hwn-qz-R7V">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="500"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0W7-LW-UNr">
|
||||
<rect key="frame" x="0.0" y="40" width="375" height="51"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Identity Server" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="g0a-45-iRa">
|
||||
<rect key="frame" x="20" y="16" width="100" height="19"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="https://vector.im" textAlignment="right" minimumFontSize="15" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="Zwv-XP-gEA">
|
||||
<rect key="frame" x="140" y="16" width="215" height="19"/>
|
||||
<nil key="textColor"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<textInputTraits key="textInputTraits"/>
|
||||
</textField>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="Zwv-XP-gEA" secondAttribute="bottom" constant="16" id="9Um-wU-TXG"/>
|
||||
<constraint firstItem="Zwv-XP-gEA" firstAttribute="top" secondItem="0W7-LW-UNr" secondAttribute="top" constant="16" id="IAN-Cz-6Rk"/>
|
||||
<constraint firstItem="Zwv-XP-gEA" firstAttribute="leading" secondItem="g0a-45-iRa" secondAttribute="trailing" constant="20" id="Lga-2A-0Wm"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Zwv-XP-gEA" secondAttribute="trailing" constant="20" id="WXH-tD-HJA"/>
|
||||
<constraint firstItem="g0a-45-iRa" firstAttribute="bottom" secondItem="Zwv-XP-gEA" secondAttribute="bottom" id="ccy-C5-fDL"/>
|
||||
<constraint firstItem="g0a-45-iRa" firstAttribute="top" secondItem="Zwv-XP-gEA" secondAttribute="top" id="eXy-mB-ywA"/>
|
||||
<constraint firstItem="g0a-45-iRa" firstAttribute="leading" secondItem="0W7-LW-UNr" secondAttribute="leading" constant="20" id="vXp-nX-Q6y"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="You are currently using vector.im to discover and be discoverable by existing contacts you know." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="HLL-Fw-u3V">
|
||||
<rect key="frame" x="20" y="111" width="335" height="36"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="h8a-2s-H3K">
|
||||
<rect key="frame" x="0.0" y="167" width="375" height="50"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="kPC-YQ-MGL">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="50"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="T9R-QE-nBi"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<inset key="contentEdgeInsets" minX="10" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="Change">
|
||||
<color key="titleColor" red="0.47843137250000001" green="0.78823529410000004" blue="0.63137254899999995" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</state>
|
||||
<state key="disabled">
|
||||
<color key="titleColor" red="0.47843137250000001" green="0.78823529410000004" blue="0.63137254899999995" alpha="0.5" colorSpace="calibratedRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="addOrChangeButtonAction:" destination="YCb-yR-1Km" eventType="touchUpInside" id="a3m-Lt-6RW"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="kPC-YQ-MGL" secondAttribute="trailing" id="185-hA-OVD"/>
|
||||
<constraint firstItem="kPC-YQ-MGL" firstAttribute="leading" secondItem="h8a-2s-H3K" secondAttribute="leading" id="OyR-iq-Gs8"/>
|
||||
<constraint firstItem="kPC-YQ-MGL" firstAttribute="top" secondItem="h8a-2s-H3K" secondAttribute="top" id="W9z-lt-umK"/>
|
||||
<constraint firstAttribute="bottom" secondItem="kPC-YQ-MGL" secondAttribute="bottom" id="vcz-SU-JOZ"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2Jk-ak-Oxh">
|
||||
<rect key="frame" x="20" y="267" width="335" height="80"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="80" id="L1f-yR-1t3"/>
|
||||
</constraints>
|
||||
<string key="text">Disconnecting from your identity server will mean you won’t be discoverable by other users and you won’t be able to invite others by email or phone.</string>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="O79-u4-Mig">
|
||||
<rect key="frame" x="0.0" y="367" width="375" height="50"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1Tg-0G-cBC">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="50"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="haa-Jh-EDc"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<inset key="contentEdgeInsets" minX="10" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="Disconnect">
|
||||
<color key="titleColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</state>
|
||||
<state key="disabled">
|
||||
<color key="titleColor" red="0.47843137250000001" green="0.78823529410000004" blue="0.63137254899999995" alpha="0.5" colorSpace="calibratedRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="disconnectButtonAction:" destination="YCb-yR-1Km" eventType="touchUpInside" id="IJj-ET-fvd"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="1Tg-0G-cBC" secondAttribute="trailing" id="69l-vf-mvU"/>
|
||||
<constraint firstItem="1Tg-0G-cBC" firstAttribute="leading" secondItem="O79-u4-Mig" secondAttribute="leading" id="9MJ-ja-xpe"/>
|
||||
<constraint firstItem="1Tg-0G-cBC" firstAttribute="top" secondItem="O79-u4-Mig" secondAttribute="top" id="pYh-MV-LFt"/>
|
||||
<constraint firstAttribute="bottom" secondItem="1Tg-0G-cBC" secondAttribute="bottom" id="xcG-78-zIp"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="2Jk-ak-Oxh" secondAttribute="trailing" constant="20" id="1wz-cm-ZYv"/>
|
||||
<constraint firstItem="0W7-LW-UNr" firstAttribute="top" secondItem="hwn-qz-R7V" secondAttribute="top" constant="40" id="7YM-zk-rCu"/>
|
||||
<constraint firstItem="h8a-2s-H3K" firstAttribute="top" secondItem="HLL-Fw-u3V" secondAttribute="bottom" constant="20" id="8Vh-O9-d29"/>
|
||||
<constraint firstAttribute="trailing" secondItem="HLL-Fw-u3V" secondAttribute="trailing" constant="20" id="Bs5-Uz-kbF"/>
|
||||
<constraint firstItem="O79-u4-Mig" firstAttribute="leading" secondItem="hwn-qz-R7V" secondAttribute="leading" id="HBn-pM-NdW"/>
|
||||
<constraint firstItem="O79-u4-Mig" firstAttribute="top" secondItem="2Jk-ak-Oxh" secondAttribute="bottom" constant="20" id="Oz0-aA-1DF"/>
|
||||
<constraint firstAttribute="trailing" secondItem="O79-u4-Mig" secondAttribute="trailing" id="SzX-d7-T9U"/>
|
||||
<constraint firstItem="2Jk-ak-Oxh" firstAttribute="top" secondItem="h8a-2s-H3K" secondAttribute="bottom" constant="50" id="TCS-5j-stz"/>
|
||||
<constraint firstItem="2Jk-ak-Oxh" firstAttribute="leading" secondItem="hwn-qz-R7V" secondAttribute="leading" constant="20" id="Wwg-l6-1QO"/>
|
||||
<constraint firstAttribute="trailing" secondItem="0W7-LW-UNr" secondAttribute="trailing" id="XOC-9V-o8H"/>
|
||||
<constraint firstItem="HLL-Fw-u3V" firstAttribute="top" secondItem="0W7-LW-UNr" secondAttribute="bottom" constant="20" id="XgK-7i-yhj"/>
|
||||
<constraint firstItem="h8a-2s-H3K" firstAttribute="leading" secondItem="hwn-qz-R7V" secondAttribute="leading" id="b8m-4H-orP"/>
|
||||
<constraint firstAttribute="width" priority="750" constant="500" id="jEc-ht-fgG"/>
|
||||
<constraint firstItem="0W7-LW-UNr" firstAttribute="leading" secondItem="hwn-qz-R7V" secondAttribute="leading" id="kbX-q7-dtp"/>
|
||||
<constraint firstItem="HLL-Fw-u3V" firstAttribute="leading" secondItem="hwn-qz-R7V" secondAttribute="leading" constant="20" id="pHb-5b-QYN"/>
|
||||
<constraint firstAttribute="trailing" secondItem="h8a-2s-H3K" secondAttribute="trailing" id="vPw-01-TaS"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="hwn-qz-R7V" firstAttribute="top" secondItem="lG2-Xw-KPE" secondAttribute="top" id="6UK-h7-Jfi"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="hwn-qz-R7V" secondAttribute="trailing" id="PWd-1a-pc6"/>
|
||||
<constraint firstAttribute="height" constant="500" id="REc-dq-NtM"/>
|
||||
<constraint firstItem="hwn-qz-R7V" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="lG2-Xw-KPE" secondAttribute="leading" id="Xde-HX-oMG"/>
|
||||
<constraint firstAttribute="bottom" secondItem="hwn-qz-R7V" secondAttribute="bottom" id="cjT-2e-tp7"/>
|
||||
<constraint firstItem="hwn-qz-R7V" firstAttribute="centerX" secondItem="lG2-Xw-KPE" secondAttribute="centerX" id="tWw-7s-Eaj"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="lG2-Xw-KPE" secondAttribute="trailing" id="2Oj-q1-byd"/>
|
||||
<constraint firstItem="lG2-Xw-KPE" firstAttribute="width" secondItem="8Oz-k6-Zyh" secondAttribute="width" id="2RP-6A-FLF"/>
|
||||
<constraint firstItem="lG2-Xw-KPE" firstAttribute="leading" secondItem="8Oz-k6-Zyh" secondAttribute="leading" id="FGn-RZ-dc5"/>
|
||||
<constraint firstAttribute="bottom" secondItem="lG2-Xw-KPE" secondAttribute="bottom" id="fGL-Ig-G6s"/>
|
||||
<constraint firstItem="lG2-Xw-KPE" firstAttribute="top" secondItem="8Oz-k6-Zyh" secondAttribute="top" id="kyx-Ao-xKa"/>
|
||||
</constraints>
|
||||
</scrollView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.94509803920000002" green="0.96078431369999995" blue="0.97254901959999995" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="8Oz-k6-Zyh" firstAttribute="leading" secondItem="0Gf-da-iK5" secondAttribute="leading" id="059-y1-rPd"/>
|
||||
<constraint firstAttribute="bottom" secondItem="8Oz-k6-Zyh" secondAttribute="bottom" id="BXd-L8-T6F"/>
|
||||
<constraint firstItem="0Gf-da-iK5" firstAttribute="top" secondItem="8Oz-k6-Zyh" secondAttribute="top" id="lkR-P4-U2b"/>
|
||||
<constraint firstItem="0Gf-da-iK5" firstAttribute="trailing" secondItem="8Oz-k6-Zyh" secondAttribute="trailing" id="vL8-o9-5PR"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="0Gf-da-iK5"/>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="addOrChangeButton" destination="kPC-YQ-MGL" id="Ebk-ko-ay1"/>
|
||||
<outlet property="addOrChangeButtonContainer" destination="h8a-2s-H3K" id="eEG-rP-zym"/>
|
||||
<outlet property="disconnectButton" destination="1Tg-0G-cBC" id="iTS-4I-0tT"/>
|
||||
<outlet property="disconnectButtonContainer" destination="O79-u4-Mig" id="KKh-kb-kKX"/>
|
||||
<outlet property="disconnectMessageLabel" destination="2Jk-ak-Oxh" id="ktM-yq-jWv"/>
|
||||
<outlet property="identityServerContainer" destination="0W7-LW-UNr" id="wTi-zd-vJH"/>
|
||||
<outlet property="identityServerLabel" destination="g0a-45-iRa" id="3n9-g9-uYC"/>
|
||||
<outlet property="identityServerTextField" destination="Zwv-XP-gEA" id="5ci-zn-EQ6"/>
|
||||
<outlet property="messageLabel" destination="HLL-Fw-u3V" id="apO-wG-hi7"/>
|
||||
<outlet property="scrollView" destination="8Oz-k6-Zyh" id="e5g-xe-zBj"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="s4k-Y2-H87" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-3772" y="-774"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,413 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Test SettingsIdentityServer
|
||||
/*
|
||||
Copyright 2019 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 UIKit
|
||||
|
||||
final class SettingsIdentityServerViewController: UIViewController {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Outlets
|
||||
|
||||
@IBOutlet private weak var scrollView: UIScrollView!
|
||||
|
||||
@IBOutlet weak var identityServerContainer: UIView!
|
||||
@IBOutlet weak var identityServerLabel: UILabel!
|
||||
@IBOutlet weak var identityServerTextField: UITextField!
|
||||
|
||||
@IBOutlet private weak var messageLabel: UILabel!
|
||||
|
||||
@IBOutlet weak var addOrChangeButtonContainer: UIView!
|
||||
@IBOutlet private weak var addOrChangeButton: UIButton!
|
||||
|
||||
@IBOutlet weak var disconnectMessageLabel: UILabel!
|
||||
@IBOutlet weak var disconnectButtonContainer: UIView!
|
||||
@IBOutlet weak var disconnectButton: UIButton!
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private var viewModel: SettingsIdentityServerViewModelType!
|
||||
private var theme: Theme!
|
||||
private var keyboardAvoider: KeyboardAvoider?
|
||||
private var errorPresenter: MXKErrorPresentation!
|
||||
private var activityPresenter: ActivityIndicatorPresenter!
|
||||
private var viewState: SettingsIdentityServerViewState?
|
||||
|
||||
private var displayMode: SettingsIdentityServerDisplayMode?
|
||||
|
||||
private weak var alertController: UIAlertController?
|
||||
|
||||
private var serviceTermsModalCoordinatorBridgePresenter: ServiceTermsModalCoordinatorBridgePresenter?
|
||||
private var serviceTermsModalCoordinatorBridgePresenterOnComplete: ((Bool) -> Void)?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
class func instantiate(with viewModel: SettingsIdentityServerViewModelType) -> SettingsIdentityServerViewController {
|
||||
let viewController = StoryboardScene.SettingsIdentityServerViewController.initialScene.instantiate()
|
||||
viewController.viewModel = viewModel
|
||||
viewController.theme = ThemeService.shared().theme
|
||||
return viewController
|
||||
}
|
||||
|
||||
// MARK: - Life cycle
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
|
||||
self.title = VectorL10n.identityServerSettingsTitle
|
||||
|
||||
self.setupViews()
|
||||
self.keyboardAvoider = KeyboardAvoider(scrollViewContainerView: self.view, scrollView: self.scrollView)
|
||||
self.activityPresenter = ActivityIndicatorPresenter()
|
||||
self.errorPresenter = MXKErrorAlertPresentation()
|
||||
|
||||
self.registerThemeServiceDidChangeThemeNotification()
|
||||
self.update(theme: self.theme)
|
||||
|
||||
self.viewModel.viewDelegate = self
|
||||
|
||||
self.viewModel.process(viewAction: .load)
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
self.keyboardAvoider?.startAvoiding()
|
||||
}
|
||||
|
||||
override func viewDidDisappear(_ animated: Bool) {
|
||||
super.viewDidDisappear(animated)
|
||||
|
||||
self.keyboardAvoider?.stopAvoiding()
|
||||
}
|
||||
|
||||
override var preferredStatusBarStyle: UIStatusBarStyle {
|
||||
return self.theme.statusBarStyle
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func update(theme: Theme) {
|
||||
self.theme = theme
|
||||
|
||||
self.view.backgroundColor = theme.headerBackgroundColor
|
||||
|
||||
if let navigationBar = self.navigationController?.navigationBar {
|
||||
theme.applyStyle(onNavigationBar: navigationBar)
|
||||
}
|
||||
|
||||
self.identityServerContainer.backgroundColor = theme.backgroundColor
|
||||
self.identityServerLabel.textColor = theme.textPrimaryColor
|
||||
theme.applyStyle(onTextField: self.identityServerTextField)
|
||||
self.identityServerTextField.textColor = theme.textSecondaryColor
|
||||
self.messageLabel.textColor = theme.textPrimaryColor
|
||||
|
||||
self.addOrChangeButtonContainer.backgroundColor = theme.backgroundColor
|
||||
theme.applyStyle(onButton: self.addOrChangeButton)
|
||||
|
||||
self.disconnectMessageLabel.textColor = theme.textPrimaryColor
|
||||
self.disconnectButtonContainer.backgroundColor = theme.backgroundColor
|
||||
theme.applyStyle(onButton: self.disconnectButton)
|
||||
self.disconnectButton.setTitleColor(self.theme.warningColor, for: .normal)
|
||||
}
|
||||
|
||||
private func registerThemeServiceDidChangeThemeNotification() {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil)
|
||||
}
|
||||
|
||||
@objc private func themeDidChange() {
|
||||
self.update(theme: ThemeService.shared().theme)
|
||||
}
|
||||
|
||||
private func setupViews() {
|
||||
self.scrollView.keyboardDismissMode = .interactive
|
||||
|
||||
self.identityServerLabel.text = VectorL10n.identityServerSettingsTitle
|
||||
|
||||
self.identityServerTextField.placeholder = VectorL10n.identityServerSettingsPlaceHolder
|
||||
self.identityServerTextField.keyboardType = .URL
|
||||
self.identityServerTextField.addTarget(self, action: #selector(identityServerTextFieldDidChange(_:)), for: .editingChanged)
|
||||
self.identityServerTextField.addTarget(self, action: #selector(identityServerTextFieldDidEndOnExit(_:)), for: .editingDidEndOnExit)
|
||||
|
||||
self.disconnectMessageLabel.text = VectorL10n.identityServerSettingsDisconnectInfo
|
||||
self.disconnectButton.setTitle(VectorL10n.identityServerSettingsDisconnect, for: .normal)
|
||||
self.disconnectButton.setTitle(VectorL10n.identityServerSettingsDisconnect, for: .highlighted)
|
||||
}
|
||||
|
||||
private func render(viewState: SettingsIdentityServerViewState) {
|
||||
switch viewState {
|
||||
case .loading:
|
||||
self.renderLoading()
|
||||
case .loaded(let displayMode):
|
||||
self.renderLoaded(displayMode: displayMode)
|
||||
case .presentTerms(let session, let accessToken, let baseUrl, let onComplete):
|
||||
self.presentTerms(session: session, accessToken: accessToken, baseUrl: baseUrl, onComplete: onComplete)
|
||||
case .alert(let alert, let onContinue):
|
||||
self.renderAlert(alert: alert, onContinue: onContinue)
|
||||
case .error(let error):
|
||||
self.render(error: error)
|
||||
}
|
||||
}
|
||||
|
||||
private func renderLoading() {
|
||||
self.activityPresenter.presentActivityIndicator(on: self.view, animated: true)
|
||||
}
|
||||
|
||||
private func renderLoaded(displayMode: SettingsIdentityServerDisplayMode) {
|
||||
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
|
||||
|
||||
self.displayMode = displayMode
|
||||
|
||||
switch displayMode {
|
||||
case .noIdentityServer:
|
||||
self.renderNoIdentityServer()
|
||||
case .identityServer(let host):
|
||||
self.renderIdentityServer(host: host)
|
||||
}
|
||||
}
|
||||
|
||||
private func renderNoIdentityServer() {
|
||||
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
|
||||
|
||||
self.identityServerTextField.text = nil
|
||||
self.messageLabel.text = VectorL10n.identityServerSettingsNoIsDescription
|
||||
|
||||
self.addOrChangeButton.setTitle(VectorL10n.identityServerSettingsAdd, for: .normal)
|
||||
self.addOrChangeButton.setTitle(VectorL10n.identityServerSettingsAdd, for: .highlighted)
|
||||
self.addOrChangeButton.isEnabled = false
|
||||
|
||||
self.disconnectMessageLabel.isHidden = true
|
||||
self.disconnectButtonContainer.isHidden = true
|
||||
}
|
||||
|
||||
private func renderIdentityServer(host: String) {
|
||||
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
|
||||
|
||||
self.identityServerTextField.text = host
|
||||
self.messageLabel.text = VectorL10n.identityServerSettingsDescription(host.hostname())
|
||||
|
||||
self.addOrChangeButton.setTitle(VectorL10n.identityServerSettingsChange, for: .normal)
|
||||
self.addOrChangeButton.setTitle(VectorL10n.identityServerSettingsChange, for: .highlighted)
|
||||
self.addOrChangeButton.isEnabled = false
|
||||
|
||||
self.disconnectMessageLabel.isHidden = false
|
||||
self.disconnectButtonContainer.isHidden = false
|
||||
}
|
||||
|
||||
private func presentTerms(session: MXSession, accessToken: String, baseUrl: String, onComplete: @escaping (Bool) -> Void) {
|
||||
let serviceTermsModalCoordinatorBridgePresenter = ServiceTermsModalCoordinatorBridgePresenter(session: session, baseUrl: baseUrl, serviceType: MXServiceTypeIdentityService, accessToken: accessToken)
|
||||
|
||||
serviceTermsModalCoordinatorBridgePresenter.present(from: self, animated: true)
|
||||
serviceTermsModalCoordinatorBridgePresenter.delegate = self
|
||||
|
||||
self.serviceTermsModalCoordinatorBridgePresenter = serviceTermsModalCoordinatorBridgePresenter
|
||||
self.serviceTermsModalCoordinatorBridgePresenterOnComplete = onComplete
|
||||
}
|
||||
|
||||
private func hideTerms(accepted: Bool) {
|
||||
guard let serviceTermsModalCoordinatorBridgePresenterOnComplete = self.serviceTermsModalCoordinatorBridgePresenterOnComplete else {
|
||||
return
|
||||
}
|
||||
self.serviceTermsModalCoordinatorBridgePresenter?.dismiss(animated: true, completion: nil)
|
||||
self.serviceTermsModalCoordinatorBridgePresenter = nil
|
||||
|
||||
serviceTermsModalCoordinatorBridgePresenterOnComplete(accepted)
|
||||
self.serviceTermsModalCoordinatorBridgePresenterOnComplete = nil
|
||||
}
|
||||
|
||||
private func renderAlert(alert: SettingsIdentityServerAlert, onContinue: @escaping () -> Void) {
|
||||
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
|
||||
|
||||
switch alert {
|
||||
case .addActionAlert(.invalidIdentityServer(let newHost)),
|
||||
.changeActionAlert(.invalidIdentityServer(let newHost)):
|
||||
self.showAlert(title: nil,
|
||||
message: VectorL10n.identityServerSettingsAlertErrorInvalidIdentityServer(newHost),
|
||||
continueButtonTitle: nil,
|
||||
cancelButtonTitle: VectorL10n.cancel,
|
||||
onContinue: onContinue)
|
||||
|
||||
case .addActionAlert(.noTerms),
|
||||
.changeActionAlert(.noTerms):
|
||||
self.showAlert(title: VectorL10n.identityServerSettingsAlertNoTermsTitle,
|
||||
message: VectorL10n.identityServerSettingsAlertNoTerms,
|
||||
continueButtonTitle: VectorL10n.continue,
|
||||
cancelButtonTitle: VectorL10n.cancel,
|
||||
onContinue: onContinue)
|
||||
|
||||
case .addActionAlert(.termsNotAccepted(let newHost)),
|
||||
.changeActionAlert(.termsNotAccepted(let newHost)):
|
||||
self.showAlert(title: nil,
|
||||
message: VectorL10n.identityServerSettingsAlertErrorTermsNotAccepted(newHost.hostname()),
|
||||
continueButtonTitle: nil,
|
||||
cancelButtonTitle: VectorL10n.cancel,
|
||||
onContinue: onContinue)
|
||||
|
||||
|
||||
case .changeActionAlert(.stillSharing3Pids(let oldHost, _)):
|
||||
self.showAlert(title: VectorL10n.identityServerSettingsAlertChangeTitle,
|
||||
message: VectorL10n.identityServerSettingsAlertDisconnectStillSharing3pid(oldHost.hostname()),
|
||||
continueButtonTitle: VectorL10n.identityServerSettingsAlertDisconnectStillSharing3pidButton,
|
||||
cancelButtonTitle: VectorL10n.cancel,
|
||||
onContinue: onContinue)
|
||||
|
||||
case .changeActionAlert(.doubleConfirmation(let oldHost, let newHost)):
|
||||
self.showAlert(title: VectorL10n.identityServerSettingsAlertChangeTitle,
|
||||
message: VectorL10n.identityServerSettingsAlertChange(oldHost.hostname(), newHost.hostname()),
|
||||
continueButtonTitle: VectorL10n.continue,
|
||||
cancelButtonTitle: VectorL10n.cancel,
|
||||
onContinue: onContinue)
|
||||
|
||||
|
||||
case .disconnectActionAlert(.stillSharing3Pids(let oldHost)):
|
||||
self.showAlert(title: VectorL10n.identityServerSettingsAlertDisconnectTitle,
|
||||
message: VectorL10n.identityServerSettingsAlertDisconnectStillSharing3pid(oldHost.hostname()),
|
||||
continueButtonTitle: VectorL10n.identityServerSettingsAlertDisconnectStillSharing3pidButton,
|
||||
cancelButtonTitle: VectorL10n.cancel,
|
||||
onContinue: onContinue)
|
||||
|
||||
case .disconnectActionAlert(.doubleConfirmation(let oldHost)):
|
||||
self.showAlert(title: VectorL10n.identityServerSettingsAlertDisconnectTitle,
|
||||
message: VectorL10n.identityServerSettingsAlertDisconnect(oldHost.hostname()),
|
||||
continueButtonTitle: VectorL10n.identityServerSettingsAlertDisconnectButton,
|
||||
cancelButtonTitle: VectorL10n.cancel,
|
||||
onContinue: onContinue)
|
||||
}
|
||||
}
|
||||
|
||||
private func render(error: Error) {
|
||||
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
|
||||
self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: nil)
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Alert
|
||||
|
||||
private func showAlert(title: String?, message: String, continueButtonTitle: String?, cancelButtonTitle: String, onContinue: @escaping () -> Void) {
|
||||
guard self.alertController == nil else {
|
||||
return
|
||||
}
|
||||
|
||||
let alertController = UIAlertController(title: title,
|
||||
message: message,
|
||||
preferredStyle: .alert)
|
||||
|
||||
alertController.addAction(UIAlertAction(title: cancelButtonTitle, style: .cancel, handler: { action in
|
||||
}))
|
||||
|
||||
if let continueButtonTitle = continueButtonTitle {
|
||||
alertController.addAction(UIAlertAction(title: continueButtonTitle, style: .default, handler: { action in
|
||||
onContinue()
|
||||
}))
|
||||
}
|
||||
|
||||
self.present(alertController, animated: true, completion: nil)
|
||||
self.alertController = alertController
|
||||
}
|
||||
|
||||
private func hideAlert(animated: Bool) {
|
||||
self.alertController?.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@objc private func identityServerTextFieldDidChange(_ textField: UITextField) {
|
||||
self.addOrChangeButton.isEnabled = textField.text?.count ?? 0 > 0
|
||||
&& (textField.text?.hostname() != self.viewModel.identityServer?.hostname())
|
||||
}
|
||||
|
||||
@objc private func identityServerTextFieldDidEndOnExit(_ textField: UITextField) {
|
||||
self.addOrChangeAction()
|
||||
}
|
||||
|
||||
|
||||
@IBAction private func addOrChangeButtonAction(_ sender: Any) {
|
||||
self.addOrChangeAction()
|
||||
}
|
||||
|
||||
private func addOrChangeAction() {
|
||||
self.identityServerTextField.resignFirstResponder()
|
||||
|
||||
guard let displayMode = self.displayMode, let identityServer = self.identityServerTextField.text else {
|
||||
return
|
||||
}
|
||||
|
||||
let viewAction: SettingsIdentityServerViewAction?
|
||||
|
||||
switch displayMode {
|
||||
case .noIdentityServer:
|
||||
viewAction = .add(identityServer: identityServer.makeURLValid())
|
||||
case .identityServer:
|
||||
viewAction = .change(identityServer: identityServer.makeURLValid())
|
||||
}
|
||||
|
||||
if let viewAction = viewAction {
|
||||
self.viewModel.process(viewAction: viewAction)
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction private func disconnectButtonAction(_ sender: Any) {
|
||||
self.viewModel.process(viewAction: .disconnect)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// MARK: - SettingsIdentityServerViewModelViewDelegate
|
||||
extension SettingsIdentityServerViewController: SettingsIdentityServerViewModelViewDelegate {
|
||||
|
||||
func settingsIdentityServerViewModel(_ viewModel: SettingsIdentityServerViewModelType, didUpdateViewState viewState: SettingsIdentityServerViewState) {
|
||||
self.viewState = viewState
|
||||
self.render(viewState: viewState)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - ServiceTermsModalCoordinatorBridgePresenterDelegate
|
||||
extension SettingsIdentityServerViewController: ServiceTermsModalCoordinatorBridgePresenterDelegate {
|
||||
func serviceTermsModalCoordinatorBridgePresenterDelegateDidAccept(_ coordinatorBridgePresenter: ServiceTermsModalCoordinatorBridgePresenter) {
|
||||
self.hideTerms(accepted: true)
|
||||
}
|
||||
|
||||
func serviceTermsModalCoordinatorBridgePresenterDelegateDidDecline(_ coordinatorBridgePresenter: ServiceTermsModalCoordinatorBridgePresenter, session: MXSession) {
|
||||
self.hideTerms(accepted: false)
|
||||
}
|
||||
|
||||
func serviceTermsModalCoordinatorBridgePresenterDelegateDidCancel(_ coordinatorBridgePresenter: ServiceTermsModalCoordinatorBridgePresenter) {
|
||||
self.hideTerms(accepted: false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Private extension
|
||||
fileprivate extension String {
|
||||
func hostname() -> String {
|
||||
return URL(string: self)?.host ?? self
|
||||
}
|
||||
|
||||
func makeURLValid() -> String {
|
||||
if self.hasPrefix("http://") || self.hasPrefix("https://") {
|
||||
return self
|
||||
} else {
|
||||
return "https://" + self
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,410 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Test SettingsIdentityServer
|
||||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
enum SettingsIdentityServerViewModelError: Error {
|
||||
case missingIdentityServer
|
||||
case unknown
|
||||
}
|
||||
|
||||
enum IdentityServerTermsStatus {
|
||||
case noTerms
|
||||
case terms(agreed: Bool)
|
||||
}
|
||||
|
||||
enum IdentityServerValidity {
|
||||
case invalid
|
||||
case valid(status: IdentityServerTermsStatus)
|
||||
}
|
||||
|
||||
final class SettingsIdentityServerViewModel: SettingsIdentityServerViewModelType {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let session: MXSession
|
||||
|
||||
private var identityService: MXIdentityService?
|
||||
private var serviceTerms: MXServiceTerms?
|
||||
|
||||
// MARK: Public
|
||||
|
||||
weak var viewDelegate: SettingsIdentityServerViewModelViewDelegate?
|
||||
var identityServer: String?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(session: MXSession) {
|
||||
self.session = session
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func process(viewAction: SettingsIdentityServerViewAction) {
|
||||
switch viewAction {
|
||||
case .load:
|
||||
self.load()
|
||||
case .add(identityServer: let identityServer):
|
||||
self.addIdentityServer(identityServer)
|
||||
case .change(identityServer: let identityServer):
|
||||
self.changeIdentityServer(identityServer)
|
||||
case .disconnect:
|
||||
self.disconnect()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private -
|
||||
// MARK: - Actions
|
||||
|
||||
private func load() {
|
||||
self.refreshIdentityServerViewState()
|
||||
}
|
||||
|
||||
|
||||
// MARK: Add IS
|
||||
|
||||
private func addIdentityServer(_ newIdentityServer: String) {
|
||||
self.checkCanAddIdentityServer(newIdentityServer: newIdentityServer,
|
||||
viewStateUpdate: { (viewState) in
|
||||
self.update(viewState: viewState)
|
||||
},
|
||||
canAddcompletion: {
|
||||
self.updateIdentityServerAndRefreshViewState(with: newIdentityServer)
|
||||
})
|
||||
}
|
||||
|
||||
private func checkCanAddIdentityServer(newIdentityServer: String,
|
||||
viewStateUpdate: @escaping (SettingsIdentityServerViewState) -> Void,
|
||||
canAddcompletion: @escaping(() -> Void)) {
|
||||
viewStateUpdate(.loading)
|
||||
|
||||
self.checkIdentityServerValidity(identityServer: newIdentityServer) { (identityServerValidityResponse) in
|
||||
print("[SettingsIdentityServerViewModel] checkCanAddIdentityServer: \(newIdentityServer). Validity: \(identityServerValidityResponse)")
|
||||
|
||||
switch identityServerValidityResponse {
|
||||
case .success(let identityServerValidity):
|
||||
switch identityServerValidity {
|
||||
case .invalid:
|
||||
// Present invalid IS alert
|
||||
viewStateUpdate(.alert(alert: SettingsIdentityServerAlert.addActionAlert(.invalidIdentityServer(newHost: newIdentityServer)), onContinue: {}))
|
||||
case .valid(status: let termsStatus):
|
||||
switch termsStatus {
|
||||
case .noTerms:
|
||||
viewStateUpdate(.alert(alert: SettingsIdentityServerAlert.addActionAlert(.noTerms(newHost: newIdentityServer)), onContinue: {
|
||||
viewStateUpdate(.loading)
|
||||
canAddcompletion()
|
||||
}))
|
||||
case .terms(agreed: let termsAgreed):
|
||||
if termsAgreed {
|
||||
canAddcompletion()
|
||||
} else {
|
||||
self.accessToken(identityServer: newIdentityServer) { (response) in
|
||||
switch response {
|
||||
case .success(let accessToken):
|
||||
guard let accessToken = accessToken else {
|
||||
print("[SettingsIdentityServerViewModel] accessToken: Error: No access token")
|
||||
viewStateUpdate(.error(SettingsIdentityServerViewModelError.unknown))
|
||||
return
|
||||
}
|
||||
|
||||
// Present terms
|
||||
viewStateUpdate(.presentTerms(session: self.session, accessToken: accessToken, baseUrl: newIdentityServer, onComplete: { (areTermsAccepted) in
|
||||
if areTermsAccepted {
|
||||
canAddcompletion()
|
||||
} else {
|
||||
viewStateUpdate(.alert(alert: SettingsIdentityServerAlert.addActionAlert(.termsNotAccepted(newHost: newIdentityServer)), onContinue: {}))
|
||||
}
|
||||
}))
|
||||
case .failure(let error):
|
||||
self.update(viewState: .error(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case .failure(let error):
|
||||
viewStateUpdate(.error(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Change IS
|
||||
|
||||
private func changeIdentityServer(_ newIdentityServer: String) {
|
||||
guard let identityServer = self.identityServer else {
|
||||
return
|
||||
}
|
||||
|
||||
let viewStateUpdate: (SettingsIdentityServerViewState) -> Void = { (viewState) in
|
||||
|
||||
// Convert states for .addActionAlert and .disconnectActionAlert to
|
||||
//.changeActionAlert
|
||||
var changeViewState = viewState
|
||||
switch viewState {
|
||||
case .alert(let alert, let onContinue):
|
||||
switch alert {
|
||||
case .addActionAlert(.invalidIdentityServer(let newHost)):
|
||||
changeViewState = .alert(
|
||||
alert: SettingsIdentityServerAlert.changeActionAlert(.invalidIdentityServer(newHost: newHost)),
|
||||
onContinue: onContinue)
|
||||
case .addActionAlert(.noTerms(let newHost)):
|
||||
changeViewState = .alert(
|
||||
alert: SettingsIdentityServerAlert.changeActionAlert(.noTerms(newHost: newHost)),
|
||||
onContinue: onContinue)
|
||||
case .addActionAlert(.termsNotAccepted(let newHost)):
|
||||
changeViewState = .alert(
|
||||
alert: SettingsIdentityServerAlert.changeActionAlert(.termsNotAccepted(newHost: newHost)),
|
||||
onContinue: onContinue)
|
||||
|
||||
case .disconnectActionAlert(.stillSharing3Pids(let oldHost)):
|
||||
changeViewState = .alert(
|
||||
alert: SettingsIdentityServerAlert.changeActionAlert(.stillSharing3Pids(oldHost: oldHost, newHost: newIdentityServer)),
|
||||
onContinue: onContinue)
|
||||
case .disconnectActionAlert(.doubleConfirmation(let oldHost)):
|
||||
changeViewState = .alert(
|
||||
alert: SettingsIdentityServerAlert.changeActionAlert(.doubleConfirmation(oldHost: oldHost, newHost: newIdentityServer)),
|
||||
onContinue: onContinue)
|
||||
default:
|
||||
break
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
self.update(viewState: changeViewState)
|
||||
}
|
||||
|
||||
self.checkCanAddIdentityServer(newIdentityServer: newIdentityServer, viewStateUpdate: viewStateUpdate) {
|
||||
self.checkCanDisconnectIdentityServer(identityServer: identityServer, viewStateUpdate: viewStateUpdate, canDisconnectCompletion: {
|
||||
self.update(viewState: .loading)
|
||||
self.disconnectIdentityServer(refreshViewState: false)
|
||||
self.updateIdentityServerAndRefreshViewState(with: newIdentityServer)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Disconnect IS
|
||||
|
||||
private func disconnect() {
|
||||
guard let identityServer = self.identityServer else {
|
||||
return
|
||||
}
|
||||
|
||||
self.checkCanDisconnectIdentityServer(identityServer: identityServer,
|
||||
viewStateUpdate: { (viewState) in
|
||||
self.update(viewState: viewState)
|
||||
},
|
||||
canDisconnectCompletion: {
|
||||
self.update(viewState: .loading)
|
||||
self.disconnectIdentityServer()
|
||||
})
|
||||
}
|
||||
|
||||
private func disconnectIdentityServer(refreshViewState: Bool = true) {
|
||||
// TODO: Make a /account/logout request
|
||||
|
||||
if refreshViewState {
|
||||
self.updateIdentityServerAndRefreshViewState(with: nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func checkCanDisconnectIdentityServer(identityServer: String,
|
||||
viewStateUpdate: @escaping (SettingsIdentityServerViewState) -> Void,
|
||||
canDisconnectCompletion: @escaping(() -> Void)) {
|
||||
self.update(viewState: .loading)
|
||||
|
||||
self.checkExistingDataOnIdentityServer { (response) in
|
||||
switch response {
|
||||
case .success(let existingData):
|
||||
if existingData {
|
||||
viewStateUpdate(.alert(alert: SettingsIdentityServerAlert.disconnectActionAlert(.stillSharing3Pids(oldHost: identityServer)),
|
||||
onContinue: canDisconnectCompletion))
|
||||
} else {
|
||||
viewStateUpdate(.alert(alert: SettingsIdentityServerAlert.disconnectActionAlert(.doubleConfirmation(oldHost: identityServer)),
|
||||
onContinue: canDisconnectCompletion))
|
||||
}
|
||||
case .failure(let error):
|
||||
viewStateUpdate( .error(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Model update
|
||||
|
||||
private func update(viewState: SettingsIdentityServerViewState) {
|
||||
self.viewDelegate?.settingsIdentityServerViewModel(self, didUpdateViewState: viewState)
|
||||
}
|
||||
|
||||
private func updateIdentityServerAndRefreshViewState(with identityServer: String?) {
|
||||
self.accessToken(identityServer: identityServer) { (response) in
|
||||
switch response {
|
||||
case .success(let accessToken):
|
||||
self.session.setIdentityServer(identityServer, andAccessToken: accessToken)
|
||||
|
||||
self.session.setAccountDataIdentityServer(identityServer, success: {
|
||||
self.refreshIdentityServerViewState()
|
||||
}, failure: { error in
|
||||
self.update(viewState: .error(error ?? SettingsIdentityServerViewModelError.unknown))
|
||||
})
|
||||
case .failure(let error):
|
||||
self.update(viewState: .error(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func refreshIdentityServerViewState() {
|
||||
if let identityService = self.session.identityService {
|
||||
let host = identityService.identityServer
|
||||
self.identityServer = host
|
||||
self.update(viewState: .loaded(displayMode: .identityServer(host: host)))
|
||||
} else {
|
||||
self.update(viewState: .loaded(displayMode: .noIdentityServer))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
private func checkExistingDataOnIdentityServer(completion: @escaping (_ response: MXResponse<Bool>) -> Void) {
|
||||
self.session.matrixRestClient.thirdPartyIdentifiers { (thirdPartyIDresponse) in
|
||||
switch thirdPartyIDresponse {
|
||||
case .success(let thirdPartyIdentifiers):
|
||||
guard let thirdPartyIdentifiers = thirdPartyIdentifiers else {
|
||||
completion(.success(false))
|
||||
return
|
||||
}
|
||||
|
||||
if thirdPartyIdentifiers.isEmpty {
|
||||
completion(.success(false))
|
||||
} else {
|
||||
let mx3Pids = SettingsIdentityServerViewModel.threePids(from: thirdPartyIdentifiers)
|
||||
self.areThereThreePidsDiscoverable(mx3Pids, completion: { discoverable3pidsResponse in
|
||||
switch discoverable3pidsResponse {
|
||||
case .success(let isThereDiscoverable3pids):
|
||||
completion(.success(isThereDiscoverable3pids))
|
||||
case .failure(let error):
|
||||
completion(.failure(error))
|
||||
}
|
||||
})
|
||||
}
|
||||
case .failure(let error):
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func accessToken(identityServer: String?, completion: @escaping (_ response: MXResponse<String?>) -> Void) {
|
||||
guard let identityServer = identityServer, let identityServerURL = URL(string: identityServer) else {
|
||||
completion(.success(nil))
|
||||
return
|
||||
}
|
||||
|
||||
let restClient: MXRestClient = self.session.matrixRestClient
|
||||
let identityService = MXIdentityService(identityServer: identityServerURL, accessToken: nil, homeserverRestClient: restClient)
|
||||
|
||||
identityService.accessToken { (response) in
|
||||
self.identityService = nil
|
||||
completion(response)
|
||||
}
|
||||
|
||||
self.identityService = identityService
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
private func areThereThreePidsDiscoverable(_ threePids: [MX3PID], completion: @escaping (_ response: MXResponse<Bool>) -> Void) -> MXHTTPOperation? {
|
||||
guard let identityService = self.session.identityService else {
|
||||
completion(.failure(SettingsIdentityServerViewModelError.missingIdentityServer))
|
||||
return nil
|
||||
}
|
||||
|
||||
return identityService.lookup3PIDs(threePids) { lookupResponse in
|
||||
switch lookupResponse {
|
||||
case .success(let threePids):
|
||||
completion(.success(threePids.isEmpty == false))
|
||||
case .failure(let error):
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func checkIdentityServerValidity(identityServer: String, completion: @escaping (_ response: MXResponse<IdentityServerValidity>) -> Void) {
|
||||
guard let identityServerURL = URL(string: identityServer) else {
|
||||
completion(.success(.invalid))
|
||||
return
|
||||
}
|
||||
|
||||
let restClient: MXRestClient = self.session.matrixRestClient
|
||||
|
||||
let identityService = MXIdentityService(identityServer: identityServerURL, accessToken: nil, homeserverRestClient: restClient)
|
||||
|
||||
// First, check the server
|
||||
identityService.pingIdentityServer { response in
|
||||
self.identityService = nil
|
||||
|
||||
switch response {
|
||||
case .success:
|
||||
// Them, check if there are terms to accept
|
||||
let serviceTerms = MXServiceTerms(baseUrl: identityService.identityServer, serviceType: MXServiceTypeIdentityService, matrixSession: self.session, accessToken: nil)
|
||||
|
||||
serviceTerms.areAllTermsAgreed({ (agreedTermsProgress) in
|
||||
self.serviceTerms = nil
|
||||
|
||||
if agreedTermsProgress.totalUnitCount == 0 {
|
||||
completion(.success(IdentityServerValidity.valid(status: .noTerms)))
|
||||
} else {
|
||||
completion(.success(IdentityServerValidity.valid(status: .terms(agreed: agreedTermsProgress.isFinished))))
|
||||
}
|
||||
|
||||
}, failure: { (error) in
|
||||
self.serviceTerms = nil
|
||||
completion(.failure(error))
|
||||
})
|
||||
|
||||
self.serviceTerms = serviceTerms
|
||||
|
||||
case .failure(let error):
|
||||
guard let nsError = error as NSError? else {
|
||||
completion(.failure(error))
|
||||
return
|
||||
}
|
||||
|
||||
if nsError.domain == MXIdentityServerRestClientErrorDomain
|
||||
|| (nsError.domain == NSURLErrorDomain
|
||||
&& (nsError.code == NSURLErrorCannotFindHost
|
||||
|| nsError.code == NSURLErrorCancelled)) {
|
||||
completion(.success(.invalid))
|
||||
} else {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.identityService = identityService
|
||||
}
|
||||
|
||||
private class func threePids(from thirdPartyIdentifiers: [MXThirdPartyIdentifier]) -> [MX3PID] {
|
||||
return thirdPartyIdentifiers.map({ (thirdPartyIdentifier) -> MX3PID in
|
||||
return MX3PID(medium: MX3PID.Medium(identifier: thirdPartyIdentifier.medium), address: thirdPartyIdentifier.address)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Test SettingsIdentityServer
|
||||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
protocol SettingsIdentityServerViewModelViewDelegate: class {
|
||||
func settingsIdentityServerViewModel(_ viewModel: SettingsIdentityServerViewModelType, didUpdateViewState viewSate: SettingsIdentityServerViewState)
|
||||
}
|
||||
|
||||
/// Protocol describing the view model used by `SettingsIdentityServerViewController`
|
||||
protocol SettingsIdentityServerViewModelType {
|
||||
|
||||
var viewDelegate: SettingsIdentityServerViewModelViewDelegate? { get set }
|
||||
|
||||
var identityServer: String? { get }
|
||||
|
||||
func process(viewAction: SettingsIdentityServerViewAction)
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Test SettingsIdentityServer
|
||||
/*
|
||||
Copyright 2019 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 Foundation
|
||||
|
||||
/// SettingsIdentityServerViewController view state
|
||||
enum SettingsIdentityServerViewState {
|
||||
case loading
|
||||
case loaded(displayMode: SettingsIdentityServerDisplayMode)
|
||||
case presentTerms(session: MXSession, accessToken: String, baseUrl: String, onComplete: (Bool) -> Void)
|
||||
case alert(alert: SettingsIdentityServerAlert, onContinue: () -> Void)
|
||||
case error(Error)
|
||||
}
|
||||
|
||||
enum SettingsIdentityServerDisplayMode {
|
||||
case noIdentityServer
|
||||
case identityServer(host: String)
|
||||
}
|
||||
|
||||
/// Alerts that can be presented when the user triggered an action among SettingsIdentityServerViewAction.
|
||||
/// These alerts allow interaction with the user to complete the action flow.
|
||||
enum SettingsIdentityServerAlert {
|
||||
case addActionAlert(AddActionAlert)
|
||||
case changeActionAlert(ChangeActionAlert)
|
||||
case disconnectActionAlert(DisconnectActionAlert)
|
||||
|
||||
enum AddActionAlert {
|
||||
case invalidIdentityServer(newHost: String)
|
||||
case noTerms(newHost: String)
|
||||
case termsNotAccepted(newHost: String)
|
||||
}
|
||||
|
||||
enum ChangeActionAlert {
|
||||
case invalidIdentityServer(newHost: String)
|
||||
case noTerms(newHost: String)
|
||||
case termsNotAccepted(newHost: String)
|
||||
case stillSharing3Pids(oldHost: String, newHost: String)
|
||||
case doubleConfirmation(oldHost: String, newHost: String)
|
||||
}
|
||||
|
||||
enum DisconnectActionAlert {
|
||||
case stillSharing3Pids(oldHost: String)
|
||||
case doubleConfirmation(oldHost: String)
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -19,14 +19,7 @@
|
|||
/**
|
||||
'StartChatViewController' instance is used to prepare new room creation.
|
||||
*/
|
||||
@interface StartChatViewController : ContactsTableViewController <UITableViewDataSource, UISearchBarDelegate, ContactsTableViewControllerDelegate>
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UIView *searchBarHeader;
|
||||
@property (weak, nonatomic) IBOutlet UISearchBar *searchBarView;
|
||||
@property (weak, nonatomic) IBOutlet UIView *searchBarHeaderBorder;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *searchBarTopConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *tableViewBottomConstraint;
|
||||
@interface StartChatViewController : ContactsTableViewController
|
||||
|
||||
/**
|
||||
Tell whether a search session is in progress
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#import "AppDelegate.h"
|
||||
#import "Riot-Swift.h"
|
||||
|
||||
@interface StartChatViewController ()
|
||||
@interface StartChatViewController () <UITableViewDataSource, UISearchBarDelegate, ContactsTableViewControllerDelegate>
|
||||
{
|
||||
// The contact used to describe the current user.
|
||||
MXKContact *userContact;
|
||||
|
@ -42,6 +42,13 @@
|
|||
NSMutableDictionary <NSString*, NSNumber*> *isMultiUseNameByDisplayName;
|
||||
}
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UIView *searchBarHeader;
|
||||
@property (weak, nonatomic) IBOutlet UISearchBar *searchBarView;
|
||||
@property (weak, nonatomic) IBOutlet UIView *searchBarHeaderBorder;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *searchBarTopConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *tableViewBottomConstraint;
|
||||
|
||||
@end
|
||||
|
||||
@implementation StartChatViewController
|
||||
|
@ -522,11 +529,7 @@
|
|||
// The identity server must be defined
|
||||
if (!self.mainSession.matrixRestClient.identityServer)
|
||||
{
|
||||
MXError *error = [[MXError alloc] initWithErrorCode:kMXSDKErrCodeStringMissingParameters error:@"No supplied identity server URL"];
|
||||
NSLog(@"[StartChatViewController] Invite %@ failed", participantId);
|
||||
// Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:[error createNSError]];
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -681,6 +684,38 @@
|
|||
|
||||
- (void)contactsTableViewController:(ContactsTableViewController *)contactsTableViewController didSelectContact:(MXKContact*)contact
|
||||
{
|
||||
// If contact has only an email the identity server must be defined
|
||||
if (!self.mainSession.matrixRestClient.identityServer && contact.matrixIdentifiers.count == 0)
|
||||
{
|
||||
NSString *participantId;
|
||||
|
||||
if (contact.emailAddresses.count)
|
||||
{
|
||||
MXKEmail *email = contact.emailAddresses.firstObject;
|
||||
participantId = email.emailAddress;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is the text filled by the user.
|
||||
participantId = contact.displayName;
|
||||
}
|
||||
|
||||
if ([MXTools isEmailAddress:participantId])
|
||||
{
|
||||
NSLog(@"[StartChatViewController] No identity server is configured, do not add participant with email");
|
||||
|
||||
[contactsTableViewController refreshCurrentSelectedCell:YES];
|
||||
|
||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSBundle mxk_localizedStringForKey:@"error"]
|
||||
message:NSLocalizedStringFromTable(@"room_creation_error_invite_user_by_email_without_identity_server", @"Vector", nil)
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
[alert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"ok"] style:UIAlertActionStyleDefault handler:nil]];
|
||||
[self presentViewController:alert animated:YES completion:nil];
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (contact)
|
||||
{
|
||||
// Update here the mutable list of participants
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.9.5</string>
|
||||
<string>0.10.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.9.5</string>
|
||||
<string>0.10.0</string>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
<true/>
|
||||
<key>ITSEncryptionExportComplianceCode</key>
|
||||
|
|
|
@ -14,3 +14,4 @@
|
|||
#import "EncryptionInfoView.h"
|
||||
#import "EventFormatter.h"
|
||||
#import "MediaPickerViewController.h"
|
||||
#import "AppDelegate.h"
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>XPC!</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.9.5</string>
|
||||
<string>0.10.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.9.5</string>
|
||||
<string>0.10.0</string>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionAttributes</key>
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>XPC!</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.9.5</string>
|
||||
<string>0.10.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.9.5</string>
|
||||
<string>0.10.0</string>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionAttributes</key>
|
||||
|
|
Loading…
Reference in a new issue