Finish v0.6.17

This commit is contained in:
manuroe 2018-06-01 17:00:51 +02:00
commit c8fd13172a
42 changed files with 1724 additions and 173 deletions

View file

@ -42,4 +42,6 @@ Joey Watts <joey.watts.96 at gmail.com>
Arash Tabrizian <a.tabriziyan at gmail.com>
* PR #1828 Fix issue #1793 Confirmation popup when leaving room
* PR #1824 Fix issue #1816 Support specifying kick and ban msgs
Doug Earnshaw <pixlwave at users.noreply.github.com>
* PR #1865 Fix timezone interval

View file

@ -1,3 +1,20 @@
Changes in 0.6.17 (2018-06-01)
===============================================
Improvements:
* Upgrade MatrixKit version (v0.7.14).
* Send Stickers (#1860).
* Settings: Add deactivate account (#1870).
* Widgets: Update from UIWebView to WKWebView to improve performance.
Bug fix:
* Quotes (by themselves) render as white blocks (#1877).
* GDPR: consent screen could not be closed (#1883).
* GDPR: Do not display error alert when receiving GDPR Consent not given (#1886).
Translations:
* Enable Icelandic.
Changes in 0.6.16 (2018-05-23)
===============================================

View file

@ -9,7 +9,7 @@ source 'https://github.com/CocoaPods/Specs.git'
# Different flavours of pods to MatrixKit
# The current MatrixKit pod version
$matrixKitVersion = '0.7.12'
$matrixKitVersion = '0.7.14'
# The develop branch version
#$matrixKitVersion = 'develop'

View file

@ -43,34 +43,34 @@ PODS:
- GZIP (1.2.1)
- HPGrowingTextView (1.1)
- libPhoneNumber-iOS (0.9.13)
- MatrixKit (0.7.12):
- MatrixKit (0.7.14):
- cmark (~> 0.24.1)
- DTCoreText (~> 1.6.21)
- HPGrowingTextView (~> 1.1)
- libPhoneNumber-iOS (~> 0.9.13)
- MatrixKit/Core (= 0.7.12)
- MatrixSDK (= 0.10.10)
- MatrixKit/AppExtension (0.7.12):
- MatrixKit/Core (= 0.7.14)
- MatrixSDK (= 0.10.11)
- MatrixKit/AppExtension (0.7.14):
- cmark (~> 0.24.1)
- DTCoreText (~> 1.6.21)
- DTCoreText/Extension
- HPGrowingTextView (~> 1.1)
- libPhoneNumber-iOS (~> 0.9.13)
- MatrixSDK (= 0.10.10)
- MatrixKit/Core (0.7.12):
- MatrixSDK (= 0.10.11)
- MatrixKit/Core (0.7.14):
- cmark (~> 0.24.1)
- DTCoreText (~> 1.6.21)
- HPGrowingTextView (~> 1.1)
- libPhoneNumber-iOS (~> 0.9.13)
- MatrixSDK (= 0.10.10)
- MatrixSDK (0.10.10):
- MatrixSDK/Core (= 0.10.10)
- MatrixSDK/Core (0.10.10):
- MatrixSDK (= 0.10.11)
- MatrixSDK (0.10.11):
- MatrixSDK/Core (= 0.10.11)
- MatrixSDK/Core (0.10.11):
- AFNetworking (~> 3.2.0)
- GZIP (~> 1.2.1)
- OLMKit (~> 2.2.2)
- Realm (~> 3.3.2)
- MatrixSDK/JingleCallStack (0.10.10):
- MatrixSDK/JingleCallStack (0.10.11):
- MatrixSDK/Core
- WebRTC (= 63.11.20455)
- OLMKit (2.2.2):
@ -90,14 +90,14 @@ DEPENDENCIES:
- cmark
- DTCoreText
- GBDeviceInfo (~> 5.1.0)
- MatrixKit (= 0.7.12)
- MatrixKit/AppExtension (= 0.7.12)
- MatrixKit (= 0.7.14)
- MatrixKit/AppExtension (= 0.7.14)
- MatrixSDK/JingleCallStack
- OLMKit
- PiwikTracker (from `https://github.com/manuroe/matomo-sdk-ios.git`, branch `feature/CustomVariables`)
SPEC REPOS:
https://github.com/CocoaPods/Specs.git:
https://github.com/cocoapods/specs.git:
- AFNetworking
- cmark
- DTCoreText
@ -131,13 +131,13 @@ SPEC CHECKSUMS:
GZIP: 7ee835f989fb3c6ea79005fc90b8fa6af710a70d
HPGrowingTextView: 88a716d97fb853bcb08a4a08e4727da17efc9b19
libPhoneNumber-iOS: e444379ac18bbfbdefad571da735b2cd7e096caa
MatrixKit: ac91b2667d1be1895994ee78654d6193a6644b09
MatrixSDK: c74ed8b41e3e55b7510d7bddf612ed1985816e04
MatrixKit: ca192403abc03229f5cc5c193bd24a292e302304
MatrixSDK: abb44d24e0426f3734630362c736d96446a629a3
OLMKit: b9d8c0ffee9ea8c45bc0aaa9afb47f93fba7efbd
PiwikTracker: 42862c7b13028065c3dfd36b4dc38db8a5765acf
Realm: d927fbf66df5532cfafc08afb5f7e53ded37b894
WebRTC: f2a6203584745fe53532633397557876b5d71640
PODFILE CHECKSUM: ba3cdb1f77ff6463e50f031aefd807535f5612ad
PODFILE CHECKSUM: f62acabc542b9493f2d704d8c5163a53051b1979
COCOAPODS: 1.5.0
COCOAPODS: 1.5.3

View file

@ -92,11 +92,13 @@
32BB89EF204D86DA002F3AEC /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 32BB89EA204D86DA002F3AEC /* Localizable.strings */; };
32BB89F0204D86DA002F3AEC /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 32BB89EC204D86DA002F3AEC /* InfoPlist.strings */; };
32C2356F1F7B871800E38FC5 /* WidgetPickerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 32C2356E1F7B871800E38FC5 /* WidgetPickerViewController.m */; };
32C699CD20C04AD100D1C5A4 /* Vector.strings in Resources */ = {isa = PBXBuildFile; fileRef = 32C699CB20C04AD100D1C5A4 /* Vector.strings */; };
32D392181EB9B7AB009A2BAF /* DirectoryServerDetailTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 32D392161EB9B7AB009A2BAF /* DirectoryServerDetailTableViewCell.m */; };
32D392191EB9B7AB009A2BAF /* DirectoryServerDetailTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 32D392171EB9B7AB009A2BAF /* DirectoryServerDetailTableViewCell.xib */; };
32E84FA11F6BD32700CA0B89 /* apps-icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 32E84F9E1F6BD32700CA0B89 /* apps-icon.png */; };
32E84FA21F6BD32700CA0B89 /* apps-icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 32E84F9F1F6BD32700CA0B89 /* apps-icon@2x.png */; };
32E84FA31F6BD32700CA0B89 /* apps-icon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 32E84FA01F6BD32700CA0B89 /* apps-icon@3x.png */; };
32EF474920B6EE990031695C /* StickerPickerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 32EF474820B6EE990031695C /* StickerPickerViewController.m */; };
32F3AE1A1F6FF4E600F0F004 /* WidgetViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 32F3AE191F6FF4E600F0F004 /* WidgetViewController.m */; };
32FD0A3D1EB0CD9B0072B066 /* BugReportViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 32FD0A3B1EB0CD9B0072B066 /* BugReportViewController.m */; };
32FD0A3E1EB0CD9B0072B066 /* BugReportViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 32FD0A3C1EB0CD9B0072B066 /* BugReportViewController.xib */; };
@ -109,6 +111,8 @@
92726A4B1F58737A004AD26F /* SiriIntents.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 92726A431F58737A004AD26F /* SiriIntents.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
92726A511F587410004AD26F /* Intents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 92726A501F587410004AD26F /* Intents.framework */; };
9D686B069F967C4D4BBC610F /* Pods_RiotPods_SiriIntents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DB50EEBE8214352B9EBD6394 /* Pods_RiotPods_SiriIntents.framework */; };
B19A173920B7F94800DF0BB0 /* DeactivateAccountViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B19A173820B7F94800DF0BB0 /* DeactivateAccountViewController.m */; };
B19A173B20B7F96700DF0BB0 /* DeactivateAccountViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B19A173A20B7F96700DF0BB0 /* DeactivateAccountViewController.storyboard */; };
DDDE2AB95F865F2292B1D315 /* Pods_RiotPods_RiotShareExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 23D7292481328A48B8D5D4ED /* Pods_RiotPods_RiotShareExtension.framework */; };
F0131DE51F2200D600CBF707 /* RiotSplitViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F0131DE41F2200D600CBF707 /* RiotSplitViewController.m */; };
F0173EB51FCF346800B5F6A3 /* Vector.strings in Resources */ = {isa = PBXBuildFile; fileRef = F0173EAF1FCF346800B5F6A3 /* Vector.strings */; };
@ -760,12 +764,15 @@
32BB89ED204D86DA002F3AEC /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bg; path = InfoPlist.strings; sourceTree = "<group>"; };
32C2356D1F7B871800E38FC5 /* WidgetPickerViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WidgetPickerViewController.h; sourceTree = "<group>"; };
32C2356E1F7B871800E38FC5 /* WidgetPickerViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WidgetPickerViewController.m; sourceTree = "<group>"; };
32C699CC20C04AD100D1C5A4 /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = Vector.strings; sourceTree = "<group>"; };
32D392151EB9B7AB009A2BAF /* DirectoryServerDetailTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectoryServerDetailTableViewCell.h; sourceTree = "<group>"; };
32D392161EB9B7AB009A2BAF /* DirectoryServerDetailTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DirectoryServerDetailTableViewCell.m; sourceTree = "<group>"; };
32D392171EB9B7AB009A2BAF /* DirectoryServerDetailTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = DirectoryServerDetailTableViewCell.xib; sourceTree = "<group>"; };
32E84F9E1F6BD32700CA0B89 /* apps-icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "apps-icon.png"; sourceTree = "<group>"; };
32E84F9F1F6BD32700CA0B89 /* apps-icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "apps-icon@2x.png"; sourceTree = "<group>"; };
32E84FA01F6BD32700CA0B89 /* apps-icon@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "apps-icon@3x.png"; sourceTree = "<group>"; };
32EF474720B6EE990031695C /* StickerPickerViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StickerPickerViewController.h; sourceTree = "<group>"; };
32EF474820B6EE990031695C /* StickerPickerViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = StickerPickerViewController.m; sourceTree = "<group>"; };
32F3AE181F6FF4E600F0F004 /* WidgetViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WidgetViewController.h; sourceTree = "<group>"; };
32F3AE191F6FF4E600F0F004 /* WidgetViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WidgetViewController.m; sourceTree = "<group>"; };
32FD0A3A1EB0CD9B0072B066 /* BugReportViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BugReportViewController.h; sourceTree = "<group>"; };
@ -794,6 +801,9 @@
92726A501F587410004AD26F /* Intents.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Intents.framework; path = System/Library/Frameworks/Intents.framework; sourceTree = SDKROOT; };
A5030B7C3C0B6EB83A9257BD /* Pods-RiotPods-Riot.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RiotPods-Riot.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RiotPods-Riot/Pods-RiotPods-Riot.debug.xcconfig"; sourceTree = "<group>"; };
B0FAA1A49F76B0CE15C5CBD8 /* Pods_RiotPods_Riot.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RiotPods_Riot.framework; sourceTree = BUILT_PRODUCTS_DIR; };
B19A173720B7F94800DF0BB0 /* DeactivateAccountViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DeactivateAccountViewController.h; sourceTree = "<group>"; };
B19A173820B7F94800DF0BB0 /* DeactivateAccountViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DeactivateAccountViewController.m; sourceTree = "<group>"; };
B19A173A20B7F96700DF0BB0 /* DeactivateAccountViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = DeactivateAccountViewController.storyboard; sourceTree = "<group>"; };
C195C53961EA28E6900AEB68 /* Pods-Riot.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Riot.release.xcconfig"; path = "Pods/Target Support Files/Pods-Riot/Pods-Riot.release.xcconfig"; sourceTree = "<group>"; };
C5258DFF261AA3AB228A3F11 /* Pods-RiotPods-RiotShareExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RiotPods-RiotShareExtension.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RiotPods-RiotShareExtension/Pods-RiotPods-RiotShareExtension.debug.xcconfig"; sourceTree = "<group>"; };
DB50EEBE8214352B9EBD6394 /* Pods_RiotPods_SiriIntents.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RiotPods_SiriIntents.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@ -1562,6 +1572,8 @@
3233F7301F31F4BF006ACA81 /* JitsiViewController.xib */,
32C2356D1F7B871800E38FC5 /* WidgetPickerViewController.h */,
32C2356E1F7B871800E38FC5 /* WidgetPickerViewController.m */,
32EF474720B6EE990031695C /* StickerPickerViewController.h */,
32EF474820B6EE990031695C /* StickerPickerViewController.m */,
);
path = Widgets;
sourceTree = "<group>";
@ -1662,6 +1674,14 @@
path = bg.lproj;
sourceTree = "<group>";
};
32C699CA20C04AD100D1C5A4 /* is.lproj */ = {
isa = PBXGroup;
children = (
32C699CB20C04AD100D1C5A4 /* Vector.strings */,
);
path = is.lproj;
sourceTree = "<group>";
};
5FC42FA41F5186AFFB6A2404 /* Frameworks */ = {
isa = PBXGroup;
children = (
@ -1717,6 +1737,16 @@
path = SiriIntents;
sourceTree = "<group>";
};
B19A173520B6F89900DF0BB0 /* DeactivateAccount */ = {
isa = PBXGroup;
children = (
B19A173720B7F94800DF0BB0 /* DeactivateAccountViewController.h */,
B19A173820B7F94800DF0BB0 /* DeactivateAccountViewController.m */,
B19A173A20B7F96700DF0BB0 /* DeactivateAccountViewController.storyboard */,
);
path = DeactivateAccount;
sourceTree = "<group>";
};
F0173EAE1FCF346800B5F6A3 /* vi.lproj */ = {
isa = PBXGroup;
children = (
@ -1797,6 +1827,7 @@
F083BB0E1E7009EC00A9B29C /* Assets */ = {
isa = PBXGroup;
children = (
32C699CA20C04AD100D1C5A4 /* is.lproj */,
32A9B3B32089CA400087E7A3 /* vi.lproj */,
32BB89E7204D86DA002F3AEC /* bg.lproj */,
3211717B203ACD32002C16C6 /* ca.lproj */,
@ -2283,6 +2314,7 @@
24B5103F1EFA88CC004C6AD2 /* ReadReceiptsViewController.xib */,
F0B4CBA31F418D0B008E99C5 /* WebViewViewController.h */,
F0B4CBA41F418D0B008E99C5 /* WebViewViewController.m */,
B19A173520B6F89900DF0BB0 /* DeactivateAccount */,
);
path = ViewController;
sourceTree = "<group>";
@ -2871,6 +2903,7 @@
vi,
ca,
bg,
is,
);
mainGroup = F094A9991B78D8F000B1FBBF;
productRefGroup = F094A9A31B78D8F000B1FBBF /* Products */;
@ -3151,6 +3184,7 @@
F083BDDA1E7009ED00A9B29C /* typing.png in Resources */,
F083BE831E7009ED00A9B29C /* RecentTableViewCell.xib in Resources */,
F046DC731FE1786500E3DAF0 /* GroupHomeViewController.xib in Resources */,
B19A173B20B7F96700DF0BB0 /* DeactivateAccountViewController.storyboard in Resources */,
F0E5D9141FF6FF3F00560D7F /* GroupRoomTableViewCell.xib in Resources */,
F083BDB71E7009ED00A9B29C /* remove_icon@2x.png in Resources */,
F083BDD31E7009ED00A9B29C /* settings_icon@3x.png in Resources */,
@ -3277,6 +3311,7 @@
F083BE3B1E7009ED00A9B29C /* RoomIncomingEncryptedAttachmentBubbleCell.xib in Resources */,
F083BD341E7009ED00A9B29C /* call_audio_mute_off_icon@2x.png in Resources */,
F083BD6E1E7009ED00A9B29C /* e2e_blocked.png in Resources */,
32C699CD20C04AD100D1C5A4 /* Vector.strings in Resources */,
F0E05A3A1EA0F9EB004B83FB /* tab_home@2x.png in Resources */,
F083BE091E7009ED00A9B29C /* AuthenticationViewController.xib in Resources */,
F083BD381E7009ED00A9B29C /* call_audio_mute_on_icon@3x.png in Resources */,
@ -3510,6 +3545,7 @@
F083BE661E7009ED00A9B29C /* RoomIncomingTextMsgWithPaginationTitleBubbleCell.m in Sources */,
F083BE141E7009ED00A9B29C /* HomeViewController.m in Sources */,
F083BDFB1E7009ED00A9B29C /* RoomSearchDataSource.m in Sources */,
32EF474920B6EE990031695C /* StickerPickerViewController.m in Sources */,
3233F73C1F3306A7006ACA81 /* WidgetManager.m in Sources */,
F0B8D0D31FDFECB200F34524 /* GroupTableViewCell.m in Sources */,
F083BE281E7009ED00A9B29C /* StartChatViewController.m in Sources */,
@ -3630,6 +3666,7 @@
F0E05A021E963103004B83FB /* FavouritesViewController.m in Sources */,
F083BE941E7009ED00A9B29C /* FilesSearchTableViewCell.m in Sources */,
F083BE921E7009ED00A9B29C /* SimpleRoomTitleView.m in Sources */,
B19A173920B7F94800DF0BB0 /* DeactivateAccountViewController.m in Sources */,
F083BE981E7009ED00A9B29C /* MessagesSearchResultTextMsgBubbleCell.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -3855,6 +3892,14 @@
name = InfoPlist.strings;
sourceTree = "<group>";
};
32C699CB20C04AD100D1C5A4 /* Vector.strings */ = {
isa = PBXVariantGroup;
children = (
32C699CC20C04AD100D1C5A4 /* is */,
);
name = Vector.strings;
sourceTree = "<group>";
};
F0173EAF1FCF346800B5F6A3 /* Vector.strings */ = {
isa = PBXVariantGroup;
children = (

View file

@ -113,6 +113,17 @@ extern NSString *const kAppDelegateNetworkStatusDidChangeNotification;
*/
- (void)logoutWithConfirmation:(BOOL)askConfirmation completion:(void (^)(BOOL isLoggedOut))completion;
/**
Log out all the accounts without confirmation.
Show the authentication screen on successful logout.
@param sendLogoutRequest Indicate whether send logout request to home server.
@param completion the block to execute at the end of the operation.
*/
- (void)logoutSendingRequestServer:(BOOL)sendLogoutServerRequest
completion:(void (^)(BOOL isLoggedOut))completion;
#pragma mark - Matrix Accounts handling
- (void)selectMatrixAccount:(void (^)(MXKAccount *selectedAccount))onSelection;

View file

@ -850,6 +850,16 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
return nil;
}
// Ignore GDPR Consent not given error. Already caught by kMXHTTPClientUserConsentNotGivenErrorNotification observation
if ([MXError isMXError:error])
{
MXError *mxError = [[MXError alloc] initWithNSError:error];
if ([mxError.errcode isEqualToString:kMXErrCodeStringConsentNotGiven])
{
return nil;
}
}
[_errorNotification dismissViewControllerAnimated:NO completion:nil];
NSString *title = [error.userInfo valueForKey:NSLocalizedFailureReasonErrorKey];
@ -2667,6 +2677,17 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
[topVC startActivityIndicator];
}
[self logoutSendingRequestServer:YES completion:^(BOOL isLoggedOut) {
if (completion)
{
completion (YES);
}
}];
}
- (void)logoutSendingRequestServer:(BOOL)sendLogoutServerRequest
completion:(void (^)(BOOL isLoggedOut))completion
{
self.pushRegistry = nil;
isPushRegistered = NO;
@ -3999,9 +4020,12 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
{
NSString *consentURI = notification.userInfo[kMXHTTPClientUserConsentNotGivenErrorNotificationConsentURIKey];
if (consentURI
&& self.gdprConsentNotGivenAlertController == nil
&& self.gdprConsentViewController == nil)
&& self.gdprConsentNotGivenAlertController.presentingViewController == nil
&& self.gdprConsentViewController.presentingViewController == nil)
{
self.gdprConsentNotGivenAlertController = nil;
self.gdprConsentViewController = nil;
UIViewController *presentingViewController = self.window.rootViewController.presentedViewController ?: self.window.rootViewController;
__weak typeof(self) weakSelf = self;
@ -4048,7 +4072,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
target:self
action:@selector(dismissGDPRConsent)];
webViewViewController.navigationItem.rightBarButtonItem = closeBarButtonItem;
webViewViewController.navigationItem.leftBarButtonItem = closeBarButtonItem;
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:webViewViewController];

View file

@ -516,3 +516,24 @@
"settings_config_no_build_info" = "Няма build информация";
"room_event_action_kick_prompt_reason" = "Причина за изгонване на потребителя";
"room_event_action_ban_prompt_reason" = "Причина за блокиране на потребителя";
// GDPR
"gdpr_consent_not_given_alert_message" = "За да продължите да използвате %@ трябва да се съгласите с условията за ползване.";
"gdpr_consent_not_given_alert_review_now_action" = "Прегледай сега";
"room_action_send_photo_or_video" = "Изпрати снимка или видео";
"room_action_send_sticker" = "Изпрати стикер";
"settings_deactivate_account" = "ДЕАКТИВАЦИЯ НА АКАУНТ";
"settings_deactivate_my_account" = "Деактивирай акаунта ми";
"widget_sticker_picker_no_stickerpacks_alert" = "В момента нямате активирани пакети със стикери.";
"widget_sticker_picker_no_stickerpacks_alert_add_now" = "Добави сега?";
"deactivate_account_title" = "Деактивиране на акаунт";
"deactivate_account_informations_part1" = "Това ще направи акаунта Ви неизползваем завинаги. Няма да можете да влезете пак, а регистрирането повторно на същия потребителски идентификатор няма да е възможно. Акаунтът Ви да напусне всички стаи, в които участва. Ще бъдат премахнати и данните за акаунта Ви от сървъра за самоличност. ";
"deactivate_account_informations_part2_emphasize" = "Действието е необратимо.";
"deactivate_account_informations_part3" = "\n\nДеактивирането на акаунта Ви ";
"deactivate_account_informations_part4_emphasize" = "по подразбиране не прави така, че изпратените съобщения да бъдат забравени. ";
"deactivate_account_informations_part5" = "Ако искате да забравим съобщенията Ви, моля отбележете с отметка по-долу\n\nВидимостта на съобщенията в Matrix е подобно на имейл системата. Нашето забравяне означава, че: изпратените от Вас съобщения няма да бъдат споделяни с нови или нерегистрирани потребители, но регистрираните потребители имащи достъп до тях ще продължат да имат достъп до своето копие.";
"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" = "За да продължите, моля въведете паролата си";

View file

@ -0,0 +1,236 @@
// Titles
"title_home" = "Domů";
"title_favourites" = "Oblíbené";
"title_people" = "Lidé";
"title_rooms" = "Místnosti";
"title_groups" = "Komunity";
"warning" = "Varování!";
// Actions
"view" = "Zobrazit zdroj";
"next" = "Další";
"back" = "Pro zabezpečení se při odhlašování odstraní všechny šifrovací klíče typu end-to-end, a i po přihlašení bude historie šifrovaných kanálů nečitelná.\nZvolte export, chcete-li je zálohovat, než se odhlásíte.";
"continue" = "Pokračovat";
"create" = "Vytvořit";
"start" = "Spustit";
"leave" = "Odejít";
"remove" = "Odebrat";
"invite" = "Pozvat";
"retry" = "Znovu";
"on" = "Zapnuto";
"off" = "Vypnuto";
"cancel" = "Zrušit";
"save" = "Uložit";
"join" = "Připojit";
"decline" = "Odmítnout";
"accept" = "Přijmout";
"preview" = "Náhled";
"camera" = "Kamera";
"voice" = "Hlas";
"video" = "Video";
"active_call" = "Aktivní hovor";
"active_call_details" = "Aktivní hovor (%@)";
"later" = "Později";
"rename" = "Přejmenovat";
"collapse" = "sbalit";
"send_to" = "Odeslat do %@";
"sending" = "Odesílání";
// Authentication
"auth_login" = "Přihlásit se";
"auth_register" = "Registrace";
"auth_submit" = "Potvrdit";
"auth_skip" = "Přeskočit";
"auth_send_reset_email" = "Poslat resetovací e-mail";
"auth_return_to_login" = "Vrátit k přihlašovací obrazovce";
"auth_user_id_placeholder" = "Email nebo uživatelské jméno";
"auth_password_placeholder" = "Heslo";
"auth_new_password_placeholder" = "Nové heslo";
"auth_user_name_placeholder" = "Uživatelské jméno";
"auth_optional_email_placeholder" = "E-mailová adresa (nepovinná)";
"auth_email_placeholder" = "E-mailová adresa";
"auth_optional_phone_placeholder" = "Číslo mobilního telefonu (nepovinné)";
"auth_phone_placeholder" = "Telefonní číslo";
"auth_repeat_password_placeholder" = "Zopakovat heslo";
"auth_repeat_new_password_placeholder" = "Potvrďte své nové heslo";
"auth_home_server_placeholder" = "URL (např. https://matrix.org)";
"auth_identity_server_placeholder" = "URL (např. https://matrix.org)";
"auth_invalid_login_param" = "Nesprávné uživatelské jméno nebo heslo";
"auth_invalid_user_name" = "Uživatelské jméno může obsahovat pouze písmena, číslice, tečky, pomlčky a podtržítka";
"auth_invalid_password" = "Heslo je velmi krátké (min 6)";
"auth_invalid_email" = "Zdá se, že toto není platná emailová adresa";
"auth_invalid_phone" = "Zdá se, že toto není platné telefonní číslo";
"auth_missing_password" = "Chybí heslo";
"auth_add_email_message" = "Přidat emailovou adresu k vašemu účtu aby vás mohli ostatní uživatelé najít a abyste si mohl vyresetovat heslo.";
"auth_add_phone_message" = "Přidat telefonní číslo k vašemu účtu aby vás mohli ostatní uživatelé najít.";
"auth_missing_email" = "Chybí emailová adresa";
"auth_missing_phone" = "Chybí telefonní číslo";
"auth_missing_email_or_phone" = "Chybí emailová adresa nebo telefonní číslo";
"auth_email_in_use" = "Tato e-mailová adresa je již používaná";
"auth_phone_in_use" = "Toto číslo se již používá";
"auth_untrusted_id_server" = "Server identit není důvěryhodný";
"auth_password_dont_match" = "Hesla se neshodují";
"auth_username_in_use" = "Uživatelské jméno je použito";
"auth_forgot_password" = "Zapomenuté heslo?";
"auth_email_not_found" = "Chyba odeslání emailu: Tato emailová adresa nebyla nalezena";
"auth_use_server_options" = "Použít vlastní možnosti serveru (pokročilé)";
"auth_email_validation_message" = "Prosím zkontrolujte své emaily, abyste mohli pokračovat v registraci";
"auth_msisdn_validation_title" = "Čeká na ověření";
"auth_recaptcha_message" = "Tento domovský server by se rád přesvědčil, že nejste robot";
"auth_reset_password_message" = "K resetování hesla vložte e-mailovou adresu spojenou s vaším účtem:";
"auth_reset_password_missing_email" = "Musíte zadat emailovou adresu spojenou s vaším účtem.";
"auth_reset_password_missing_password" = "Musíte zadat nové heslo.";
"auth_reset_password_email_validation_message" = "Na adresu %@ byla odeslána zpráva. Potom, co přejdete na odkaz z této zprávy, klikněte níže.";
"auth_reset_password_next_step_button" = "Ověřil/a jsem svoji e-mailovou adresu";
"auth_reset_password_error_unauthorized" = "E-mailovou adresu se nepodařilo ověřit. Přesvědčte se, že jste kliknul/a na zaslaný odkaz";
"auth_reset_password_error_not_found" = "Vaše e-mailová adresa zřejmě nepatří k žádnému Matrix ID na tomto domovském serveru.";
// Chat creation
"room_creation_title" = "Nový chat";
"room_creation_account" = "Účet";
"room_creation_appearance" = "Přítomnost";
"room_creation_appearance_name" = "Jméno";
"room_creation_privacy" = "Soukromí";
"room_creation_private_room" = "Tento chat je soukromý";
"room_creation_public_room" = "Tento chat je veřejný";
"room_creation_make_public" = "Zveřejnit";
"room_creation_make_public_prompt_title" = "Zveřejnit tento chat?";
"room_creation_keep_private" = "Zachovat jako soukromí";
"room_creation_make_private" = "Nastavit jako soukromé";
"room_creation_wait_for_creation" = "Místnost byla již vytvořena. Prosím vyčkejte.";
"room_creation_invite_another_user" = "Hledat / Pozvat podle uživatelského ID, jména nebo emailu";
// Room recents
"room_recents_directory_section" = "ADRESÁŘ MÍSTNOSTÍ";
"room_recents_directory_section_network" = "Síť";
"room_recents_favourites_section" = "OBLÍBENÉ";
"room_recents_people_section" = "LIDÉ";
"room_recents_conversations_section" = "MÍSTNOSTI";
"room_recents_no_conversation" = "Žádne místností";
"room_recents_low_priority_section" = "NÍZKÁ PRIORITA";
"room_recents_invites_section" = "POZVÁNÍ";
"room_recents_start_chat_with" = "Začít chat";
"room_recents_create_empty_room" = "Vytvořit místnost";
"room_recents_join_room" = "Připojit se k místnosti";
"room_recents_join_room_title" = "Připojit se k místnosti";
// People tab
"people_invites_section" = "POZVÁNÍ";
"people_conversation_section" = "KONVERZACE";
"people_no_conversation" = "Žádné konverzace";
// Rooms tab
"room_directory_no_public_room" = "Žádné veřejné mistnosti nejsou k dispozici";
// Groups tab
"group_invite_section" = "POZVÁNÍ";
"group_section" = "KOMUNITY";
// Search
"search_rooms" = "Místnosti";
"search_messages" = "Zprávy";
"search_people" = "Lidé";
"search_files" = "Soubory";
"search_default_placeholder" = "Hledat";
"search_people_placeholder" = "Hledat dle uživatelského ID, jména nebo emailu";
"search_no_result" = "Žádné výsledky";
"search_in_progress" = "Hledání…";
// Directory
"directory_cell_title" = "Procházet adresář";
"directory_cell_description" = "%tu místnosti";
"directory_search_results_title" = "Procházet výsledky výhledávání v adresáři";
"directory_search_results" = "%tu výsledky nalezeny pro %@";
"directory_search_results_more_than" = ">%tu výsledky nalezeny pro %@";
"directory_searching_title" = "Vyhledávání v adresáři…";
"directory_search_fail" = "Chyba získání dat";
// Contacts
"contacts_address_book_section" = "LOKÁLNÍ KONTAKTY";
"contacts_address_book_matrix_users_toggle" = "Pouze Matrix uživatelé";
"contacts_address_book_no_contact" = "Žádné lokální kontakty";
"contacts_address_book_permission_denied" = "Nepovolil jste přístup aplikace Riot k místním kontaktům";
"contacts_user_directory_section" = "UŽIVATELSKÝ ADRESÁŘ";
"contacts_user_directory_offline_section" = "UŽIVATELSKÝ ADRESÁŘ (offline)";
// Chat participants
"room_participants_title" = "Účastníci";
"room_participants_add_participant" = "Přidat účastníka";
"room_participants_one_participant" = "1 účastník";
"room_participants_multi_participants" = "%d účastníci";
"room_participants_leave_prompt_title" = "Odejít z místnosti";
"room_participants_leave_prompt_msg" = "Opravdu chcete opustit tuto místnost?";
"room_participants_remove_prompt_title" = "Potvrzení";
"room_participants_invite_prompt_title" = "Potvrzení";
"room_participants_filter_room_members" = "Filtrovat členy místnosti";
"room_participants_invite_malformed_id_title" = "Chyba pozvání";
"room_participants_invited_section" = "POZVANÍ";
"room_participants_online" = "Online";
"room_participants_offline" = "Offline";
"room_participants_unknown" = "Neznámý";
"room_participants_idle" = "Nečinný/á";
"room_participants_now" = "nyní";
"room_participants_ago" = "před";
"room_participants_action_section_admin_tools" = "Nástroje pro správce";
"room_participants_action_section_direct_chats" = "Přímé chaty";
"room_participants_action_section_devices" = "Zařízení";
"room_participants_action_section_other" = "Další";
"room_participants_action_invite" = "Pozvat";
"room_participants_action_leave" = "Odejít z místnosti";
"room_participants_action_remove" = "Odebrat z této místnosti";
"room_participants_action_unban" = "Přijmout zpět";
"room_participants_action_ignore" = "Schovat všechny zprávy od tohoto uživatele";
"room_participants_action_unignore" = "Zobrazit všechny zprávy od tohoto uživatele";
"room_participants_action_set_default_power_level" = "Resetovat na normálního uživatele";
"room_participants_action_set_moderator" = "Udělit moderátorství";
"room_participants_action_set_admin" = "Udělit admin práva";
"room_participants_action_start_new_chat" = "Začít novou konverzaci";
"room_participants_action_start_voice_call" = "Začít hlasový hovor";
"room_participants_action_start_video_call" = "Začít video hovor";
"room_participants_action_mention" = "Zmínka";
// Chat
"room_jump_to_first_unread" = "Přeskočit na první nepřečtenou zprávu";
"room_new_message_notification" = "%d nová zpráva";
"room_new_messages_notification" = "%d nových zpráv";
"room_one_user_is_typing" = "%@ právě píše…";
"room_two_users_are_typing" = "%@ & %@ právě píšou…";
"room_many_users_are_typing" = "%@, %@ a další píší…";
"room_message_placeholder" = "Odeslat zprávu (nešifrovanou)…";
"room_do_not_have_permission_to_post" = "Na přispívání do této místnosti nemáte právo";
"encrypted_room_message_placeholder" = "Odeslat šifrovanou zprávu…";
"room_message_short_placeholder" = "Odeslat zprávu…";
"room_offline_notification" = "Spojení se serverem bylo přerušené.";
"room_ongoing_conference_call_close" = "Zavřít";
"room_prompt_resend" = "Znovu poslat vše";
"room_prompt_cancel" = "zrušit vše";
"room_resend_unsent_messages" = "Znovu poslat neodeslané zprávy";
"room_delete_unsent_messages" = "Smazat neodeslané zprávy";
"room_event_action_copy" = "Kopírovat";
"room_event_action_quote" = "Citovat";
"room_event_action_redact" = "Redigovat";
"room_event_action_more" = "Víc";
"room_event_action_share" = "Sdílet";
"room_event_action_permalink" = "Trvalý odkaz";
"room_event_action_view_source" = "Zobrazit zdroj";
"room_event_action_report" = "Nahlasit obsah";
"room_event_action_report_prompt_reason" = "Důvod proč nahlásit obsah";
"room_event_action_save" = "Uložit";
"room_event_action_resend" = "Poslat znovu";
"room_event_action_delete" = "Odstranit";
"room_event_action_cancel_send" = "Zrušit odesílání";
"room_event_action_cancel_download" = "Zrušit stahování";
"room_event_action_view_encryption" = "Informace o šifrování";
"room_event_failed_to_send" = "Odeslání se nezdařilo";
// Unknown devices
"unknown_devices_alert_title" = "V místnosti jsou neznámá zařízení";
"unknown_devices_send_anyway" = "Přesto poslat";
"unknown_devices_call_anyway" = "Přesto zavolat";
"unknown_devices_answer_anyway" = "Přesto přijmout";
"unknown_devices_verify" = "Ověřit…";
"unknown_devices_title" = "Neznámá zařízení";
// Room Title
"room_title_new_room" = "Nová místnost";
"room_participants_invite_another_user" = "Hledat / Pozvat podle uživatelského ID, jména nebo emailu";
"room_ongoing_conference_call" = "Probíhající konferenční hovor. Připojit se jako %@ nebo %@.";
"room_ongoing_conference_call_with_close" = "Probíhající konferenční hovor. Připojit se jako %@ nebo %@. %@ to.";
"room_title_invite_members" = "Pozvat členy";
"room_title_one_member" = "1 člen";
// Room Preview
"room_preview_invitation_format" = "%@ vás pozval/a ke vstupu do této místnosti";
"room_preview_subtitle" = "Toto je náhled místnosti. Interakce byly zakázány.";
// Settings
"settings_title" = "Nastavení";
"account_logout_all" = "Odhlásit všechny účty";
"settings_report_bug" = "Nahlásit chybu";
"settings_config_home_server" = "Domácího serveru je %@";
"settings_config_identity_server" = "Server identit je %@";
"settings_config_user_id" = "Přihlášen/a jako %@";

View file

@ -517,3 +517,24 @@
"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";
"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.";
"widget_sticker_picker_no_stickerpacks_alert_add_now" = "Welche hinzufügen?";
// GDPR
"gdpr_consent_not_given_alert_message" = "Um den %@ -Heimserver weiter zu verwenden, musst du die Geschäftsbedingungen sichten und ihnen zustimmen.";
"gdpr_consent_not_given_alert_review_now_action" = "Jetzt sichten";
"deactivate_account_title" = "Deaktiviere Account";
"deactivate_account_informations_part1" = "Dies wird deinen Account permanent unbenutzbar machen. Du wirst dich nicht erneut anmelden können und keiner wird dieselbe Nutzer-ID erneut registrieren. Alle Räume, in denen dein Account ist, werden verlassen werden und deine Account-Daten werden vom Identitätsserver gelöscht werden. ";
"deactivate_account_informations_part2_emphasize" = "Diese Aktion ist irreversibel.";
"deactivate_account_informations_part3" = "\n\nDeinen Account deaktivieren ";
"deactivate_account_informations_part4_emphasize" = "wird standardmäßig nicht dafür sorgen, dass wir alle Nachrichten löschen, die du gesendet hast. ";
"deactivate_account_informations_part5" = "Wenn du möchtest, dass wir deine Nachrichten löschen, wähle das Auswahlfeld unten aus.\n\nDie Sichtbarkeit der Nachrichten in Matrix ist wie bei E-Mails: Wenn wir deine Nachrichten löschen, werden sie nicht mehr mit neuen oder nicht registrierten Benutzern geteilt, aber bereits registrierte Nutzer werden den Zugriff auf ihre Kopie deiner Nachrichten behalten.";
"deactivate_account_forget_messages_information_part1" = "Bitte vergesst alle Nachrichten, die ich gesendet habe, wenn mein Account deaktiviert wird (";
"deactivate_account_forget_messages_information_part2_emphasize" = "Warnung";
"deactivate_account_forget_messages_information_part3" = ": Dies wird dafür sorgen, dass zukünftige Nutzer eine unvollständige Konversation sehen)";
"deactivate_account_validate_action" = "Account deaktiveren";
"deactivate_account_password_alert_title" = "Account deaktivieren";
"deactivate_account_password_alert_message" = "Zum Fortfahren, Password eingeben";

View file

@ -267,6 +267,8 @@
"room_event_action_view_encryption" = "Encryption Information";
"room_warning_about_encryption" = "End-to-end encryption is in beta and may not be reliable.\n\nYou should not yet trust it to secure data.\n\nDevices will not yet be able to decrypt history from before they joined the room.\n\nEncrypted messages will not be visible on clients that do not yet implement encryption.";
"room_event_failed_to_send" = "Failed to send";
"room_action_send_photo_or_video" = "Send photo or video";
"room_action_send_sticker" = "Send sticker";
// Unknown devices
"unknown_devices_alert_title" = "Room contains unknown devices";
@ -316,6 +318,7 @@
"settings_flair" = "Show flair where allowed";
"settings_devices" = "DEVICES";
"settings_cryptography" = "CRYPTOGRAPHY";
"settings_deactivate_account" = "DEACTIVATE ACCOUNT";
"settings_sign_out" = "Sign Out";
"settings_sign_out_confirmation" = "Are you sure?";
@ -396,6 +399,8 @@
"settings_crypto_export" = "Export keys";
"settings_crypto_blacklist_unverified_devices" = "Encrypt to verified devices only";
"settings_deactivate_my_account" = "Deactivate my account";
// Room Details
"room_details_title" = "Room Details";
"room_details_people" = "Members";
@ -568,6 +573,8 @@
// Widget
"widget_no_power_to_manage" = "You need permission to manage widgets in this room";
"widget_creation_failure" = "Widget creation has failed";
"widget_sticker_picker_no_stickerpacks_alert" = "You don't currently have any stickerpacks enabled.";
"widget_sticker_picker_no_stickerpacks_alert_add_now" = "Add some now?";
// Widget Integration Manager
"widget_integration_need_to_be_able_to_invite" = "You need to be able to invite users to do that.";
@ -596,3 +603,22 @@
// GDPR
"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";
// Deactivate account
"deactivate_account_title" = "Deactivate Account";
"deactivate_account_informations_part1" = "This will make your account permanently unusable. You will not be able to log in, and no one will be able to re-register the same user ID. This will cause your account to leave all rooms it is participating in, and it will remove your account details from your identity server. ";
"deactivate_account_informations_part2_emphasize" = "This action is irreversible.";
"deactivate_account_informations_part3" = "\n\nDeactivating your account ";
"deactivate_account_informations_part4_emphasize" = "does not by default cause us to forget messages you have sent. ";
"deactivate_account_informations_part5" = "If you would like us to forget your messages, please tick the box below\n\nMessage visibility in Matrix is similar to email. Our forgetting your messages means that messages you have sent will not be shared with any new or unregistered users, but registered users who already have access to these messages will still have access to their copy.";
"deactivate_account_forget_messages_information_part1" = "Please forget all messages I have sent when my account is deactivated (";
"deactivate_account_forget_messages_information_part2_emphasize" = "Warning";
"deactivate_account_forget_messages_information_part3" = ": this will cause future users to see an incomplete view of conversations)";
"deactivate_account_validate_action" = "Deactivate account";
"deactivate_account_password_alert_title" = "Deactivate Account";
"deactivate_account_password_alert_message" = "To continue, please enter your password";

View file

@ -60,3 +60,4 @@
"auth_missing_password" = "Contraseña ausente";
"auth_add_email_message" = "Añade un correo electrónico a tu cuenta para poder ser descubierto por otros usuarios, y ser capaz de recomponer tu contraseña.";
"auth_add_phone_message" = "Añade un número telefónico a tu cuenta para ser descubierto por otros usuarios.";
"title_groups" = "Comunidades";

View file

@ -519,3 +519,6 @@
"room_do_not_have_permission_to_post" = "Ez duzu gela honetara mezuak bidaltzeko baimenik";
"room_event_action_kick_prompt_reason" = "Erabiltzaile hau kanporatzeko arrazoia";
"room_event_action_ban_prompt_reason" = "Erabiltzaile hau debekatzeko arrazoia";
// GDPR
"gdpr_consent_not_given_alert_message" = "%@ hasiera-zerbitzaria erabiltzen jarraitzeko erabilera baldintzak irakurri eta onartu behar dituzu.";
"gdpr_consent_not_given_alert_review_now_action" = "Irakurri orain";

View file

@ -517,3 +517,24 @@
"room_do_not_have_permission_to_post" = "Vous n'avez pas la permission d'envoyer des messages dans ce salon";
"room_event_action_kick_prompt_reason" = "Raison de l'exclusion de l'utilisateur";
"room_event_action_ban_prompt_reason" = "Raison du bannissement de l'utilisateur";
// GDPR
"gdpr_consent_not_given_alert_message" = "Pour continuer à utiliser le serveur d'accueil %@, vous devez lire et accepter les conditions générales.";
"gdpr_consent_not_given_alert_review_now_action" = "Voir maintenant";
"room_action_send_photo_or_video" = "Envoyer une photo ou une vidéo";
"room_action_send_sticker" = "Envoyer un sticker";
"settings_deactivate_account" = "DÉSACTIVER LE COMPTE";
"settings_deactivate_my_account" = "Désactiver mon compte";
"widget_sticker_picker_no_stickerpacks_alert" = "Vous n'avez aucun pack de stickers activé.";
"widget_sticker_picker_no_stickerpacks_alert_add_now" = "En ajouter maintenant ?";
"deactivate_account_title" = "Désactiver le compte";
"deactivate_account_informations_part1" = "Votre compte sera inutilisable de façon permanente. Vous ne pourrez plus vous connecter et personne ne pourra se réenregistrer avec le même identifiant d'utilisateur. Votre compte quittera tous les salons auxquels il participe, et tous les détails du compte seront supprimés du serveur d'identité. ";
"deactivate_account_informations_part2_emphasize" = "Cette action est irréversible.";
"deactivate_account_informations_part3" = "\n\nLa désactivation de votre compte ";
"deactivate_account_informations_part4_emphasize" = "ne nous fait pas oublier les messages que vous avez envoyés par défaut. ";
"deactivate_account_informations_part5" = "Si vous souhaitez que nous oubliions vos messages, cochez la case ci-dessous\n\nLa visibilité des messages dans Matrix est similaire à celle des e-mails. Notre oubli des messages signifie que les messages que vous avez envoyés ne seront pas partagés avec les nouveaux utilisateurs ou les utilisateurs non enregistrés, mais les utilisateurs qui ont déjà accès à ces messages auront toujours accès à leur copie.";
"deactivate_account_forget_messages_information_part1" = "Veuillez oublier tous les messages que j'ai envoyé quand mon compte sera désactivé (";
"deactivate_account_forget_messages_information_part2_emphasize" = "Avertissement";
"deactivate_account_forget_messages_information_part3" = ": les futurs utilisateurs auront alors une vue incomplète des conversations)";
"deactivate_account_validate_action" = "Désactiver le compte";
"deactivate_account_password_alert_title" = "Désactiver le compte";
"deactivate_account_password_alert_message" = "Pour continuer, veuillez renseigner votre mot de passe";

View file

@ -380,7 +380,7 @@
"room_event_action_kick_prompt_reason" = "Ástæða fyrir að sparka þessum notanda";
"room_event_action_ban_prompt_reason" = "Ástæða fyrir að banna þennan notanda";
"settings_unignore_user" = "Sýna öll skilaboð frá %@?";
"settings_labs_create_conference_with_jitsi" = "Búa til ráðstefnusamtöl með Jitsi";
"settings_labs_create_conference_with_jitsi" = "Búa til símafundi með Jitsi";
"room_details_history_section_members_only" = "Einungis meðlimir (síðan þessi kostur var valinn)";
"room_details_history_section_members_only_since_invited" = "Einungis meðlimir (síðan þeim var boðið)";
"room_details_history_section_members_only_since_joined" = "Einungis meðlimir (síðan þeir skráðu sig)";
@ -391,3 +391,101 @@
"group_participants_leave_prompt_msg" = "Ertu viss um að þú viljir fara út úr hópnum?";
"group_participants_remove_prompt_msg" = "Ertu viss um að þú viljir fjarlægja %@ úr hópnum ?";
"group_participants_invite_another_user" = "Leita/Bjóða eftir notandaauðkenni eða nafni";
"auth_add_email_message" = "Bættu tölvupóstfangi við notandaaðganginn þinn til að gera öðrum notendum kleift að finna þig og einnig til að endurstilla lykilorðið þitt.";
"auth_add_phone_message" = "Bættu símanúmeri við notandaaðganginn þinn til að gera öðrum notendum kleift að finna þig.";
"auth_add_email_phone_message" = "Bættu tölvupóstfangi og/eða símanúmeri við notandaaðganginn þinn til að gera öðrum notendum kleift að finna þig. Tölvupóstfang nýtist einnig til að endurstilla lykilorðið þitt.";
"auth_add_email_and_phone_message" = "Bættu tölvupóstfangi og símanúmeri við notandaaðganginn þinn til að gera öðrum notendum kleift að finna þig. Tölvupóstfang nýtist einnig til að endurstilla lykilorðið þitt.";
"auth_recaptcha_message" = "Þessi heimavefþjónn vill ganga úr skugga um að þú sért ekki vélmenni";
"auth_reset_password_message" = "Til að endursetja lykilorðið þitt, settu þá inn tölvupóstfangið sem tengt er notandaaðgangnum þínum:";
"auth_reset_password_missing_email" = "Það þarf að setja inn tölvupóstfangið sem tengt er notandaaðgangnum þínum.";
"auth_reset_password_email_validation_message" = "Tölvupóstur hefur verið sendur á %@ Þegar þú ert búin/n að fylgja tenglinum sem sá póstur inniheldur, smelltu þá hér fyrir neðan.";
"auth_reset_password_error_unauthorized" = "Gat ekki sannprófað tölvupóstfang: gakktu úr skugga um að þú hafir smellt á tengilinn í tölvupóstinum";
"auth_reset_password_success_message" = "Lykilorðið þitt hefur verið endurstillt.\n\nÞú hefur verið skráður út af öllum tækjum og munt ekki lengur fá ýti-tilkynningar. Til að endurvirkja tilkynningar, þarf að skrá sig aftur inn á hverju tæki fyrir sig.";
"directory_search_results" = "%tu niðurstöður fundust fyrir %@";
"directory_search_results_more_than" = ">%tu niðurstöður fundust fyrir %@";
"contacts_address_book_permission_denied" = "Þú heimilaðir Riot ekki aðgang að tengiliðum á tækinu";
"room_participants_remove_prompt_msg" = "Ertu viss um að þú viljir fjarlægja %@ úr þessu spjalli?";
"room_participants_invite_prompt_msg" = "Ertu viss um að þú viljir bjóða %@ á þetta spjall?";
"room_participants_invite_malformed_id" = "Rangt formað auðkenni. Ætti að vera tölvupóstfang eða Matrix-auðkenni á borð við'@sérheiti:lén'";
"room_unsent_messages_notification" = "Skilaboð ekki send. %@ eða %@ núna?";
"room_unsent_messages_unknown_devices_notification" = "Skilaboð ekki send vegna þess að vart var við óþekkt tæki. %@ eða %@ núna?";
"room_ongoing_conference_call" = "Símafundur í gangi. Taka þátt með %@ eða %@.";
"room_ongoing_conference_call_with_close" = "Símafundur í gangi. Taka þátt með %@ eða %@. %@ því.";
"room_conference_call_no_power" = "Þú þarft aðgangsheimildir til að sýsla með símafundi á þessari spjallrás";
"settings_contacts_phonebook_country" = "Land símaskrár";
"settings_enable_rageshake" = "Hristu ákveðið til að senda villutilkynningu";
"settings_crypto_blacklist_unverified_devices" = "Aðeins dulrita til sannvottaðra tækja";
"room_details_access_section_invited_only" = "Aðeins fólk sem hefur verið boðið";
"room_details_access_section_no_address_warning" = "Til að tengja við spjallrás verður hún að vera með vistfang";
"room_details_access_section_directory_toggle" = "Setja þessa spjallrás á skrá yfir spjallrásir";
"room_details_addresses_invalid_address_prompt_title" = "Ógilt snið samnefnis";
"room_details_advanced_e2e_encryption_blacklist_unverified_devices" = "Aðeins dulrita til sannvottaðra tækja";
// Read Receipts
"read_receipts_list" = "Listi yfir leskvittanir";
"directory_server_type_homeserver" = "Skrifaðu heimanetþjón til að telja upp opinberar spjallrásir á";
"bug_report_prompt" = "Forritið hrundi síðast. Myndirðu vilja senda inn villuskýrslu?";
"rage_shake_prompt" = "Það er eins og þú sért að hrista símann ákveðið. Myndirðu vilja senda villuskýrslu?";
// room display name
"room_displayname_invite_from" = "Boð frá %@";
"room_displayname_room_invite" = "Boð á spjallrás";
"call_jitsi_error" = "Mistókst að taka þátt í símafundi.";
"bug_report_description" = "Lýstu villunni. Hvað varstu að gera? Hverju áttirðu von á? Hvað gerðist í raun?";
"bug_crash_report_description" = "Lýstu því hvað þú varst að gera þegar forritið hrundi (á ensku):";
"bug_report_logs_description" = "Til að geta greint vandamál eru atvikaskrár þessa forrits sendar með þessari villuskýrslu. Ef þú vilt einungis senda textann hér fyrir ofan, taktu þá gátmerkið úr reitnum:";
// Widget
"widget_no_power_to_manage" = "Þú þarft aðgangsheimildir til að sýsla með viðmótshluta á þessari spjallrás";
"widget_creation_failure" = "Gerð viðmótshluta mistókst";
"widget_integration_unable_to_create" = "Gat ekki búið til viðmótshluta.";
"widget_integration_failed_to_send_request" = "Mistókst að senda beiðni.";
"widget_integration_positive_power_level" = "Völd verða að vera jákvæð heiltala.";
"widget_integration_missing_room_id" = "Vantar spjallrásarauðkenni í beiðni.";
"widget_integration_missing_user_id" = "Vantar notandaauðkenni í beiðni.";
"widget_integration_room_not_visible" = "Spjallrásin %@ er ekki sýnileg.";
// Room key request dialog
"e2e_room_key_request_title" = "Beiðni um dulritunarlykil";
"gdpr_consent_not_given_alert_review_now_action" = "Yfirfara núna";
"room_creation_make_public_prompt_msg" = "Ertu viss um að þú viljir gera þetta spjall opinbert? Hver sem er gæti þá lesið skilaboðin þín og tekið þátt í spjallinu.";
"contacts_address_book_permission_required" = "Heimild þarf til að fá aðgang að tengiliðum á tækinu";
"room_participants_invite_malformed_id_title" = "Villa við boð";
"room_preview_subtitle" = "Þetta er forskoðun á spjallrásinni. Samskipti spjallrásarinnar hafa verið gerð óvirk.";
"room_preview_try_join_an_unknown_room" = "Þú ert að reyna að tengjast %@ Myndirðu vilja gerast meðlimur til að geta tekið þátt í samræðunni?";
"settings_fail_to_update_profile" = "Mistókst að uppfæra notandasnið";
"settings_pin_rooms_with_missed_notif" = "Festa spjallrásir með óskoðuðum tilkynningum";
"settings_pin_rooms_with_unread" = "Festa spjallrásir með ólesnum skilaboðum";
"settings_on_denied_notification" = "Tilkynningum er hafnað fyrir %@, leyfðu þær í stillingum tækisins";
"settings_ui_theme_picker_message" = "\"Sjálfvirkt\" notar \"Umsnúa litum\" stillingar tækisins";
"settings_contacts_discover_matrix_users" = "Notaðu tölvupóstföng og símanúmer til að finna notendur";
"settings_labs_e2e_encryption_prompt_message" = "Til að ljúka við uppsetningu á dulritun verðurðu að skrá þig inn aftur.";
"room_details_access_section_anyone_apart_from_guest" = "Hver sá sem þekkir slóðina á spjallrásina, fyrir utan gesti";
"room_details_access_section_anyone" = "Hver sá sem þekkir slóðina á spjallrásina, fyrir utan gesti";
"room_details_new_address_placeholder" = "Bæta við nýju vistfangi (t.d. #foo%@)";
"room_details_addresses_invalid_address_prompt_msg" = "%@ er ekki gilt snið fyrir samnefni";
"room_details_addresses_disable_main_address_prompt_title" = "Aðvaranir vegna aðalvistfangs";
"room_details_advanced_enable_e2e_encryption" = "Virkja dulritun (aðvörun: er ekki hægt að gera aftur óvirkt!)";
"room_details_fail_to_update_avatar" = "Mistókst að uppfæra mynd spjallrásar";
"room_details_fail_to_update_room_name" = "Mistókst að uppfæra heiti spjallrásar";
"room_details_fail_to_update_topic" = "Mistókst að uppfæra umræðuefnið";
"room_details_fail_to_update_room_guest_access" = "Mistókst að uppfæra gestaaðgang spjallrásar";
"room_details_fail_to_update_room_join_rule" = "Mistókst að uppfæra reglu fyrir þátttöku";
"room_details_fail_to_update_room_directory_visibility" = "Mistókst að uppfæra sýnileika spjallrásarskrár";
"room_details_fail_to_update_history_visibility" = "Mistókst að uppfæra sýnileika ferilskráningar";
"room_details_fail_to_update_room_canonical_alias" = "Mistókst að uppfæra aðalvistfangið";
"room_details_fail_to_enable_encryption" = "Mistókst að virkja dulritun á þessari spjallrás";
"room_details_set_main_address" = "Setja sem aðalvistfang";
"room_details_unset_main_address" = "Ekki setja sem aðalvistfang";
"group_participants_invite_prompt_msg" = "Ertu viss um að þú viljir bjóða %@ í þennan hóp?";
"group_participants_invite_malformed_id_title" = "Villa við boð";
"group_participants_invite_malformed_id" = "Rangt formað auðkenni. Ætti að vera Matrix-auðkenni á borð við'@sérheiti:lén'";
"directory_server_placeholder" = "matrix.org";
// Events formatter
"event_formatter_member_updates" = "%tu breytingar á aðild";
"event_formatter_widget_added" = "%@ viðmótshluta bætt við af %@";
"event_formatter_widget_removed" = "%@ viðmótshluti fjarlægður af %@";
"event_formatter_jitsi_widget_added" = "VoIP-símafundi bætt við af %@";
"event_formatter_jitsi_widget_removed" = "VoIP-símafundur fjarlægður af %@";
"public_room_section_title" = "Opinberar spjallrásir (á %@):";
"widget_integration_room_not_recognised" = "Spjallrás er ekki þekkt.";
// Share extension
"share_extension_auth_prompt" = "Skráðu inn í aðalforrit til að deila efni";
"e2e_room_key_request_message_new_device" = "Þú bættir við nýju tæki '%@', sem er að krefjast dulritunarlykla.";
"e2e_room_key_request_message" = "Ósannvottaða tækið þitt '%@' er að krefjast dulritunarlykla.";

View file

@ -0,0 +1,5 @@
// Permissions usage explanations
"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" = "La rubrica viene utilizzata per ricercare utenti tramite email o numero di telefono su Riot.";

View file

@ -0,0 +1,30 @@
/* New message from a specific person, not referencing a room */
"MSG_FROM_USER" = "Messaggio ricevuto da %@";
/* New message from a specific person in a named room */
"MSG_FROM_USER_IN_ROOM" = "%@ ha scritto in %@";
/* 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" = "%@ in %@: %@";
/* 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" = "%@ ha inviato un'immagine %@";
/* New action message from a specific person in a named room. */
"IMAGE_FROM_USER_IN_ROOM" = "%@ ha inviato un'immagine %@ in %@";
/* A single unread message in a room */
"SINGLE_UNREAD_IN_ROOM" = "Hai ricevuto un messaggio in %@";
/* A single unread message */
"SINGLE_UNREAD" = "Hai ricevuto un messaggio";
/* Multiple unread messages in a room */
"UNREAD_IN_ROOM" = "%@ nuovi messaggi in %@";
/* Multiple unread messages from a specific person, not referencing a room */
"MSGS_FROM_USER" = "%@ nuovi messaggi in %@";
/* Multiple unread messages from two people */
"MSGS_FROM_TWO_USERS" = "%@ nuovi messaggi da %@ e %@";
/* Multiple unread messages from three people */
"MSGS_FROM_THREE_USERS" = "%@ nuovi messaggi da %@, %@ e %@";
/* Multiple unread messages from two plus people (ie. for 4+ people: 'others' replaces the third person) */
"MSGS_FROM_TWO_PLUS_USERS" = "%@ nuovi messaggi da %@, %@ e altri";

View file

@ -0,0 +1,5 @@
// Titles
"title_home" = "Home";
"title_favourites" = "Preferiti";
"title_people" = "Persone";
"title_rooms" = "Stanze";

View file

@ -1,5 +1,5 @@
// Permissions usage explanations
"NSCameraUsageDescription" = "カメラや写真撮影や動画撮影、映像付き通話のために使用されます。";
"NSCameraUsageDescription" = "ビデオ通話や写真撮影、動画撮影などを行うときにカメラを使用します。";
"NSPhotoLibraryUsageDescription" = "フォトライブラリは、写真や動画の送信に使用されます。";
"NSMicrophoneUsageDescription" = "マイクは動画撮影や通話に使用されます。";
"NSContactsUsageDescription" = "本体内の連絡先、アドレス帳は、Riotのユーザを電子メールアドレスや電話番号で検索する際に使用します。";

View file

@ -31,15 +31,6 @@ window.riotIOS.events = {};
// Listen to messages posted by the widget
window.riotIOS.onMessage = function(event) {
// Do not SPAM ObjC with event already managed
if (riotIOS.events[event.data._id]) {
return;
}
if (!event.origin) { // stupid chrome
event.origin = event.originalEvent.origin;
}
// Use an internal "_id" field for matching onMessage events and requests
// _id was originally used by the Modular API. Keep it
if (!event.data._id) {
@ -52,6 +43,15 @@ window.riotIOS.onMessage = function(event) {
if (!event.data._id) {
event.data._id = Date.now() + "-" + Math.random().toString(36);
}
// Do not SPAM ObjC with event already managed
if (riotIOS.events[event.data._id]) {
return;
}
if (!event.origin) { // stupid chrome
event.origin = event.originalEvent.origin;
}
// Keep this event for future usage
riotIOS.events[event.data._id] = event;

View file

@ -541,3 +541,8 @@
// Group rooms
"group_rooms_filter_rooms" = "Gemeenschapsruimtes filteren";
"e2e_room_key_request_message_new_device" = "Je hebt een nieuwe apparaat '%@' toegevoegd, die een verzoek doet naar versleutelingssleutels.";
"room_event_action_kick_prompt_reason" = "Reden voor het verwijderen van deze gebruiker";
"room_event_action_ban_prompt_reason" = "Reden voor het verbannen van deze gebruiker";
// GDPR
"gdpr_consent_not_given_alert_message" = "Om de %@ thuisserver te blijven gebruiken moet je de algemeen voorwaarden lezen en daarmee akkoord gaan.";
"gdpr_consent_not_given_alert_review_now_action" = "Nu doorlezen";

View file

@ -518,3 +518,24 @@
"room_details_flair_section" = "Показать настроение для сообществ";
"room_event_action_kick_prompt_reason" = "Причина по которой этот пользователь будет выкинут";
"room_event_action_ban_prompt_reason" = "Причина по которой этот пользователь будет забанен";
// GDPR
"gdpr_consent_not_given_alert_message" = "Для продолжения использования сервера %@ вы должны принять условия и положения.";
"gdpr_consent_not_given_alert_review_now_action" = "Просмотреть сейчас";
"room_action_send_photo_or_video" = "Отправить фото или видео";
"room_action_send_sticker" = "Отправить стикер";
"settings_deactivate_account" = "ДЕАКТИВАЦИЯ АККАУНТА";
"settings_deactivate_my_account" = "Деактивировать мой аккаунт";
"widget_sticker_picker_no_stickerpacks_alert_add_now" = "Добавить сейчас?";
"deactivate_account_title" = "Деактивировать аккаунт";
"deactivate_account_informations_part1" = "Это действие сделает вашу учетную запись непригодной для дальнейшего использования. Вы не сможете войти в систему и никто другой не сможет заново зарегистрировать учетную запись с вашим идентификатором. Также, это приведет к тому, что вы покинете все комнаты, в которых участвовали и данные о вашей учетной записи будут удалены с сервера идентификации. ";
"deactivate_account_informations_part2_emphasize" = "Это действие необратимо.";
"deactivate_account_informations_part3" = "\n\nДеактивация вашего аккаунта ";
"deactivate_account_informations_part4_emphasize" = "по умолчанию не удаляет отправленные вами сообщения. ";
"deactivate_account_informations_part5" = "Если вы хотите, чтобы мы удалили все ваши сообщения - поставьте отметку в поле ниже.\n\nВидимость сообщений в Matrix похожа на электронную почту. Удаление ваших сообщений означает, что отправленные вами сообщения не будут показаны новым или не зарегистрированным пользователям, но те пользователи, которые уже получили эти сообщения - по прежнему будут их видеть.";
"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" = "Чтобы продолжить, введите пароль";
"widget_sticker_picker_no_stickerpacks_alert" = "У вас пока нет включенных пакетов стикеров.";

View file

@ -68,7 +68,7 @@
"auth_msisdn_validation_title" = "等待验证中";
"auth_msisdn_validation_message" = "我们通过短信向您发送了一条验证码,请在下方输入它。";
"auth_msisdn_validation_error" = "无法验证此手机号。";
"auth_recaptcha_message" = "此主服务器想确认你不是机器人";
"auth_recaptcha_message" = "此主服务器想确保您不是机器人";
"auth_reset_password_message" = "为了重置您的密码,请输入与您帐号关联的邮箱地址:";
"auth_reset_password_missing_email" = "必须输入与您的账户关联的邮箱地址。";
"auth_reset_password_missing_password" = "必须输入新的密码。";
@ -76,7 +76,7 @@
"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_reset_password_success_message" = "您的密码已重置。\n\n您的所有设备都会被登出并且不会收到推送通知。要想重新收到通知请在每个设备上重新登录。";
"auth_add_email_and_phone_warning" = "在 API 出现之前,还不支持使用邮箱地址或手机号码直接注册。只有手机号码会和此账户绑定。您可以在设置中添加邮箱地址。";
// Chat creation
"room_creation_title" = "创建聊天";
@ -198,7 +198,7 @@
"room_delete_unsent_messages" = "删除未发送消息";
"room_event_action_copy" = "复制";
"room_event_action_quote" = "引用";
"room_event_action_redact" = "移除";
"room_event_action_redact" = "撤回";
"room_event_action_more" = "移动";
"room_event_action_share" = "分享";
"room_event_action_permalink" = "永久链接";
@ -398,11 +398,11 @@
// Crash report
"google_analytics_use_prompt" = "您打算通过自动报告匿名的崩溃报告和使用数据来帮助提升 %@ 吗?";
// Crypto
"e2e_enabling_on_app_update" = "Riot 目前支持端对端加密但是您需要重新登录来启用。\n\n您可以现在重新登录也可以之后从应用程序设置里选择。";
"e2e_enabling_on_app_update" = "Riot 目前支持端对端加密,但是您需要重新登录以启用它。\n\n您可以现在重新登录也可以之后再从应用程序设置中选择开启。";
"e2e_need_log_in_again" = "您需要登录回来以便为此设备生成端对端加密密钥并提交公钥到您的主服务器。\n这只需要做一次很抱歉造成打扰。";
// Bug report
"bug_report_title" = "Bug 报告";
"bug_report_description" = "请描述此 bug。您做了什么您期待发生什么?以及实际发生了什么?";
"bug_report_description" = "请描述此 bug。您做了什么本来应该发生什么?以及实际发生了什么?";
"bug_crash_report_title" = "崩溃报告";
"bug_crash_report_description" = "请描述崩溃前发生了什么:";
"bug_report_logs_description" = "为了诊断问题,这个客户端的日志会随这个 bug 报告发送。如果你只想发送上面的文字,请取消选择:";

View file

@ -17,11 +17,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.6.16</string>
<string>0.6.17</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>0.6.16</string>
<string>0.6.17</string>
<key>ITSAppUsesNonExemptEncryption</key>
<true/>
<key>ITSEncryptionExportComplianceCode</key>

View file

@ -35,6 +35,7 @@ FOUNDATION_EXPORT NSString *const kWidgetModularEventTypeString;
Known types widgets.
*/
FOUNDATION_EXPORT NSString *const kWidgetTypeJitsi;
FOUNDATION_EXPORT NSString *const kWidgetTypeStickerPicker;
/**
Posted when a widget has been created, updated or disabled.
@ -101,6 +102,15 @@ WidgetManagerErrorCode;
*/
- (NSArray<Widget*> *)userWidgets:(MXSession*)mxSession;
/**
List all widgets of a given type of an account.
@param mxSession the session of the user account.
@param widgetTypes the types of widget to search. Nil means all types.
@return a list of widgets.
*/
- (NSArray<Widget*> *)userWidgets:(MXSession*)mxSession ofTypes:(NSArray<NSString*>*)widgetTypes;
/**
Add a modular widget to a room.

View file

@ -23,6 +23,7 @@
NSString *const kWidgetMatrixEventTypeString = @"m.widget";
NSString *const kWidgetModularEventTypeString = @"im.vector.modular.widgets";
NSString *const kWidgetTypeJitsi = @"jitsi";
NSString *const kWidgetTypeStickerPicker = @"m.stickerpicker";
NSString *const kWidgetManagerDidUpdateWidgetNotification = @"kWidgetManagerDidUpdateWidgetNotification";
@ -174,14 +175,22 @@ NSString *const WidgetManagerErrorDomain = @"WidgetManagerErrorDomain";
- (NSArray<Widget*> *)userWidgets:(MXSession*)mxSession
{
// Disable user widgets (sticker picker) for now
return nil;
return [self userWidgets:mxSession ofTypes:nil];
}
- (NSArray<Widget*> *)userWidgets:(MXSession*)mxSession ofTypes:(NSArray<NSString*>*)widgetTypes
{
// Get all widgets in the user account data
NSMutableArray<Widget *> *userWidgets = [NSMutableArray array];
for (NSDictionary *widgetEventContent in [mxSession.accountData accountDataForEventType:@"m.widgets"].allValues)
for (NSDictionary *widgetEventContent in [mxSession.accountData accountDataForEventType:kMXAccountDataTypeUserWidgets].allValues)
{
// Patch: Modular uses a malformed key: "stateKey" instead of "state_key"
if (![widgetEventContent isKindOfClass:NSDictionary.class])
{
NSLog(@"[WidgetManager] userWidgets: ERROR: invalid user widget format: %@", widgetEventContent);
continue;
}
// Patch: Modular used a malformed key: "stateKey" instead of "state_key"
// TODO: To remove once fixed server side
NSDictionary *widgetEventContentFixed = widgetEventContent;
if (!widgetEventContent[@"state_key"] && widgetEventContent[@"stateKey"])
@ -192,7 +201,8 @@ NSString *const WidgetManagerErrorDomain = @"WidgetManagerErrorDomain";
}
MXEvent *widgetEvent = [MXEvent modelFromJSON:widgetEventContentFixed];
if (widgetEvent)
if (widgetEvent
&& (!widgetTypes || [widgetTypes containsObject:widgetEvent.content[@"type"]]))
{
Widget *widget = [[Widget alloc] initWithWidgetEvent:widgetEvent inMatrixSession:mxSession];
if (widget)

View file

@ -0,0 +1,45 @@
/*
Copyright 2018 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;
@import MatrixKit;
#pragma mark - Types
@class DeactivateAccountViewController;
#pragma mark - Protocol
@protocol DeactivateAccountViewControllerDelegate <NSObject>
- (void)deactivateAccountViewControllerDidCancel:(DeactivateAccountViewController*)deactivateAccountViewController;
- (void)deactivateAccountViewControllerDidDeactivateWithSuccess:(DeactivateAccountViewController*)deactivateAccountViewController;
@end
#pragma mark - Interface
@interface DeactivateAccountViewController : MXKViewController
#pragma mark - Properties
@property (nonatomic, weak) id<DeactivateAccountViewControllerDelegate> delegate;
#pragma mark - Class Methods
+ (DeactivateAccountViewController*)instantiateWithMatrixSession:(MXSession*)matrixSession;
@end

View file

@ -0,0 +1,334 @@
/*
Copyright 2018 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 "DeactivateAccountViewController.h"
#import "RiotDesignValues.h"
#import "AppDelegate.h"
#pragma mark - Defines & Constants
static CGFloat const kButtonCornerRadius = 5.0;
static CGFloat const kTextFontSize = 15.0;
#pragma mark - Private Interface
@interface DeactivateAccountViewController ()
#pragma mark - Outlets
@property (weak, nonatomic) IBOutlet UILabel *deactivateAccountInfosLabel;
@property (weak, nonatomic) IBOutlet UILabel *forgetMessagesInfoLabel;
@property (weak, nonatomic) IBOutlet UIButton *forgetMessageButton;
@property (weak, nonatomic) IBOutlet UIButton *deactivateAcccountButton;
#pragma mark - Private Properties
@property (strong, nonatomic) NSDictionary *normalStringAttributes;
@property (strong, nonatomic) NSDictionary *emphasizeStringAttributes;
@property (strong, nonatomic) MXKErrorAlertPresentation *errorPresentation;
@property (weak, nonatomic) id <NSObject> themeDidChangeNotificationObserver;
@end
#pragma mark - Implementation
@implementation DeactivateAccountViewController
#pragma mark - Setup & Teardown
+ (DeactivateAccountViewController*)instantiateWithMatrixSession:(MXSession*)matrixSession
{
DeactivateAccountViewController* viewController = [[UIStoryboard storyboardWithName:NSStringFromClass([DeactivateAccountViewController class]) bundle:[NSBundle mainBundle]] instantiateInitialViewController];
[viewController addMatrixSession:matrixSession];
return viewController;
}
- (void)destroy
{
id<NSObject> notificationObserver = self.themeDidChangeNotificationObserver;
if (notificationObserver)
{
[[NSNotificationCenter defaultCenter] removeObserver:notificationObserver];
}
[super destroy];
}
#pragma mark - View life cycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.title = NSLocalizedStringFromTable(@"deactivate_account_title", @"Vector", nil);
self.errorPresentation = [[MXKErrorAlertPresentation alloc] init];
[self setupStringAttributes];
[self setupViews];
[self userInterfaceThemeDidChange];
[self registerThemeNotification];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// Screen tracking
[[AppDelegate theDelegate] trackScreen:@"DeactivateAccount"];
}
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
[self.deactivateAcccountButton.layer setCornerRadius:kButtonCornerRadius];
}
- (UIStatusBarStyle)preferredStatusBarStyle
{
return kRiotDesignStatusBarStyle;
}
#pragma mark - Private
- (void)registerThemeNotification
{
self.themeDidChangeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
[self userInterfaceThemeDidChange];
}];
}
- (void)userInterfaceThemeDidChange
{
self.view.backgroundColor = kRiotPrimaryBgColor;
self.defaultBarTintColor = kRiotSecondaryBgColor;
self.activityIndicator.backgroundColor = kRiotOverlayColor;
}
- (void)setupStringAttributes
{
self.normalStringAttributes = @{
NSFontAttributeName: [UIFont systemFontOfSize:kTextFontSize],
NSForegroundColorAttributeName: kRiotPrimaryTextColor
};
self.emphasizeStringAttributes = @{
NSFontAttributeName: [UIFont systemFontOfSize:kTextFontSize weight:UIFontWeightBold],
NSForegroundColorAttributeName: kRiotPrimaryTextColor
};
}
- (void)setupViews
{
[self setupNavigationBar];
[self setupDeactivateAcccountButton];
[self setupDeactivateAccountInfosLabel];
[self setupForgetMessagesInfoLabel];
}
- (void)setupNavigationBar
{
self.navigationController.navigationBar.titleTextAttributes = @{ NSForegroundColorAttributeName: kRiotColorRed };
UIBarButtonItem *cancelBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedStringFromTable(@"cancel", @"Vector", nil) style:UIBarButtonItemStylePlain target:self action:@selector(cancelButtonAction:)];
self.navigationItem.rightBarButtonItem = cancelBarButtonItem;
}
- (void)setupDeactivateAcccountButton
{
// Adjust button font size for small devices
self.deactivateAcccountButton.titleLabel.adjustsFontSizeToFitWidth = YES;
self.deactivateAcccountButton.titleLabel.minimumScaleFactor = 0.5;
self.deactivateAcccountButton.titleLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
self.deactivateAcccountButton.layer.masksToBounds = YES;
self.deactivateAcccountButton.backgroundColor = kRiotColorGreen;
[self.deactivateAcccountButton setTitle:NSLocalizedStringFromTable(@"deactivate_account_validate_action", @"Vector", nil) forState:UIControlStateNormal];
[self.deactivateAcccountButton setTitleColor:kRiotColorSilver forState:UIControlStateDisabled];
}
- (void)setupDeactivateAccountInfosLabel
{
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init];
[attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"deactivate_account_informations_part1", @"Vector", nil) attributes:self.normalStringAttributes]];
[attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"deactivate_account_informations_part2_emphasize", @"Vector", nil) attributes:self.emphasizeStringAttributes]];
[attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"deactivate_account_informations_part3", @"Vector", nil) attributes:self.normalStringAttributes]];
[attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"deactivate_account_informations_part4_emphasize", @"Vector", nil) attributes:self.emphasizeStringAttributes]];
[attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"deactivate_account_informations_part5", @"Vector", nil) attributes:self.normalStringAttributes]];
[self.deactivateAccountInfosLabel setAttributedText:attributedString];
}
- (void)setupForgetMessagesInfoLabel
{
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init];
[attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"deactivate_account_forget_messages_information_part1", @"Vector", nil) attributes:self.normalStringAttributes]];
[attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"deactivate_account_forget_messages_information_part2_emphasize", @"Vector", nil) attributes:self.emphasizeStringAttributes]];
[attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"deactivate_account_forget_messages_information_part3", @"Vector", nil) attributes:self.normalStringAttributes]];
[self.forgetMessagesInfoLabel setAttributedText:attributedString];
}
- (void)enableUserActions:(BOOL)enableUserActions
{
self.navigationItem.rightBarButtonItem.enabled = enableUserActions;
self.forgetMessageButton.userInteractionEnabled = enableUserActions;
self.deactivateAcccountButton.enabled = enableUserActions;
}
- (void)presentPasswordRequiredAlertWithSubmitHandler:(void (^)(NSString *password))submitHandler
cancelHandler:(dispatch_block_t)cancelHandler
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedStringFromTable(@"deactivate_account_password_alert_title", @"Vector", nil)
message:NSLocalizedStringFromTable(@"deactivate_account_password_alert_message", @"Vector", nil) preferredStyle:UIAlertControllerStyleAlert];
[alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
textField.secureTextEntry = YES;
textField.placeholder = nil;
textField.keyboardType = UIKeyboardTypeDefault;
}];
[alert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"]
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action) {
if (cancelHandler)
{
cancelHandler();
}
}]];
__weak typeof(self) weakSelf = self;
[alert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"submit"]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
UITextField *textField = alert.textFields.firstObject;
typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf)
{
NSString *password = textField.text;
if (submitHandler)
{
submitHandler(password);
}
}
}]];
[self presentViewController:alert animated:YES completion:nil];
}
- (void)deactivateAccountWithUserId:(NSString*)userId
andPassword:(NSString*)password
eraseAllMessages:(BOOL)eraseAllMessages
{
if (password && userId)
{
[self enableUserActions:NO];
[self startActivityIndicator];
// This assumes that the homeserver requires password UI auth
// for this endpoint. In reality it could be any UI auth.
__weak typeof(self) weakSelf = self;
NSDictionary *authParameters = @{@"user": userId,
@"password": password,
@"type": kMXLoginFlowTypePassword};
[self.mainSession deactivateAccountWithAuthParameters:authParameters eraseAccount:eraseAllMessages success:^{
NSLog(@"[SettingsViewController] Deactivate account with success");
typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf)
{
[strongSelf stopActivityIndicator];
[strongSelf enableUserActions:YES];
[strongSelf.delegate deactivateAccountViewControllerDidDeactivateWithSuccess:strongSelf];
}
} failure:^(NSError *error) {
NSLog(@"[SettingsViewController] Failed to deactivate account");
typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf)
{
[strongSelf stopActivityIndicator];
[strongSelf enableUserActions:YES];
[strongSelf.errorPresentation presentErrorFromViewController:strongSelf forError:error animated:YES handler:nil];
}
}];
}
else
{
NSLog(@"[SettingsViewController] Failed to deactivate account");
[self.errorPresentation presentGenericErrorFromViewController:self animated:YES handler:nil];
}
}
#pragma mark - Actions
- (void)cancelButtonAction:(id)sender
{
[self.delegate deactivateAccountViewControllerDidCancel:self];
}
- (IBAction)forgetMessagesButtonAction:(UIButton*)sender
{
self.forgetMessageButton.selected = !self.forgetMessageButton.selected;
}
- (IBAction)deactivateAccountButtonAction:(id)sender
{
__weak typeof(self) weakSelf = self;
[self presentPasswordRequiredAlertWithSubmitHandler:^(NSString *password) {
typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf)
{
NSString *userId = strongSelf.mainSession.myUser.userId;
[strongSelf deactivateAccountWithUserId:userId andPassword:password eraseAllMessages:strongSelf.forgetMessageButton.isEnabled];
}
} cancelHandler:nil];
}
@end

View file

@ -0,0 +1,130 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="IHf-2R-Nmh">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Deactivate Account View Controller-->
<scene sceneID="qDi-ox-hHh">
<objects>
<viewController automaticallyAdjustsScrollViewInsets="NO" id="IHf-2R-Nmh" customClass="DeactivateAccountViewController" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="QVw-lB-bra">
<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="OSw-nj-Wdk">
<rect key="frame" x="0.0" y="20" width="375" height="647"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="r6I-6D-FLD">
<rect key="frame" x="0.0" y="0.0" width="375" height="641"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="justified" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uaL-Wi-UcQ">
<rect key="frame" x="20" y="15" width="335" height="426.5"/>
<string key="text">This will make your account permanently unusable. You will not be able to log in, and no one will be able to re-register the same user ID. This will cause your account to leave all rooms it is participating in, and it will remove your account details from your identity server. This action is irreversible.
Deactivating your account does not by default cause us to forget messages you have sent. If you would like us to forget your messages, please tick the box below.
Message visibility in Matrix is similar to email. Our forgetting your messages means that messages you have sent will not be shared with any new or unregistered users, but registered users who already have access to these messages will still have access to their copy.
</string>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="UBr-xR-a5z">
<rect key="frame" x="10" y="449.5" width="44" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="3Bn-lP-a2k"/>
<constraint firstAttribute="width" secondItem="UBr-xR-a5z" secondAttribute="height" multiplier="1:1" id="6Nd-IG-Wda"/>
</constraints>
<state key="normal" image="selection_untick.png"/>
<state key="selected" image="selection_tick.png"/>
<connections>
<action selector="forgetMessagesButtonAction:" destination="IHf-2R-Nmh" eventType="touchUpInside" id="gbq-6b-IU4"/>
</connections>
</button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2AU-Ro-4rr">
<rect key="frame" x="54" y="459.5" width="301" height="101.5"/>
<string key="text">Please forget all messages I have sent when my account is deactivated (Warning: this will cause future users to see an incomplete view of conversations)</string>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="7fz-Dy-5pc">
<rect key="frame" x="83" y="586" width="208" height="30"/>
<color key="backgroundColor" red="0.028153735480000001" green="0.82494870580000002" blue="0.051896891280000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="AuthenticationVCLoginButton"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="GpW-8Z-aDc"/>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="100" id="gMI-XP-i84"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="16"/>
<inset key="contentEdgeInsets" minX="30" minY="0.0" maxX="30" maxY="0.0"/>
<state key="normal" title="Deactivate Account">
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<connections>
<action selector="deactivateAccountButtonAction:" destination="IHf-2R-Nmh" eventType="touchUpInside" id="ZgL-dj-3sa"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="2AU-Ro-4rr" firstAttribute="leading" secondItem="UBr-xR-a5z" secondAttribute="trailing" id="2dA-G3-YmX"/>
<constraint firstAttribute="trailing" secondItem="uaL-Wi-UcQ" secondAttribute="trailing" constant="20" id="3VC-8f-t4r"/>
<constraint firstItem="7fz-Dy-5pc" firstAttribute="centerX" secondItem="r6I-6D-FLD" secondAttribute="centerX" id="ArL-9U-gev"/>
<constraint firstItem="7fz-Dy-5pc" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="r6I-6D-FLD" secondAttribute="leading" constant="20" id="GdW-9q-ham"/>
<constraint firstItem="UBr-xR-a5z" firstAttribute="leading" secondItem="r6I-6D-FLD" secondAttribute="leading" constant="10" id="HEu-UC-ZqJ"/>
<constraint firstItem="2AU-Ro-4rr" firstAttribute="top" secondItem="UBr-xR-a5z" secondAttribute="top" constant="10" id="Je8-yX-RL7"/>
<constraint firstItem="7fz-Dy-5pc" firstAttribute="top" secondItem="2AU-Ro-4rr" secondAttribute="bottom" constant="25" id="Rie-CJ-sjU"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="7fz-Dy-5pc" secondAttribute="trailing" constant="20" id="aBJ-Qh-98C"/>
<constraint firstItem="uaL-Wi-UcQ" firstAttribute="top" secondItem="r6I-6D-FLD" secondAttribute="top" constant="15" id="gNW-9W-tWy"/>
<constraint firstItem="uaL-Wi-UcQ" firstAttribute="leading" secondItem="r6I-6D-FLD" secondAttribute="leading" constant="20" id="hkc-Mh-1eX"/>
<constraint firstAttribute="bottom" secondItem="7fz-Dy-5pc" secondAttribute="bottom" constant="25" id="pcJ-cW-k1P"/>
<constraint firstItem="2AU-Ro-4rr" firstAttribute="trailing" secondItem="uaL-Wi-UcQ" secondAttribute="trailing" id="unG-rW-hIH"/>
<constraint firstItem="UBr-xR-a5z" firstAttribute="top" secondItem="uaL-Wi-UcQ" secondAttribute="bottom" constant="8" id="ygz-iG-BYI"/>
</constraints>
</view>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="r6I-6D-FLD" secondAttribute="trailing" id="Cv8-1O-u62"/>
<constraint firstItem="r6I-6D-FLD" firstAttribute="width" secondItem="OSw-nj-Wdk" secondAttribute="width" id="LbL-Rk-YWQ"/>
<constraint firstItem="r6I-6D-FLD" firstAttribute="top" secondItem="OSw-nj-Wdk" secondAttribute="top" id="bWG-YM-ufd"/>
<constraint firstAttribute="bottom" secondItem="r6I-6D-FLD" secondAttribute="bottom" id="eTa-ak-f7f"/>
<constraint firstItem="r6I-6D-FLD" firstAttribute="leading" secondItem="OSw-nj-Wdk" secondAttribute="leading" id="jDI-GL-r0a"/>
</constraints>
</scrollView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="HwH-O8-jKY" firstAttribute="top" secondItem="OSw-nj-Wdk" secondAttribute="top" id="0VJ-Ig-2ed"/>
<constraint firstItem="HwH-O8-jKY" firstAttribute="leading" secondItem="OSw-nj-Wdk" secondAttribute="leading" id="Hc0-LV-lRt"/>
<constraint firstItem="HwH-O8-jKY" firstAttribute="trailing" secondItem="OSw-nj-Wdk" secondAttribute="trailing" id="slf-Q8-PKr"/>
<constraint firstItem="HwH-O8-jKY" firstAttribute="bottom" secondItem="OSw-nj-Wdk" secondAttribute="bottom" id="vr6-Pc-AP8"/>
</constraints>
<viewLayoutGuide key="safeArea" id="HwH-O8-jKY"/>
</view>
<connections>
<outlet property="deactivateAcccountButton" destination="7fz-Dy-5pc" id="DMS-cL-nZT"/>
<outlet property="deactivateAccountInfosLabel" destination="uaL-Wi-UcQ" id="zDZ-bW-s0Z"/>
<outlet property="forgetMessageButton" destination="UBr-xR-a5z" id="NfP-c4-AxP"/>
<outlet property="forgetMessagesInfoLabel" destination="2AU-Ro-4rr" id="tTS-bh-g58"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dTx-N1-Ytz" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-239.19999999999999" y="103.89805097451276"/>
</scene>
</scenes>
<resources>
<image name="selection_tick.png" width="22" height="22"/>
<image name="selection_untick.png" width="22" height="22"/>
</resources>
</document>

View file

@ -115,6 +115,7 @@
#import "IntegrationManagerViewController.h"
#import "WidgetPickerViewController.h"
#import "StickerPickerViewController.h"
@interface RoomViewController ()
{
@ -2854,6 +2855,80 @@
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
}
#pragma mark - RoomInputToolbarViewDelegate
- (void)roomInputToolbarViewPresentStickerPicker:(MXKRoomInputToolbarView*)toolbarView
{
// Search for the sticker picker widget in the user account
Widget *widget = [[WidgetManager sharedManager] userWidgets:self.roomDataSource.mxSession ofTypes:@[kWidgetTypeStickerPicker]].firstObject;
if (widget)
{
// Display the widget
[widget widgetUrl:^(NSString * _Nonnull widgetUrl) {
StickerPickerViewController *stickerPickerVC = [[StickerPickerViewController alloc] initWithUrl:widgetUrl forWidget:widget];
stickerPickerVC.roomDataSource = self.roomDataSource;
[self.navigationController pushViewController:stickerPickerVC animated:YES];
} failure:^(NSError * _Nonnull error) {
NSLog(@"[RoomVC] Cannot display widget %@", widget);
[[AppDelegate theDelegate] showErrorAsAlert:error];
}];
}
else
{
// The Sticker picker widget is not installed yet. Propose the user to install it
__weak typeof(self) weakSelf = self;
[currentAlert dismissViewControllerAnimated:NO completion:nil];
NSString *alertMessage = [NSString stringWithFormat:@"%@\n%@",
NSLocalizedStringFromTable(@"widget_sticker_picker_no_stickerpacks_alert", @"Vector", nil),
NSLocalizedStringFromTable(@"widget_sticker_picker_no_stickerpacks_alert_add_now", @"Vector", nil)
];
currentAlert = [UIAlertController alertControllerWithTitle:nil message:alertMessage preferredStyle:UIAlertControllerStyleAlert];
[currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"no"]
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action)
{
if (weakSelf)
{
typeof(self) self = weakSelf;
self->currentAlert = nil;
}
}]];
[currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"yes"]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
if (weakSelf)
{
typeof(self) self = weakSelf;
self->currentAlert = nil;
// Show the sticker picker settings screen
IntegrationManagerViewController *modularVC = [[IntegrationManagerViewController alloc]
initForMXSession:self.roomDataSource.mxSession
inRoom:self.roomDataSource.roomId
screen:[IntegrationManagerViewController screenForWidget:kWidgetTypeStickerPicker]
widgetId:nil];
[self presentViewController:modularVC animated:NO completion:nil];
}
}]];
[currentAlert mxk_setAccessibilityIdentifier:@"RoomVCStickerPickerAlert"];
[self presentViewController:currentAlert animated:YES completion:nil];
}
}
#pragma mark - MXKRoomInputToolbarViewDelegate
- (void)roomInputToolbarView:(MXKRoomInputToolbarView*)toolbarView isTyping:(BOOL)typing
@ -3064,7 +3139,7 @@
// Matrix Apps button
else if (self.navigationItem.rightBarButtonItems.count == 2 && sender == self.navigationItem.rightBarButtonItems[1])
{
if ([self widgetsCount:YES])
if ([self widgetsCount:NO])
{
WidgetPickerViewController *widgetPicker = [[WidgetPickerViewController alloc] initForMXSession:self.roomDataSource.mxSession
inRoom:self.roomDataSource.roomId];
@ -3650,7 +3725,7 @@
inRoom:self.roomDataSource.room].count;
if (includeUserWidgets)
{
widgetsCount = [[WidgetManager sharedManager] userWidgets:self.roomDataSource.room.mxSession].count;
widgetsCount += [[WidgetManager sharedManager] userWidgets:self.roomDataSource.room.mxSession].count;
}
return widgetsCount;

View file

@ -34,6 +34,7 @@
#import "CountryPickerViewController.h"
#import "LanguagePickerViewController.h"
#import "DeactivateAccountViewController.h"
#import "NBPhoneNumberUtil.h"
#import "RageShakeManager.h"
@ -62,6 +63,7 @@ enum
SETTINGS_SECTION_CRYPTOGRAPHY_INDEX,
SETTINGS_SECTION_FLAIR_INDEX,
SETTINGS_SECTION_DEVICES_INDEX,
SETTINGS_SECTION_DEACTIVATE_ACCOUNT_INDEX,
SETTINGS_SECTION_COUNT
};
@ -130,7 +132,7 @@ enum {
typedef void (^blockSettingsViewController_onReadyToDestroy)();
@interface SettingsViewController ()
@interface SettingsViewController () <DeactivateAccountViewControllerDelegate>
{
// Current alert (if any).
UIAlertController *currentAlert;
@ -234,6 +236,8 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
*/
@property (nonatomic) BOOL newPhoneEditingEnabled;
@property (weak, nonatomic) DeactivateAccountViewController *deactivateAccountViewController;
@end
@implementation SettingsViewController
@ -258,6 +262,9 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
self.navigationItem.title = NSLocalizedStringFromTable(@"settings_title", @"Vector", nil);
// Remove back bar button title when pushing a view controller
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
[self.tableView registerClass:MXKTableViewCellWithLabelAndTextField.class forCellReuseIdentifier:[MXKTableViewCellWithLabelAndTextField defaultReuseIdentifier]];
[self.tableView registerClass:MXKTableViewCellWithLabelAndSwitch.class forCellReuseIdentifier:[MXKTableViewCellWithLabelAndSwitch defaultReuseIdentifier]];
[self.tableView registerClass:MXKTableViewCellWithLabelAndMXKImageView.class forCellReuseIdentifier:[MXKTableViewCellWithLabelAndMXKImageView defaultReuseIdentifier]];
@ -310,6 +317,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(onSave:)];
self.navigationItem.rightBarButtonItem.accessibilityIdentifier=@"SettingsVCNavBarSaveButton";
// Observe user interface theme change.
kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
@ -1268,6 +1276,10 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
count = CRYPTOGRAPHY_COUNT;
}
}
else if (section == SETTINGS_SECTION_DEACTIVATE_ACCOUNT_INDEX)
{
count = 1;
}
return count;
}
@ -2151,6 +2163,32 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
cell = exportKeysBtnCell;
}
}
else if (section == SETTINGS_SECTION_DEACTIVATE_ACCOUNT_INDEX)
{
MXKTableViewCellWithButton *deactivateAccountBtnCell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCellWithButton defaultReuseIdentifier]];
if (!deactivateAccountBtnCell)
{
deactivateAccountBtnCell = [[MXKTableViewCellWithButton alloc] init];
}
else
{
// Fix https://github.com/vector-im/riot-ios/issues/1354
deactivateAccountBtnCell.mxkButton.titleLabel.text = nil;
}
NSString *btnTitle = NSLocalizedStringFromTable(@"settings_deactivate_my_account", @"Vector", nil);
[deactivateAccountBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal];
[deactivateAccountBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted];
[deactivateAccountBtnCell.mxkButton setTintColor:kRiotColorRed];
deactivateAccountBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17];
[deactivateAccountBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside];
[deactivateAccountBtnCell.mxkButton addTarget:self action:@selector(deactivateAccountAction) forControlEvents:UIControlEventTouchUpInside];
deactivateAccountBtnCell.mxkButton.accessibilityIdentifier = nil;
cell = deactivateAccountBtnCell;
}
return cell;
}
@ -2228,6 +2266,18 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
return NSLocalizedStringFromTable(@"settings_cryptography", @"Vector", nil);
}
}
else if (section == SETTINGS_SECTION_CRYPTOGRAPHY_INDEX)
{
// Check whether this section is visible
if (self.mainSession.crypto)
{
return NSLocalizedStringFromTable(@"settings_cryptography", @"Vector", nil);
}
}
else if (section == SETTINGS_SECTION_DEACTIVATE_ACCOUNT_INDEX)
{
return NSLocalizedStringFromTable(@"settings_deactivate_my_account", @"Vector", nil);
}
return nil;
}
@ -3673,6 +3723,20 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
[self presentViewController:themePicker animated:YES completion:nil];
}
- (void)deactivateAccountAction
{
DeactivateAccountViewController *deactivateAccountViewController = [DeactivateAccountViewController instantiateWithMatrixSession:self.mainSession];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:deactivateAccountViewController];
navigationController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:navigationController animated:YES completion:nil];
deactivateAccountViewController.delegate = self;
self.deactivateAccountViewController = deactivateAccountViewController;
}
#pragma mark - MediaPickerViewController Delegate
- (void)dismissMediaPicker
@ -4033,4 +4097,21 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
[self refreshSettings];
}
#pragma mark - DeactivateAccountViewControllerDelegate
- (void)deactivateAccountViewControllerDidDeactivateWithSuccess:(DeactivateAccountViewController *)deactivateAccountViewController
{
NSLog(@"[SettingsViewController] Deactivate account with success");
[[AppDelegate theDelegate] logoutSendingRequestServer:NO completion:^(BOOL isLoggedOut) {
NSLog(@"[SettingsViewController] Complete clear user data after account deactivation");
}];
}
- (void)deactivateAccountViewControllerDidCancel:(DeactivateAccountViewController *)deactivateAccountViewController
{
[deactivateAccountViewController dismissViewControllerAnimated:YES completion:nil];
}
@end

View file

@ -37,4 +37,12 @@ FOUNDATION_EXPORT NSString *const kIntegrationManagerAddIntegrationScreen;
*/
- (instancetype)initForMXSession:(MXSession*)mxSession inRoom:(NSString*)roomId screen:(NSString*)screen widgetId:(NSString*)widgetId;
/**
Get the integration manager settings screen for a given widget type.
@param widgetType the widget type.
@return the screen id for that widget type.
*/
+ (NSString*)screenForWidget:(NSString*)widgetType;
@end

View file

@ -50,6 +50,11 @@ NSString *const kIntegrationManagerAddIntegrationScreen = @"add_integ";
return self;
}
+ (NSString*)screenForWidget:(NSString*)widgetType
{
return [NSString stringWithFormat:@"type_%@", widgetType];
}
- (void)destroy
{
[super destroy];
@ -147,8 +152,25 @@ NSString *const kIntegrationManagerAddIntegrationScreen = @"add_integ";
if (!roomIdInEvent)
{
[self sendLocalisedError:@"widget_integration_missing_room_id" toRequest:requestId];
return;
// These APIs don't require roomId
// Get and set user widgets (not associated with a specific room)
// If roomId is specified, it must be validated, so room-based widgets agreed
// handled further down.
if ([@"set_widget" isEqualToString:action])
{
[self setWidget:requestId data:requestData];
return;
}
else if ([@"get_widgets" isEqualToString:action])
{
[self getWidgets:requestId data:requestData];
return;
}
else
{
[self sendLocalisedError:@"widget_integration_missing_room_id" toRequest:requestId];
return;
}
}
if (![roomIdInEvent isEqualToString:roomId])
@ -157,6 +179,17 @@ NSString *const kIntegrationManagerAddIntegrationScreen = @"add_integ";
return;
}
// Get and set room-based widgets
if ([@"set_widget" isEqualToString:action])
{
[self setWidget:requestId data:requestData];
return;
}
else if ([@"get_widgets" isEqualToString:action])
{
[self getWidgets:requestId data:requestData];
return;
}
// These APIs don't require userId
if ([@"join_rules_state" isEqualToString:action])
@ -174,14 +207,9 @@ NSString *const kIntegrationManagerAddIntegrationScreen = @"add_integ";
[self getMembershipCount:requestId data:requestData];
return;
}
else if ([@"set_widget" isEqualToString:action])
else if ([@"get_room_enc_state" isEqualToString:action])
{
[self setWidget:requestId data:requestData];
return;
}
else if ([@"get_widgets" isEqualToString:action])
{
[self getWidgets:requestId data:requestData];
[self getRoomEncState:requestId data:requestData];
return;
}
else if ([@"can_send_event" isEqualToString:action])
@ -281,75 +309,120 @@ NSString *const kIntegrationManagerAddIntegrationScreen = @"add_integ";
- (void)setWidget:(NSString*)requestId data:(NSDictionary*)requestData
{
NSLog(@"[IntegrationManagerVC] Received request to set widget in room %@.", roomId);
NSLog(@"[IntegrationManagerVC] Received request to set widget");
MXRoom *room = [self roomCheckForRequest:requestId data:requestData];
NSString *widget_id, *widgetType, *widgetUrl;
NSString *widgetName; // optional
NSDictionary *widgetData ; // optional
BOOL userWidget = NO;
if (room)
MXJSONModelSetString(widget_id, requestData[@"widget_id"]);
MXJSONModelSetString(widgetType, requestData[@"type"]);
MXJSONModelSetString(widgetUrl, requestData[@"url"]);
MXJSONModelSetString(widgetName, requestData[@"name"]);
MXJSONModelSetDictionary(widgetData, requestData[@"data"]);
MXJSONModelSetBoolean(userWidget, requestData[@"userWidget"]);
if (!widget_id)
{
NSString *widget_id, *widgetType, *widgetUrl;
NSString *widgetName; // optional
NSDictionary *widgetData ; // optional
[self sendLocalisedError:@"widget_integration_unable_to_create" toRequest:requestId]; // new Error("Missing required widget fields."));
return;
}
MXJSONModelSetString(widget_id, requestData[@"widget_id"]);
MXJSONModelSetString(widgetType, requestData[@"type"]);
MXJSONModelSetString(widgetUrl, requestData[@"url"]);
MXJSONModelSetString(widgetName, requestData[@"name"]);
MXJSONModelSetDictionary(widgetData, requestData[@"data"]);
if (!widgetType)
{
[self sendLocalisedError:@"widget_integration_unable_to_create" toRequest:requestId];
return;
}
if (!widget_id)
NSMutableDictionary *widgetEventContent = [NSMutableDictionary dictionary];
if (widgetUrl)
{
widgetEventContent[@"type"] = widgetType;
widgetEventContent[@"url"] = widgetUrl;
if (widgetName)
{
[self sendLocalisedError:@"widget_integration_unable_to_create" toRequest:requestId]; // new Error("Missing required widget fields."));
return;
widgetEventContent[@"name"] = widgetName;
}
if (widgetData)
{
widgetEventContent[@"data"] = widgetData;
}
}
// else this is a deletion
NSMutableDictionary *widgetEventContent = [NSMutableDictionary dictionary];
__weak __typeof__(self) weakSelf = self;
if (userWidget)
{
// Update the user account data
NSMutableDictionary *userWidgets = [NSMutableDictionary dictionaryWithDictionary:[mxSession.accountData accountDataForEventType:kMXAccountDataTypeUserWidgets]];
// Delete existing widget with ID
[userWidgets removeObjectForKey:widget_id];
// Add new widget / update
if (widgetUrl)
{
if (!widgetType)
{
[self sendLocalisedError:@"widget_integration_unable_to_create" toRequest:requestId];
return;
}
widgetEventContent[@"type"] = widgetType;
widgetEventContent[@"url"] = widgetUrl;
if (widgetName)
{
widgetEventContent[@"name"] = widgetName;
}
if (widgetData)
{
widgetEventContent[@"data"] = widgetData;
}
userWidgets[widget_id] = @{
@"content": widgetEventContent,
@"sender": mxSession.myUser.userId,
@"state_key": widget_id,
@"type": kWidgetMatrixEventTypeString,
@"id": widget_id,
};
}
__weak __typeof__(self) weakSelf = self;
[mxSession setAccountData:userWidgets forType:kMXAccountDataTypeUserWidgets success:^{
// TODO: Move to kWidgetMatrixEventTypeString ("m.widget") type but when?
[room sendStateEventOfType:kWidgetModularEventTypeString
content:widgetEventContent
stateKey:widget_id
success:^(NSString *eventId) {
typeof(self) self = weakSelf;
if (self)
{
[self sendNSObjectResponse:@{
@"success": @(YES)
}
toRequest:requestId];
}
} failure:^(NSError *error) {
typeof(self) self = weakSelf;
if (self)
{
[self sendNSObjectResponse:@{
@"success": @(YES)
}
toRequest:requestId];
typeof(self) self = weakSelf;
if (self)
{
[self sendLocalisedError:@"widget_integration_unable_to_create" toRequest:requestId];
}
}];
}
else
{
// Room widget
MXRoom *room = [self roomCheckForRequest:requestId data:requestData];
if (room)
{
// TODO: Move to kWidgetMatrixEventTypeString ("m.widget") type but when?
[room sendStateEventOfType:kWidgetModularEventTypeString
content:widgetEventContent
stateKey:widget_id
success:^(NSString *eventId) {
typeof(self) self = weakSelf;
if (self)
{
[self sendNSObjectResponse:@{
@"success": @(YES)
}
toRequest:requestId];
}
}
}
failure:^(NSError *error) {
failure:^(NSError *error) {
typeof(self) self = weakSelf;
if (self)
{
[self sendLocalisedError:@"widget_integration_failed_to_send_request" toRequest:requestId];
}
}];
typeof(self) self = weakSelf;
if (self)
{
[self sendLocalisedError:@"widget_integration_failed_to_send_request" toRequest:requestId];
}
}];
}
}
}
@ -376,6 +449,15 @@ NSString *const kIntegrationManagerAddIntegrationScreen = @"add_integ";
[self sendNSObjectResponse:widgetStateEvents toRequest:requestId];
}
- (void)getRoomEncState:(NSString*)requestId data:(NSDictionary*)requestData
{
MXRoom *room = [self roomCheckForRequest:requestId data:requestData];
if (room)
{
[self sendBoolResponse:room.state.isEncrypted toRequest:requestId];
}
}
- (void)canSendEvent:(NSString*)requestId data:(NSDictionary*)requestData
{
NSString *eventType;

View file

@ -0,0 +1,21 @@
/*
Copyright 2018 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 "WidgetViewController.h"
@interface StickerPickerViewController : WidgetViewController
@end

View file

@ -0,0 +1,60 @@
/*
Copyright 2018 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 "StickerPickerViewController.h"
#import "IntegrationManagerViewController.h"
@interface StickerPickerViewController ()
@end
@implementation StickerPickerViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.title = NSLocalizedStringFromTable(@"room_action_send_sticker", @"Vector", nil);
// Hide back button title
self.parentViewController.navigationItem.backBarButtonItem =[[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
UIBarButtonItem *editButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(onEditButtonPressed)];
[self.navigationItem setRightBarButtonItem: editButton animated:YES];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// Make sure the content is up-to-date when we come back from the sticker picker settings screen
[webView reload];
}
- (void)onEditButtonPressed
{
// Show the sticker picker settings screen
IntegrationManagerViewController *modularVC = [[IntegrationManagerViewController alloc]
initForMXSession:self.roomDataSource.mxSession
inRoom:self.roomDataSource.roomId
screen:[IntegrationManagerViewController screenForWidget:kWidgetTypeStickerPicker]
widgetId:self.widget.widgetId];
[self presentViewController:modularVC animated:NO completion:nil];
}
@end

View file

@ -53,15 +53,9 @@
MXRoom *room = [mxSession roomWithRoomId:roomId];
NSArray<Widget*> *roomWidgets = [[WidgetManager sharedManager] widgetsNotOfTypes:@[kWidgetTypeJitsi]
NSArray<Widget*> *widgets = [[WidgetManager sharedManager] widgetsNotOfTypes:@[kWidgetTypeJitsi]
inRoom:room];
NSArray<Widget*> *userWidgets = [[WidgetManager sharedManager] userWidgets:room.mxSession];
NSMutableArray<Widget*> *widgets = [NSMutableArray array];
[widgets addObjectsFromArray:roomWidgets];
[widgets addObjectsFromArray:userWidgets];
// List widgets
for (Widget *widget in widgets)
{

View file

@ -27,6 +27,11 @@
*/
@interface WidgetViewController : WebViewViewController
/**
The displayed widget.
*/
@property (nonatomic, readonly) Widget *widget;
/**
The room data source.
Required if the widget needs to post messages.

View file

@ -1,5 +1,6 @@
/*
Copyright 2017 Vector Creations Ltd
Copyright 2018 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.
@ -17,17 +18,16 @@
#import "WidgetViewController.h"
#import "AppDelegate.h"
#import "IntegrationManagerViewController.h"
NSString *const kJavascriptSendResponseToPostMessageAPI = @"riotIOS.sendResponse('%@', %@);";
@interface WidgetViewController ()
{
Widget *widget;
}
@end
@implementation WidgetViewController
@synthesize widget;
- (instancetype)initWithUrl:(NSString*)widgetUrl forWidget:(Widget*)theWidget
{
@ -43,7 +43,6 @@ NSString *const kJavascriptSendResponseToPostMessageAPI = @"riotIOS.sendResponse
{
[super viewDidLoad];
webView.scalesPageToFit = NO;
webView.scrollView.bounces = NO;
// Disable opacity so that the webview background uses the current interface theme
@ -92,16 +91,16 @@ NSString *const kJavascriptSendResponseToPostMessageAPI = @"riotIOS.sendResponse
[self presentViewController:alert animated:YES completion:nil];
}
#pragma mark - UIWebViewDelegate
#pragma mark - WKNavigationDelegate
-(void)webViewDidFinishLoad:(UIWebView *)theWebView
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
[self enableDebug];
// Setup js code
NSString *path = [[NSBundle mainBundle] pathForResource:@"postMessageAPI" ofType:@"js"];
NSString *js = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
[webView stringByEvaluatingJavaScriptFromString:js];
[webView evaluateJavaScript:js completionHandler:nil];
[self stopActivityIndicator];
@ -120,14 +119,16 @@ NSString *const kJavascriptSendResponseToPostMessageAPI = @"riotIOS.sendResponse
}
}
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
NSString *urlString = [[request URL] absoluteString];
NSString *urlString = navigationAction.request.URL.absoluteString;
// TODO: We should use the WebKit PostMessage API and the
// `didReceiveScriptMessage` delegate to manage the JS<->Native bridge
if ([urlString hasPrefix:@"js:"])
{
// Listen only to scheme of the JS-UIWebView bridge
NSString *jsonString = [[[urlString componentsSeparatedByString:@"js:"] lastObject] stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
// Listen only to the scheme of the JS<->Native bridge
NSString *jsonString = [[[urlString componentsSeparatedByString:@"js:"] lastObject] stringByRemovingPercentEncoding];
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
@ -152,20 +153,22 @@ NSString *const kJavascriptSendResponseToPostMessageAPI = @"riotIOS.sendResponse
}
}
return NO;
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
if (navigationType == UIWebViewNavigationTypeLinkClicked )
if (navigationAction.navigationType == WKNavigationTypeLinkActivated)
{
// Open links outside the app
[[UIApplication sharedApplication] openURL:[request URL]];
return NO;
[[UIApplication sharedApplication] openURL:navigationAction.request.URL];
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
return YES;
decisionHandler(WKNavigationActionPolicyAllow);
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error
{
// Filter out the users's scalar token
NSString *errorDescription = error.description;
@ -216,6 +219,37 @@ NSString *const kJavascriptSendResponseToPostMessageAPI = @"riotIOS.sendResponse
// Consider we are done with the sticker picker widget
[self withdrawViewControllerAnimated:YES completion:nil];
}
else if ([@"integration_manager_open" isEqualToString:action])
{
NSDictionary *widgetData;
NSString *integType, *integId;
MXJSONModelSetDictionary(widgetData, requestData[@"widgetData"]);
if (widgetData)
{
MXJSONModelSetString(integType, widgetData[@"integType"]);
MXJSONModelSetString(integId, widgetData[@"integId"]);
}
if (integType && integId)
{
// Open the integration manager requested page
IntegrationManagerViewController *modularVC = [[IntegrationManagerViewController alloc]
initForMXSession:self.roomDataSource.mxSession
inRoom:self.roomDataSource.roomId
screen:[IntegrationManagerViewController screenForWidget:integType]
widgetId:integId];
[self presentViewController:modularVC animated:NO completion:nil];
}
else
{
NSLog(@"[WidgetVC] onPostMessageRequest: ERROR: Invalid content for integration_manager_open: %@", requestData);
}
}
else
{
NSLog(@"[WidgetVC] onPostMessageRequest: ERROR: Unsupported action: %@: %@", action, requestData);
}
}
- (void)sendBoolResponse:(BOOL)response toRequest:(NSString*)requestId
@ -225,7 +259,7 @@ NSString *const kJavascriptSendResponseToPostMessageAPI = @"riotIOS.sendResponse
requestId,
response ? @"true" : @"false"];
[webView stringByEvaluatingJavaScriptFromString:js];
[webView evaluateJavaScript:js completionHandler:nil];
}
- (void)sendIntegerResponse:(NSUInteger)response toRequest:(NSString*)requestId
@ -234,7 +268,7 @@ NSString *const kJavascriptSendResponseToPostMessageAPI = @"riotIOS.sendResponse
requestId,
@(response)];
[webView stringByEvaluatingJavaScriptFromString:js];
[webView evaluateJavaScript:js completionHandler:nil];
}
- (void)sendNSObjectResponse:(NSObject*)response toRequest:(NSString*)requestId
@ -260,7 +294,7 @@ NSString *const kJavascriptSendResponseToPostMessageAPI = @"riotIOS.sendResponse
requestId,
jsString];
[webView stringByEvaluatingJavaScriptFromString:js];
[webView evaluateJavaScript:js completionHandler:nil];
}
- (void)sendError:(NSString*)message toRequest:(NSString*)requestId

View file

@ -18,12 +18,28 @@
#import "MediaPickerViewController.h"
@protocol RoomInputToolbarViewDelegate <MXKRoomInputToolbarViewDelegate>
/**
Tells the delegate that the user wants to display the sticker picker.
@param toolbarView the room input toolbar view.
*/
- (void)roomInputToolbarViewPresentStickerPicker:(MXKRoomInputToolbarView*)toolbarView;
@end
/**
`RoomInputToolbarView` instance is a view used to handle all kinds of available inputs
for a room (message composer, attachments selection...).
*/
@interface RoomInputToolbarView : MXKRoomInputToolbarViewWithHPGrowingText <MediaPickerViewControllerDelegate>
/**
The delegate notified when inputs are ready.
*/
@property (nonatomic) id<RoomInputToolbarViewDelegate> delegate;
@property (weak, nonatomic) IBOutlet UIView *mainToolbarView;
@property (weak, nonatomic) IBOutlet UIView *separatorView;

View file

@ -29,17 +29,21 @@
#import <MobileCoreServices/MobileCoreServices.h>
#import "WidgetManager.h"
#import "IntegrationManagerViewController.h"
@interface RoomInputToolbarView()
{
MediaPickerViewController *mediaPicker;
// The call type selection (voice or video)
UIAlertController *callActionSheet;
// The intermediate action sheet
UIAlertController *actionSheet;
}
@end
@implementation RoomInputToolbarView
@dynamic delegate;
+ (UINib *)nib
{
@ -228,24 +232,53 @@
// Check whether media attachment is supported
if ([self.delegate respondsToSelector:@selector(roomInputToolbarView:presentViewController:)])
{
// MediaPickerViewController is based on the Photos framework. So it is available only for iOS 8 and later.
Class PHAsset_class = NSClassFromString(@"PHAsset");
if (PHAsset_class)
{
mediaPicker = [MediaPickerViewController mediaPickerViewController];
mediaPicker.mediaTypes = @[(NSString *)kUTTypeImage, (NSString *)kUTTypeMovie];
mediaPicker.delegate = self;
UINavigationController *navigationController = [UINavigationController new];
[navigationController pushViewController:mediaPicker animated:NO];
[self.delegate roomInputToolbarView:self presentViewController:navigationController];
}
else
{
// We use UIImagePickerController by default for iOS < 8
self.leftInputToolbarButton = self.attachMediaButton;
[super onTouchUpInside:self.leftInputToolbarButton];
}
// Ask the user the kind of the call: voice or video?
actionSheet = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
__weak typeof(self) weakSelf = self;
[actionSheet addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_action_send_photo_or_video", @"Vector", nil)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
typeof(self) self = weakSelf;
self->actionSheet = nil;
[self showMediaPicker];
}
}]];
[actionSheet addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_action_send_sticker", @"Vector", nil)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
typeof(self) self = weakSelf;
self->actionSheet = nil;
[self.delegate roomInputToolbarViewPresentStickerPicker:self];
}
}]];
[actionSheet addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"]
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action) {
if (weakSelf)
{
typeof(self) self = weakSelf;
self->actionSheet = nil;
}
}]];
[actionSheet popoverPresentationController].sourceView = self.voiceCallButton;
[actionSheet popoverPresentationController].sourceRect = self.voiceCallButton.bounds;
[self.window.rootViewController presentViewController:actionSheet animated:YES completion:nil];
}
else
{
@ -257,52 +290,52 @@
if ([self.delegate respondsToSelector:@selector(roomInputToolbarView:placeCallWithVideo:)])
{
// Ask the user the kind of the call: voice or video?
callActionSheet = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
actionSheet = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
__weak typeof(self) weakSelf = self;
[callActionSheet addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"voice", @"Vector", nil)
[actionSheet addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"voice", @"Vector", nil)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
typeof(self) self = weakSelf;
self->callActionSheet = nil;
self->actionSheet = nil;
[self.delegate roomInputToolbarView:self placeCallWithVideo:NO];
}
}]];
[callActionSheet addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"video", @"Vector", nil)
[actionSheet addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"video", @"Vector", nil)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
typeof(self) self = weakSelf;
self->callActionSheet = nil;
self->actionSheet = nil;
[self.delegate roomInputToolbarView:self placeCallWithVideo:YES];
}
}]];
[callActionSheet addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"]
[actionSheet addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"]
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action) {
if (weakSelf)
{
typeof(self) self = weakSelf;
self->callActionSheet = nil;
self->actionSheet = nil;
}
}]];
[callActionSheet popoverPresentationController].sourceView = self.voiceCallButton;
[callActionSheet popoverPresentationController].sourceRect = self.voiceCallButton.bounds;
[self.window.rootViewController presentViewController:callActionSheet animated:YES completion:nil];
[actionSheet popoverPresentationController].sourceView = self.voiceCallButton;
[actionSheet popoverPresentationController].sourceRect = self.voiceCallButton.bounds;
[self.window.rootViewController presentViewController:actionSheet animated:YES completion:nil];
}
}
else if (button == self.hangupCallButton)
@ -316,15 +349,36 @@
[super onTouchUpInside:button];
}
- (void)showMediaPicker
{
// MediaPickerViewController is based on the Photos framework. So it is available only for iOS 8 and later.
Class PHAsset_class = NSClassFromString(@"PHAsset");
if (PHAsset_class)
{
mediaPicker = [MediaPickerViewController mediaPickerViewController];
mediaPicker.mediaTypes = @[(NSString *)kUTTypeImage, (NSString *)kUTTypeMovie];
mediaPicker.delegate = self;
UINavigationController *navigationController = [UINavigationController new];
[navigationController pushViewController:mediaPicker animated:NO];
[self.delegate roomInputToolbarView:self presentViewController:navigationController];
}
else
{
// We use UIImagePickerController by default for iOS < 8
self.leftInputToolbarButton = self.attachMediaButton;
[super onTouchUpInside:self.leftInputToolbarButton];
}
}
- (void)destroy
{
[self dismissMediaPicker];
if (callActionSheet)
if (actionSheet)
{
[callActionSheet dismissViewControllerAnimated:NO completion:nil];
callActionSheet = nil;
[actionSheet dismissViewControllerAnimated:NO completion:nil];
actionSheet = nil;
}
[super destroy];

View file

@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>0.6.16</string>
<string>0.6.17</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSExtension</key>

View file

@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>0.6.16</string>
<string>0.6.17</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSExtension</key>