mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-05-12 18:59:59 +02:00
Finish v0.6.18
This commit is contained in:
+18
-1
@@ -1,3 +1,20 @@
|
||||
Changes in 0.6.18 (2018-07-03)
|
||||
===============================================
|
||||
|
||||
Improvements:
|
||||
* Upgrade MatrixKit version (v0.7.15).
|
||||
* RoomVC: Add a re-request keys button on message unable to decrypt (#1879).
|
||||
* Analytics: Move code from AppDelegate to a dedicated class: Analytics.
|
||||
* Analytics: Track Matrix SDK stats (time to startup the app).
|
||||
* Crypto: Add telemetry for events unable to decrypt (UTDs).
|
||||
* Added the i18n localisation strings to the accessibility labels (#1842), thanks to @einMarco (PR#1906).
|
||||
* Added titles to sound files ID3 tags.
|
||||
|
||||
Bug fix:
|
||||
* RoomVC: Read receipts processing dramatically slows down UI (#1899).
|
||||
* Lag in typing (#1820).
|
||||
* E2E messages not decrypted in notifs after logging back in (#1914).
|
||||
|
||||
Changes in 0.6.17 (2018-06-01)
|
||||
===============================================
|
||||
|
||||
@@ -1116,4 +1133,4 @@ Changes in Vector iOS in 0.1.0 (2016-01-29)
|
||||
Changes in Vector iOS in 0.0.1 (2015-11-16)
|
||||
===============================================
|
||||
|
||||
* Creation : The first implementation of Vector application based on Matrix iOS Kit v0.2.7.
|
||||
* Creation : The first implementation of Vector application based on Matrix iOS Kit v0.2.7.
|
||||
|
||||
@@ -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.14'
|
||||
$matrixKitVersion = '0.7.15'
|
||||
|
||||
# The develop branch version
|
||||
#$matrixKitVersion = 'develop'
|
||||
@@ -58,7 +58,7 @@ end
|
||||
|
||||
abstract_target 'RiotPods' do
|
||||
|
||||
pod 'GBDeviceInfo', '~> 5.1.0'
|
||||
pod 'GBDeviceInfo', '~> 5.2.0'
|
||||
|
||||
# Piwik for analytics
|
||||
# While https://github.com/matomo-org/matomo-sdk-ios/pull/223 is not released, use the PR branch
|
||||
|
||||
+26
-26
@@ -37,40 +37,40 @@ PODS:
|
||||
- DTFoundation/Core
|
||||
- DTFoundation/UIKit (1.7.13):
|
||||
- DTFoundation/Core
|
||||
- GBDeviceInfo (5.1.0):
|
||||
- GBDeviceInfo/Core (= 5.1.0)
|
||||
- GBDeviceInfo/Core (5.1.0)
|
||||
- GBDeviceInfo (5.2.0):
|
||||
- GBDeviceInfo/Core (= 5.2.0)
|
||||
- GBDeviceInfo/Core (5.2.0)
|
||||
- GZIP (1.2.1)
|
||||
- HPGrowingTextView (1.1)
|
||||
- libPhoneNumber-iOS (0.9.13)
|
||||
- MatrixKit (0.7.14):
|
||||
- MatrixKit (0.7.15):
|
||||
- cmark (~> 0.24.1)
|
||||
- DTCoreText (~> 1.6.21)
|
||||
- HPGrowingTextView (~> 1.1)
|
||||
- libPhoneNumber-iOS (~> 0.9.13)
|
||||
- MatrixKit/Core (= 0.7.14)
|
||||
- MatrixSDK (= 0.10.11)
|
||||
- MatrixKit/AppExtension (0.7.14):
|
||||
- MatrixKit/Core (= 0.7.15)
|
||||
- MatrixSDK (= 0.10.12)
|
||||
- MatrixKit/AppExtension (0.7.15):
|
||||
- cmark (~> 0.24.1)
|
||||
- DTCoreText (~> 1.6.21)
|
||||
- DTCoreText/Extension
|
||||
- HPGrowingTextView (~> 1.1)
|
||||
- libPhoneNumber-iOS (~> 0.9.13)
|
||||
- MatrixSDK (= 0.10.11)
|
||||
- MatrixKit/Core (0.7.14):
|
||||
- MatrixSDK (= 0.10.12)
|
||||
- MatrixKit/Core (0.7.15):
|
||||
- cmark (~> 0.24.1)
|
||||
- DTCoreText (~> 1.6.21)
|
||||
- HPGrowingTextView (~> 1.1)
|
||||
- libPhoneNumber-iOS (~> 0.9.13)
|
||||
- MatrixSDK (= 0.10.11)
|
||||
- MatrixSDK (0.10.11):
|
||||
- MatrixSDK/Core (= 0.10.11)
|
||||
- MatrixSDK/Core (0.10.11):
|
||||
- MatrixSDK (= 0.10.12)
|
||||
- MatrixSDK (0.10.12):
|
||||
- MatrixSDK/Core (= 0.10.12)
|
||||
- MatrixSDK/Core (0.10.12):
|
||||
- AFNetworking (~> 3.2.0)
|
||||
- GZIP (~> 1.2.1)
|
||||
- OLMKit (~> 2.2.2)
|
||||
- Realm (~> 3.3.2)
|
||||
- MatrixSDK/JingleCallStack (0.10.11):
|
||||
- Realm (~> 3.6.0)
|
||||
- MatrixSDK/JingleCallStack (0.10.12):
|
||||
- MatrixSDK/Core
|
||||
- WebRTC (= 63.11.20455)
|
||||
- OLMKit (2.2.2):
|
||||
@@ -81,17 +81,17 @@ PODS:
|
||||
- PiwikTracker (4.4.2):
|
||||
- PiwikTracker/Core (= 4.4.2)
|
||||
- PiwikTracker/Core (4.4.2)
|
||||
- Realm (3.3.2):
|
||||
- Realm/Headers (= 3.3.2)
|
||||
- Realm/Headers (3.3.2)
|
||||
- Realm (3.6.0):
|
||||
- Realm/Headers (= 3.6.0)
|
||||
- Realm/Headers (3.6.0)
|
||||
- WebRTC (63.11.20455)
|
||||
|
||||
DEPENDENCIES:
|
||||
- cmark
|
||||
- DTCoreText
|
||||
- GBDeviceInfo (~> 5.1.0)
|
||||
- MatrixKit (= 0.7.14)
|
||||
- MatrixKit/AppExtension (= 0.7.14)
|
||||
- GBDeviceInfo (~> 5.2.0)
|
||||
- MatrixKit (= 0.7.15)
|
||||
- MatrixKit/AppExtension (= 0.7.15)
|
||||
- MatrixSDK/JingleCallStack
|
||||
- OLMKit
|
||||
- PiwikTracker (from `https://github.com/manuroe/matomo-sdk-ios.git`, branch `feature/CustomVariables`)
|
||||
@@ -127,17 +127,17 @@ SPEC CHECKSUMS:
|
||||
cmark: ec0275215b504780287b6fca360224e384368af8
|
||||
DTCoreText: e5d688cffc9f6a61eddd1a4f94e2046851230de3
|
||||
DTFoundation: f03be9fd786f11e505bb8fc44e2a3732bf0917df
|
||||
GBDeviceInfo: 8e43440ae1264d9a79beea81800363cf192ce322
|
||||
GBDeviceInfo: 2c65ceb9404f9079264d4c238f5b81916fdfc5e2
|
||||
GZIP: 7ee835f989fb3c6ea79005fc90b8fa6af710a70d
|
||||
HPGrowingTextView: 88a716d97fb853bcb08a4a08e4727da17efc9b19
|
||||
libPhoneNumber-iOS: e444379ac18bbfbdefad571da735b2cd7e096caa
|
||||
MatrixKit: ca192403abc03229f5cc5c193bd24a292e302304
|
||||
MatrixSDK: abb44d24e0426f3734630362c736d96446a629a3
|
||||
MatrixKit: 5668775ddcb36939f22cb5e76dcf617980c52c75
|
||||
MatrixSDK: 5d5eae9a9a098ec130022da4a4925332df8df1d9
|
||||
OLMKit: b9d8c0ffee9ea8c45bc0aaa9afb47f93fba7efbd
|
||||
PiwikTracker: 42862c7b13028065c3dfd36b4dc38db8a5765acf
|
||||
Realm: d927fbf66df5532cfafc08afb5f7e53ded37b894
|
||||
Realm: 08b464b462d4f31bbd4ba5f5a1c8722ef0a700b7
|
||||
WebRTC: f2a6203584745fe53532633397557876b5d71640
|
||||
|
||||
PODFILE CHECKSUM: f62acabc542b9493f2d704d8c5163a53051b1979
|
||||
PODFILE CHECKSUM: 948cd5479b6467245ee83ba82304e73d83c7e4e2
|
||||
|
||||
COCOAPODS: 1.5.3
|
||||
|
||||
@@ -59,6 +59,13 @@
|
||||
32471CE11F13AC1500BDF50A /* RoomMembershipExpandedWithPaginationTitleBubbleCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 32471CDF1F13AC1500BDF50A /* RoomMembershipExpandedWithPaginationTitleBubbleCell.m */; };
|
||||
32471CE21F13AC1500BDF50A /* RoomMembershipExpandedWithPaginationTitleBubbleCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 32471CE01F13AC1500BDF50A /* RoomMembershipExpandedWithPaginationTitleBubbleCell.xib */; };
|
||||
325E1C151E8D03950018D91E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 325E1C131E8D03950018D91E /* LaunchScreen.storyboard */; };
|
||||
3267EFB220E2A04100FF1CAA /* Analytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 3267EFB120E2A04100FF1CAA /* Analytics.m */; };
|
||||
3267EFB720E379FE00FF1CAA /* CHANGES.rst in Resources */ = {isa = PBXBuildFile; fileRef = 3267EFB320E379FD00FF1CAA /* CHANGES.rst */; };
|
||||
3267EFB820E379FE00FF1CAA /* Podfile in Resources */ = {isa = PBXBuildFile; fileRef = 3267EFB420E379FD00FF1CAA /* Podfile */; };
|
||||
3267EFB920E379FE00FF1CAA /* AUTHORS.rst in Resources */ = {isa = PBXBuildFile; fileRef = 3267EFB520E379FD00FF1CAA /* AUTHORS.rst */; };
|
||||
3267EFBA20E379FE00FF1CAA /* README.rst in Resources */ = {isa = PBXBuildFile; fileRef = 3267EFB620E379FD00FF1CAA /* README.rst */; };
|
||||
3267EFC020E4A3DD00FF1CAA /* DecryptionFailureTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 3267EFBE20E4A3DD00FF1CAA /* DecryptionFailureTracker.m */; };
|
||||
3267EFC320E5055800FF1CAA /* DecryptionFailure.m in Sources */ = {isa = PBXBuildFile; fileRef = 3267EFC220E5055800FF1CAA /* DecryptionFailure.m */; };
|
||||
327382B51F276AD200356143 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 327382A81F276AD200356143 /* InfoPlist.strings */; };
|
||||
327382B61F276AD200356143 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 327382AA1F276AD200356143 /* Localizable.strings */; };
|
||||
327382B71F276AD200356143 /* Vector.strings in Resources */ = {isa = PBXBuildFile; fileRef = 327382AC1F276AD200356143 /* Vector.strings */; };
|
||||
@@ -113,6 +120,8 @@
|
||||
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 */; };
|
||||
B1D818C020EA4C7400D5F36D /* RiotSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D818BF20EA4C7400D5F36D /* RiotSettings.swift */; };
|
||||
B1D818C120EA794400D5F36D /* RiotSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D818BF20EA4C7400D5F36D /* RiotSettings.swift */; };
|
||||
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 */; };
|
||||
@@ -725,6 +734,16 @@
|
||||
32471CDF1F13AC1500BDF50A /* RoomMembershipExpandedWithPaginationTitleBubbleCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoomMembershipExpandedWithPaginationTitleBubbleCell.m; sourceTree = "<group>"; };
|
||||
32471CE01F13AC1500BDF50A /* RoomMembershipExpandedWithPaginationTitleBubbleCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = RoomMembershipExpandedWithPaginationTitleBubbleCell.xib; sourceTree = "<group>"; };
|
||||
325E1C141E8D03950018D91E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
3267EFB020E2A04100FF1CAA /* Analytics.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Analytics.h; path = Riot/Analytics/Analytics.h; sourceTree = SOURCE_ROOT; };
|
||||
3267EFB120E2A04100FF1CAA /* Analytics.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Analytics.m; path = Riot/Analytics/Analytics.m; sourceTree = SOURCE_ROOT; };
|
||||
3267EFB320E379FD00FF1CAA /* CHANGES.rst */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGES.rst; sourceTree = "<group>"; };
|
||||
3267EFB420E379FD00FF1CAA /* Podfile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Podfile; sourceTree = "<group>"; };
|
||||
3267EFB520E379FD00FF1CAA /* AUTHORS.rst */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = AUTHORS.rst; sourceTree = "<group>"; };
|
||||
3267EFB620E379FD00FF1CAA /* README.rst */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.rst; sourceTree = "<group>"; };
|
||||
3267EFBE20E4A3DD00FF1CAA /* DecryptionFailureTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DecryptionFailureTracker.m; path = Riot/Analytics/DecryptionFailureTracker.m; sourceTree = SOURCE_ROOT; };
|
||||
3267EFBF20E4A3DD00FF1CAA /* DecryptionFailureTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DecryptionFailureTracker.h; path = Riot/Analytics/DecryptionFailureTracker.h; sourceTree = SOURCE_ROOT; };
|
||||
3267EFC120E5055800FF1CAA /* DecryptionFailure.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DecryptionFailure.h; path = Riot/Analytics/DecryptionFailure.h; sourceTree = SOURCE_ROOT; };
|
||||
3267EFC220E5055800FF1CAA /* DecryptionFailure.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = DecryptionFailure.m; path = Riot/Analytics/DecryptionFailure.m; sourceTree = SOURCE_ROOT; };
|
||||
327382A91F276AD200356143 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = InfoPlist.strings; sourceTree = "<group>"; };
|
||||
327382AB1F276AD200356143 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = Localizable.strings; sourceTree = "<group>"; };
|
||||
327382AD1F276AD200356143 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = Vector.strings; sourceTree = "<group>"; };
|
||||
@@ -804,6 +823,9 @@
|
||||
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>"; };
|
||||
B1D818BC20E66C3300D5F36D /* Riot-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Riot-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
B1D818BF20EA4C7400D5F36D /* RiotSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RiotSettings.swift; sourceTree = "<group>"; };
|
||||
B1D818C220EA7DB500D5F36D /* RiotShareExtension-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "RiotShareExtension-Bridging-Header.h"; path = "RiotShareExtension/RiotShareExtension-Bridging-Header.h"; sourceTree = SOURCE_ROOT; };
|
||||
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; };
|
||||
@@ -1489,6 +1511,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2466B7551F2F80B800AE27B0 /* Info.plist */,
|
||||
B1D818C220EA7DB500D5F36D /* RiotShareExtension-Bridging-Header.h */,
|
||||
2466B7561F2F80B800AE27B0 /* RiotShareExtension.entitlements */,
|
||||
24D6B3441F3C8F8A00FC7A71 /* ViewController */,
|
||||
2439DD5F1F6BBE390090F42D /* Views */,
|
||||
@@ -1597,6 +1620,20 @@
|
||||
path = "jitsi-meet";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
3267EFAF20E2A00F00FF1CAA /* Analytics */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3267EFB020E2A04100FF1CAA /* Analytics.h */,
|
||||
3267EFB120E2A04100FF1CAA /* Analytics.m */,
|
||||
3267EFBF20E4A3DD00FF1CAA /* DecryptionFailureTracker.h */,
|
||||
3267EFBE20E4A3DD00FF1CAA /* DecryptionFailureTracker.m */,
|
||||
3267EFC120E5055800FF1CAA /* DecryptionFailure.h */,
|
||||
3267EFC220E5055800FF1CAA /* DecryptionFailure.m */,
|
||||
);
|
||||
name = Analytics;
|
||||
path = "New Group";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
327382A71F276AD200356143 /* de.lproj */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -1796,6 +1833,7 @@
|
||||
F083BB081E7009EC00A9B29C /* Riot */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3267EFAF20E2A00F00FF1CAA /* Analytics */,
|
||||
F083BB091E7009EC00A9B29C /* API */,
|
||||
F083BB0E1E7009EC00A9B29C /* Assets */,
|
||||
F083BBE41E7009EC00A9B29C /* Categories */,
|
||||
@@ -2215,6 +2253,7 @@
|
||||
F083BC151E7009EC00A9B29C /* Tools.m */,
|
||||
F083BC161E7009EC00A9B29C /* RiotDesignValues.h */,
|
||||
F083BC171E7009EC00A9B29C /* RiotDesignValues.m */,
|
||||
B1D818BF20EA4C7400D5F36D /* RiotSettings.swift */,
|
||||
);
|
||||
path = Utils;
|
||||
sourceTree = "<group>";
|
||||
@@ -2667,6 +2706,7 @@
|
||||
F083BEA41E700B2800A9B29C /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B1D818BC20E66C3300D5F36D /* Riot-Bridging-Header.h */,
|
||||
F0DD05CF1F615ECF00CB5292 /* LaunchScreenRiot.png */,
|
||||
F083BBED1E7009EC00A9B29C /* empty.mm */,
|
||||
F083BBEE1E7009EC00A9B29C /* GoogleService-Info.plist */,
|
||||
@@ -2682,6 +2722,10 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F083BB081E7009EC00A9B29C /* Riot */,
|
||||
3267EFB520E379FD00FF1CAA /* AUTHORS.rst */,
|
||||
3267EFB320E379FD00FF1CAA /* CHANGES.rst */,
|
||||
3267EFB420E379FD00FF1CAA /* Podfile */,
|
||||
3267EFB620E379FD00FF1CAA /* README.rst */,
|
||||
F083BB021E7005FD00A9B29C /* RiotTests */,
|
||||
24CBEC4F1F0EAD310093EABB /* RiotShareExtension */,
|
||||
92726A441F58737A004AD26F /* SiriIntents */,
|
||||
@@ -2870,6 +2914,7 @@
|
||||
F094A9A11B78D8F000B1FBBF = {
|
||||
CreatedOnToolsVersion = 6.2;
|
||||
DevelopmentTeam = 7J4U792NQT;
|
||||
LastSwiftMigration = 0940;
|
||||
ProvisioningStyle = Automatic;
|
||||
SystemCapabilities = {
|
||||
com.apple.ApplicationGroups.iOS = {
|
||||
@@ -2988,6 +3033,7 @@
|
||||
F083BD641E7009ED00A9B29C /* direct_icon@3x.png in Resources */,
|
||||
F083BE261E7009ED00A9B29C /* SegmentedViewController.xib in Resources */,
|
||||
F083BE161E7009ED00A9B29C /* MediaAlbumContentViewController.xib in Resources */,
|
||||
3267EFB720E379FE00FF1CAA /* CHANGES.rst in Resources */,
|
||||
F083BD441E7009ED00A9B29C /* call_speaker_on_icon@3x.png in Resources */,
|
||||
F0614A0F1EDDCCE700F5DC9A /* jump_to_unread@3x.png in Resources */,
|
||||
F083BE511E7009ED00A9B29C /* RoomOutgoingEncryptedTextMsgBubbleCell.xib in Resources */,
|
||||
@@ -3040,6 +3086,7 @@
|
||||
32BB89F0204D86DA002F3AEC /* InfoPlist.strings in Resources */,
|
||||
F083BD3E1E7009ED00A9B29C /* call_hangup_icon@3x.png in Resources */,
|
||||
32AE61F21F0D2183007255F4 /* InfoPlist.strings in Resources */,
|
||||
3267EFB920E379FE00FF1CAA /* AUTHORS.rst in Resources */,
|
||||
F083BDB91E7009ED00A9B29C /* remove_icon_pink.png in Resources */,
|
||||
F083BE531E7009ED00A9B29C /* RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.xib in Resources */,
|
||||
F083BD7F1E7009ED00A9B29C /* error@3x.png in Resources */,
|
||||
@@ -3070,6 +3117,7 @@
|
||||
F083BD5F1E7009ED00A9B29C /* details_icon.png in Resources */,
|
||||
F083BE241E7009ED00A9B29C /* RoomViewController.xib in Resources */,
|
||||
F083BE7B1E7009ED00A9B29C /* RoomInputToolbarView.xib in Resources */,
|
||||
3267EFB820E379FE00FF1CAA /* Podfile in Resources */,
|
||||
F0E05A3D1EA0F9EB004B83FB /* tab_people_selected@2x.png in Resources */,
|
||||
F0E05A451EA0F9EB004B83FB /* tab_rooms.png in Resources */,
|
||||
F083BE751E7009ED00A9B29C /* RoomOutgoingTextMsgWithoutSenderNameBubbleCell.xib in Resources */,
|
||||
@@ -3319,6 +3367,7 @@
|
||||
F0E05A3C1EA0F9EB004B83FB /* tab_people_selected.png in Resources */,
|
||||
F083BD221E7009ED00A9B29C /* add_participant.png in Resources */,
|
||||
F083BDC61E7009ED00A9B29C /* search_bg@2x.png in Resources */,
|
||||
3267EFBA20E379FE00FF1CAA /* README.rst in Resources */,
|
||||
F083BD421E7009ED00A9B29C /* call_speaker_on_icon.png in Resources */,
|
||||
F04AF26D1F83A4C100D20F4D /* Localizable.strings in Resources */,
|
||||
F083BD9A1E7009ED00A9B29C /* logo@3x.png in Resources */,
|
||||
@@ -3477,6 +3526,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
24EEE5A01F23A08900B3C705 /* RoomTableViewCell.m in Sources */,
|
||||
B1D818C120EA794400D5F36D /* RiotSettings.swift in Sources */,
|
||||
24D6B3581F3C90D300FC7A71 /* ShareDataSource.m in Sources */,
|
||||
245FC3EF1F3DD30800603C6A /* RecentCellData.m in Sources */,
|
||||
24D6B35C1F3CA03600FC7A71 /* RoomsListViewController.m in Sources */,
|
||||
@@ -3543,6 +3593,7 @@
|
||||
321082B21F0E9F40002E0091 /* RoomMembershipCollapsedBubbleCell.m in Sources */,
|
||||
32C2356F1F7B871800E38FC5 /* WidgetPickerViewController.m in Sources */,
|
||||
F083BE661E7009ED00A9B29C /* RoomIncomingTextMsgWithPaginationTitleBubbleCell.m in Sources */,
|
||||
3267EFB220E2A04100FF1CAA /* Analytics.m in Sources */,
|
||||
F083BE141E7009ED00A9B29C /* HomeViewController.m in Sources */,
|
||||
F083BDFB1E7009ED00A9B29C /* RoomSearchDataSource.m in Sources */,
|
||||
32EF474920B6EE990031695C /* StickerPickerViewController.m in Sources */,
|
||||
@@ -3591,6 +3642,7 @@
|
||||
F083BE2D1E7009ED00A9B29C /* ForgotPasswordInputsView.m in Sources */,
|
||||
F083BE7E1E7009ED00A9B29C /* InviteRecentTableViewCell.m in Sources */,
|
||||
F083BE3C1E7009ED00A9B29C /* RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.m in Sources */,
|
||||
3267EFC320E5055800FF1CAA /* DecryptionFailure.m in Sources */,
|
||||
F083BE211E7009ED00A9B29C /* RoomSearchViewController.m in Sources */,
|
||||
32185B311F20FA2B00752141 /* LanguagePickerViewController.m in Sources */,
|
||||
F083BE3E1E7009ED00A9B29C /* RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.m in Sources */,
|
||||
@@ -3632,6 +3684,7 @@
|
||||
F083BE781E7009ED00A9B29C /* RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m in Sources */,
|
||||
F083BE5E1E7009ED00A9B29C /* RoomIncomingAttachmentWithPaginationTitleBubbleCell.m in Sources */,
|
||||
F083BD1E1E7009ED00A9B29C /* AppDelegate.m in Sources */,
|
||||
B1D818C020EA4C7400D5F36D /* RiotSettings.swift in Sources */,
|
||||
F083BE8A1E7009ED00A9B29C /* ExpandedRoomTitleView.m in Sources */,
|
||||
F083BE0C1E7009ED00A9B29C /* ContactDetailsViewController.m in Sources */,
|
||||
F083BE821E7009ED00A9B29C /* RecentTableViewCell.m in Sources */,
|
||||
@@ -3655,6 +3708,7 @@
|
||||
F083BE101E7009ED00A9B29C /* CountryPickerViewController.m in Sources */,
|
||||
F083BE581E7009ED00A9B29C /* RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m in Sources */,
|
||||
F083BDF61E7009ED00A9B29C /* Contact.m in Sources */,
|
||||
3267EFC020E4A3DD00FF1CAA /* DecryptionFailureTracker.m in Sources */,
|
||||
F083BE961E7009ED00A9B29C /* MessagesSearchResultAttachmentBubbleCell.m in Sources */,
|
||||
F083BE391E7009ED00A9B29C /* RoomEncryptedDataBubbleCell.m in Sources */,
|
||||
F083BDF01E7009ED00A9B29C /* UIViewController+RiotSearch.m in Sources */,
|
||||
@@ -3988,12 +4042,19 @@
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = 7J4U792NQT;
|
||||
ENABLE_BITCODE = NO;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"$(inherited)",
|
||||
"COCOAPODS=1",
|
||||
"IS_SHARE_EXTENSION=1",
|
||||
);
|
||||
INFOPLIST_FILE = RiotShareExtension/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = im.vector.app.shareExtension;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/$(PRODUCT_NAME)/RiotShareExtension-Bridging-Header.h";
|
||||
SWIFT_VERSION = 4.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -4011,12 +4072,19 @@
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = 7J4U792NQT;
|
||||
ENABLE_BITCODE = NO;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"$(inherited)",
|
||||
"COCOAPODS=1",
|
||||
"IS_SHARE_EXTENSION=1",
|
||||
);
|
||||
INFOPLIST_FILE = RiotShareExtension/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = im.vector.app.shareExtension;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/$(PRODUCT_NAME)/RiotShareExtension-Bridging-Header.h";
|
||||
SWIFT_VERSION = 4.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@@ -4082,6 +4150,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEFINES_MODULE = YES;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
@@ -4099,7 +4168,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@@ -4128,6 +4197,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
@@ -4138,7 +4208,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
@@ -4150,7 +4220,9 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = A5030B7C3C0B6EB83A9257BD /* Pods-RiotPods-Riot.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Riot/Riot.entitlements;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
DEVELOPMENT_TEAM = 7J4U792NQT;
|
||||
@@ -4177,6 +4249,9 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = im.vector.app;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/$(PRODUCT_NAME)/Riot-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 4.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
@@ -4185,7 +4260,9 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = F546BCBBB9BBEE67DB28878A /* Pods-RiotPods-Riot.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Riot/Riot.entitlements;
|
||||
DEVELOPMENT_TEAM = 7J4U792NQT;
|
||||
ENABLE_BITCODE = NO;
|
||||
@@ -4211,6 +4288,8 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = im.vector.app;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/$(PRODUCT_NAME)/Riot-Bridging-Header.h";
|
||||
SWIFT_VERSION = 4.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
@@ -4218,6 +4297,7 @@
|
||||
F094A9CC1B78D8F000B1FBBF /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
DEVELOPMENT_TEAM = 7J4U792NQT;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
@@ -4239,6 +4319,7 @@
|
||||
F094A9CD1B78D8F000B1FBBF /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
DEVELOPMENT_TEAM = 7J4U792NQT;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
|
||||
#import <MatrixKit/MatrixKit.h>
|
||||
|
||||
#import "Riot-Swift.h"
|
||||
|
||||
static RageShakeManager* sharedInstance = nil;
|
||||
|
||||
@interface RageShakeManager() {
|
||||
@@ -111,7 +113,7 @@ static RageShakeManager* sharedInstance = nil;
|
||||
// Start only if the application is in foreground
|
||||
// And if the rageshake user setting is enabled
|
||||
if ([AppDelegate theDelegate].isAppForeground
|
||||
&& [[NSUserDefaults standardUserDefaults] boolForKey:@"enableRageShake"]
|
||||
&& RiotSettings.shared.enableRageShake
|
||||
&& !confirmationAlert)
|
||||
{
|
||||
NSLog(@"[RageShakeManager] Start shaking with [%@]", [responder class]);
|
||||
@@ -163,8 +165,7 @@ static RageShakeManager* sharedInstance = nil;
|
||||
self->confirmationAlert = nil;
|
||||
|
||||
// Disable rageshake user setting
|
||||
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"enableRageShake"];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
RiotSettings.shared.enableRageShake = NO;
|
||||
}
|
||||
|
||||
}]];
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
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 <Foundation/Foundation.h>
|
||||
|
||||
#import <MatrixSDK/MatrixSDK.h>
|
||||
#import "DecryptionFailureTracker.h"
|
||||
|
||||
/**
|
||||
`Analytics` sends analytics to an analytics tool.
|
||||
*/
|
||||
@interface Analytics : NSObject <MXAnalyticsDelegate, MXDecryptionFailureDelegate>
|
||||
|
||||
/**
|
||||
Returns the shared Analytics manager.
|
||||
|
||||
@return the shared Analytics manager.
|
||||
*/
|
||||
+ (instancetype)sharedInstance;
|
||||
|
||||
/**
|
||||
Start doing analytics if the settings `enableCrashReport` is enabled.
|
||||
*/
|
||||
- (void)start;
|
||||
|
||||
/**
|
||||
Stop doing analytics.
|
||||
*/
|
||||
- (void)stop;
|
||||
|
||||
/**
|
||||
Track a screen display.
|
||||
|
||||
@param screenName the name of the displayed screen.
|
||||
*/
|
||||
- (void)trackScreen:(NSString*)screenName;
|
||||
|
||||
/**
|
||||
Flush analytics data.
|
||||
*/
|
||||
- (void)dispatch;
|
||||
|
||||
/**
|
||||
Track how long the launch screen has been displayed to the end user.
|
||||
|
||||
@param seconds the duration in seconds.
|
||||
*/
|
||||
- (void)trackLaunchScreenDisplayDuration: (NSTimeInterval)seconds;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
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 "Analytics.h"
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import "Riot-Swift.h"
|
||||
|
||||
// All metrics are store under a Piwik category called "Metrics".
|
||||
// Then, there are 2 Piwik actions: "iOS.startup" and "iOS.stats" (these actions
|
||||
// are namespaced by plaform to have a nice rendering on the Piwik website).
|
||||
// Then, we use constants defined by the Matrix SDK as Piwik Names (ex:"mountData")
|
||||
NSString *const kAnalyticsMetricsCategory = @"Metrics";
|
||||
NSString *const kAnalyticsMetricsActionPattern = @"iOS.%@";
|
||||
|
||||
// E2E telemetry is stored under a Piwik category called "E2E".
|
||||
NSString *const kAnalyticsE2eCategory = @"E2E";
|
||||
NSString *const kAnalyticsE2eDecryptionFailureAction = @"Decryption failure";
|
||||
|
||||
|
||||
@import PiwikTracker;
|
||||
|
||||
@implementation Analytics
|
||||
|
||||
+ (instancetype)sharedInstance
|
||||
{
|
||||
static Analytics *sharedInstance = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedInstance = [[Analytics alloc] init];
|
||||
});
|
||||
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (void)start
|
||||
{
|
||||
NSDictionary *piwikConfig = [[NSUserDefaults standardUserDefaults] objectForKey:@"piwik"];
|
||||
[PiwikTracker configureSharedInstanceWithSiteID:piwikConfig[@"siteId"]
|
||||
baseURL:[NSURL URLWithString:piwikConfig[@"url"]]
|
||||
userAgent:@"iOSPiwikTracker"];
|
||||
|
||||
// Check whether the user has enabled the sending of crash reports.
|
||||
if (RiotSettings.shared.enableCrashReport)
|
||||
{
|
||||
[PiwikTracker shared].isOptedOut = NO;
|
||||
|
||||
[[PiwikTracker shared] setCustomVariableWithIndex:1 name:@"App Platform" value:@"iOS Platform"];
|
||||
[[PiwikTracker shared] setCustomVariableWithIndex:2 name:@"App Version" value:[AppDelegate theDelegate].appVersion];
|
||||
|
||||
// The language is either the one selected by the user within the app
|
||||
// or, else, the one configured by the OS
|
||||
NSString *language = [NSBundle mxk_language] ? [NSBundle mxk_language] : [[NSBundle mainBundle] preferredLocalizations][0];
|
||||
[[PiwikTracker shared] setCustomVariableWithIndex:4 name:@"Chosen Language" value:language];
|
||||
|
||||
MXKAccount* account = [MXKAccountManager sharedManager].activeAccounts.firstObject;
|
||||
if (account)
|
||||
{
|
||||
[[PiwikTracker shared] setCustomVariableWithIndex:7 name:@"Homeserver URL" value:account.mxCredentials.homeServer];
|
||||
[[PiwikTracker shared] setCustomVariableWithIndex:8 name:@"Identity Server URL" value:account.identityServerURL];
|
||||
}
|
||||
|
||||
// TODO: We should also track device and os version
|
||||
// But that needs to be decided for all platforms
|
||||
|
||||
// Catch and log crashes
|
||||
[MXLogger logCrashes:YES];
|
||||
[MXLogger setBuildVersion:[AppDelegate theDelegate].build];
|
||||
|
||||
#ifdef DEBUG
|
||||
// Disable analytics in debug as it pollutes stats
|
||||
[PiwikTracker shared].isOptedOut = YES;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"[AppDelegate] The user decided to not send analytics");
|
||||
[PiwikTracker shared].isOptedOut = YES;
|
||||
[MXLogger logCrashes:NO];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)stop
|
||||
{
|
||||
[PiwikTracker shared].isOptedOut = YES;
|
||||
[MXLogger logCrashes:NO];
|
||||
}
|
||||
|
||||
- (void)trackScreen:(NSString *)screenName
|
||||
{
|
||||
// Use the same pattern as Android
|
||||
NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"];
|
||||
NSString *appVersion = [AppDelegate theDelegate].appVersion;
|
||||
|
||||
[[PiwikTracker shared] trackWithView:@[@"ios", appName, appVersion, screenName]
|
||||
url:nil];
|
||||
}
|
||||
|
||||
- (void)dispatch
|
||||
{
|
||||
[[PiwikTracker shared] dispatch];
|
||||
}
|
||||
|
||||
- (void)trackLaunchScreenDisplayDuration:(NSTimeInterval)seconds
|
||||
{
|
||||
NSString *action = [NSString stringWithFormat:kAnalyticsMetricsActionPattern, kMXAnalyticsStartupCategory];
|
||||
|
||||
[[PiwikTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory
|
||||
action:action
|
||||
name:kMXAnalyticsStartupLaunchScreen
|
||||
number:@(seconds * 1000)
|
||||
url:nil];
|
||||
}
|
||||
|
||||
#pragma mark - MXAnalyticsDelegate
|
||||
|
||||
- (void)trackStartupStorePreloadDuration: (NSTimeInterval)seconds
|
||||
{
|
||||
NSString *action = [NSString stringWithFormat:kAnalyticsMetricsActionPattern, kMXAnalyticsStartupCategory];
|
||||
|
||||
[[PiwikTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory
|
||||
action:action
|
||||
name:kMXAnalyticsStartupStorePreload
|
||||
number:@(seconds * 1000)
|
||||
url:nil];
|
||||
}
|
||||
|
||||
- (void)trackStartupMountDataDuration: (NSTimeInterval)seconds
|
||||
{
|
||||
NSString *action = [NSString stringWithFormat:kAnalyticsMetricsActionPattern, kMXAnalyticsStartupCategory];
|
||||
|
||||
[[PiwikTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory
|
||||
action:action
|
||||
name:kMXAnalyticsStartupMountData
|
||||
number:@(seconds * 1000)
|
||||
url:nil];
|
||||
}
|
||||
|
||||
- (void)trackStartupSyncDuration: (NSTimeInterval)seconds isInitial: (BOOL)isInitial
|
||||
{
|
||||
NSString *action = [NSString stringWithFormat:kAnalyticsMetricsActionPattern, kMXAnalyticsStartupCategory];
|
||||
|
||||
[[PiwikTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory
|
||||
action:action
|
||||
name:isInitial ? kMXAnalyticsStartupInititialSync : kMXAnalyticsStartupIncrementalSync
|
||||
number:@(seconds * 1000)
|
||||
url:nil];
|
||||
}
|
||||
|
||||
- (void)trackRoomCount: (NSUInteger)roomCount
|
||||
{
|
||||
NSString *action = [NSString stringWithFormat:kAnalyticsMetricsActionPattern, kMXAnalyticsStatsCategory];
|
||||
|
||||
[[PiwikTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory
|
||||
action:action
|
||||
name:kMXAnalyticsStatsRooms
|
||||
number:@(roomCount)
|
||||
url:nil];
|
||||
}
|
||||
|
||||
#pragma mark - MXDecryptionFailureDelegate
|
||||
|
||||
- (void)trackFailures:(NSDictionary<NSString *,NSNumber *> *)failuresCounts
|
||||
{
|
||||
for (NSString *reason in failuresCounts)
|
||||
{
|
||||
[[PiwikTracker shared] trackWithEventWithCategory:kAnalyticsE2eCategory
|
||||
action:kAnalyticsE2eDecryptionFailureAction
|
||||
name:reason
|
||||
number:failuresCounts[reason]
|
||||
url:nil];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
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 <Foundation/Foundation.h>
|
||||
|
||||
/**
|
||||
Failure reasons as defined in https://docs.google.com/document/d/1es7cTCeJEXXfRCTRgZerAM2Wg5ZerHjvlpfTW-gsOfI.
|
||||
*/
|
||||
struct DecryptionFailureReasonStruct
|
||||
{
|
||||
__unsafe_unretained NSString * const unspecified;
|
||||
__unsafe_unretained NSString * const olmKeysNotSent;
|
||||
__unsafe_unretained NSString * const olmIndexError;
|
||||
__unsafe_unretained NSString * const unexpected;
|
||||
};
|
||||
extern const struct DecryptionFailureReasonStruct DecryptionFailureReason;
|
||||
|
||||
/**
|
||||
`DecryptionFailure` represents a decryption failure.
|
||||
*/
|
||||
@interface DecryptionFailure : NSObject
|
||||
|
||||
/**
|
||||
The id of the event that was unabled to decrypt.
|
||||
*/
|
||||
@property (nonatomic) NSString *failedEventId;
|
||||
|
||||
/**
|
||||
The time the failure has been reported.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSTimeInterval ts;
|
||||
|
||||
/**
|
||||
Decryption failure reason.
|
||||
*/
|
||||
@property (nonatomic) NSString *reason;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
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 "DecryptionFailure.h"
|
||||
|
||||
const struct DecryptionFailureReasonStruct DecryptionFailureReason = {
|
||||
.unspecified = @"unspecified_error",
|
||||
.olmKeysNotSent = @"olm_keys_not_sent_error",
|
||||
.olmIndexError = @"olm_index_error",
|
||||
.unexpected = @"unexpected_error"
|
||||
};
|
||||
|
||||
@implementation DecryptionFailure
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self)
|
||||
{
|
||||
_ts = [NSDate date].timeIntervalSince1970;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
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 <Foundation/Foundation.h>
|
||||
|
||||
#import "DecryptionFailure.h"
|
||||
|
||||
@import MatrixSDK;
|
||||
|
||||
@protocol MXDecryptionFailureDelegate;
|
||||
|
||||
@interface DecryptionFailureTracker : NSObject
|
||||
|
||||
/**
|
||||
Returns the shared tracker.
|
||||
|
||||
@return the shared tracker.
|
||||
*/
|
||||
+ (instancetype)sharedInstance;
|
||||
|
||||
/**
|
||||
The delegate object to receive analytics events.
|
||||
*/
|
||||
@property (nonatomic) id<MXDecryptionFailureDelegate> delegate;
|
||||
|
||||
/**
|
||||
Report an event unable to decrypt.
|
||||
|
||||
This error can be momentary. The DecryptionFailureTracker will check if it gets
|
||||
fixed. Else, it will generate a failure (@see `trackFailures`).
|
||||
|
||||
@param event the event.
|
||||
@param roomState the room state when the event was received.
|
||||
@param userId my user id.
|
||||
*/
|
||||
- (void)reportUnableToDecryptErrorForEvent:(MXEvent*)event withRoomState:(MXRoomState*)roomState myUser:(NSString*)userId;
|
||||
|
||||
/**
|
||||
Flush current data.
|
||||
*/
|
||||
- (void)dispatch;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
The `MXDecryptionFailureDelegate` protocol receives some stats computed by
|
||||
`DecryptionFailureTracker`.
|
||||
*/
|
||||
@protocol MXDecryptionFailureDelegate <NSObject>
|
||||
|
||||
/**
|
||||
Stats for decryption failures.
|
||||
|
||||
@param failuresCounts the number of errors per failure reason.
|
||||
*/
|
||||
- (void)trackFailures:(NSDictionary<NSString*, NSNumber*> *)failuresCounts;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
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 "DecryptionFailureTracker.h"
|
||||
|
||||
|
||||
// Call `checkFailures` every `CHECK_INTERVAL`
|
||||
#define CHECK_INTERVAL 5
|
||||
|
||||
// Give events a chance to be decrypted by waiting `GRACE_PERIOD` before counting
|
||||
// and reporting them as failures
|
||||
#define GRACE_PERIOD 60
|
||||
|
||||
|
||||
@interface DecryptionFailureTracker()
|
||||
{
|
||||
// Reported failures
|
||||
// Every `CHECK_INTERVAL`, this list is checked for failures that happened
|
||||
// more than`GRACE_PERIOD` ago. Those that did are reported to the delegate.
|
||||
NSMutableDictionary<NSString* /* eventId */, DecryptionFailure*> *reportedFailures;
|
||||
|
||||
// Event ids of failures that were tracked previously
|
||||
NSMutableSet<NSString*> *trackedEvents;
|
||||
|
||||
// Timer for periodic check
|
||||
NSTimer *checkFailuresTimer;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation DecryptionFailureTracker
|
||||
|
||||
+ (instancetype)sharedInstance
|
||||
{
|
||||
static DecryptionFailureTracker *sharedInstance = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedInstance = [[DecryptionFailureTracker alloc] init];
|
||||
});
|
||||
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self)
|
||||
{
|
||||
reportedFailures = [NSMutableDictionary dictionary];
|
||||
trackedEvents = [NSMutableSet set];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(eventDidDecrypt:) name:kMXEventDidDecryptNotification object:nil];
|
||||
|
||||
checkFailuresTimer = [NSTimer scheduledTimerWithTimeInterval:CHECK_INTERVAL
|
||||
target:self
|
||||
selector:@selector(checkFailures)
|
||||
userInfo:nil
|
||||
repeats:YES];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)reportUnableToDecryptErrorForEvent:(MXEvent *)event withRoomState:(MXRoomState *)roomState myUser:(NSString *)userId
|
||||
{
|
||||
if (reportedFailures[event.eventId] || [trackedEvents containsObject:event.eventId])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Filter out "expected" UTDs
|
||||
// We cannot decrypt messages sent before the user joined the room
|
||||
MXRoomMember *myUser = [roomState memberWithUserId:userId];
|
||||
if (!myUser || myUser.membership != MXMembershipJoin)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DecryptionFailure *decryptionFailure = [[DecryptionFailure alloc] init];
|
||||
decryptionFailure.failedEventId = event.eventId;
|
||||
|
||||
// Categorise the error
|
||||
switch (event.decryptionError.code)
|
||||
{
|
||||
case MXDecryptingErrorUnknownInboundSessionIdCode:
|
||||
decryptionFailure.reason = DecryptionFailureReason.olmKeysNotSent;
|
||||
break;
|
||||
|
||||
case MXDecryptingErrorOlmCode:
|
||||
decryptionFailure.reason = DecryptionFailureReason.olmIndexError;
|
||||
break;
|
||||
|
||||
case MXDecryptingErrorEncryptionNotEnabledCode:
|
||||
case MXDecryptingErrorUnableToDecryptCode:
|
||||
decryptionFailure.reason = DecryptionFailureReason.unexpected;
|
||||
break;
|
||||
|
||||
default:
|
||||
decryptionFailure.reason = DecryptionFailureReason.unspecified;
|
||||
break;
|
||||
}
|
||||
|
||||
reportedFailures[event.eventId] = decryptionFailure;
|
||||
}
|
||||
|
||||
- (void)dispatch
|
||||
{
|
||||
[self checkFailures];
|
||||
}
|
||||
|
||||
#pragma mark - Private methods
|
||||
|
||||
/**
|
||||
Mark reported failures that occured before tsNow - GRACE_PERIOD as failures that should be
|
||||
tracked.
|
||||
*/
|
||||
- (void)checkFailures
|
||||
{
|
||||
NSTimeInterval tsNow = [NSDate date].timeIntervalSince1970;
|
||||
|
||||
NSMutableArray *failuresToTrack = [NSMutableArray array];
|
||||
|
||||
for (DecryptionFailure *reportedFailure in reportedFailures.allValues)
|
||||
{
|
||||
if (reportedFailure.ts < tsNow - GRACE_PERIOD)
|
||||
{
|
||||
[failuresToTrack addObject:reportedFailure];
|
||||
[reportedFailures removeObjectForKey:reportedFailure.failedEventId];
|
||||
[trackedEvents addObject:reportedFailure.failedEventId];
|
||||
}
|
||||
}
|
||||
|
||||
if (_delegate && failuresToTrack.count)
|
||||
{
|
||||
// Sort failures by error reason
|
||||
NSMutableDictionary<NSString*, NSNumber*> *failuresCounts = [NSMutableDictionary dictionary];
|
||||
for (DecryptionFailure *failure in failuresToTrack)
|
||||
{
|
||||
failuresCounts[failure.reason] = @(failuresCounts[failure.reason].unsignedIntegerValue + 1);
|
||||
}
|
||||
|
||||
NSLog(@"[DecryptionFailureTracker] trackFailures: %@", failuresCounts);
|
||||
|
||||
[_delegate trackFailures:failuresCounts];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)eventDidDecrypt:(NSNotification *)notif
|
||||
{
|
||||
// Could be an event in the reportedFailures, remove it
|
||||
MXEvent *event = notif.object;
|
||||
[reportedFailures removeObjectForKey:event.eventId];
|
||||
}
|
||||
|
||||
@end
|
||||
+1
-6
@@ -22,6 +22,7 @@
|
||||
#import "JitsiViewController.h"
|
||||
|
||||
#import "RageShakeManager.h"
|
||||
#import "Analytics.h"
|
||||
|
||||
#import "RiotDesignValues.h"
|
||||
|
||||
@@ -128,12 +129,6 @@ extern NSString *const kAppDelegateNetworkStatusDidChangeNotification;
|
||||
|
||||
- (void)selectMatrixAccount:(void (^)(MXKAccount *selectedAccount))onSelection;
|
||||
|
||||
#pragma mark - Analytics
|
||||
|
||||
- (void)startAnalytics;
|
||||
- (void)stopAnalytics;
|
||||
- (void)trackScreen:(NSString*)screenName;
|
||||
|
||||
#pragma mark - Push notifications
|
||||
|
||||
- (void)registerUserNotificationSettings;
|
||||
|
||||
+39
-84
@@ -48,14 +48,14 @@
|
||||
|
||||
#import "WebViewViewController.h"
|
||||
|
||||
@import PiwikTracker;
|
||||
|
||||
// Calls
|
||||
#import "CallViewController.h"
|
||||
|
||||
#import "MXSession+Riot.h"
|
||||
#import "MXRoom+Riot.h"
|
||||
|
||||
#import "Riot-Swift.h"
|
||||
|
||||
//#define MX_CALL_STACK_OPENWEBRTC
|
||||
#ifdef MX_CALL_STACK_OPENWEBRTC
|
||||
#import <MatrixOpenWebRTCWrapper/MatrixOpenWebRTCWrapper.h>
|
||||
@@ -235,10 +235,6 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
|
||||
MXSDKOptions *sdkOptions = [MXSDKOptions sharedInstance];
|
||||
sdkOptions.applicationGroupIdentifier = @"group.im.vector";
|
||||
|
||||
// Track SDK performance on Google analytics
|
||||
// TODO: needs the same tool
|
||||
//sdkOptions.analyticsDelegate = [[MXGoogleAnalytics alloc] init];
|
||||
|
||||
// Redirect NSLogs to files only if we are not debugging
|
||||
if (!isatty(STDERR_FILENO))
|
||||
{
|
||||
@@ -461,15 +457,12 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
|
||||
|
||||
_isAppForeground = NO;
|
||||
|
||||
// Retrieve custom configuration
|
||||
NSString* userDefaults = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UserDefaults"];
|
||||
NSString *defaultsPathFromApp = [[NSBundle mainBundle] pathForResource:userDefaults ofType:@"plist"];
|
||||
NSDictionary *defaults = [NSDictionary dictionaryWithContentsOfFile:defaultsPathFromApp];
|
||||
[[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
[self setupUserDefaults];
|
||||
|
||||
// Configure Google Analytics here if the option is enabled
|
||||
[self startAnalytics];
|
||||
// Configure our analytics. It will indeed start if the option is enabled
|
||||
[MXSDKOptions sharedInstance].analyticsDelegate = [Analytics sharedInstance];
|
||||
[DecryptionFailureTracker sharedInstance].delegate = [Analytics sharedInstance];
|
||||
[[Analytics sharedInstance] start];
|
||||
|
||||
// Prepare Pushkit handling
|
||||
_incomingPushEventIds = [NSMutableDictionary dictionary];
|
||||
@@ -563,7 +556,8 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
|
||||
_isAppForeground = NO;
|
||||
|
||||
// Analytics: Force to send the pending actions
|
||||
[[PiwikTracker shared] dispatch];
|
||||
[[DecryptionFailureTracker sharedInstance] dispatch];
|
||||
[[Analytics sharedInstance] dispatch];
|
||||
}
|
||||
|
||||
- (void)applicationWillEnterForeground:(UIApplication *)application
|
||||
@@ -594,7 +588,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
|
||||
NSLog(@"[AppDelegate] applicationDidBecomeActive");
|
||||
|
||||
// Check if there is crash log to send
|
||||
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"enableCrashReport"])
|
||||
if (RiotSettings.shared.enableCrashReport)
|
||||
{
|
||||
[self checkExceptionToReport];
|
||||
}
|
||||
@@ -1026,70 +1020,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Analytics
|
||||
|
||||
- (void)startAnalytics
|
||||
{
|
||||
NSDictionary *piwikConfig = [[NSUserDefaults standardUserDefaults] objectForKey:@"piwik"];
|
||||
[PiwikTracker configureSharedInstanceWithSiteID:piwikConfig[@"siteId"]
|
||||
baseURL:[NSURL URLWithString:piwikConfig[@"url"]]
|
||||
userAgent:@"iOSPiwikTracker"];
|
||||
|
||||
// Check whether the user has enabled the sending of crash reports.
|
||||
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"enableCrashReport"])
|
||||
{
|
||||
[PiwikTracker shared].isOptedOut = NO;
|
||||
|
||||
[[PiwikTracker shared] setCustomVariableWithIndex:1 name:@"App Platform" value:@"iOS Platform"];
|
||||
[[PiwikTracker shared] setCustomVariableWithIndex:2 name:@"App Version" value:[self appVersion]];
|
||||
|
||||
// The language is either the one selected by the user within the app
|
||||
// or, else, the one configured by the OS
|
||||
NSString *language = [NSBundle mxk_language] ? [NSBundle mxk_language] : [[NSBundle mainBundle] preferredLocalizations][0];
|
||||
[[PiwikTracker shared] setCustomVariableWithIndex:4 name:@"Chosen Language" value:language];
|
||||
|
||||
MXKAccount* account = [MXKAccountManager sharedManager].activeAccounts.firstObject;
|
||||
if (account)
|
||||
{
|
||||
[[PiwikTracker shared] setCustomVariableWithIndex:7 name:@"Homeserver URL" value:account.mxCredentials.homeServer];
|
||||
[[PiwikTracker shared] setCustomVariableWithIndex:8 name:@"Identity Server URL" value:account.identityServerURL];
|
||||
}
|
||||
|
||||
// TODO: We should also track device and os version
|
||||
// But that needs to be decided for all platforms
|
||||
|
||||
// Catch and log crashes
|
||||
[MXLogger logCrashes:YES];
|
||||
[MXLogger setBuildVersion:[AppDelegate theDelegate].build];
|
||||
|
||||
#ifdef DEBUG
|
||||
// Disable analytics in debug as it pollutes stats
|
||||
[PiwikTracker shared].isOptedOut = YES;
|
||||
#endif
|
||||
}
|
||||
else if ([[NSUserDefaults standardUserDefaults] objectForKey:@"enableCrashReport"])
|
||||
{
|
||||
NSLog(@"[AppDelegate] The user decided to not ");
|
||||
[PiwikTracker shared].isOptedOut = YES;
|
||||
[MXLogger logCrashes:NO];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)stopAnalytics
|
||||
{
|
||||
[PiwikTracker shared].isOptedOut = YES;
|
||||
[MXLogger logCrashes:NO];
|
||||
}
|
||||
|
||||
- (void)trackScreen:(NSString *)screenName
|
||||
{
|
||||
// Use the same pattern as Android
|
||||
NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"];
|
||||
NSString *appVersion = [self appVersion];
|
||||
|
||||
[[PiwikTracker shared] trackWithView:@[@"ios", appName, appVersion, screenName]
|
||||
url:nil];
|
||||
}
|
||||
#pragma mark - Crash handling
|
||||
|
||||
// Check if there is a crash log to send to server
|
||||
- (void)checkExceptionToReport
|
||||
@@ -1471,7 +1402,8 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
|
||||
@"user_id": account.mxCredentials.userId
|
||||
};
|
||||
|
||||
BOOL isNotificationContentShown = !event.isEncrypted || account.showDecryptedContentInNotifications;
|
||||
BOOL isNotificationContentShown = !event.isEncrypted || RiotSettings.shared.showDecryptedContentInNotifications;
|
||||
|
||||
if ((event.eventType == MXEventTypeRoomMessage || event.eventType == MXEventTypeRoomEncrypted) && isNotificationContentShown)
|
||||
{
|
||||
eventNotification.category = @"QUICK_REPLY";
|
||||
@@ -1559,7 +1491,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
|
||||
NSString *msgType = event.content[@"msgtype"];
|
||||
NSString *content = event.content[@"body"];
|
||||
|
||||
if (event.isEncrypted && !account.showDecryptedContentInNotifications)
|
||||
if (event.isEncrypted && !RiotSettings.shared.showDecryptedContentInNotifications)
|
||||
{
|
||||
// Hide the content
|
||||
msgType = nil;
|
||||
@@ -2914,8 +2846,11 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
|
||||
|
||||
if (launchAnimationContainerView)
|
||||
{
|
||||
NSTimeInterval durationMs = [[NSDate date] timeIntervalSinceDate:launchAnimationStart] * 1000;
|
||||
NSLog(@"[AppDelegate] LaunchAnimation was shown for %.3fms", durationMs);
|
||||
NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:launchAnimationStart];
|
||||
NSLog(@"[AppDelegate] LaunchAnimation was shown for %.3fms", duration * 1000);
|
||||
|
||||
// Track it on our analytics
|
||||
[[Analytics sharedInstance] trackLaunchScreenDisplayDuration:duration];
|
||||
|
||||
// TODO: Send durationMs to Piwik
|
||||
// Such information should be the same on all platforms
|
||||
@@ -4086,4 +4021,24 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
|
||||
[self.gdprConsentViewController dismissViewControllerAnimated:YES completion:nil];
|
||||
}
|
||||
|
||||
#pragma mark - Settings
|
||||
|
||||
- (void)setupUserDefaults
|
||||
{
|
||||
// Register "Riot-Defaults.plist" default values
|
||||
NSString* userDefaults = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UserDefaults"];
|
||||
NSString *defaultsPathFromApp = [[NSBundle mainBundle] pathForResource:userDefaults ofType:@"plist"];
|
||||
NSDictionary *defaults = [NSDictionary dictionaryWithContentsOfFile:defaultsPathFromApp];
|
||||
[[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
|
||||
|
||||
// Now use RiotSettings and NSUserDefaults to store `showDecryptedContentInNotifications` setting option
|
||||
// Migrate this information from main MXKAccount to RiotSettings, if value is not in UserDefaults
|
||||
|
||||
if (!RiotSettings.shared.isShowDecryptedContentInNotificationsHasBeenSetOnce)
|
||||
{
|
||||
MXKAccount *currentAccount = [MXKAccountManager sharedManager].activeAccounts.firstObject;
|
||||
RiotSettings.shared.showDecryptedContentInNotifications = currentAccount.showDecryptedContentInNotifications;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -537,3 +537,8 @@
|
||||
"deactivate_account_validate_action" = "Деактивирай акаунта";
|
||||
"deactivate_account_password_alert_title" = "Деактивиране на акаунт";
|
||||
"deactivate_account_password_alert_message" = "За да продължите, моля въведете паролата си";
|
||||
"event_formatter_rerequest_keys_part1_link" = "Изисквай повторно ключове за шифроване";
|
||||
"event_formatter_rerequest_keys_part2" = " от другите ми устройства.";
|
||||
// Re-request confirmation dialog
|
||||
"rerequest_keys_alert_title" = "Заявката е изпратена";
|
||||
"rerequest_keys_alert_message" = "Моля стартирайте Riot на друго устройство можещо да разшифрова съобщението, за да може то да изпрати ключовете до това устройство.";
|
||||
|
||||
@@ -318,7 +318,7 @@
|
||||
"settings_add_phone_number" = "Telefonnummer hinzufügen";
|
||||
"settings_fail_to_update_profile" = "Profilaktualisierung fehlgeschlagen";
|
||||
"settings_global_settings_info" = "Globale Benachrichtungseinstellungen sind verfügbar auf dem %@ Web Client";
|
||||
"settings_pin_rooms_with_missed_notif" = "Pinnen von Räumen mit vepassten Benachrichtigungen";
|
||||
"settings_pin_rooms_with_missed_notif" = "Pinnen von Räumen mit verpassten Benachrichtigungen";
|
||||
"settings_pin_rooms_with_unread" = "Pinnen von Räumen mit ungelesenen Nachrichten";
|
||||
"settings_on_denied_notification" = "Benachrichtigungen verboten für %@, bitte in den Geräte-Einstellungen erlauben";
|
||||
"settings_contacts_discover_matrix_users" = "Entdecke andere Benutzer mittels E-Mail-Adressen oder Telefonnummern";
|
||||
@@ -538,3 +538,8 @@
|
||||
"deactivate_account_validate_action" = "Account deaktiveren";
|
||||
"deactivate_account_password_alert_title" = "Account deaktivieren";
|
||||
"deactivate_account_password_alert_message" = "Zum Fortfahren, Password eingeben";
|
||||
"event_formatter_rerequest_keys_part1_link" = "Verschlüsselungsschlüssel erneut";
|
||||
"event_formatter_rerequest_keys_part2" = " von deinen anderen Geräten anfragen.";
|
||||
// Re-request confirmation dialog
|
||||
"rerequest_keys_alert_title" = "Anfrage gesendet";
|
||||
"rerequest_keys_alert_message" = "Öffne Riot bitte auf einem anderen Gerät, dass die Nachricht entschlüsseln kann, damit es die Schlüssel an dieses Gerät senden kann.";
|
||||
|
||||
@@ -518,6 +518,8 @@
|
||||
"event_formatter_widget_removed" = "%@ widget removed by %@";
|
||||
"event_formatter_jitsi_widget_added" = "VoIP conference added by %@";
|
||||
"event_formatter_jitsi_widget_removed" = "VoIP conference removed by %@";
|
||||
"event_formatter_rerequest_keys_part1_link" = "Re-request encryption keys";
|
||||
"event_formatter_rerequest_keys_part2" = " from your other devices.";
|
||||
|
||||
// Others
|
||||
"or" = "or";
|
||||
@@ -622,3 +624,7 @@
|
||||
|
||||
"deactivate_account_password_alert_title" = "Deactivate Account";
|
||||
"deactivate_account_password_alert_message" = "To continue, please enter your password";
|
||||
|
||||
// Re-request confirmation dialog
|
||||
"rerequest_keys_alert_title" = "Request Sent";
|
||||
"rerequest_keys_alert_message" = "Please launch Riot on another device that can decrypt the message so it can send the keys to this device.";
|
||||
|
||||
@@ -522,3 +522,26 @@
|
||||
// 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";
|
||||
"room_action_send_photo_or_video" = "Bidali argazki edo bideoa";
|
||||
"room_action_send_sticker" = "Bidali eranskailua";
|
||||
"settings_deactivate_account" = "DESAKTIBATU KONTUA";
|
||||
"settings_deactivate_my_account" = "Desaktibatu nire kontua";
|
||||
"widget_sticker_picker_no_stickerpacks_alert" = "Ez duzu orain eranskailu multzo aktiborik.";
|
||||
"widget_sticker_picker_no_stickerpacks_alert_add_now" = "Baten bat gehitu orain?";
|
||||
"deactivate_account_title" = "Desaktibatu kontua";
|
||||
"deactivate_account_informations_part1" = "Honek kontua behin betirako erabilgaitza bihurtuko du. Ezin izango duzu saioa hasi, eta ezin izango du beste inork ID hori erabili. Kontua dagoen gela guztietatik aterako da, eta kontuaren xehetasunak identitate-zerbitzaritik ezabatuko dira. ";
|
||||
"deactivate_account_informations_part2_emphasize" = "Ekintza hau ezin da desegin.";
|
||||
"deactivate_account_informations_part3" = "\n\nZure kontua desaktibatzen ";
|
||||
"deactivate_account_informations_part4_emphasize" = "ez du lehenetsita guk zuk bidalitako mezuak ahaztea eragingo ";
|
||||
"deactivate_account_informations_part5" = "Guk zure mezuak ahaztea nahi baduzu markatu beheko kutxa.\n\nMatrix-eko mezuen ikusgaitasuna e-mail sistemaren antekoa da. Guk zure mezuak ahaztean ez dizkiogu erabiltzaile berriei edo izena eman ez dutenei erakutsiko, baina jada zure mezuak jaso dituzten erregistratutako erabiltzaileen bere kopia izaten jarraituko dute.";
|
||||
"deactivate_account_forget_messages_information_part1" = "Ahaztu bidali ditudan mezu guztiak kontua desaktibatzean (";
|
||||
"deactivate_account_forget_messages_information_part2_emphasize" = "Abisua";
|
||||
"deactivate_account_forget_messages_information_part3" = ": Honekin etorkizuneko erabiltzaileek elkarrizketaren bertsio ez oso bat ikusiko dute)";
|
||||
"deactivate_account_validate_action" = "Desaktibatu kontua";
|
||||
"deactivate_account_password_alert_title" = "Desaktibatu kontua";
|
||||
"deactivate_account_password_alert_message" = "Jarraitzeko sartu zure pasahitza";
|
||||
"event_formatter_rerequest_keys_part1_link" = "Berreskatu zifratze gakoak";
|
||||
"event_formatter_rerequest_keys_part2" = " zure beste gailuetatik.";
|
||||
// Re-request confirmation dialog
|
||||
"rerequest_keys_alert_title" = "Eskaria bidalita";
|
||||
"rerequest_keys_alert_message" = "Abiatu Riot mezua deszifratu dezakeen beste gailuren batean handik hona gakoak bidali ahal izateko.";
|
||||
|
||||
@@ -538,3 +538,8 @@
|
||||
"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";
|
||||
"event_formatter_rerequest_keys_part1_link" = "Redemander les clés de chiffrement";
|
||||
"event_formatter_rerequest_keys_part2" = " depuis vos autres appareils.";
|
||||
// Re-request confirmation dialog
|
||||
"rerequest_keys_alert_title" = "Demande envoyée";
|
||||
"rerequest_keys_alert_message" = "Veuillez lancer Riot sur un autre appareil qui peut déchiffrer le message pour qu'il puisse envoyer les clés sur cet appareil.";
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
"auth_password_dont_match" = "De wachtwoorden komen niet overeen";
|
||||
"auth_username_in_use" = "De gebruikersnaam is al in gebruik";
|
||||
"auth_forgot_password" = "Wachtwoord vergeten?";
|
||||
"auth_use_server_options" = "Gebruik aangepaste server options (geavanceerd)";
|
||||
"auth_use_server_options" = "Gebruik alternatieve serverinstellingen (geavanceerd)";
|
||||
"auth_email_validation_message" = "Bekijk je e-mail om verder te gaan met de registratie";
|
||||
"auth_msisdn_validation_title" = "Verificatie Aanhangig";
|
||||
"auth_msisdn_validation_message" = "We hebben een SMS met een activatie code gestuurd. Vul deze code hieronder in.";
|
||||
@@ -227,7 +227,7 @@
|
||||
"room_event_action_cancel_upload" = "Uploaden annuleren";
|
||||
"room_event_action_cancel_download" = "Downloaden annuleren";
|
||||
"room_event_action_view_encryption" = "Versleutelingsinformatie";
|
||||
"room_warning_about_encryption" = "Eind-tot-eind versleuteling is nog in beta en kan onbetrouwbaar zijn.\n\nHet is beter om het nog niet met gevoelige gegevens te vertrouwen.\n\nApparaten kunnen nog niet de geschiedenis van voordat ze de ruimte betraden kunnen ontsleutelen.\n\nVersleutelde berichten zullen nog niet zichtbaar zijn op applicaties die geen versleuteling ondersteunen.";
|
||||
"room_warning_about_encryption" = "End-to-endbeveiliging is in bèta en kan onbetrouwbaar zijn.\n\nHet is beter om het nog niet met gevoelige gegevens te vertrouwen.\n\nApparaten kunnen de geschiedenis van voordat ze de ruimte betraden nog niet ontsleutelen.\n\nVersleutelde berichten zullen nog niet zichtbaar zijn op programma's die geen versleuteling ondersteunen.";
|
||||
// Unknown devices
|
||||
"unknown_devices_alert_title" = "Ruimte bevat onbekende apparaten";
|
||||
"unknown_devices_alert" = "Deze ruimte bevat onbekende apparaten die niet geen geverifieerd.\nDit betekent dat er geen garantie is dat de apparaten bij de gebruikers horen waar het beweert dat het bij hoort.\nWe raden je aan om bij elk apparaat door het verificatieprocces heen te gaan voordat je doorgaat, maar je kan het bericht opnieuw versturen zonder te verifiëren als je dat prefereert.";
|
||||
@@ -302,7 +302,7 @@
|
||||
"settings_unignore_user" = "Alle berichten van %@ laten zien?";
|
||||
"settings_contacts_discover_matrix_users" = "Gebruik e-mailadressen en telefoonnummers om gebruikers te vinden";
|
||||
"settings_contacts_phonebook_country" = "Telefoonboek land";
|
||||
"settings_labs_e2e_encryption" = "Eind-tot-Eind versleuteling";
|
||||
"settings_labs_e2e_encryption" = "End-to-endbeveiliging";
|
||||
"settings_labs_e2e_encryption_prompt_message" = "Om het opzetten van de versleuteling af te ronden moet je opnieuw inloggen.";
|
||||
"settings_version" = "Versie %@";
|
||||
"settings_olm_version" = "Olm Versie %@";
|
||||
@@ -365,8 +365,8 @@
|
||||
"room_details_advanced_e2e_encryption_enabled" = "Versleuteling staat aan in deze ruimte";
|
||||
"room_details_advanced_e2e_encryption_disabled" = "Versleuteling staat niet aan in deze ruimte.";
|
||||
"room_details_advanced_e2e_encryption_blacklist_unverified_devices" = "Alleen naar geverifieerde apparaten versleutelen";
|
||||
"room_details_advanced_e2e_encryption_prompt_message" = "Eind-tot-eind versleuteling is experimenteel en kan onbetrouwbaar zijn.\n\nHet is beter om het nog niet met gevoelige gegevens te vertrouwen.\n\nApparaten kunnen nog niet de geschiedenis van voordat ze de ruimte betraden kunnen ontsleutelen.\n\nZodra de versleuteling aan staat kan het niet meer worden uitgezet (voor nu).\n\nVersleutelde berichten zullen nog niet zichtbaar zijn op applicaties die geen versleuteling ondersteunen.";
|
||||
"room_details_fail_to_update_avatar" = "Ruimte foto vernieuwen mislukt";
|
||||
"room_details_advanced_e2e_encryption_prompt_message" = "End-to-endbeveiliging is experimenteel en kan onbetrouwbaar zijn.\n\nHet is beter om het nog niet met gevoelige gegevens te vertrouwen.\n\nApparaten kunnen de geschiedenis van voordat ze de ruimte betraden nog niet ontsleutelen.\n\nZodra de versleuteling aan staat kan het (voorlopig) niet worden uitgezet.\n\nVersleutelde berichten zullen nog niet zichtbaar zijn op programma's die geen versleuteling ondersteunen.";
|
||||
"room_details_fail_to_update_avatar" = "Ruimte-foto vernieuwen mislukt";
|
||||
"room_details_fail_to_update_room_name" = "Ruimtenaam vernieuwen mislukt";
|
||||
"room_details_fail_to_update_topic" = "Ruimteonderwerp vernieuwen mislukt";
|
||||
"room_details_fail_to_update_room_guest_access" = "Ruimte's gast toegang vernieuwen mislukt";
|
||||
@@ -420,7 +420,7 @@
|
||||
"google_analytics_use_prompt" = "Wil je helpen met het verbeteren van %@ bij het automatisch rapporteren van crash rapporten en data van gebruik?";
|
||||
// Crypto
|
||||
"e2e_enabling_on_app_update" = "Riot ondersteunt nu eind-tot-eind sleuteling maar je moet opnieuw inloggen om het aan te zetten.\n\nJe kan het nu of later doen vanaf de applicatie instellingen.";
|
||||
"e2e_need_log_in_again" = "Je moet opnieuw inloggen om eind-tot-eind versleuteling sleutels te genereren voor dit apparaat en om de publieke sleutel naar de thuisserver te sturen.\nDit is eenmalig; excuses voor het ongemak.";
|
||||
"e2e_need_log_in_again" = "Je moet opnieuw inloggen om end-to-endbeveligingssleutels te genereren voor dit apparaat en om de publieke sleutel naar de thuisserver te sturen.\nDit is eenmalig; excuses voor het ongemak.";
|
||||
// Bug report
|
||||
"bug_report_title" = "Foutmelding";
|
||||
"bug_report_description" = "Beschrijf de foutmelding. Wat heb je gedaan? Wat verwachte je dat er zou gebeuren? Wat gebeurde er werkelijk?";
|
||||
@@ -546,3 +546,26 @@
|
||||
// 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";
|
||||
"room_action_send_photo_or_video" = "Foto of video versturen";
|
||||
"room_action_send_sticker" = "Sticker versturen";
|
||||
"settings_deactivate_account" = "DEACTIVEER ACCOUNT";
|
||||
"deactivate_account_forget_messages_information_part2_emphasize" = "Waarschuwing";
|
||||
// Re-request confirmation dialog
|
||||
"rerequest_keys_alert_title" = "Aanvraag verstuurd";
|
||||
"rerequest_keys_alert_message" = "Start Riot alstublieft op een ander apparaat dat het bericht kan ontsleutelen zodat deze de sleutels kan sturen naar dit apparaat.";
|
||||
"settings_deactivate_my_account" = "Account deactiveren";
|
||||
"event_formatter_rerequest_keys_part1_link" = "Vraag beveiligingssleutels opnieuw aan";
|
||||
"event_formatter_rerequest_keys_part2" = " van je andere apparaten.";
|
||||
"widget_sticker_picker_no_stickerpacks_alert" = "Je hebt momenteel geen stickerpakketten aan staan.";
|
||||
"widget_sticker_picker_no_stickerpacks_alert_add_now" = "Wil je er nu een paar toevoegen?";
|
||||
"deactivate_account_title" = "Account deactiveren";
|
||||
"deactivate_account_informations_part1" = "Dit zal je account voorgoed onbruikbaar maken. Je zal niet meer in kunnen loggen en niemand anders zal met dezelfde gebruikers ID kunnen registreren. Dit zal er voor zorgen dat je account alle ruimtes verlaat waar het momenteel onderdeel van is en het verwijderd de accountgegevens van de identiteitsserver. ";
|
||||
"deactivate_account_informations_part2_emphasize" = "Deze actie is onomkeerbaar.";
|
||||
"deactivate_account_informations_part3" = "\n\nHet deactiveren van je account ";
|
||||
"deactivate_account_informations_part4_emphasize" = "zal er niet standaard voor zorgen dat de berichten die je verzonden hebt vergeten worden. ";
|
||||
"deactivate_account_informations_part5" = "Als je wilt dat wij de berichten vergeten, klikt alsjeblieft op het vakje hieronder.\n\nDe zichtbaarheid van berichten in Matrix is hetzelfde als in e-mail. Het vergeten van je berichten betekent dat berichten die je hebt verstuurd niet meer gedeeld worden met nieuwe of ongeregistreerde gebruikers, maar geregistreerde gebruikers die al toegang hebben tot deze berichten zullen alsnog toegang hebben tot hun eigen kopie van het bericht.";
|
||||
"deactivate_account_forget_messages_information_part1" = "Vergeet alle berichten die ik heb verstuurd wanneer mijn account gedeactiveerd is (";
|
||||
"deactivate_account_forget_messages_information_part3" = ": dit zal er voor zorgen dat toekomstige gebruikers een incompleet beeld krijgen van gesprekken)";
|
||||
"deactivate_account_validate_action" = "Account deactiveren";
|
||||
"deactivate_account_password_alert_title" = "Account deactiveren";
|
||||
"deactivate_account_password_alert_message" = "Voer je wachtwoord in om verder te gaan";
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
// Permissions usage explanations
|
||||
"NSCameraUsageDescription" = "A câmera será usada para tomar fotos e vídeos, e também para a realização de chamadas de vídeo.";
|
||||
"NSPhotoLibraryUsageDescription" = "A galeria de fotos é usada para o envio de fotos e vídeos.";
|
||||
"NSMicrophoneUsageDescription" = "O microfone é usado para gravar vídeos e fazer chamadas, tanto de áudio como de vídeo.";
|
||||
"NSContactsUsageDescription" = "O cadernos de contatos é usado para fazer busca de usuárias/os no Riot a partir do e-mail ou do número de telefone.";
|
||||
@@ -0,0 +1,52 @@
|
||||
/* New message from a specific person, not referencing a room */
|
||||
"MSG_FROM_USER" = "Mensagem de %@";
|
||||
/* New message from a specific person in a named room */
|
||||
"MSG_FROM_USER_IN_ROOM" = "%@ enviou mensagem em %@";
|
||||
/* 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" = "%@ em %@: %@";
|
||||
/* 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" = "%@ enviou a você uma imagem %@";
|
||||
/* New action message from a specific person in a named room. */
|
||||
"IMAGE_FROM_USER_IN_ROOM" = "%@ enviou uma imagem %@ na sala %@";
|
||||
/* A single unread message in a room */
|
||||
"SINGLE_UNREAD_IN_ROOM" = "Você recebeu uma mensagem na sala %@";
|
||||
/* A single unread message */
|
||||
"SINGLE_UNREAD" = "Você recebeu uma mensagem";
|
||||
/* Multiple unread messages in a room */
|
||||
"UNREAD_IN_ROOM" = "%@ novas mensagens na sala %@";
|
||||
/* Multiple unread messages from a specific person, not referencing a room */
|
||||
"MSGS_FROM_USER" = "%@ novas mensagens de %@";
|
||||
/* Multiple unread messages from two people */
|
||||
"MSGS_FROM_TWO_USERS" = "%@ novas mensagens de %@ e %@";
|
||||
/* Multiple unread messages from three people */
|
||||
"MSGS_FROM_THREE_USERS" = "%@ novas mensagens de %@, %@ e %@";
|
||||
/* Multiple unread messages from two plus people (ie. for 4+ people: 'others' replaces the third person) */
|
||||
"MSGS_FROM_TWO_PLUS_USERS" = "%@ novas mensagens de %@, %@ e outras/os";
|
||||
/* Multiple messages in two rooms */
|
||||
"MSGS_IN_TWO_ROOMS" = "%@ novas mensagens nas salas %@ e %@";
|
||||
/* Look, stuff's happened, alright? Just open the app. */
|
||||
"MSGS_IN_TWO_PLUS_ROOMS" = "%@ novas mensagens nas salas %@ e %@, dentre outras";
|
||||
/* A user has invited you to a chat */
|
||||
"USER_INVITE_TO_CHAT" = "%@ convidou você para conversar";
|
||||
/* A user has invited you to an (unamed) group chat */
|
||||
"USER_INVITE_TO_CHAT_GROUP_CHAT" = "%@ convidou você para uma conversa em grupo";
|
||||
/* A user has invited you to a named room */
|
||||
"USER_INVITE_TO_NAMED_ROOM" = "%@ convidou você para a sala %@";
|
||||
/* Incoming one-to-one voice call */
|
||||
"VOICE_CALL_FROM_USER" = "Chamada de %@";
|
||||
/* Incoming one-to-one video call */
|
||||
"VIDEO_CALL_FROM_USER" = "Chamada de vídeo de %@";
|
||||
/* Incoming unnamed voice conference invite from a specific person */
|
||||
"VOICE_CONF_FROM_USER" = "Chamada coletiva de %@";
|
||||
/* Incoming unnamed video conference invite from a specific person */
|
||||
"VIDEO_CONF_FROM_USER" = "Vídeo-chamada coletiva de %@";
|
||||
/* Incoming named voice conference invite from a specific person */
|
||||
"VOICE_CONF_NAMED_FROM_USER" = "Vídeo chamada coletiva de %@: '%@'";
|
||||
/* Incoming named video conference invite from a specific person */
|
||||
"VIDEO_CONF_NAMED_FROM_USER" = "Vídeo-chamada coletiva de %@: '%@'";
|
||||
@@ -0,0 +1,156 @@
|
||||
// Titles
|
||||
"title_home" = "Início";
|
||||
"title_favourites" = "Favoritos";
|
||||
"title_people" = "Pessoas";
|
||||
"title_rooms" = "Salas";
|
||||
"title_groups" = "Comunidades";
|
||||
"warning" = "Atenção";
|
||||
// Actions
|
||||
"view" = "Ver";
|
||||
"next" = "Próximo";
|
||||
"back" = "Voltar";
|
||||
"continue" = "Continuar";
|
||||
"create" = "Criar";
|
||||
"start" = "Iniciar";
|
||||
"leave" = "Sair";
|
||||
"remove" = "Remover";
|
||||
"invite" = "Convidar";
|
||||
"retry" = "Tentar novamente";
|
||||
"on" = "Ativado";
|
||||
"off" = "Desativado";
|
||||
"cancel" = "Cancelar";
|
||||
"save" = "Salvar";
|
||||
"join" = "Entrar";
|
||||
"decline" = "Recusar";
|
||||
"accept" = "Aceitar";
|
||||
"preview" = "Pré-visualização";
|
||||
"camera" = "Câmera";
|
||||
"voice" = "Voz";
|
||||
"video" = "Vídeo";
|
||||
"active_call" = "Chamada em andamento";
|
||||
"active_call_details" = "Chamada em andamento (%@)";
|
||||
"later" = "Mais tarde";
|
||||
"rename" = "Renomear";
|
||||
"collapse" = "reduzir";
|
||||
"send_to" = "Enviar para %@";
|
||||
"sending" = "Enviando";
|
||||
// Authentication
|
||||
"auth_login" = "Fazer login";
|
||||
"auth_register" = "Criar nova conta";
|
||||
"auth_submit" = "Enviar";
|
||||
"auth_skip" = "Ignorar";
|
||||
"auth_send_reset_email" = "Enviar e-mail de redefinição de senha";
|
||||
"auth_return_to_login" = "Voltar à tela de login";
|
||||
"auth_user_id_placeholder" = "E-mail ou nome de usuária/o";
|
||||
"auth_password_placeholder" = "Senha";
|
||||
"auth_new_password_placeholder" = "Nova senha";
|
||||
"auth_user_name_placeholder" = "Nome de usuária/o";
|
||||
"auth_optional_email_placeholder" = "Endereço de e-mail (opcional)";
|
||||
"auth_email_placeholder" = "Endereço de e-mail";
|
||||
"auth_optional_phone_placeholder" = "Número de telefone (opcional)";
|
||||
"auth_phone_placeholder" = "Número de telefone";
|
||||
"auth_repeat_password_placeholder" = "Repita a senha";
|
||||
"auth_repeat_new_password_placeholder" = "Confirme sua nova senha";
|
||||
"auth_home_server_placeholder" = "URL (p.ex. https://matrix.org)";
|
||||
"auth_identity_server_placeholder" = "URL (p.ex. https://matrix.org)";
|
||||
"auth_invalid_login_param" = "Nome de usuária/o e/ou senha incorretos";
|
||||
"auth_invalid_user_name" = "Nomes de usuária/o podem apenas conter letras, números, pontos, hífen e linha de sublinhar";
|
||||
"auth_invalid_password" = "Senha muito curta (mín. 6 letras)";
|
||||
"auth_invalid_email" = "O endereço de e-mail não parece válido";
|
||||
"auth_invalid_phone" = "O número de telefone não parece válido";
|
||||
"auth_missing_password" = "Falta a senha";
|
||||
"auth_add_email_message" = "Adicione um endereço de e-mail para a sua conta para permitir que outras pessoas possam te achar, e também para que você possa redefinir sua senha.";
|
||||
"auth_add_phone_message" = "Adicione um número de telefone à sua conta para permitir que outras pessoas te encontrem.";
|
||||
"auth_add_email_phone_message" = "Adicione um endereço de e-mail e/ou um telefone à sua conta para permitir que outras pessoas encontrem você. O endereço de e-mail também permite que você redefina a sua senha.";
|
||||
"auth_add_email_and_phone_message" = "Adicione um endereço de e-mail e um telefone à sua conta para permitir que outras pessoas encontrem você. O endereço de e-mail também permite que você redefina a sua senha.";
|
||||
"auth_missing_email" = "Falta o endereço de e-mail";
|
||||
"auth_missing_phone" = "Falta o número de telefone";
|
||||
"auth_missing_email_or_phone" = "Falta o endereço de e-mail ou o número de telefone";
|
||||
"auth_email_in_use" = "Este endereço de e-mail já está sendo usado por outra pessoa";
|
||||
"auth_phone_in_use" = "Este número de telefone já está sendo usado por outra pessoa";
|
||||
"auth_untrusted_id_server" = "Este servidor de identidades não é confiável";
|
||||
"auth_password_dont_match" = "As senhas não são iguais";
|
||||
"auth_username_in_use" = "Este nome de usuária/o já está sendo usado por outra pessoa";
|
||||
"auth_forgot_password" = "Esqueceu sua senha?";
|
||||
"auth_email_not_found" = "Não consegui enviar e-mail: este endereço de e-mail não foi encontrado";
|
||||
"auth_use_server_options" = "Usar opções personalizadas de servidor (avançado)";
|
||||
"auth_email_validation_message" = "Por favor, verifique o seu e-mail para continuar seu cadastro";
|
||||
"auth_msisdn_validation_title" = "Faltando verificação";
|
||||
"auth_msisdn_validation_message" = "Nós enviamos um SMS com um código de ativação. Por favor, coloque abaixo este código.";
|
||||
"auth_msisdn_validation_error" = "Não foi possível verificar o número de telefone.";
|
||||
"auth_recaptcha_message" = "Este Servidor de Base (Home Server) quer ter certeza que você não é um robô";
|
||||
"auth_reset_password_message" = "Para redefinir sua senha, coloque o endereço de e-mail relacionado à sua conta:";
|
||||
"auth_reset_password_missing_email" = "O endereço de e-mail relacionado à sua conta tem que ser inserido.";
|
||||
"auth_reset_password_missing_password" = "Uma nova senha tem que ser inserida.";
|
||||
"auth_reset_password_email_validation_message" = "Um e-mail foi enviado para %@. Quando você clicar no link do e-mail, clique abaixo.";
|
||||
"auth_reset_password_next_step_button" = "Eu verifiquei meu endereço de e-mail";
|
||||
"auth_reset_password_error_unauthorized" = "Não foi possível verificar o endereço de e-mail: confirme que realmente clicou no link contido na mensagem de e-mail";
|
||||
"auth_reset_password_error_not_found" = "O seu endereço de e-mail não parece estar associado a um ID Matrix neste Servidor de Base (Home Server).";
|
||||
"auth_reset_password_success_message" = "Sua senha foi redefinida.\n\nVocê foi deslogado de todos os dispositivos e não receberá notificações. Para reativar as notificações, faça login novamente em cada um dos dispositivos.";
|
||||
"auth_add_email_and_phone_warning" = "Registro com email e número de telefone ainda não é suportado enquanto existir a API. Apenas o número de telefone será associado a sua conta. Você pode adicionar seu email ao seu perfil nas configurações.";
|
||||
"room_creation_appearance" = "Aparência";
|
||||
"room_creation_appearance_name" = "Nome";
|
||||
"room_creation_appearance_picture" = "Imagem da Sala (opcional)";
|
||||
"room_creation_privacy" = "Privacidade";
|
||||
"room_creation_private_room" = "Esta conversa é privada";
|
||||
"room_creation_public_room" = "Esta conversa é pública";
|
||||
"room_creation_make_public" = "Tornar público";
|
||||
"room_creation_make_public_prompt_title" = "Tornar esta conversa pública?";
|
||||
"room_creation_make_public_prompt_msg" = "Você tem certeza que deseja tornar esta conversa pública? Qualquer um poderá ler suas mensagens e entrar na conversa.";
|
||||
"room_creation_keep_private" = "Manter privada";
|
||||
"room_creation_make_private" = "Manter privada";
|
||||
"room_creation_wait_for_creation" = "A sala já está sendo criada. Por favor aguarde.";
|
||||
"room_creation_invite_another_user" = "Procurar / convidar por ID da usuária/o, Nome ou email";
|
||||
"room_recents_directory_section_network" = "Rede";
|
||||
"room_recents_favourites_section" = "FAVORITOS";
|
||||
"room_recents_people_section" = "PESSOAS";
|
||||
"room_recents_conversations_section" = "SALAS";
|
||||
"room_recents_no_conversation" = "Nenhuma sala";
|
||||
"room_recents_low_priority_section" = "BAIXA PRIORIDADE";
|
||||
"room_recents_invites_section" = "CONVITES";
|
||||
"room_recents_start_chat_with" = "Iniciar conversa";
|
||||
"room_recents_create_empty_room" = "Criar sala";
|
||||
"room_recents_join_room" = "Entrar na sala";
|
||||
"room_recents_join_room_title" = "Entrar na sala";
|
||||
"room_recents_join_room_prompt" = "Digite o id da sala ou o nome da sala";
|
||||
// People tab
|
||||
"people_invites_section" = "CONVITES";
|
||||
"people_conversation_section" = "CONVERSAS";
|
||||
"people_no_conversation" = "Nenhuma conversa";
|
||||
// Rooms tab
|
||||
"room_directory_no_public_room" = "Não existem salas públicas disponíveis";
|
||||
// Groups tab
|
||||
"group_invite_section" = "CONVITES";
|
||||
"group_section" = "Comunidades";
|
||||
// Search
|
||||
"search_rooms" = "Salas";
|
||||
"search_messages" = "Mensagens";
|
||||
"search_people" = "Pessoas";
|
||||
"search_files" = "Arquivos";
|
||||
"search_default_placeholder" = "Procurar";
|
||||
"search_people_placeholder" = "Procurar por ID da/o usuária/o, Nome ou email";
|
||||
"search_no_result" = "Nenhum resultado";
|
||||
"search_in_progress" = "Procurando…";
|
||||
// Directory
|
||||
"directory_cell_title" = "Procurar no diretório";
|
||||
"directory_cell_description" = "%tu salas";
|
||||
"directory_search_results" = "%tu resultados encontrados para %@";
|
||||
"directory_search_results_more_than" = ">%tu resultados encontrados para %@";
|
||||
"directory_searching_title" = "Procurando no diretório…";
|
||||
// Contacts
|
||||
"contacts_address_book_section" = "CONTATOS LOCAIS";
|
||||
"contacts_address_book_matrix_users_toggle" = "Apenas usuários Matrix";
|
||||
"contacts_address_book_no_contact" = "Nenhum contato local";
|
||||
"contacts_address_book_permission_required" = "É preciso autorização para acessar contatos locais";
|
||||
"contacts_address_book_permission_denied" = "Você não permitiu o Riot acessar seus contatos locais";
|
||||
"contacts_user_directory_section" = "DIRETÓRIO DE USUÁRIOS";
|
||||
"contacts_user_directory_offline_section" = "DIRETÓRIO DE USUÁRIOS (sem conexão)";
|
||||
// Chat participants
|
||||
"room_participants_title" = "Participantes";
|
||||
"room_participants_add_participant" = "Adicionar participantes";
|
||||
"room_participants_one_participant" = "1 participante";
|
||||
"room_participants_multi_participants" = "%d participantes";
|
||||
"room_participants_leave_prompt_title" = "Sair da sala";
|
||||
"room_participants_leave_prompt_msg" = "Você tem certeza que deseja sair da sala?";
|
||||
"room_participants_remove_prompt_title" = "Confirmação";
|
||||
"room_participants_remove_prompt_msg" = "Você tem certeza que deseja remover %@ desta conversa?";
|
||||
@@ -539,3 +539,8 @@
|
||||
"deactivate_account_password_alert_title" = "Деактивировать аккаунт";
|
||||
"deactivate_account_password_alert_message" = "Чтобы продолжить, введите пароль";
|
||||
"widget_sticker_picker_no_stickerpacks_alert" = "У вас пока нет включенных пакетов стикеров.";
|
||||
"event_formatter_rerequest_keys_part1_link" = "Повторно запросить ключи шифрования";
|
||||
"event_formatter_rerequest_keys_part2" = " с других устройств.";
|
||||
// Re-request confirmation dialog
|
||||
"rerequest_keys_alert_title" = "Запрос отправлен";
|
||||
"rerequest_keys_alert_message" = "Запустите Riot на другом устройстве, которое может расшифровать сообщение, чтобы оно могло отправить ключи этому устройству.";
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="H1p-Uh-vWS">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14113" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="H1p-Uh-vWS">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13527"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
|
||||
<capability name="Navigation items with more than one left or right bar item" minToolsVersion="7.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
@@ -51,7 +51,7 @@
|
||||
<segue destination="e7G-NU-7ck" kind="show" identifier="showRoomDetails" id="vCz-dl-6xQ"/>
|
||||
<segue destination="KDg-aD-xlK" kind="show" identifier="showRoomSearch" id="hdA-V1-9AF"/>
|
||||
<segue destination="nDS-pp-sWM" kind="show" identifier="showMemberDetails" id="cUw-vU-gJq"/>
|
||||
<segue destination="gkO-rP-nGK" kind="show" identifier="showContactDetails" action="showDetailViewController:sender:" id="f5u-Y1-7nt"/>
|
||||
<segue destination="gkO-rP-nGK" kind="show" identifier="showContactDetails" id="f5u-Y1-7nt"/>
|
||||
<segue destination="ZZb-IS-a1F" kind="presentation" identifier="showUnknownDevices" id="wUx-4y-ybn"/>
|
||||
<segue destination="udm-55-AMb" kind="show" identifier="showContactPicker" id="Q6y-9M-Ugl"/>
|
||||
</connections>
|
||||
@@ -247,7 +247,7 @@
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<tabBarItem key="tabBarItem" image="tab_home.png" selectedImage="tab_home_selected.png" id="hNI-yH-EXj">
|
||||
<tabBarItem key="tabBarItem" title="" image="tab_home.png" selectedImage="tab_home_selected.png" id="hNI-yH-EXj">
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="accessibilityIdentifier" value="TabBarItemHome"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
@@ -608,7 +608,7 @@
|
||||
<image name="tab_rooms.png" width="25" height="25"/>
|
||||
</resources>
|
||||
<inferredMetricsTieBreakers>
|
||||
<segue reference="bwO-oZ-2vj"/>
|
||||
<segue reference="mhb-l9-pM3"/>
|
||||
<segue reference="fIR-e3-ssz"/>
|
||||
<segue reference="f5u-Y1-7nt"/>
|
||||
<segue reference="vCz-dl-6xQ"/>
|
||||
|
||||
+2
-2
@@ -17,11 +17,11 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.6.17</string>
|
||||
<string>0.6.18</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.6.17</string>
|
||||
<string>0.6.18</string>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
<true/>
|
||||
<key>ITSEncryptionExportComplianceCode</key>
|
||||
|
||||
@@ -34,10 +34,6 @@ typedef NS_ENUM(NSInteger, RoomBubbleCellDataTag)
|
||||
*/
|
||||
@property(nonatomic) BOOL containsLastMessage;
|
||||
|
||||
/**
|
||||
A Boolean value that determines whether some read receipts are currently displayed in this bubble.
|
||||
*/
|
||||
@property(nonatomic) BOOL hasReadReceipts;
|
||||
|
||||
/**
|
||||
The event id of the current selected event inside the bubble. Default is nil.
|
||||
|
||||
@@ -48,12 +48,11 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
|
||||
// Increase maximum number of components
|
||||
self.maxComponentCount = 20;
|
||||
|
||||
// Initialize receipts flag
|
||||
_hasReadReceipts = NO;
|
||||
|
||||
// Force the update of the text message to take into account the potential read receipts in the bubble display.
|
||||
// Note: we don't update this attributed string here because the RoomBubbleCellData instances are created on a processing
|
||||
// thread different from the UI thread.
|
||||
// Initialize read receipts
|
||||
self.readReceipts = [NSMutableDictionary dictionary];
|
||||
self.readReceipts[event.eventId] = [roomDataSource.room getEventReceipts:event.eventId sorted:YES];
|
||||
|
||||
// Reset attributedTextMessage to force reset MXKRoomCellData parameters
|
||||
self.attributedTextMessage = nil;
|
||||
}
|
||||
|
||||
@@ -79,7 +78,6 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
|
||||
[self refreshBubbleComponentsPosition];
|
||||
}
|
||||
|
||||
|
||||
shouldUpdateComponentsPosition = NO;
|
||||
}
|
||||
}
|
||||
@@ -163,9 +161,6 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
|
||||
|
||||
NSMutableAttributedString *currentAttributedTextMsg;
|
||||
|
||||
// Refresh the receipt flag during this process
|
||||
_hasReadReceipts = NO;
|
||||
|
||||
NSInteger selectedComponentIndex = self.selectedComponentIndex;
|
||||
NSInteger lastMessageIndex = self.containsLastMessage ? self.mostRecentComponentIndex : NSNotFound;
|
||||
|
||||
@@ -203,11 +198,10 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
|
||||
// Init attributed string with the first text component
|
||||
currentAttributedTextMsg = [[NSMutableAttributedString alloc] initWithAttributedString:componentString];
|
||||
}
|
||||
|
||||
// Vertical whitespace is added in case of read receipts
|
||||
if ([roomDataSource.room getEventReceipts:component.event.eventId sorted:NO])
|
||||
|
||||
if (self.readReceipts[component.event.eventId].count)
|
||||
{
|
||||
_hasReadReceipts = YES;
|
||||
// Add vertical whitespace in case of read receipts
|
||||
[currentAttributedTextMsg appendAttributedString:[RoomBubbleCellData readReceiptVerticalWhitespace]];
|
||||
}
|
||||
|
||||
@@ -246,10 +240,9 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
|
||||
// Append attributed text
|
||||
[currentAttributedTextMsg appendAttributedString:componentString];
|
||||
|
||||
// Add vertical whitespace in case of read receipts
|
||||
if ([roomDataSource.room getEventReceipts:component.event.eventId sorted:NO])
|
||||
if (self.readReceipts[component.event.eventId].count)
|
||||
{
|
||||
_hasReadReceipts = YES;
|
||||
// Add vertical whitespace in case of read receipts
|
||||
[currentAttributedTextMsg appendAttributedString:[RoomBubbleCellData readReceiptVerticalWhitespace]];
|
||||
}
|
||||
}
|
||||
@@ -262,14 +255,13 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
|
||||
{
|
||||
// CAUTION: This method must be called on the main thread.
|
||||
|
||||
// Refresh the receipt flag during this process.
|
||||
_hasReadReceipts = NO;
|
||||
|
||||
@synchronized(bubbleComponents)
|
||||
{
|
||||
// Check whether there is at least one component.
|
||||
if (bubbleComponents.count)
|
||||
{
|
||||
BOOL hasReadReceipts = NO;
|
||||
|
||||
// Set position of the first component
|
||||
CGFloat positionY = (self.attachment == nil || self.attachment.type == MXKAttachmentTypeFile || self.attachment.type == MXKAttachmentTypeAudio) ? MXKROOMBUBBLECELLDATA_TEXTVIEW_DEFAULT_VERTICAL_INSET : 0;
|
||||
MXKRoomBubbleComponent *component;
|
||||
@@ -283,7 +275,7 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
|
||||
|
||||
if (component.attributedTextMessage)
|
||||
{
|
||||
_hasReadReceipts = ([roomDataSource.room getEventReceipts:component.event.eventId sorted:NO] != nil);
|
||||
hasReadReceipts = (self.readReceipts[component.event.eventId].count > 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -308,7 +300,7 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
|
||||
}
|
||||
|
||||
// Vertical whitespace is added in case of read receipts
|
||||
if (_hasReadReceipts)
|
||||
if (hasReadReceipts)
|
||||
{
|
||||
[attributedString appendAttributedString:[RoomBubbleCellData readReceiptVerticalWhitespace]];
|
||||
}
|
||||
@@ -348,9 +340,8 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
|
||||
component.position = CGPointMake(0, positionY);
|
||||
|
||||
// Add vertical whitespace in case of read receipts.
|
||||
if ([roomDataSource.room getEventReceipts:component.event.eventId sorted:NO])
|
||||
if (self.readReceipts[component.event.eventId].count)
|
||||
{
|
||||
_hasReadReceipts = YES;
|
||||
[attributedString appendAttributedString:[RoomBubbleCellData readReceiptVerticalWhitespace]];
|
||||
}
|
||||
|
||||
@@ -379,19 +370,6 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setHasReadReceipts:(BOOL)hasReadReceipts
|
||||
{
|
||||
// Check whether there is something to do
|
||||
if (_hasReadReceipts || hasReadReceipts)
|
||||
{
|
||||
// Update flag
|
||||
_hasReadReceipts = hasReadReceipts;
|
||||
|
||||
// Recompute the text message layout
|
||||
self.attributedTextMessage = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setSelectedEventId:(NSString *)selectedEventId
|
||||
{
|
||||
// Check whether there is something to do
|
||||
@@ -517,6 +495,9 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Update read receipts for this bubble
|
||||
self.readReceipts[event.eventId] = [roomDataSource.room getEventReceipts:event.eventId sorted:YES];
|
||||
|
||||
return [super addEvent:event andRoomState:roomState];
|
||||
}
|
||||
|
||||
|
||||
@@ -96,24 +96,102 @@
|
||||
|
||||
- (void)didReceiveReceiptEvent:(MXEvent *)receiptEvent roomState:(MXRoomState *)roomState
|
||||
{
|
||||
// Override this callback to force rendering of each cell with read receipts information.
|
||||
@synchronized(bubbles)
|
||||
{
|
||||
for (RoomBubbleCellData *cellData in bubbles)
|
||||
// Do the processing on the same processing queue as MXKRoomDataSource
|
||||
dispatch_async(MXKRoomDataSource.processingQueue, ^{
|
||||
|
||||
// Remove the previous displayed read receipt for each user who sent a
|
||||
// new read receipt.
|
||||
// To implement it, we need to find the sender id of each new read receipt
|
||||
// among the read receipts array of all events in all bubbles.
|
||||
NSMutableArray *readReceiptSenders = [receiptEvent.readReceiptSenders mutableCopy];
|
||||
|
||||
@synchronized(bubbles)
|
||||
{
|
||||
cellData.hasReadReceipts = NO;
|
||||
NSMutableDictionary<NSString* /* eventId */, NSArray<MXReceiptData*> *> *updatedCellDataReadReceipts = [NSMutableDictionary dictionary];
|
||||
for (RoomBubbleCellData *cellData in bubbles)
|
||||
{
|
||||
for (NSString *eventId in cellData.readReceipts)
|
||||
{
|
||||
for (MXReceiptData *receiptData in cellData.readReceipts[eventId])
|
||||
{
|
||||
NSMutableArray *foundSenders = [NSMutableArray array];
|
||||
for (NSString *senderId in readReceiptSenders)
|
||||
{
|
||||
if ([receiptData.userId isEqualToString:senderId])
|
||||
{
|
||||
// We find an existing displayed receipt, remove it
|
||||
[foundSenders addObject:senderId];
|
||||
|
||||
if (!updatedCellDataReadReceipts[eventId])
|
||||
{
|
||||
updatedCellDataReadReceipts[eventId] = cellData.readReceipts[eventId];
|
||||
}
|
||||
|
||||
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"userId!=%@", receiptData.userId];
|
||||
updatedCellDataReadReceipts[eventId] = [updatedCellDataReadReceipts[eventId] filteredArrayUsingPredicate:predicate];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// As there is one (the last) read receipt displayed per user,
|
||||
// we do not need to search for other read receipts of found users.
|
||||
[readReceiptSenders removeObjectsInArray:foundSenders];
|
||||
if (!readReceiptSenders.count)
|
||||
{
|
||||
// All senders have been found
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Flush found changed to the cell data
|
||||
for (NSString *eventId in updatedCellDataReadReceipts)
|
||||
{
|
||||
if (updatedCellDataReadReceipts[eventId].count)
|
||||
{
|
||||
cellData.readReceipts[eventId] = updatedCellDataReadReceipts[eventId];
|
||||
}
|
||||
else
|
||||
{
|
||||
cellData.readReceipts[eventId] = nil;
|
||||
}
|
||||
}
|
||||
|
||||
if (!readReceiptSenders.count)
|
||||
{
|
||||
// All senders have been found
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NSArray *readEventIds = receiptEvent.readReceiptEventIds;
|
||||
for (NSString* eventId in readEventIds)
|
||||
{
|
||||
RoomBubbleCellData *cellData = [self cellDataOfEventWithEventId:eventId];
|
||||
// Ignore the read receipts on the events without an actual display.
|
||||
cellData.hasReadReceipts = !cellData.hasNoDisplay;
|
||||
}
|
||||
|
||||
[super didReceiveReceiptEvent:receiptEvent roomState:roomState];
|
||||
|
||||
// Update cell data we have received a read receipt for
|
||||
NSArray *readEventIds = receiptEvent.readReceiptEventIds;
|
||||
for (NSString* eventId in readEventIds)
|
||||
{
|
||||
RoomBubbleCellData *cellData = [self cellDataOfEventWithEventId:eventId];
|
||||
if (cellData)
|
||||
{
|
||||
@synchronized(bubbles)
|
||||
{
|
||||
if (!cellData.hasNoDisplay)
|
||||
{
|
||||
cellData.readReceipts[eventId] = [self.room getEventReceipts:eventId sorted:YES];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ignore the read receipts on the events without an actual display.
|
||||
cellData.readReceipts[eventId] = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
// TODO: Be smarter and update only updated cells
|
||||
[super didReceiveReceiptEvent:receiptEvent roomState:roomState];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
@@ -181,7 +259,7 @@
|
||||
// Handle read receipts and read marker display.
|
||||
// Ignore the read receipts on the bubble without actual display.
|
||||
// Ignore the read receipts on collapsed bubbles
|
||||
if ((self.showBubbleReceipts && cellData.hasReadReceipts && !isCollapsableCellCollapsed) || self.showReadMarker)
|
||||
if ((self.showBubbleReceipts && cellData.readReceipts.count && !isCollapsableCellCollapsed) || self.showReadMarker)
|
||||
{
|
||||
// Read receipts container are inserted here on the right side into the content view.
|
||||
// Some vertical whitespaces are added in message text view (see RoomBubbleCellData class) to insert correctly multiple receipts.
|
||||
@@ -194,10 +272,10 @@
|
||||
if (component.event.sentState != MXEventSentStateFailed)
|
||||
{
|
||||
// Handle read receipts (if any)
|
||||
if (self.showBubbleReceipts && cellData.hasReadReceipts && !isCollapsableCellCollapsed)
|
||||
if (self.showBubbleReceipts && cellData.readReceipts.count && !isCollapsableCellCollapsed)
|
||||
{
|
||||
// Get the events receipts by ignoring the current user receipt.
|
||||
NSArray* receipts = [self.room getEventReceipts:component.event.eventId sorted:YES];
|
||||
NSArray* receipts = cellData.readReceipts[component.event.eventId];
|
||||
NSMutableArray *roomMembers;
|
||||
NSMutableArray *placeholders;
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
#import "Riot-Swift.h"
|
||||
|
||||
#define RECENTSDATASOURCE_SECTION_DIRECTORY 0x01
|
||||
#define RECENTSDATASOURCE_SECTION_INVITES 0x02
|
||||
#define RECENTSDATASOURCE_SECTION_FAVORITES 0x04
|
||||
@@ -1193,8 +1195,8 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
|
||||
if (_recentsDataSourceMode == RecentsDataSourceModeHome)
|
||||
{
|
||||
BOOL pinMissedNotif = [[NSUserDefaults standardUserDefaults] boolForKey:@"pinRoomsWithMissedNotif"];
|
||||
BOOL pinUnread = [[NSUserDefaults standardUserDefaults] boolForKey:@"pinRoomsWithUnread"];
|
||||
BOOL pinMissedNotif = RiotSettings.shared.pinRoomsWithMissedNotificationsOnHome;
|
||||
BOOL pinUnread = RiotSettings.shared.pinRoomsWithUnreadMessagesOnHome;
|
||||
NSComparator comparator = nil;
|
||||
|
||||
if (pinMissedNotif)
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
//
|
||||
// Use this file to import your target's public headers that you would like to expose to Swift.
|
||||
//
|
||||
|
||||
@@ -16,6 +16,16 @@
|
||||
|
||||
#import <MatrixKit/MatrixKit.h>
|
||||
|
||||
/**
|
||||
Link string used in attributed strings to mark a keys re-request action.
|
||||
*/
|
||||
FOUNDATION_EXPORT NSString *const kEventFormatterOnReRequestKeysLinkAction;
|
||||
|
||||
/**
|
||||
Parameters separator in the link string.
|
||||
*/
|
||||
FOUNDATION_EXPORT NSString *const kEventFormatterOnReRequestKeysLinkActionSeparator;
|
||||
|
||||
/**
|
||||
`EventFormatter` class inherits from `MXKEventFormatter` to define Vector formatting
|
||||
*/
|
||||
|
||||
@@ -21,6 +21,14 @@
|
||||
|
||||
#import "WidgetManager.h"
|
||||
|
||||
#import "MXDecryptionResult.h"
|
||||
#import "DecryptionFailureTracker.h"
|
||||
|
||||
#pragma mark - Constants definitions
|
||||
|
||||
NSString *const kEventFormatterOnReRequestKeysLinkAction = @"kEventFormatterOnReRequestKeysLinkAction";
|
||||
NSString *const kEventFormatterOnReRequestKeysLinkActionSeparator = @"/";
|
||||
|
||||
@interface EventFormatter ()
|
||||
{
|
||||
/**
|
||||
@@ -107,7 +115,47 @@
|
||||
}
|
||||
}
|
||||
|
||||
return [super attributedStringFromEvent:event withRoomState:roomState error:error];
|
||||
NSAttributedString *attributedString = [super attributedStringFromEvent:event withRoomState:roomState error:error];
|
||||
|
||||
if (event.sentState == MXEventSentStateSent
|
||||
&& [event.decryptionError.domain isEqualToString:MXDecryptingErrorDomain])
|
||||
{
|
||||
// Track e2e failures
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[[DecryptionFailureTracker sharedInstance] reportUnableToDecryptErrorForEvent:event withRoomState:roomState myUser:mxSession.myUser.userId];
|
||||
});
|
||||
|
||||
if (event.decryptionError.code == MXDecryptingErrorUnknownInboundSessionIdCode)
|
||||
{
|
||||
// Append to the displayed error an attibuted string with a tappable link
|
||||
// so that the user can try to fix the UTD
|
||||
NSMutableAttributedString *attributedStringWithRerequestMessage = [attributedString mutableCopy];
|
||||
[attributedStringWithRerequestMessage appendAttributedString:[[NSAttributedString alloc] initWithString:@"\n"]];
|
||||
|
||||
NSString *linkActionString = [NSString stringWithFormat:@"%@%@%@", kEventFormatterOnReRequestKeysLinkAction,
|
||||
kEventFormatterOnReRequestKeysLinkActionSeparator,
|
||||
event.eventId];
|
||||
|
||||
[attributedStringWithRerequestMessage appendAttributedString:
|
||||
[[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"event_formatter_rerequest_keys_part1_link", @"Vector", nil)
|
||||
attributes:@{
|
||||
NSLinkAttributeName: linkActionString,
|
||||
NSForegroundColorAttributeName: self.sendingTextColor,
|
||||
NSFontAttributeName: self.encryptedMessagesTextFont
|
||||
}]];
|
||||
|
||||
[attributedStringWithRerequestMessage appendAttributedString:
|
||||
[[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"event_formatter_rerequest_keys_part2", @"Vector", nil)
|
||||
attributes:@{
|
||||
NSForegroundColorAttributeName: self.sendingTextColor,
|
||||
NSFontAttributeName: self.encryptedMessagesTextFont
|
||||
}]];
|
||||
|
||||
attributedString = attributedStringWithRerequestMessage;
|
||||
}
|
||||
}
|
||||
|
||||
return attributedString;
|
||||
}
|
||||
|
||||
- (NSAttributedString*)attributedStringFromEvents:(NSArray<MXEvent*>*)events withRoomState:(MXRoomState*)roomState error:(MXKEventFormatterError*)error
|
||||
|
||||
@@ -17,6 +17,13 @@
|
||||
|
||||
#import "RiotDesignValues.h"
|
||||
|
||||
#ifdef IS_SHARE_EXTENSION
|
||||
#import "RiotShareExtension-Swift.h"
|
||||
#else
|
||||
#import "Riot-Swift.h"
|
||||
#endif
|
||||
|
||||
|
||||
NSString *const kRiotDesignValuesDidChangeThemeNotification = @"kRiotDesignValuesDidChangeThemeNotification";
|
||||
|
||||
UIColor *kRiotPrimaryBgColor;
|
||||
@@ -134,7 +141,7 @@ UIKeyboardAppearance kRiotKeyboard;
|
||||
- (void)accessibilityInvertColorsStatusDidChange
|
||||
{
|
||||
// Refresh the theme only for "auto"
|
||||
NSString *theme = [[NSUserDefaults standardUserDefaults] stringForKey:@"userInterfaceTheme"];
|
||||
NSString *theme = RiotSettings.shared.userInterfaceTheme;
|
||||
if (!theme || [theme isEqualToString:@"auto"])
|
||||
{
|
||||
[self userInterfaceThemeDidChange];
|
||||
@@ -144,7 +151,7 @@ UIKeyboardAppearance kRiotKeyboard;
|
||||
- (void)userInterfaceThemeDidChange
|
||||
{
|
||||
// Retrieve the current selected theme ("light" if none. "auto" is used as default from iOS 11).
|
||||
NSString *theme = [[NSUserDefaults standardUserDefaults] stringForKey:@"userInterfaceTheme"];
|
||||
NSString *theme = RiotSettings.shared.userInterfaceTheme;
|
||||
|
||||
if (!theme || [theme isEqualToString:@"auto"])
|
||||
{
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
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 Foundation
|
||||
|
||||
/// Store Riot specific app settings.
|
||||
@objcMembers
|
||||
final class RiotSettings: NSObject {
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
private enum UserDefaultsKeys {
|
||||
static let enableCrashReport = "enableCrashReport"
|
||||
static let enableRageShake = "enableRageShake"
|
||||
static let createConferenceCallsWithJitsi = "createConferenceCallsWithJitsi"
|
||||
static let userInterfaceTheme = "userInterfaceTheme"
|
||||
static let notificationsShowDecryptedContent = "showDecryptedContent"
|
||||
static let pinRoomsWithMissedNotifications = "pinRoomsWithMissedNotif"
|
||||
static let pinRoomsWithUnreadMessages = "pinRoomsWithUnread"
|
||||
}
|
||||
|
||||
static let shared = RiotSettings()
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
// MARK: Notifications
|
||||
|
||||
/// Indicate if `showDecryptedContentInNotifications` settings has been set once.
|
||||
var isShowDecryptedContentInNotificationsHasBeenSetOnce: Bool {
|
||||
return UserDefaults.standard.object(forKey: UserDefaultsKeys.notificationsShowDecryptedContent) != nil
|
||||
}
|
||||
|
||||
/// Indicate if encrypted messages content should be displayed in notifications.
|
||||
var showDecryptedContentInNotifications: Bool {
|
||||
get {
|
||||
return UserDefaults.standard.bool(forKey: UserDefaultsKeys.notificationsShowDecryptedContent)
|
||||
} set {
|
||||
UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.notificationsShowDecryptedContent)
|
||||
}
|
||||
}
|
||||
|
||||
/// Indicate if rooms with missed notifications should be displayed first on home screen.
|
||||
var pinRoomsWithMissedNotificationsOnHome: Bool {
|
||||
get {
|
||||
return UserDefaults.standard.bool(forKey: UserDefaultsKeys.pinRoomsWithMissedNotifications)
|
||||
} set {
|
||||
UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.pinRoomsWithMissedNotifications)
|
||||
}
|
||||
}
|
||||
|
||||
/// Indicate if rooms with unread messages should be displayed first on home screen.
|
||||
var pinRoomsWithUnreadMessagesOnHome: Bool {
|
||||
get {
|
||||
return UserDefaults.standard.bool(forKey: UserDefaultsKeys.pinRoomsWithUnreadMessages)
|
||||
} set {
|
||||
UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.pinRoomsWithUnreadMessages)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: User interface
|
||||
|
||||
var userInterfaceTheme: String? {
|
||||
get {
|
||||
return UserDefaults.standard.string(forKey: UserDefaultsKeys.userInterfaceTheme)
|
||||
} set {
|
||||
UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.userInterfaceTheme)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Other
|
||||
|
||||
/// Indicate if `enableCrashReport` settings has been set once.
|
||||
var isEnableCrashReportHasBeenSetOnce: Bool {
|
||||
return UserDefaults.standard.object(forKey: UserDefaultsKeys.enableCrashReport) != nil
|
||||
}
|
||||
|
||||
var enableCrashReport: Bool {
|
||||
get {
|
||||
return UserDefaults.standard.bool(forKey: UserDefaultsKeys.enableCrashReport)
|
||||
} set {
|
||||
UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.enableCrashReport)
|
||||
}
|
||||
}
|
||||
|
||||
var enableRageShake: Bool {
|
||||
get {
|
||||
return UserDefaults.standard.bool(forKey: UserDefaultsKeys.enableRageShake)
|
||||
} set {
|
||||
UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.enableRageShake)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Labs
|
||||
|
||||
var createConferenceCallsWithJitsi: Bool {
|
||||
get {
|
||||
return UserDefaults.standard.bool(forKey: UserDefaultsKeys.createConferenceCallsWithJitsi)
|
||||
} set {
|
||||
UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.createConferenceCallsWithJitsi)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,7 +73,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"AttachmentsViewer"];
|
||||
[[Analytics sharedInstance] trackScreen:@"AttachmentsViewer"];
|
||||
}
|
||||
|
||||
- (void)destroy
|
||||
|
||||
@@ -193,7 +193,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"Authentication"];
|
||||
[[Analytics sharedInstance] trackScreen:@"Authentication"];
|
||||
}
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated
|
||||
|
||||
@@ -135,7 +135,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"GroupDetails"];
|
||||
[[Analytics sharedInstance] trackScreen:@"GroupDetails"];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated
|
||||
|
||||
@@ -182,7 +182,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"GroupDetailsHome"];
|
||||
[[Analytics sharedInstance] trackScreen:@"GroupDetailsHome"];
|
||||
|
||||
// Release the potential pushed view controller
|
||||
[self releasePushedViewController];
|
||||
|
||||
@@ -217,7 +217,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"GroupDetailsPeople"];
|
||||
[[Analytics sharedInstance] trackScreen:@"GroupDetailsPeople"];
|
||||
|
||||
// Release the potential pushed view controller
|
||||
[self releasePushedViewController];
|
||||
|
||||
@@ -181,7 +181,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"GroupDetailsRooms"];
|
||||
[[Analytics sharedInstance] trackScreen:@"GroupDetailsRooms"];
|
||||
|
||||
// Release the potential pushed view controller
|
||||
[self releasePushedViewController];
|
||||
|
||||
@@ -186,7 +186,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"Groups"];
|
||||
[[Analytics sharedInstance] trackScreen:@"Groups"];
|
||||
|
||||
// Deselect the current selected row, it will be restored on viewDidAppear (if any)
|
||||
NSIndexPath *indexPath = [self.groupsTableView indexPathForSelectedRow];
|
||||
|
||||
@@ -263,7 +263,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"ContactDetails"];
|
||||
[[Analytics sharedInstance] trackScreen:@"ContactDetails"];
|
||||
|
||||
// Hide the bottom border of the navigation bar to display the expander header
|
||||
[self hideNavigationBarBorder:YES];
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
@property (nonatomic) BOOL shouldScrollToTopOnRefresh;
|
||||
|
||||
/**
|
||||
The Google Analytics Instance screen name (Default is "ContactsTable").
|
||||
The analytics instance screen name (Default is "ContactsTable").
|
||||
*/
|
||||
@property (nonatomic) NSString *screenName;
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:_screenName];
|
||||
[[Analytics sharedInstance] trackScreen:_screenName];
|
||||
|
||||
// Check whether the access to the local contacts has not been already asked.
|
||||
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined)
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"CountryPicker"];
|
||||
[[Analytics sharedInstance] trackScreen:@"CountryPicker"];
|
||||
}
|
||||
|
||||
- (void)destroy
|
||||
|
||||
@@ -96,7 +96,7 @@ static CGFloat const kTextFontSize = 15.0;
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"DeactivateAccount"];
|
||||
[[Analytics sharedInstance] trackScreen:@"DeactivateAccount"];
|
||||
}
|
||||
|
||||
- (void)viewDidLayoutSubviews
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"DirectoryServerPicker"];
|
||||
[[Analytics sharedInstance] trackScreen:@"DirectoryServerPicker"];
|
||||
|
||||
// Observe kAppDelegateDidTapStatusBarNotificationObserver.
|
||||
kAppDelegateDidTapStatusBarNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kAppDelegateDidTapStatusBarNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"Directory"];
|
||||
[[Analytics sharedInstance] trackScreen:@"Directory"];
|
||||
|
||||
// Observe kAppDelegateDidTapStatusBarNotificationObserver.
|
||||
kAppDelegateDidTapStatusBarNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kAppDelegateDidTapStatusBarNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"FilesGlobalSearch"];
|
||||
[[Analytics sharedInstance] trackScreen:@"FilesGlobalSearch"];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshSearchResult:) name:kMXSessionDidLeaveRoomNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshSearchResult:) name:kMXSessionNewRoomNotification object:nil];
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"MessagesGlobalSearch"];
|
||||
[[Analytics sharedInstance] trackScreen:@"MessagesGlobalSearch"];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshSearchResult:) name:kMXSessionDidLeaveRoomNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshSearchResult:) name:kMXSessionNewRoomNotification object:nil];
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"CountryPicker"];
|
||||
[[Analytics sharedInstance] trackScreen:@"CountryPicker"];
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#import "MXRoom+Riot.h"
|
||||
#import "MXSession+Riot.h"
|
||||
|
||||
#import "Riot-Swift.h"
|
||||
|
||||
@interface MasterTabBarController ()
|
||||
{
|
||||
// Array of `MXSession` instances.
|
||||
@@ -77,6 +79,15 @@
|
||||
_roomsViewController = [self.viewControllers objectAtIndex:TABBAR_ROOMS_INDEX];
|
||||
_groupsViewController = [self.viewControllers objectAtIndex:TABBAR_GROUPS_INDEX];
|
||||
|
||||
// Set the accessibility labels for all buttons #1842
|
||||
[_settingsBarButtonItem setAccessibilityLabel:NSLocalizedStringFromTable(@"settings_title", @"Vector", nil)];
|
||||
[_searchBarButtonIem setAccessibilityLabel:NSLocalizedStringFromTable(@"search_default_placeholder", @"Vector", nil)];
|
||||
[_homeViewController setAccessibilityLabel:NSLocalizedStringFromTable(@"title_home", @"Vector", nil)];
|
||||
[_favouritesViewController setAccessibilityLabel:NSLocalizedStringFromTable(@"title_favourites", @"Vector", nil)];
|
||||
[_peopleViewController setAccessibilityLabel:NSLocalizedStringFromTable(@"title_people", @"Vector", nil)];
|
||||
[_roomsViewController setAccessibilityLabel:NSLocalizedStringFromTable(@"title_rooms", @"Vector", nil)];
|
||||
[_groupsViewController setAccessibilityLabel:NSLocalizedStringFromTable(@"title_groups", @"Vector", nil)];
|
||||
|
||||
// Sanity check
|
||||
NSAssert(_homeViewController && _favouritesViewController && _peopleViewController && _roomsViewController && _groupsViewController, @"Something wrong in Main.storyboard");
|
||||
|
||||
@@ -136,10 +147,10 @@
|
||||
else
|
||||
{
|
||||
// Check whether the user has been already prompted to send crash reports.
|
||||
// (Check whether 'enableCrashReport' flag has been set once)
|
||||
if (![[NSUserDefaults standardUserDefaults] objectForKey:@"enableCrashReport"])
|
||||
// (Check whether 'enableCrashReport' flag has been set once)
|
||||
if (!RiotSettings.shared.isEnableCrashReportHasBeenSetOnce)
|
||||
{
|
||||
[self promptUserBeforeUsingGoogleAnalytics];
|
||||
[self promptUserBeforeUsingAnalytics];
|
||||
}
|
||||
|
||||
[self refreshTabBarBadges];
|
||||
@@ -762,7 +773,7 @@
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)promptUserBeforeUsingGoogleAnalytics
|
||||
- (void)promptUserBeforeUsingAnalytics
|
||||
{
|
||||
NSLog(@"[MasterTabBarController]: Invite the user to send crash reports");
|
||||
|
||||
@@ -778,8 +789,7 @@
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"enableCrashReport"];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
RiotSettings.shared.enableCrashReport = NO;
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
@@ -792,21 +802,20 @@
|
||||
[currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"yes"]
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"enableCrashReport"];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
|
||||
RiotSettings.shared.enableCrashReport = YES;
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
self->currentAlert = nil;
|
||||
}
|
||||
|
||||
[[AppDelegate theDelegate] startAnalytics];
|
||||
|
||||
[[Analytics sharedInstance] start];
|
||||
|
||||
}]];
|
||||
|
||||
[currentAlert mxk_setAccessibilityIdentifier: @"HomeVCUseGoogleAnalyticsAlert"];
|
||||
[currentAlert mxk_setAccessibilityIdentifier: @"HomeVCUseAnalyticsAlert"];
|
||||
[self presentViewController:currentAlert animated:YES completion:nil];
|
||||
}
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"MediaAlbumContent"];
|
||||
[[Analytics sharedInstance] trackScreen:@"MediaAlbumContent"];
|
||||
|
||||
self.navigationItem.title = _assetsCollection.localizedTitle;
|
||||
|
||||
|
||||
@@ -236,7 +236,7 @@ static void *RecordingContext = &RecordingContext;
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"MediaPicker"];
|
||||
[[Analytics sharedInstance] trackScreen:@"MediaPicker"];
|
||||
|
||||
if (!userAlbumsQueue)
|
||||
{
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
@property (nonatomic) CGFloat stickyHeaderHeight;
|
||||
|
||||
/**
|
||||
The Google Analytics Instance screen name (Default is "RecentsScreen").
|
||||
The analytics instance screen name (Default is "RecentsScreen").
|
||||
*/
|
||||
@property (nonatomic) NSString *screenName;
|
||||
|
||||
|
||||
@@ -231,7 +231,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:_screenName];
|
||||
[[Analytics sharedInstance] trackScreen:_screenName];
|
||||
|
||||
// Deselect the current selected row, it will be restored on viewDidAppear (if any)
|
||||
NSIndexPath *indexPath = [self.recentsTableView indexPathForSelectedRow];
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"RoomFilesSearch"];
|
||||
[[Analytics sharedInstance] trackScreen:@"RoomFilesSearch"];
|
||||
|
||||
// Observe kAppDelegateDidTapStatusBarNotificationObserver.
|
||||
kAppDelegateDidTapStatusBarNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kAppDelegateDidTapStatusBarNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
|
||||
|
||||
@@ -251,7 +251,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"RoomMemberDetails"];
|
||||
[[Analytics sharedInstance] trackScreen:@"RoomMemberDetails"];
|
||||
|
||||
// Hide the bottom border of the navigation bar to display the expander header
|
||||
[self hideNavigationBarBorder:YES];
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"RoomMessagesSearch"];
|
||||
[[Analytics sharedInstance] trackScreen:@"RoomMessagesSearch"];
|
||||
|
||||
// Observe kAppDelegateDidTapStatusBarNotificationObserver.
|
||||
kAppDelegateDidTapStatusBarNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kAppDelegateDidTapStatusBarNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
|
||||
|
||||
@@ -245,7 +245,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"RoomParticipants"];
|
||||
[[Analytics sharedInstance] trackScreen:@"RoomParticipants"];
|
||||
|
||||
if (memberDetailsViewController)
|
||||
{
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
}
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"RoomsSearch"];
|
||||
[[Analytics sharedInstance] trackScreen:@"RoomsSearch"];
|
||||
|
||||
// Enable the search field by default at the screen opening
|
||||
if (self.searchBarHidden)
|
||||
|
||||
@@ -289,7 +289,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"RoomSettings"];
|
||||
[[Analytics sharedInstance] trackScreen:@"RoomSettings"];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didUpdateRules:) name:kMXNotificationCenterDidUpdateRules object:nil];
|
||||
|
||||
|
||||
@@ -117,6 +117,10 @@
|
||||
#import "WidgetPickerViewController.h"
|
||||
#import "StickerPickerViewController.h"
|
||||
|
||||
#import "EventFormatter.h"
|
||||
|
||||
#import "Riot-Swift.h"
|
||||
|
||||
@interface RoomViewController ()
|
||||
{
|
||||
// The expanded header
|
||||
@@ -181,6 +185,9 @@
|
||||
|
||||
// Observer kMXRoomSummaryDidChangeNotification to keep updated the missed discussion count
|
||||
id mxRoomSummaryDidChangeObserver;
|
||||
|
||||
// Observer for removing the re-request explanation/waiting dialog
|
||||
id mxEventDidDecryptNotificationObserver;
|
||||
|
||||
// The table view cell in which the read marker is displayed (nil by default).
|
||||
MXKRoomBubbleTableViewCell *readMarkerTableViewCell;
|
||||
@@ -445,7 +452,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"ChatRoom"];
|
||||
[[Analytics sharedInstance] trackScreen:@"ChatRoom"];
|
||||
|
||||
// Refresh the room title view
|
||||
[self refreshRoomTitle];
|
||||
@@ -592,6 +599,12 @@
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:mxRoomSummaryDidChangeObserver];
|
||||
mxRoomSummaryDidChangeObserver = nil;
|
||||
}
|
||||
|
||||
if (mxEventDidDecryptNotificationObserver)
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:mxEventDidDecryptNotificationObserver];
|
||||
mxEventDidDecryptNotificationObserver = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewDidLayoutSubviews
|
||||
@@ -1103,6 +1116,11 @@
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:mxRoomSummaryDidChangeObserver];
|
||||
mxRoomSummaryDidChangeObserver = nil;
|
||||
}
|
||||
if (mxEventDidDecryptNotificationObserver)
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:mxEventDidDecryptNotificationObserver];
|
||||
mxEventDidDecryptNotificationObserver = nil;
|
||||
}
|
||||
|
||||
[self removeCallNotificationsListeners];
|
||||
[self removeWidgetNotificationsListeners];
|
||||
@@ -2680,6 +2698,20 @@
|
||||
NSString *fragment = [NSString stringWithFormat:@"/group/%@", [absoluteURLString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
|
||||
[[AppDelegate theDelegate] handleUniversalLinkFragment:fragment];
|
||||
}
|
||||
else if ([absoluteURLString hasPrefix:kEventFormatterOnReRequestKeysLinkAction])
|
||||
{
|
||||
NSArray<NSString*> *arguments = [absoluteURLString componentsSeparatedByString:kEventFormatterOnReRequestKeysLinkActionSeparator];
|
||||
if (arguments.count > 1)
|
||||
{
|
||||
NSString *eventId = arguments[1];
|
||||
MXEvent *event = [self.roomDataSource eventWithEventId:eventId];
|
||||
|
||||
if (event)
|
||||
{
|
||||
[self reRequestKeysAndShowExplanationAlert:event];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return shouldDoAction;
|
||||
@@ -2982,7 +3014,7 @@
|
||||
}
|
||||
|
||||
// If enabled, create the conf using jitsi widget and open it directly
|
||||
else if ([[NSUserDefaults standardUserDefaults] boolForKey:@"createConferenceCallsWithJitsi"]
|
||||
else if (RiotSettings.shared.createConferenceCallsWithJitsi
|
||||
&& self.roomDataSource.room.state.joinedMembers.count > 2)
|
||||
{
|
||||
[self startActivityIndicator];
|
||||
@@ -4582,5 +4614,57 @@
|
||||
[self presentViewController:currentAlert animated:YES completion:nil];
|
||||
}
|
||||
|
||||
#pragma mark - Re-request encryption keys
|
||||
|
||||
- (void)reRequestKeysAndShowExplanationAlert:(MXEvent*)event
|
||||
{
|
||||
MXWeakify(self);
|
||||
__block UIAlertController *alert;
|
||||
|
||||
// Make the re-request
|
||||
[self.mainSession.crypto reRequestRoomKeyForEvent:event];
|
||||
|
||||
// Observe kMXEventDidDecryptNotification to remove automatically the dialog
|
||||
// if the user has shared the keys from another device
|
||||
mxEventDidDecryptNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXEventDidDecryptNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
MXEvent *decryptedEvent = notif.object;
|
||||
|
||||
if ([decryptedEvent.eventId isEqualToString:event.eventId])
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self->mxEventDidDecryptNotificationObserver];
|
||||
self->mxEventDidDecryptNotificationObserver = nil;
|
||||
|
||||
if (self->currentAlert == alert)
|
||||
{
|
||||
[self->currentAlert dismissViewControllerAnimated:YES completion:nil];
|
||||
self->currentAlert = nil;
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
||||
// Show the explanation dialog
|
||||
alert = [UIAlertController alertControllerWithTitle:NSLocalizedStringFromTable(@"rerequest_keys_alert_title", @"Vector", nil)
|
||||
message:NSLocalizedStringFromTable(@"rerequest_keys_alert_message", @"Vector", nil)
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
currentAlert = alert;
|
||||
|
||||
|
||||
[alert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"ok"]
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action)
|
||||
{
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self->mxEventDidDecryptNotificationObserver];
|
||||
self->mxEventDidDecryptNotificationObserver = nil;
|
||||
|
||||
self->currentAlert = nil;
|
||||
}]];
|
||||
|
||||
[self presentViewController:currentAlert animated:YES completion:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
|
||||
#import "GBDeviceInfo_iOS.h"
|
||||
|
||||
#import "Riot-Swift.h"
|
||||
|
||||
NSString* const kSettingsViewControllerPhoneBookCountryCellId = @"kSettingsViewControllerPhoneBookCountryCellId";
|
||||
|
||||
enum
|
||||
@@ -423,7 +425,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"Settings"];
|
||||
[[Analytics sharedInstance] trackScreen:@"Settings"];
|
||||
|
||||
// Release the potential pushed view controller
|
||||
[self releasePushedViewController];
|
||||
@@ -1681,7 +1683,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
|
||||
MXKTableViewCellWithLabelAndSwitch* labelAndSwitchCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath];
|
||||
|
||||
labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_show_decrypted_content", @"Vector", nil);
|
||||
labelAndSwitchCell.mxkSwitch.on = account.showDecryptedContentInNotifications;
|
||||
labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.showDecryptedContentInNotifications;
|
||||
labelAndSwitchCell.mxkSwitch.enabled = account.isPushKitNotificationActive;
|
||||
[labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleShowDecodedContent:) forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
@@ -1705,7 +1707,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
|
||||
MXKTableViewCellWithLabelAndSwitch* labelAndSwitchCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath];
|
||||
|
||||
labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_pin_rooms_with_missed_notif", @"Vector", nil);
|
||||
labelAndSwitchCell.mxkSwitch.on = [[NSUserDefaults standardUserDefaults] boolForKey:@"pinRoomsWithMissedNotif"];
|
||||
labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.pinRoomsWithMissedNotificationsOnHome;
|
||||
labelAndSwitchCell.mxkSwitch.enabled = YES;
|
||||
[labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(togglePinRoomsWithMissedNotif:) forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
@@ -1716,7 +1718,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
|
||||
MXKTableViewCellWithLabelAndSwitch* labelAndSwitchCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath];
|
||||
|
||||
labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_pin_rooms_with_unread", @"Vector", nil);
|
||||
labelAndSwitchCell.mxkSwitch.on = [[NSUserDefaults standardUserDefaults] boolForKey:@"pinRoomsWithUnread"];
|
||||
labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.pinRoomsWithUnreadMessagesOnHome;
|
||||
labelAndSwitchCell.mxkSwitch.enabled = YES;
|
||||
[labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(togglePinRoomsWithUnread:) forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
@@ -1782,7 +1784,8 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
|
||||
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:kSettingsViewControllerPhoneBookCountryCellId];
|
||||
}
|
||||
|
||||
NSString *theme = [[NSUserDefaults standardUserDefaults] stringForKey:@"userInterfaceTheme"];
|
||||
NSString *theme = RiotSettings.shared.userInterfaceTheme;
|
||||
|
||||
if (!theme)
|
||||
{
|
||||
if (@available(iOS 11.0, *))
|
||||
@@ -1942,7 +1945,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
|
||||
MXKTableViewCellWithLabelAndSwitch* sendCrashReportCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath];
|
||||
|
||||
sendCrashReportCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_send_crash_report", @"Vector", nil);
|
||||
sendCrashReportCell.mxkSwitch.on = [[NSUserDefaults standardUserDefaults] boolForKey:@"enableCrashReport"];
|
||||
sendCrashReportCell.mxkSwitch.on = RiotSettings.shared.enableCrashReport;
|
||||
sendCrashReportCell.mxkSwitch.enabled = YES;
|
||||
[sendCrashReportCell.mxkSwitch addTarget:self action:@selector(toggleSendCrashReport:) forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
@@ -1953,7 +1956,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
|
||||
MXKTableViewCellWithLabelAndSwitch* enableRageShakeCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath];
|
||||
|
||||
enableRageShakeCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_enable_rageshake", @"Vector", nil);
|
||||
enableRageShakeCell.mxkSwitch.on = [[NSUserDefaults standardUserDefaults] boolForKey:@"enableRageShake"];
|
||||
enableRageShakeCell.mxkSwitch.on = RiotSettings.shared.enableRageShake;
|
||||
enableRageShakeCell.mxkSwitch.enabled = YES;
|
||||
[enableRageShakeCell.mxkSwitch addTarget:self action:@selector(toggleEnableRageShake:) forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
@@ -2042,7 +2045,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
|
||||
MXKTableViewCellWithLabelAndSwitch* labelAndSwitchCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath];
|
||||
|
||||
labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_labs_create_conference_with_jitsi", @"Vector", nil);
|
||||
labelAndSwitchCell.mxkSwitch.on = [[NSUserDefaults standardUserDefaults] boolForKey:@"createConferenceCallsWithJitsi"];
|
||||
labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.createConferenceCallsWithJitsi;
|
||||
|
||||
[labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleJitsiForConference:) forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
@@ -2820,8 +2823,8 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
|
||||
|
||||
- (void)toggleShowDecodedContent:(id)sender
|
||||
{
|
||||
MXKAccount* account = [MXKAccountManager sharedManager].activeAccounts.firstObject;
|
||||
account.showDecryptedContentInNotifications = !account.showDecryptedContentInNotifications;
|
||||
UISwitch *switchButton = (UISwitch*)sender;
|
||||
RiotSettings.shared.showDecryptedContentInNotifications = switchButton.isOn;
|
||||
}
|
||||
|
||||
- (void)toggleLocalContactsSync:(id)sender
|
||||
@@ -2847,25 +2850,25 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
|
||||
|
||||
- (void)toggleSendCrashReport:(id)sender
|
||||
{
|
||||
BOOL enable = [[NSUserDefaults standardUserDefaults] boolForKey:@"enableCrashReport"];
|
||||
BOOL enable = RiotSettings.shared.enableCrashReport;
|
||||
if (enable)
|
||||
{
|
||||
NSLog(@"[SettingsViewController] disable automatic crash report sending");
|
||||
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"enableCrashReport"];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
NSLog(@"[SettingsViewController] disable automatic crash report and analytics sending");
|
||||
|
||||
[[AppDelegate theDelegate] stopAnalytics];
|
||||
RiotSettings.shared.enableCrashReport = NO;
|
||||
|
||||
[[Analytics sharedInstance] stop];
|
||||
|
||||
// Remove potential crash file.
|
||||
[MXLogger deleteCrashLog];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"[SettingsViewController] enable automatic crash report sending");
|
||||
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"enableCrashReport"];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
NSLog(@"[SettingsViewController] enable automatic crash report and analytics sending");
|
||||
|
||||
[[AppDelegate theDelegate] startAnalytics];
|
||||
RiotSettings.shared.enableCrashReport = YES;
|
||||
|
||||
[[Analytics sharedInstance] start];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2875,8 +2878,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
|
||||
{
|
||||
UISwitch *switchButton = (UISwitch*)sender;
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] setBool:switchButton.isOn forKey:@"enableRageShake"];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
RiotSettings.shared.enableRageShake = switchButton.isOn;
|
||||
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
@@ -2887,9 +2889,8 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
|
||||
if (sender && [sender isKindOfClass:UISwitch.class])
|
||||
{
|
||||
UISwitch *switchButton = (UISwitch*)sender;
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] setBool:switchButton.isOn forKey:@"createConferenceCallsWithJitsi"];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
|
||||
RiotSettings.shared.createConferenceCallsWithJitsi = switchButton.isOn;
|
||||
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
@@ -3012,16 +3013,14 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
|
||||
{
|
||||
UISwitch *switchButton = (UISwitch*)sender;
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] setBool:switchButton.on forKey:@"pinRoomsWithMissedNotif"];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
RiotSettings.shared.pinRoomsWithMissedNotificationsOnHome = switchButton.on;
|
||||
}
|
||||
|
||||
- (void)togglePinRoomsWithUnread:(id)sender
|
||||
{
|
||||
UISwitch *switchButton = (UISwitch*)sender;
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] setBool:switchButton.on forKey:@"pinRoomsWithUnread"];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
|
||||
RiotSettings.shared.pinRoomsWithUnreadMessagesOnHome = switchButton.on;
|
||||
}
|
||||
|
||||
- (void)toggleCommunityFlair:(id)sender
|
||||
@@ -3661,15 +3660,14 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
|
||||
newTheme = @"black";
|
||||
}
|
||||
|
||||
NSString *theme = [[NSUserDefaults standardUserDefaults] stringForKey:@"userInterfaceTheme"];
|
||||
NSString *theme = RiotSettings.shared.userInterfaceTheme;
|
||||
if (newTheme && ![newTheme isEqualToString:theme])
|
||||
{
|
||||
// Clear fake Riot Avatars based on the previous theme.
|
||||
[AvatarGenerator clear];
|
||||
|
||||
// The user wants to select this theme
|
||||
[[NSUserDefaults standardUserDefaults] setObject:newTheme forKey:@"userInterfaceTheme"];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
RiotSettings.shared.userInterfaceTheme = newTheme;
|
||||
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"UnifiedSearch"];
|
||||
[[Analytics sharedInstance] trackScreen:@"UnifiedSearch"];
|
||||
|
||||
// Let's child display the loading not the home view controller
|
||||
if (self.activityIndicator)
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"UnknowDevices"];
|
||||
[[Analytics sharedInstance] trackScreen:@"UnknowDevices"];
|
||||
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
|
||||
@@ -25,6 +25,11 @@
|
||||
|
||||
#import "MXRoomSummary+Riot.h"
|
||||
|
||||
#pragma mark - Defines & Constants
|
||||
|
||||
static const CGFloat kDirectRoomBorderColorAlpha = 0.75;
|
||||
static const CGFloat kDirectRoomBorderWidth = 3.0;
|
||||
|
||||
@implementation RecentTableViewCell
|
||||
|
||||
#pragma mark - Class methods
|
||||
@@ -48,10 +53,14 @@
|
||||
self.missedNotifAndUnreadBadgeLabel.textColor = kRiotPrimaryBgColor;
|
||||
|
||||
// Prepare direct room border
|
||||
CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(kRiotColorGreen.CGColor, kDirectRoomBorderColorAlpha);
|
||||
|
||||
[self.directRoomBorderView.layer setCornerRadius:self.directRoomBorderView.frame.size.width / 2];
|
||||
self.directRoomBorderView.clipsToBounds = YES;
|
||||
self.directRoomBorderView.layer.borderColor = CGColorCreateCopyWithAlpha(kRiotColorGreen.CGColor, 0.75);
|
||||
self.directRoomBorderView.layer.borderWidth = 3;
|
||||
self.directRoomBorderView.layer.borderColor = directRoomBorderColor;
|
||||
self.directRoomBorderView.layer.borderWidth = kDirectRoomBorderWidth;
|
||||
|
||||
CFRelease(directRoomBorderColor);
|
||||
|
||||
self.roomAvatar.defaultBackgroundColor = [UIColor clearColor];
|
||||
}
|
||||
|
||||
@@ -24,6 +24,11 @@
|
||||
|
||||
#import "MXTools.h"
|
||||
|
||||
#pragma mark - Defines & Constants
|
||||
|
||||
static const CGFloat kDirectRoomBorderColorAlpha = 0.75;
|
||||
static const CGFloat kDirectRoomBorderWidth = 3.0;
|
||||
|
||||
@implementation RoomCollectionViewCell
|
||||
|
||||
#pragma mark - Class methods
|
||||
@@ -66,10 +71,14 @@
|
||||
self.missedNotifAndUnreadBadgeLabel.textColor = kRiotPrimaryBgColor;
|
||||
|
||||
// Prepare direct room border
|
||||
CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(kRiotColorGreen.CGColor, kDirectRoomBorderColorAlpha);
|
||||
|
||||
[self.directRoomBorderView.layer setCornerRadius:self.directRoomBorderView.frame.size.width / 2];
|
||||
self.directRoomBorderView.clipsToBounds = YES;
|
||||
self.directRoomBorderView.layer.borderColor = CGColorCreateCopyWithAlpha(kRiotColorGreen.CGColor, 0.75);
|
||||
self.directRoomBorderView.layer.borderWidth = 3;
|
||||
self.directRoomBorderView.layer.borderColor = directRoomBorderColor;
|
||||
self.directRoomBorderView.layer.borderWidth = kDirectRoomBorderWidth;
|
||||
|
||||
CFRelease(directRoomBorderColor);
|
||||
|
||||
self.editionArrowView.backgroundColor = kRiotSecondaryBgColor;
|
||||
|
||||
|
||||
@@ -20,6 +20,11 @@
|
||||
#import "RiotDesignValues.h"
|
||||
#import "MXRoomSummary+Riot.h"
|
||||
|
||||
#pragma mark - Defines & Constants
|
||||
|
||||
static const CGFloat kDirectRoomBorderColorAlpha = 0.75;
|
||||
static const CGFloat kDirectRoomBorderWidth = 3.0;
|
||||
|
||||
@implementation RoomTableViewCell
|
||||
|
||||
#pragma mark - Class methods
|
||||
@@ -31,10 +36,14 @@
|
||||
self.titleLabel.textColor = kRiotPrimaryTextColor;
|
||||
|
||||
// Prepare direct room border
|
||||
CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(kRiotColorGreen.CGColor, kDirectRoomBorderColorAlpha);
|
||||
|
||||
[self.directRoomBorderView.layer setCornerRadius:self.directRoomBorderView.frame.size.width / 2];
|
||||
self.directRoomBorderView.clipsToBounds = YES;
|
||||
self.directRoomBorderView.layer.borderColor = CGColorCreateCopyWithAlpha(kRiotColorGreen.CGColor, 0.75);
|
||||
self.directRoomBorderView.layer.borderWidth = 3;
|
||||
self.directRoomBorderView.layer.borderColor = directRoomBorderColor;
|
||||
self.directRoomBorderView.layer.borderWidth = kDirectRoomBorderWidth;
|
||||
|
||||
CFRelease(directRoomBorderColor);
|
||||
|
||||
self.avatarImageView.defaultBackgroundColor = [UIColor clearColor];
|
||||
}
|
||||
|
||||
@@ -114,19 +114,6 @@
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
<br/><br/>
|
||||
</li>
|
||||
<li>
|
||||
<b>GoogleAnalytics</b> (<a
|
||||
href="https://www.google.com/analytics">https://www.google.com/analytics</a>)
|
||||
<br/><br/>Measure your app performance.
|
||||
<br/><br/>Copyright (c) 2011-2016 Google Inc. All rights reserved.
|
||||
<br/><br/>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with the License. You may obtain a copy of the License at:
|
||||
<br/><br/><a
|
||||
href="https://www.apache.org/licenses/LICENSE-2.0">https://www.apache.org/licenses/LICENSE-2.0</a>
|
||||
<br/><br/>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.
|
||||
<br/><br/>Google Analytics Terms of Service: <a
|
||||
href="https://www.google.com/analytics/terms">https://www.google.com/analytics/terms</a>
|
||||
<br/><br/>
|
||||
</li>
|
||||
<li>
|
||||
<b>GZIP</b> (<a
|
||||
href="https://github.com/nicklockwood/GZIP">https://github.com/nicklockwood/GZIP</a>)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>XPC!</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.6.17</string>
|
||||
<string>0.6.18</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>NSExtension</key>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
//
|
||||
// Use this file to import your target's public headers that you would like to expose to Swift.
|
||||
//
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>XPC!</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.6.17</string>
|
||||
<string>0.6.18</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>NSExtension</key>
|
||||
|
||||
Reference in New Issue
Block a user