mirror of
https://github.com/vector-im/element-ios.git
synced 2024-09-28 23:32:41 +00:00
Merge pull request #3603 from vector-im/reduce_warnings
Reduce Xcode warnings
This commit is contained in:
commit
1e6b0da7ca
40 changed files with 153 additions and 1401 deletions
|
@ -28,7 +28,8 @@ included:
|
||||||
excluded:
|
excluded:
|
||||||
- Carthage
|
- Carthage
|
||||||
- Pods
|
- Pods
|
||||||
- Riot/Generated/
|
- Riot/Generated/
|
||||||
|
- Riot/Modules/LaunchLoading/LoadingAnimation/
|
||||||
|
|
||||||
line_length:
|
line_length:
|
||||||
warning: 250
|
warning: 250
|
||||||
|
|
10
Podfile
10
Podfile
|
@ -61,7 +61,8 @@ abstract_target 'RiotPods' do
|
||||||
# Remove warnings from "bad" pods
|
# Remove warnings from "bad" pods
|
||||||
pod 'OLMKit', :inhibit_warnings => true
|
pod 'OLMKit', :inhibit_warnings => true
|
||||||
pod 'cmark', :inhibit_warnings => true
|
pod 'cmark', :inhibit_warnings => true
|
||||||
pod 'zxcvbn-ios'
|
pod 'zxcvbn-ios', :inhibit_warnings => true
|
||||||
|
pod 'HPGrowingTextView', :inhibit_warnings => true
|
||||||
|
|
||||||
# Tools
|
# Tools
|
||||||
pod 'SwiftGen', '~> 6.1'
|
pod 'SwiftGen', '~> 6.1'
|
||||||
|
@ -101,12 +102,7 @@ post_install do |installer|
|
||||||
# Because the WebRTC pod (included by the JingleCallStack pod) does not support it.
|
# Because the WebRTC pod (included by the JingleCallStack pod) does not support it.
|
||||||
# Plus the app does not enable it
|
# Plus the app does not enable it
|
||||||
target.build_configurations.each do |config|
|
target.build_configurations.each do |config|
|
||||||
config.build_settings['ENABLE_BITCODE'] = 'NO'
|
config.build_settings['ENABLE_BITCODE'] = 'NO'
|
||||||
|
|
||||||
# Force SwiftUTI Swift version to 5.0 (as there is no code changes to perform for SwiftUTI fork using Swift 4.2)
|
|
||||||
if target.name.include? 'SwiftUTI'
|
|
||||||
config.build_settings['SWIFT_VERSION'] = '5.0'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -145,9 +145,6 @@
|
||||||
32FD757924D2C9BA00BA7B37 /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32FD757524D2C9BA00BA7B37 /* Bundle.swift */; };
|
32FD757924D2C9BA00BA7B37 /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32FD757524D2C9BA00BA7B37 /* Bundle.swift */; };
|
||||||
32FD757A24D2C9BA00BA7B37 /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32FD757524D2C9BA00BA7B37 /* Bundle.swift */; };
|
32FD757A24D2C9BA00BA7B37 /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32FD757524D2C9BA00BA7B37 /* Bundle.swift */; };
|
||||||
32FDC1CD2386CD390084717A /* RiotSettingIntegrationProvisioning.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32FDC1CC2386CD390084717A /* RiotSettingIntegrationProvisioning.swift */; };
|
32FDC1CD2386CD390084717A /* RiotSettingIntegrationProvisioning.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32FDC1CC2386CD390084717A /* RiotSettingIntegrationProvisioning.swift */; };
|
||||||
39D49C6524B8D40500FEDBC8 /* ElementViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39D49C6224B8D40500FEDBC8 /* ElementViewController.swift */; };
|
|
||||||
39D49C6624B8D40500FEDBC8 /* Timeline_1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39D49C6324B8D40500FEDBC8 /* Timeline_1.swift */; };
|
|
||||||
39D49C6724B8D40500FEDBC8 /* ElementView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39D49C6424B8D40500FEDBC8 /* ElementView.swift */; };
|
|
||||||
3AF393339D2D566CE14AC200 /* Pods_RiotTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 129EB7E27E7E4AC3F5F098F5 /* Pods_RiotTests.framework */; };
|
3AF393339D2D566CE14AC200 /* Pods_RiotTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 129EB7E27E7E4AC3F5F098F5 /* Pods_RiotTests.framework */; };
|
||||||
405FD41D306133A48D9B5AA1 /* Pods_RiotPods_Riot.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1ACF09217ADF1D7E7A35BC02 /* Pods_RiotPods_Riot.framework */; };
|
405FD41D306133A48D9B5AA1 /* Pods_RiotPods_Riot.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1ACF09217ADF1D7E7A35BC02 /* Pods_RiotPods_Riot.framework */; };
|
||||||
670966FEFE120D865FD8A5B6 /* Pods_RiotPods_SiriIntents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51187E952D5CECF6D6F5A28E /* Pods_RiotPods_SiriIntents.framework */; };
|
670966FEFE120D865FD8A5B6 /* Pods_RiotPods_SiriIntents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51187E952D5CECF6D6F5A28E /* Pods_RiotPods_SiriIntents.framework */; };
|
||||||
|
@ -186,6 +183,9 @@
|
||||||
B1098C1021ED07E4000DDA48 /* Presentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098C0B21ED07E4000DDA48 /* Presentable.swift */; };
|
B1098C1021ED07E4000DDA48 /* Presentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098C0B21ED07E4000DDA48 /* Presentable.swift */; };
|
||||||
B1098C1121ED07E4000DDA48 /* NavigationRouterType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098C0C21ED07E4000DDA48 /* NavigationRouterType.swift */; };
|
B1098C1121ED07E4000DDA48 /* NavigationRouterType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098C0C21ED07E4000DDA48 /* NavigationRouterType.swift */; };
|
||||||
B109D6F1222D8C400061B6D9 /* UIApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = B109D6F0222D8C400061B6D9 /* UIApplication.swift */; };
|
B109D6F1222D8C400061B6D9 /* UIApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = B109D6F0222D8C400061B6D9 /* UIApplication.swift */; };
|
||||||
|
B10A3E8E24FE4368007C380F /* ElementView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B10A3E8B24FE4367007C380F /* ElementView.swift */; };
|
||||||
|
B10A3E8F24FE4368007C380F /* Timeline_1.swift in Sources */ = {isa = PBXBuildFile; fileRef = B10A3E8C24FE4367007C380F /* Timeline_1.swift */; };
|
||||||
|
B10A3E9024FE4368007C380F /* ElementViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B10A3E8D24FE4367007C380F /* ElementViewController.swift */; };
|
||||||
B10CFBC32268D99D00A5842E /* JitsiService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B10CFBC22268D99D00A5842E /* JitsiService.swift */; };
|
B10CFBC32268D99D00A5842E /* JitsiService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B10CFBC22268D99D00A5842E /* JitsiService.swift */; };
|
||||||
B1107EC82200B0720038014B /* KeyBackupRecoverSuccessViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1107EC72200B0720038014B /* KeyBackupRecoverSuccessViewController.swift */; };
|
B1107EC82200B0720038014B /* KeyBackupRecoverSuccessViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1107EC72200B0720038014B /* KeyBackupRecoverSuccessViewController.swift */; };
|
||||||
B1107ECA2200B09F0038014B /* KeyBackupRecoverSuccessViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B1107EC92200B09F0038014B /* KeyBackupRecoverSuccessViewController.storyboard */; };
|
B1107ECA2200B09F0038014B /* KeyBackupRecoverSuccessViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B1107EC92200B09F0038014B /* KeyBackupRecoverSuccessViewController.storyboard */; };
|
||||||
|
@ -1060,9 +1060,6 @@
|
||||||
32FD757524D2C9BA00BA7B37 /* Bundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bundle.swift; sourceTree = "<group>"; };
|
32FD757524D2C9BA00BA7B37 /* Bundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bundle.swift; sourceTree = "<group>"; };
|
||||||
32FDC1CC2386CD390084717A /* RiotSettingIntegrationProvisioning.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RiotSettingIntegrationProvisioning.swift; sourceTree = "<group>"; };
|
32FDC1CC2386CD390084717A /* RiotSettingIntegrationProvisioning.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RiotSettingIntegrationProvisioning.swift; sourceTree = "<group>"; };
|
||||||
3942DD65EBEB7AE647C6392A /* Pods-RiotPods-SiriIntents.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RiotPods-SiriIntents.debug.xcconfig"; path = "Target Support Files/Pods-RiotPods-SiriIntents/Pods-RiotPods-SiriIntents.debug.xcconfig"; sourceTree = "<group>"; };
|
3942DD65EBEB7AE647C6392A /* Pods-RiotPods-SiriIntents.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RiotPods-SiriIntents.debug.xcconfig"; path = "Target Support Files/Pods-RiotPods-SiriIntents/Pods-RiotPods-SiriIntents.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
39D49C6224B8D40500FEDBC8 /* ElementViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ElementViewController.swift; sourceTree = "<group>"; };
|
|
||||||
39D49C6324B8D40500FEDBC8 /* Timeline_1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Timeline_1.swift; sourceTree = "<group>"; };
|
|
||||||
39D49C6424B8D40500FEDBC8 /* ElementView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ElementView.swift; sourceTree = "<group>"; };
|
|
||||||
3D78489021AC9E6400B98A7D /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
3D78489021AC9E6400B98A7D /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||||
3D78489121AC9E6500B98A7D /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Localizable.strings; sourceTree = "<group>"; };
|
3D78489121AC9E6500B98A7D /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
3D78489221AC9E6500B98A7D /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Vector.strings; sourceTree = "<group>"; };
|
3D78489221AC9E6500B98A7D /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Vector.strings; sourceTree = "<group>"; };
|
||||||
|
@ -1114,6 +1111,9 @@
|
||||||
B1098C0B21ED07E4000DDA48 /* Presentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Presentable.swift; sourceTree = "<group>"; };
|
B1098C0B21ED07E4000DDA48 /* Presentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Presentable.swift; sourceTree = "<group>"; };
|
||||||
B1098C0C21ED07E4000DDA48 /* NavigationRouterType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationRouterType.swift; sourceTree = "<group>"; };
|
B1098C0C21ED07E4000DDA48 /* NavigationRouterType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationRouterType.swift; sourceTree = "<group>"; };
|
||||||
B109D6F0222D8C400061B6D9 /* UIApplication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIApplication.swift; sourceTree = "<group>"; };
|
B109D6F0222D8C400061B6D9 /* UIApplication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIApplication.swift; sourceTree = "<group>"; };
|
||||||
|
B10A3E8B24FE4367007C380F /* ElementView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ElementView.swift; sourceTree = "<group>"; };
|
||||||
|
B10A3E8C24FE4367007C380F /* Timeline_1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Timeline_1.swift; sourceTree = "<group>"; };
|
||||||
|
B10A3E8D24FE4367007C380F /* ElementViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ElementViewController.swift; sourceTree = "<group>"; };
|
||||||
B10CFBC22268D99D00A5842E /* JitsiService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JitsiService.swift; sourceTree = "<group>"; };
|
B10CFBC22268D99D00A5842E /* JitsiService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JitsiService.swift; sourceTree = "<group>"; };
|
||||||
B1107EC72200B0720038014B /* KeyBackupRecoverSuccessViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverSuccessViewController.swift; sourceTree = "<group>"; };
|
B1107EC72200B0720038014B /* KeyBackupRecoverSuccessViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverSuccessViewController.swift; sourceTree = "<group>"; };
|
||||||
B1107EC92200B09F0038014B /* KeyBackupRecoverSuccessViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = KeyBackupRecoverSuccessViewController.storyboard; sourceTree = "<group>"; };
|
B1107EC92200B09F0038014B /* KeyBackupRecoverSuccessViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = KeyBackupRecoverSuccessViewController.storyboard; sourceTree = "<group>"; };
|
||||||
|
@ -2398,16 +2398,6 @@
|
||||||
path = Config;
|
path = Config;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
39D49C6124B8D3B000FEDBC8 /* LaunchLoadingAnimation */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
39D49C6424B8D40500FEDBC8 /* ElementView.swift */,
|
|
||||||
39D49C6224B8D40500FEDBC8 /* ElementViewController.swift */,
|
|
||||||
39D49C6324B8D40500FEDBC8 /* Timeline_1.swift */,
|
|
||||||
);
|
|
||||||
name = LaunchLoadingAnimation;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
4220F60B660591FD80AF3428 /* Pods */ = {
|
4220F60B660591FD80AF3428 /* Pods */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -2554,6 +2544,16 @@
|
||||||
path = Routers;
|
path = Routers;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
B10A3E8A24FE4367007C380F /* LoadingAnimation */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
B10A3E8B24FE4367007C380F /* ElementView.swift */,
|
||||||
|
B10A3E8C24FE4367007C380F /* Timeline_1.swift */,
|
||||||
|
B10A3E8D24FE4367007C380F /* ElementViewController.swift */,
|
||||||
|
);
|
||||||
|
path = LoadingAnimation;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
B1107EC62200B0190038014B /* Success */ = {
|
B1107EC62200B0190038014B /* Success */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -2699,7 +2699,7 @@
|
||||||
B1560DA024B65A9500490F50 /* LaunchLoading */ = {
|
B1560DA024B65A9500490F50 /* LaunchLoading */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
39D49C6124B8D3B000FEDBC8 /* LaunchLoadingAnimation */,
|
B10A3E8A24FE4367007C380F /* LoadingAnimation */,
|
||||||
B1560DA124B65AFA00490F50 /* LaunchLoadingView.swift */,
|
B1560DA124B65AFA00490F50 /* LaunchLoadingView.swift */,
|
||||||
B1560DA324B65B3700490F50 /* LaunchLoadingView.xib */,
|
B1560DA324B65B3700490F50 /* LaunchLoadingView.xib */,
|
||||||
);
|
);
|
||||||
|
@ -5969,6 +5969,7 @@
|
||||||
B1B558C920EF768F00210D55 /* RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.m in Sources */,
|
B1B558C920EF768F00210D55 /* RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.m in Sources */,
|
||||||
B1B5571B20EE6C4D00210D55 /* DeactivateAccountViewController.m in Sources */,
|
B1B5571B20EE6C4D00210D55 /* DeactivateAccountViewController.m in Sources */,
|
||||||
B1DCC63922E85E9A00625807 /* EmojiMartStore.swift in Sources */,
|
B1DCC63922E85E9A00625807 /* EmojiMartStore.swift in Sources */,
|
||||||
|
B10A3E9024FE4368007C380F /* ElementViewController.swift in Sources */,
|
||||||
B1B5590620EF768F00210D55 /* RoomMembershipCollapsedWithPaginationTitleBubbleCell.m in Sources */,
|
B1B5590620EF768F00210D55 /* RoomMembershipCollapsedWithPaginationTitleBubbleCell.m in Sources */,
|
||||||
B139C21D21FE5BF500BB68EC /* KeyBackupRecoverFromPassphraseViewModelType.swift in Sources */,
|
B139C21D21FE5BF500BB68EC /* KeyBackupRecoverFromPassphraseViewModelType.swift in Sources */,
|
||||||
B157FA9F23264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsCoordinator.swift in Sources */,
|
B157FA9F23264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsCoordinator.swift in Sources */,
|
||||||
|
@ -6143,7 +6144,6 @@
|
||||||
B1B557D820EF5EA900210D55 /* RoomActivitiesView.m in Sources */,
|
B1B557D820EF5EA900210D55 /* RoomActivitiesView.m in Sources */,
|
||||||
B1B9DEE922EB34EF0065E677 /* ReactionHistoryViewController.swift in Sources */,
|
B1B9DEE922EB34EF0065E677 /* ReactionHistoryViewController.swift in Sources */,
|
||||||
B1B5596620EF9E9B00210D55 /* RoomTableViewCell.m in Sources */,
|
B1B5596620EF9E9B00210D55 /* RoomTableViewCell.m in Sources */,
|
||||||
39D49C6624B8D40500FEDBC8 /* Timeline_1.swift in Sources */,
|
|
||||||
EC711B7D24A63B37008F830C /* SecretsSetupRecoveryPassphraseViewModel.swift in Sources */,
|
EC711B7D24A63B37008F830C /* SecretsSetupRecoveryPassphraseViewModel.swift in Sources */,
|
||||||
EC711B8024A63B37008F830C /* SecretsSetupRecoveryPassphraseViewState.swift in Sources */,
|
EC711B8024A63B37008F830C /* SecretsSetupRecoveryPassphraseViewState.swift in Sources */,
|
||||||
B1C45A89232A8C2600165425 /* SettingsIdentityServerViewController.swift in Sources */,
|
B1C45A89232A8C2600165425 /* SettingsIdentityServerViewController.swift in Sources */,
|
||||||
|
@ -6206,12 +6206,11 @@
|
||||||
B1B5574720EE6C4D00210D55 /* UsersDevicesViewController.m in Sources */,
|
B1B5574720EE6C4D00210D55 /* UsersDevicesViewController.m in Sources */,
|
||||||
B1098BFF21ECFE65000DDA48 /* PasswordStrengthView.swift in Sources */,
|
B1098BFF21ECFE65000DDA48 /* PasswordStrengthView.swift in Sources */,
|
||||||
B1B558D220EF768F00210D55 /* RoomEncryptedDataBubbleCell.m in Sources */,
|
B1B558D220EF768F00210D55 /* RoomEncryptedDataBubbleCell.m in Sources */,
|
||||||
|
B10A3E8F24FE4368007C380F /* Timeline_1.swift in Sources */,
|
||||||
EC711BB024A63B58008F830C /* SecureBackupBannerCell.swift in Sources */,
|
EC711BB024A63B58008F830C /* SecureBackupBannerCell.swift in Sources */,
|
||||||
B1B558FA20EF768F00210D55 /* RoomMembershipBubbleCell.m in Sources */,
|
B1B558FA20EF768F00210D55 /* RoomMembershipBubbleCell.m in Sources */,
|
||||||
39D49C6724B8D40500FEDBC8 /* ElementView.swift in Sources */,
|
|
||||||
B157FAA223264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsViewAction.swift in Sources */,
|
B157FAA223264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsViewAction.swift in Sources */,
|
||||||
EC85D6AE2477DC89002C44C9 /* RoundedButton.swift in Sources */,
|
EC85D6AE2477DC89002C44C9 /* RoundedButton.swift in Sources */,
|
||||||
39D49C6524B8D40500FEDBC8 /* ElementViewController.swift in Sources */,
|
|
||||||
B1CE83D72422817200D07506 /* KeyVerificationVerifyByScanningViewModelType.swift in Sources */,
|
B1CE83D72422817200D07506 /* KeyVerificationVerifyByScanningViewModelType.swift in Sources */,
|
||||||
3232ABA1225730E100AD6A5C /* KeyVerificationCoordinatorType.swift in Sources */,
|
3232ABA1225730E100AD6A5C /* KeyVerificationCoordinatorType.swift in Sources */,
|
||||||
B1C562D9228C0B760037F12A /* RoomContextualMenuItem.swift in Sources */,
|
B1C562D9228C0B760037F12A /* RoomContextualMenuItem.swift in Sources */,
|
||||||
|
@ -6329,6 +6328,7 @@
|
||||||
B1B9DEEE22EB34EF0065E677 /* ReactionHistoryViewAction.swift in Sources */,
|
B1B9DEEE22EB34EF0065E677 /* ReactionHistoryViewAction.swift in Sources */,
|
||||||
EC711BB624A63C11008F830C /* AuthenticatedSessionViewControllerFactory.swift in Sources */,
|
EC711BB624A63C11008F830C /* AuthenticatedSessionViewControllerFactory.swift in Sources */,
|
||||||
B1C543A4239E98E400DCA1FA /* KeyVerificationCellInnerContentView.swift in Sources */,
|
B1C543A4239E98E400DCA1FA /* KeyVerificationCellInnerContentView.swift in Sources */,
|
||||||
|
B10A3E8E24FE4368007C380F /* ElementView.swift in Sources */,
|
||||||
B1CE83B62422812100D07506 /* KeyVerificationCoordinatorBridgePresenter.swift in Sources */,
|
B1CE83B62422812100D07506 /* KeyVerificationCoordinatorBridgePresenter.swift in Sources */,
|
||||||
32B94DFA228EC26400716A26 /* ReactionsMenuButton.swift in Sources */,
|
32B94DFA228EC26400716A26 /* ReactionsMenuButton.swift in Sources */,
|
||||||
B1B9DEEC22EB34EF0065E677 /* ReactionHistoryViewModelType.swift in Sources */,
|
B1B9DEEC22EB34EF0065E677 /* ReactionHistoryViewModelType.swift in Sources */,
|
||||||
|
|
|
@ -26,13 +26,8 @@ extension UIApplication {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if #available(iOS 10.0, *) {
|
application.open(url, options: [:], completionHandler: { success in
|
||||||
application.open(url, options: [:], completionHandler: { success in
|
|
||||||
completion?(success)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
let success = application.openURL(url)
|
|
||||||
completion?(success)
|
completion?(success)
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,10 @@ final class RiotSettings: NSObject {
|
||||||
|
|
||||||
/// UserDefaults to be used on reads and writes.
|
/// UserDefaults to be used on reads and writes.
|
||||||
private lazy var defaults: UserDefaults = {
|
private lazy var defaults: UserDefaults = {
|
||||||
return UserDefaults(suiteName: BuildSettings.applicationGroupIdentifier)!
|
guard let userDefaults = UserDefaults(suiteName: BuildSettings.applicationGroupIdentifier) else {
|
||||||
|
fatalError("[RiotSettings] Fail to load shared UserDefaults")
|
||||||
|
}
|
||||||
|
return userDefaults
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
|
@ -93,12 +93,12 @@ import UIKit
|
||||||
/// Apply the theme on a navigation bar
|
/// Apply the theme on a navigation bar
|
||||||
///
|
///
|
||||||
/// - Parameter navigationBar: the navigation bar to customise.
|
/// - Parameter navigationBar: the navigation bar to customise.
|
||||||
func applyStyle(onNavigationBar: UINavigationBar)
|
func applyStyle(onNavigationBar navigationBar: UINavigationBar)
|
||||||
|
|
||||||
/// Apply the theme on a search bar.
|
/// Apply the theme on a search bar.
|
||||||
///
|
///
|
||||||
/// - Parameter searchBar: the search bar to customise.
|
/// - Parameter searchBar: the search bar to customise.
|
||||||
func applyStyle(onSearchBar: UISearchBar)
|
func applyStyle(onSearchBar searchBar: UISearchBar)
|
||||||
|
|
||||||
/// Apply the theme on a text field.
|
/// Apply the theme on a text field.
|
||||||
///
|
///
|
||||||
|
|
|
@ -1134,16 +1134,14 @@
|
||||||
{
|
{
|
||||||
NSLog(@"[AuthenticationVC] showResourceLimitExceededError");
|
NSLog(@"[AuthenticationVC] showResourceLimitExceededError");
|
||||||
|
|
||||||
[self showResourceLimitExceededError:errorDict onAdminContactTapped:^(NSURL *adminContact) {
|
[self showResourceLimitExceededError:errorDict onAdminContactTapped:^(NSURL *adminContactURL) {
|
||||||
|
|
||||||
if ([[UIApplication sharedApplication] canOpenURL:adminContact])
|
[[UIApplication sharedApplication] vc_open:adminContactURL completionHandler:^(BOOL success) {
|
||||||
{
|
if (!success)
|
||||||
[[UIApplication sharedApplication] openURL:adminContact];
|
{
|
||||||
}
|
NSLog(@"[AuthenticationVC] adminContact(%@) cannot be opened", adminContactURL);
|
||||||
else
|
}
|
||||||
{
|
}];
|
||||||
NSLog(@"[AuthenticationVC] adminContact(%@) cannot be opened", adminContact);
|
|
||||||
}
|
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,151 +0,0 @@
|
||||||
// Copyright © 2016-2019 JABT Labs Inc.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to
|
|
||||||
// deal in the Software without restriction, including without limitation the
|
|
||||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
||||||
// sell copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions: The above copyright
|
|
||||||
// notice and this permission notice shall be included in all copies or
|
|
||||||
// substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
||||||
// IN THE SOFTWARE.
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
open class Animation: NSObject, CAAnimationDelegate {
|
|
||||||
/// Key frame animations which animate the properties of `layer`.
|
|
||||||
fileprivate var keyframeAnimations: [CAKeyframeAnimation]
|
|
||||||
|
|
||||||
/// The CALayer whose properties are animated.
|
|
||||||
open var layer: CALayer
|
|
||||||
|
|
||||||
/// Specifies whether or not the animation should autoreverse.
|
|
||||||
var autoreverses: Bool
|
|
||||||
|
|
||||||
/// Determines the number of times the animation will repeat.
|
|
||||||
///
|
|
||||||
/// May be fractional. If the repeatCount is 0, it is ignored.
|
|
||||||
/// Setting this property to greatestFiniteMagnitude will cause the animation to repeat forever.
|
|
||||||
var repeatCount: Float
|
|
||||||
|
|
||||||
weak var delegate: AnimationDelegate?
|
|
||||||
|
|
||||||
/// The current time of the animation. i.e. what time is being displayed.
|
|
||||||
var time: TimeInterval {
|
|
||||||
return layer.timeOffset
|
|
||||||
}
|
|
||||||
|
|
||||||
/// True if the animation is playing.
|
|
||||||
var playing: Bool {
|
|
||||||
return layer.speed != 0.0
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Initializers
|
|
||||||
|
|
||||||
public init(layer: CALayer, keyframeAnimations: [CAKeyframeAnimation], autoreverses: Bool = false, repeatCount: Float = 0) {
|
|
||||||
self.layer = layer
|
|
||||||
self.keyframeAnimations = keyframeAnimations
|
|
||||||
self.autoreverses = autoreverses
|
|
||||||
self.repeatCount = repeatCount
|
|
||||||
|
|
||||||
super.init()
|
|
||||||
keyframeAnimations.forEach(configure)
|
|
||||||
reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
private func configure(keyframeAnimation: CAKeyframeAnimation) {
|
|
||||||
keyframeAnimation.delegate = self
|
|
||||||
keyframeAnimation.isRemovedOnCompletion = false
|
|
||||||
keyframeAnimation.fillMode = .both
|
|
||||||
keyframeAnimation.autoreverses = autoreverses
|
|
||||||
keyframeAnimation.repeatCount = repeatCount
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Playing & Resetting Animation
|
|
||||||
|
|
||||||
/// Resumes the animation from where it was paused.
|
|
||||||
open func play() {
|
|
||||||
let pausedTime = layer.timeOffset
|
|
||||||
layer.speed = 1.0
|
|
||||||
layer.timeOffset = 0.0
|
|
||||||
layer.beginTime = 0.0
|
|
||||||
let timeSincePause = layer.convertTime(CACurrentMediaTime(), from: nil) - pausedTime
|
|
||||||
layer.beginTime = timeSincePause
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Pauses the animation.
|
|
||||||
open func pause() {
|
|
||||||
let pausedTime = layer.convertTime(CACurrentMediaTime(), from: nil)
|
|
||||||
offset(to: pausedTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Resets the animation to time 0.
|
|
||||||
open func reset() {
|
|
||||||
CATransaction.suppressAnimations {
|
|
||||||
layer.removeAllAnimations()
|
|
||||||
layer.beginTime = 0
|
|
||||||
offset(to: 0)
|
|
||||||
|
|
||||||
for keyframeAnimation in keyframeAnimations {
|
|
||||||
layer.setValue(keyframeAnimation.values?.first, forKeyPath: keyframeAnimation.keyPath!)
|
|
||||||
}
|
|
||||||
|
|
||||||
addAllAnimations()
|
|
||||||
layer.speed = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Adds all the animations to `layer` so they can be played.
|
|
||||||
private func addAllAnimations() {
|
|
||||||
DispatchQueue.main.async { [weak self] in
|
|
||||||
guard let keyframeAnimations = self?.keyframeAnimations, let layer = self?.layer else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for keyframeAnimation in keyframeAnimations {
|
|
||||||
layer.add(keyframeAnimation, forKey: keyframeAnimation.keyPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Driving Animation
|
|
||||||
|
|
||||||
/// Shows the animation at time `time`.
|
|
||||||
open func offset(to time: TimeInterval) {
|
|
||||||
layer.speed = 0.0
|
|
||||||
layer.timeOffset = time
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - CAAnimationDelegate
|
|
||||||
|
|
||||||
public func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
|
|
||||||
guard flag else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let time = autoreverses ? 0 : (keyframeAnimations.first?.duration ?? 0)
|
|
||||||
offset(to: time)
|
|
||||||
|
|
||||||
if let keyframeAnimation = anim as? CAKeyframeAnimation,
|
|
||||||
keyframeAnimations.first?.keyPath == keyframeAnimation.keyPath {
|
|
||||||
delegate?.didStop(animation: self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public extension Animation {
|
|
||||||
var reversed: Animation {
|
|
||||||
let reversedKeyFrameAnimations = keyframeAnimations.map { $0.reversed }
|
|
||||||
return Animation(layer: layer, keyframeAnimations: reversedKeyFrameAnimations)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protocol AnimationDelegate: class {
|
|
||||||
func didStop(animation: Animation)
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
// Copyright © 2016-2019 JABT Labs Inc.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to
|
|
||||||
// deal in the Software without restriction, including without limitation the
|
|
||||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
||||||
// sell copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions: The above copyright
|
|
||||||
// notice and this permission notice shall be included in all copies or
|
|
||||||
// substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
||||||
// IN THE SOFTWARE.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
public extension CAKeyframeAnimation {
|
|
||||||
var reversed: CAKeyframeAnimation {
|
|
||||||
let reversed = CAKeyframeAnimation(keyPath: keyPath)
|
|
||||||
reversed.keyTimes = keyTimes?.reversed().map { NSNumber(floatLiteral: 1.0 - $0.doubleValue) }
|
|
||||||
reversed.values = values?.reversed()
|
|
||||||
reversed.timingFunctions = timingFunctions?.reversed().map { $0.reversed }
|
|
||||||
reversed.duration = duration
|
|
||||||
return reversed
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
// Copyright © 2016-2019 JABT Labs Inc.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to
|
|
||||||
// deal in the Software without restriction, including without limitation the
|
|
||||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
||||||
// sell copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions: The above copyright
|
|
||||||
// notice and this permission notice shall be included in all copies or
|
|
||||||
// substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
||||||
// IN THE SOFTWARE.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
public extension CAMediaTimingFunction {
|
|
||||||
static let linear = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
|
|
||||||
static let easeIn = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeIn)
|
|
||||||
static let easeOut = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)
|
|
||||||
static let easeInEaseOut = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
|
|
||||||
|
|
||||||
var reversed: CAMediaTimingFunction {
|
|
||||||
let (c1, c2) = controlPoints
|
|
||||||
let x1 = Float(1 - c2.x)
|
|
||||||
let y1 = Float(1 - c2.y)
|
|
||||||
let x2 = Float(1 - c1.x)
|
|
||||||
let y2 = Float(1 - c1.y)
|
|
||||||
return CAMediaTimingFunction(controlPoints: x1, y1, x2, y2)
|
|
||||||
}
|
|
||||||
|
|
||||||
var controlPoints: (CGPoint, CGPoint) {
|
|
||||||
var c1: [Float] = [0, 0]
|
|
||||||
var c2: [Float] = [0, 0]
|
|
||||||
getControlPoint(at: 1, values: &c1)
|
|
||||||
getControlPoint(at: 2, values: &c2)
|
|
||||||
|
|
||||||
let c1x = CGFloat(c1[0])
|
|
||||||
let c1y = CGFloat(c1[1])
|
|
||||||
let c2x = CGFloat(c2[0])
|
|
||||||
let c2y = CGFloat(c2[1])
|
|
||||||
|
|
||||||
return (CGPoint(x: c1x, y: c1y), CGPoint(x: c2x, y: c2y))
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
// Copyright © 2016-2019 JABT Labs Inc.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to
|
|
||||||
// deal in the Software without restriction, including without limitation the
|
|
||||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
||||||
// sell copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions: The above copyright
|
|
||||||
// notice and this permission notice shall be included in all copies or
|
|
||||||
// substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
||||||
// IN THE SOFTWARE.
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
extension CATransaction {
|
|
||||||
static public func suppressAnimations(actions: () -> Void) {
|
|
||||||
begin()
|
|
||||||
setAnimationDuration(0)
|
|
||||||
actions()
|
|
||||||
commit()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,310 +0,0 @@
|
||||||
// Copyright © 2016-2019 JABT Labs Inc.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to
|
|
||||||
// deal in the Software without restriction, including without limitation the
|
|
||||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
||||||
// sell copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions: The above copyright
|
|
||||||
// notice and this permission notice shall be included in all copies or
|
|
||||||
// substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
||||||
// IN THE SOFTWARE.
|
|
||||||
|
|
||||||
import QuartzCore
|
|
||||||
|
|
||||||
public func CGPathCreateWithSVGString(_ string: String) -> CGPath? {
|
|
||||||
let parser = SVGPathStringParser()
|
|
||||||
return try? parser.parse(string)
|
|
||||||
}
|
|
||||||
|
|
||||||
class SVGPathStringParser {
|
|
||||||
enum Error: Swift.Error {
|
|
||||||
case invalidSyntax
|
|
||||||
case missingValues
|
|
||||||
}
|
|
||||||
|
|
||||||
let path = CGMutablePath()
|
|
||||||
var currentPoint = CGPoint()
|
|
||||||
var lastControlPoint = CGPoint()
|
|
||||||
|
|
||||||
var command: UnicodeScalar?
|
|
||||||
var values = [CGFloat]()
|
|
||||||
|
|
||||||
func parse(_ string: String) throws -> CGPath {
|
|
||||||
let tokens = SVGPathStringTokenizer(string: string).tokenize()
|
|
||||||
|
|
||||||
for token in tokens {
|
|
||||||
switch token {
|
|
||||||
case .command(let c):
|
|
||||||
command = c
|
|
||||||
values.removeAll()
|
|
||||||
|
|
||||||
case .value(let v):
|
|
||||||
values.append(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
try addCommand()
|
|
||||||
} catch Error.missingValues {
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
|
|
||||||
fileprivate func addCommand() throws {
|
|
||||||
guard let command = command else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch command {
|
|
||||||
case "M":
|
|
||||||
if values.count < 2 { throw Error.missingValues }
|
|
||||||
path.move(to: CGPoint(x: values[0], y: values[1]))
|
|
||||||
currentPoint = CGPoint(x: values[0], y: values[1])
|
|
||||||
lastControlPoint = currentPoint
|
|
||||||
values.removeFirst(2)
|
|
||||||
|
|
||||||
case "m":
|
|
||||||
if values.count < 2 { throw Error.missingValues }
|
|
||||||
let point = CGPoint(x: currentPoint.x + values[0], y: currentPoint.y + values[1])
|
|
||||||
path.move(to: point)
|
|
||||||
currentPoint.x += values[0]
|
|
||||||
currentPoint.y += values[1]
|
|
||||||
lastControlPoint = currentPoint
|
|
||||||
values.removeFirst(2)
|
|
||||||
|
|
||||||
case "L":
|
|
||||||
if values.count < 2 { throw Error.missingValues }
|
|
||||||
let point = CGPoint(x: values[0], y: values[1])
|
|
||||||
path.addLine(to: point)
|
|
||||||
currentPoint = CGPoint(x: values[0], y: values[1])
|
|
||||||
lastControlPoint = currentPoint
|
|
||||||
values.removeFirst(2)
|
|
||||||
|
|
||||||
case "l":
|
|
||||||
if values.count < 2 { throw Error.missingValues }
|
|
||||||
let point = CGPoint(x: currentPoint.x + values[0], y: currentPoint.y + values[1])
|
|
||||||
path.addLine(to: point)
|
|
||||||
currentPoint.x += values[0]
|
|
||||||
currentPoint.y += values[1]
|
|
||||||
lastControlPoint = currentPoint
|
|
||||||
values.removeFirst(2)
|
|
||||||
|
|
||||||
case "H":
|
|
||||||
if values.count < 1 { throw Error.missingValues }
|
|
||||||
let point = CGPoint(x: values[0], y: currentPoint.y)
|
|
||||||
path.addLine(to: point)
|
|
||||||
currentPoint.x = values[0]
|
|
||||||
lastControlPoint = currentPoint
|
|
||||||
values.removeFirst(1)
|
|
||||||
|
|
||||||
case "h":
|
|
||||||
if values.count < 1 { throw Error.missingValues }
|
|
||||||
let point = CGPoint(x: currentPoint.x + values[0], y: currentPoint.y)
|
|
||||||
path.addLine(to: point)
|
|
||||||
currentPoint.x += values[0]
|
|
||||||
lastControlPoint = currentPoint
|
|
||||||
values.removeFirst(1)
|
|
||||||
|
|
||||||
case "V":
|
|
||||||
if values.count < 1 { throw Error.missingValues }
|
|
||||||
let point = CGPoint(x: currentPoint.x, y: values[0])
|
|
||||||
path.addLine(to: point)
|
|
||||||
currentPoint.y = values[0]
|
|
||||||
lastControlPoint = currentPoint
|
|
||||||
values.removeFirst(1)
|
|
||||||
|
|
||||||
case "v":
|
|
||||||
if values.count < 1 { throw Error.missingValues }
|
|
||||||
let point = CGPoint(x: currentPoint.x, y: currentPoint.y + values[0])
|
|
||||||
path.addLine(to: point)
|
|
||||||
currentPoint.y += values[0]
|
|
||||||
lastControlPoint = currentPoint
|
|
||||||
values.removeFirst(1)
|
|
||||||
|
|
||||||
case "C":
|
|
||||||
if values.count < 6 { throw Error.missingValues }
|
|
||||||
let c1 = CGPoint(x: values[0], y: values[1])
|
|
||||||
let c2 = CGPoint(x: values[2], y: values[3])
|
|
||||||
let to = CGPoint(x: values[4], y: values[5])
|
|
||||||
path.addCurve(to: to, control1: c1, control2: c2)
|
|
||||||
lastControlPoint = c2
|
|
||||||
currentPoint = to
|
|
||||||
values.removeFirst(6)
|
|
||||||
|
|
||||||
case "c":
|
|
||||||
if values.count < 6 { throw Error.missingValues }
|
|
||||||
let c1 = CGPoint(x: currentPoint.x + values[0], y: currentPoint.y + values[1])
|
|
||||||
let c2 = CGPoint(x: currentPoint.x + values[2], y: currentPoint.y + values[3])
|
|
||||||
let to = CGPoint(x: currentPoint.x + values[4], y: currentPoint.y + values[5])
|
|
||||||
path.addCurve(to: to, control1: c1, control2: c2)
|
|
||||||
lastControlPoint = c2
|
|
||||||
currentPoint = to
|
|
||||||
values.removeFirst(6)
|
|
||||||
|
|
||||||
case "S":
|
|
||||||
if values.count < 4 { throw Error.missingValues }
|
|
||||||
var c1 = CGPoint()
|
|
||||||
c1.x = currentPoint.x + (currentPoint.x - lastControlPoint.x)
|
|
||||||
c1.y = currentPoint.y + (currentPoint.y - lastControlPoint.y)
|
|
||||||
let c2 = CGPoint(x: values[0], y: values[1])
|
|
||||||
let to = CGPoint(x: values[2], y: values[3])
|
|
||||||
path.addCurve(to: to, control1: c1, control2: c2)
|
|
||||||
lastControlPoint = c2
|
|
||||||
currentPoint = to
|
|
||||||
values.removeFirst(4)
|
|
||||||
|
|
||||||
case "s":
|
|
||||||
if values.count < 4 { throw Error.missingValues }
|
|
||||||
var c1 = CGPoint()
|
|
||||||
c1.x = currentPoint.x + (currentPoint.x - lastControlPoint.x)
|
|
||||||
c1.y = currentPoint.y + (currentPoint.y - lastControlPoint.y)
|
|
||||||
let c2 = CGPoint(x: currentPoint.x + values[0], y: currentPoint.y + values[1])
|
|
||||||
let to = CGPoint(x: currentPoint.x + values[2], y: currentPoint.y + values[3])
|
|
||||||
path.addCurve(to: to, control1: c1, control2: c2)
|
|
||||||
lastControlPoint = c2
|
|
||||||
currentPoint = to
|
|
||||||
values.removeFirst(4)
|
|
||||||
|
|
||||||
case "Q":
|
|
||||||
if values.count < 4 { throw Error.missingValues }
|
|
||||||
let control = CGPoint(x: values[0], y: values[1])
|
|
||||||
let to = CGPoint(x: values[2], y: values[3])
|
|
||||||
path.addQuadCurve(to: to, control: control)
|
|
||||||
lastControlPoint = control
|
|
||||||
currentPoint = to
|
|
||||||
values.removeFirst(4)
|
|
||||||
|
|
||||||
case "q":
|
|
||||||
if values.count < 4 { throw Error.missingValues }
|
|
||||||
let control = CGPoint(x: currentPoint.x + values[0], y: currentPoint.y + values[1])
|
|
||||||
let to = CGPoint(x: currentPoint.x + values[2], y: currentPoint.y + values[3])
|
|
||||||
path.addQuadCurve(to: to, control: control)
|
|
||||||
lastControlPoint = control
|
|
||||||
currentPoint = to
|
|
||||||
values.removeFirst(4)
|
|
||||||
|
|
||||||
case "T":
|
|
||||||
if values.count < 2 { throw Error.missingValues }
|
|
||||||
var control = CGPoint()
|
|
||||||
control.x = currentPoint.x + (currentPoint.x - lastControlPoint.x)
|
|
||||||
control.y = currentPoint.y + (currentPoint.y - lastControlPoint.y)
|
|
||||||
let to = CGPoint(x: values[0], y: values[1])
|
|
||||||
path.addQuadCurve(to: to, control: control)
|
|
||||||
lastControlPoint = control
|
|
||||||
currentPoint = to
|
|
||||||
values.removeFirst(2)
|
|
||||||
|
|
||||||
case "t":
|
|
||||||
if values.count < 2 { throw Error.missingValues }
|
|
||||||
var control = CGPoint()
|
|
||||||
control.x = currentPoint.x + (currentPoint.x - lastControlPoint.x)
|
|
||||||
control.y = currentPoint.y + (currentPoint.y - lastControlPoint.y)
|
|
||||||
let to = CGPoint(x: currentPoint.x + values[0], y: currentPoint.y + values[1])
|
|
||||||
path.addQuadCurve(to: to, control: control)
|
|
||||||
lastControlPoint = control
|
|
||||||
currentPoint = to
|
|
||||||
values.removeFirst(2)
|
|
||||||
|
|
||||||
case "Z", "z":
|
|
||||||
path.closeSubpath()
|
|
||||||
self.command = nil
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw Error.invalidSyntax
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SVGPathStringTokenizer {
|
|
||||||
enum Token {
|
|
||||||
case command(UnicodeScalar)
|
|
||||||
case value(CGFloat)
|
|
||||||
}
|
|
||||||
|
|
||||||
let separatorCharacterSet = CharacterSet(charactersIn: " \t\r\n,")
|
|
||||||
let commandCharacterSet = CharacterSet(charactersIn: "mMLlHhVvzZCcSsQqTt")
|
|
||||||
let numberStartCharacterSet = CharacterSet(charactersIn: "-+.0123456789")
|
|
||||||
let numberCharacterSet = CharacterSet(charactersIn: ".0123456789eE")
|
|
||||||
|
|
||||||
var string: String
|
|
||||||
var range: Range<String.UnicodeScalarView.Index>
|
|
||||||
|
|
||||||
init(string: String) {
|
|
||||||
self.string = string
|
|
||||||
range = string.unicodeScalars.startIndex..<string.unicodeScalars.endIndex
|
|
||||||
}
|
|
||||||
|
|
||||||
func tokenize() -> [Token] {
|
|
||||||
var array = [Token]()
|
|
||||||
while let token = nextToken() {
|
|
||||||
array.append(token)
|
|
||||||
}
|
|
||||||
return array
|
|
||||||
}
|
|
||||||
|
|
||||||
func nextToken() -> Token? {
|
|
||||||
skipSeparators()
|
|
||||||
|
|
||||||
guard let c = get() else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if commandCharacterSet.isMember(c) {
|
|
||||||
return .command(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
if numberStartCharacterSet.isMember(c) {
|
|
||||||
var numberString = String(c)
|
|
||||||
while let c = peek(), numberCharacterSet.isMember(c) {
|
|
||||||
numberString += String(c)
|
|
||||||
get()
|
|
||||||
}
|
|
||||||
|
|
||||||
if let value = Double(numberString) {
|
|
||||||
return .value(CGFloat(value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
func get() -> UnicodeScalar? {
|
|
||||||
guard range.lowerBound != range.upperBound else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
let c = string.unicodeScalars[range.lowerBound]
|
|
||||||
range = string.unicodeScalars.index(after: range.lowerBound)..<range.upperBound
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func peek() -> UnicodeScalar? {
|
|
||||||
guard range.lowerBound != range.upperBound else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return string.unicodeScalars[range.lowerBound]
|
|
||||||
}
|
|
||||||
|
|
||||||
func skipSeparators() {
|
|
||||||
while range.lowerBound != range.upperBound && separatorCharacterSet.isMember(string.unicodeScalars[range.lowerBound]) {
|
|
||||||
range = string.unicodeScalars.index(after: range.lowerBound)..<range.upperBound
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
extension CharacterSet {
|
|
||||||
public func isMember(_ c: UnicodeScalar) -> Bool {
|
|
||||||
return contains(UnicodeScalar(c.value)!)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
// Copyright © 2016-2019 JABT Labs Inc.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to
|
|
||||||
// deal in the Software without restriction, including without limitation the
|
|
||||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
||||||
// sell copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions: The above copyright
|
|
||||||
// notice and this permission notice shall be included in all copies or
|
|
||||||
// substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
||||||
// IN THE SOFTWARE.
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
extension NSMutableParagraphStyle {
|
|
||||||
convenience init(alignment: NSTextAlignment,
|
|
||||||
firstLineHeadIndent: CGFloat,
|
|
||||||
headIndent: CGFloat,
|
|
||||||
tailIndent: CGFloat,
|
|
||||||
lineHeightMultiple: CGFloat,
|
|
||||||
maximumLineHeight: CGFloat,
|
|
||||||
minimumLineHeight: CGFloat,
|
|
||||||
lineSpacing: CGFloat,
|
|
||||||
paragraphSpacing: CGFloat,
|
|
||||||
paragraphSpacingBefore: CGFloat) {
|
|
||||||
self.init()
|
|
||||||
self.alignment = alignment
|
|
||||||
self.firstLineHeadIndent = firstLineHeadIndent
|
|
||||||
self.headIndent = headIndent
|
|
||||||
self.tailIndent = tailIndent
|
|
||||||
self.lineHeightMultiple = lineHeightMultiple
|
|
||||||
self.maximumLineHeight = maximumLineHeight
|
|
||||||
self.minimumLineHeight = minimumLineHeight
|
|
||||||
self.lineSpacing = lineSpacing
|
|
||||||
self.paragraphSpacing = paragraphSpacing
|
|
||||||
self.paragraphSpacingBefore = paragraphSpacingBefore
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
// Copyright © 2016-2019 JABT Labs Inc.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to
|
|
||||||
// deal in the Software without restriction, including without limitation the
|
|
||||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
||||||
// sell copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions: The above copyright
|
|
||||||
// notice and this permission notice shall be included in all copies or
|
|
||||||
// substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
||||||
// IN THE SOFTWARE.
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
extension NSShadow {
|
|
||||||
convenience init(blurRadius: CGFloat, offset: CGSize, color: UIColor) {
|
|
||||||
self.init()
|
|
||||||
shadowBlurRadius = blurRadius
|
|
||||||
shadowOffset = offset
|
|
||||||
shadowColor = color
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
// Copyright © 2016-2019 JABT
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to
|
|
||||||
// deal in the Software without restriction, including without limitation the
|
|
||||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
||||||
// sell copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions: The above copyright
|
|
||||||
// notice and this permission notice shall be included in all copies or
|
|
||||||
// substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
||||||
// IN THE SOFTWARE.
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
open class ShapeView: UIView {
|
|
||||||
open var shapeLayer: CAShapeLayer {
|
|
||||||
return (layer as? CAShapeLayer)!
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A sublayer which can be used to apply a gradient fill to `self`.
|
|
||||||
open var gradientLayer: CAGradientLayer? {
|
|
||||||
set {
|
|
||||||
// Remove old gradient layer
|
|
||||||
if let gradientLayer = gradientLayer {
|
|
||||||
gradientLayer.removeFromSuperlayer()
|
|
||||||
}
|
|
||||||
// Replace old gradient with new one
|
|
||||||
if let newGradientLayer = newValue {
|
|
||||||
layer.addSublayer(newGradientLayer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get {
|
|
||||||
return layer.sublayers?.first(where: { $0 is CAGradientLayer }) as? CAGradientLayer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public func addGradient(type: CAGradientLayerType, startPoint: CGPoint, endPoint: CGPoint, stops: [(color: CGColor, location: NSNumber)]) {
|
|
||||||
let gradientLayer = CAGradientLayer()
|
|
||||||
gradientLayer.frame = shapeLayer.bounds
|
|
||||||
self.gradientLayer = gradientLayer
|
|
||||||
|
|
||||||
|
|
||||||
let mask = CAShapeLayer()
|
|
||||||
mask.path = shapeLayer.path
|
|
||||||
mask.fillColor = UIColor.black.cgColor
|
|
||||||
mask.strokeColor = nil
|
|
||||||
|
|
||||||
gradientLayer.startPoint = startPoint
|
|
||||||
gradientLayer.endPoint = endPoint
|
|
||||||
gradientLayer.colors = stops.map { $0.color }
|
|
||||||
gradientLayer.locations = stops.map { $0.location }
|
|
||||||
gradientLayer.type = type
|
|
||||||
gradientLayer.frame = shapeLayer.bounds
|
|
||||||
gradientLayer.mask = mask
|
|
||||||
}
|
|
||||||
|
|
||||||
open var path: CGPath? {
|
|
||||||
get {
|
|
||||||
return shapeLayer.path
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
shapeLayer.path = newValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override open class var layerClass: AnyClass {
|
|
||||||
return CAShapeLayer.self
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
// Copyright © 2016-2019 JABT Labs Inc.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to
|
|
||||||
// deal in the Software without restriction, including without limitation the
|
|
||||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
||||||
// sell copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions: The above copyright
|
|
||||||
// notice and this permission notice shall be included in all copies or
|
|
||||||
// substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
||||||
// IN THE SOFTWARE.
|
|
||||||
|
|
||||||
import AVFoundation
|
|
||||||
|
|
||||||
public final class Sound {
|
|
||||||
|
|
||||||
static func playAudio(_ audio: AVAudioPlayer, delay: TimeInterval) {
|
|
||||||
audio.prepareToPlay()
|
|
||||||
let time = DispatchTime.now() + Double(Int64(delay * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: time) {
|
|
||||||
audio.play()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
// Copyright © 2016-2019 JABT
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to
|
|
||||||
// deal in the Software without restriction, including without limitation the
|
|
||||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
||||||
// sell copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions: The above copyright
|
|
||||||
// notice and this permission notice shall be included in all copies or
|
|
||||||
// substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
||||||
// IN THE SOFTWARE.
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
open class TextView: UILabel {
|
|
||||||
open var textLayer: CATextLayer {
|
|
||||||
return (layer as? CATextLayer)!
|
|
||||||
}
|
|
||||||
|
|
||||||
override open class var layerClass: AnyClass {
|
|
||||||
return CATextLayer.self
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,144 +0,0 @@
|
||||||
// Copyright © 2016-2019 JABT Labs Inc.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to
|
|
||||||
// deal in the Software without restriction, including without limitation the
|
|
||||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
||||||
// sell copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions: The above copyright
|
|
||||||
// notice and this permission notice shall be included in all copies or
|
|
||||||
// substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
||||||
// IN THE SOFTWARE.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import UIKit
|
|
||||||
import AVFoundation
|
|
||||||
|
|
||||||
open class Timeline {
|
|
||||||
public var view: UIView
|
|
||||||
public var duration: TimeInterval
|
|
||||||
public let animations: [Animation]
|
|
||||||
public let sounds: [(sound: AVAudioPlayer, delay: TimeInterval)]
|
|
||||||
|
|
||||||
/// Specifies whether or not the timeline's animations autoreverse.
|
|
||||||
public let autoreverses: Bool
|
|
||||||
|
|
||||||
/// Determines the number of times the timeline's animations will repeat.
|
|
||||||
///
|
|
||||||
/// May be fractional. If the repeatCount is 0, it is ignored.
|
|
||||||
/// Setting this property to greatestFiniteMagnitude will cause the timeline to repeat forever.
|
|
||||||
public let repeatCount: Float
|
|
||||||
|
|
||||||
public var time: TimeInterval {
|
|
||||||
return animations.first?.time ?? 0
|
|
||||||
}
|
|
||||||
|
|
||||||
public var playing: Bool {
|
|
||||||
return animations.first?.playing ?? false
|
|
||||||
}
|
|
||||||
|
|
||||||
public weak var delegate: TimelineDelegate?
|
|
||||||
|
|
||||||
// MARK: - Initializers
|
|
||||||
|
|
||||||
public convenience init(view: UIView, animationsByLayer: [CALayer: [CAKeyframeAnimation]], sounds: [(sound: AVAudioPlayer, delay: TimeInterval)], duration: TimeInterval, autoreverses: Bool = false, repeatCount: Float = 0) {
|
|
||||||
|
|
||||||
let animations = animationsByLayer.map {
|
|
||||||
Animation(layer: $0.0, keyframeAnimations: $0.1, autoreverses: autoreverses, repeatCount: repeatCount)
|
|
||||||
}
|
|
||||||
|
|
||||||
self.init(view: view, animations: animations, sounds: sounds, duration: duration, autoreverses: autoreverses, repeatCount: repeatCount)
|
|
||||||
}
|
|
||||||
|
|
||||||
init(view: UIView, animations: [Animation], sounds: [(sound: AVAudioPlayer, delay: TimeInterval)], duration: TimeInterval, autoreverses: Bool, repeatCount: Float) {
|
|
||||||
self.view = view
|
|
||||||
self.duration = duration
|
|
||||||
self.sounds = sounds
|
|
||||||
self.autoreverses = autoreverses
|
|
||||||
self.repeatCount = repeatCount
|
|
||||||
self.animations = animations
|
|
||||||
self.animations.first?.delegate = self
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Timeline Playback controls
|
|
||||||
|
|
||||||
/// Reset to the initial state of the timeline
|
|
||||||
public func reset() {
|
|
||||||
for animation in animations {
|
|
||||||
animation.reset()
|
|
||||||
}
|
|
||||||
delegate?.didReset(timeline: self)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Resume playing the timeline.
|
|
||||||
public func play() {
|
|
||||||
playSounds()
|
|
||||||
for animation in animations {
|
|
||||||
animation.play()
|
|
||||||
}
|
|
||||||
delegate?.didPlay(timeline: self)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func playSounds() {
|
|
||||||
for (sound, delay) in sounds {
|
|
||||||
Sound.playAudio(sound, delay: delay)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Pause playing of timeline.
|
|
||||||
public func pause() {
|
|
||||||
for animation in animations {
|
|
||||||
animation.pause()
|
|
||||||
}
|
|
||||||
delegate?.didPause(timeline: self)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Show timeline at time `time`.
|
|
||||||
public func offset(to time: TimeInterval) {
|
|
||||||
let time = max(min(time, duration), 0)
|
|
||||||
for animation in animations {
|
|
||||||
animation.offset(to: time)
|
|
||||||
}
|
|
||||||
delegate?.didOffset(timeline: self, to: time)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a reverses version of `self`.
|
|
||||||
var reversed: Timeline {
|
|
||||||
let reversedAnimations = animations.map { $0.reversed }
|
|
||||||
return Timeline(view: view, animations: reversedAnimations, sounds: sounds, duration: duration, autoreverses: autoreverses, repeatCount: repeatCount)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Timeline: AnimationDelegate {
|
|
||||||
func didStop(animation: Animation) {
|
|
||||||
delegate?.didStop(timeline: self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public protocol TimelineDelegate: class {
|
|
||||||
/// Informs the delegate that the timeline `timeline` was reset.
|
|
||||||
func didReset(timeline: Timeline)
|
|
||||||
|
|
||||||
/// Informs the delegate that the timeline `timeline` did start playing.
|
|
||||||
func didPlay(timeline: Timeline)
|
|
||||||
|
|
||||||
/// Informs the delegate that the timeline `timeline` was paused.
|
|
||||||
func didPause(timeline: Timeline)
|
|
||||||
|
|
||||||
/// Informs the delegate that the timeline `timeline` was offset.
|
|
||||||
///
|
|
||||||
/// - Parameters:
|
|
||||||
/// - timeline: The timeline which was offset.
|
|
||||||
/// - time: The time to which `timeline` was offset to.
|
|
||||||
func didOffset(timeline: Timeline, to time: TimeInterval)
|
|
||||||
|
|
||||||
/// Informs the delegate that the timeline `timeline` was stopped because it completed its active duration.
|
|
||||||
func didStop(timeline: Timeline)
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
// Copyright © 2016-2019 JABT Labs Inc.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to
|
|
||||||
// deal in the Software without restriction, including without limitation the
|
|
||||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
||||||
// sell copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions: The above copyright
|
|
||||||
// notice and this permission notice shall be included in all copies or
|
|
||||||
// substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
||||||
// IN THE SOFTWARE.
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
extension UIImage {
|
|
||||||
func resized(to size: CGSize) -> UIImage {
|
|
||||||
let rect = CGRect(origin: .zero, size: size)
|
|
||||||
let vertical = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: size.height)
|
|
||||||
return UIGraphicsImageRenderer(size: size).image { _ in
|
|
||||||
let ctx = UIGraphicsGetCurrentContext()
|
|
||||||
ctx?.saveGState()
|
|
||||||
ctx?.concatenate(vertical)
|
|
||||||
draw(in: rect)
|
|
||||||
ctx?.restoreGState()
|
|
||||||
UIGraphicsEndImageContext()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
// Copyright © 2016-2019 JABT Labs Inc.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to
|
|
||||||
// deal in the Software without restriction, including without limitation the
|
|
||||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
||||||
// sell copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions: The above copyright
|
|
||||||
// notice and this permission notice shall be included in all copies or
|
|
||||||
// substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
||||||
// IN THE SOFTWARE.
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
extension UIView {
|
|
||||||
func setTransform(scaleX: CGFloat, scaleY: CGFloat, rotationAngle: CGFloat) {
|
|
||||||
var transform = CGAffineTransform.identity
|
|
||||||
transform = transform.concatenating(CGAffineTransform(scaleX: scaleX, y: 1.0))
|
|
||||||
transform = transform.concatenating(CGAffineTransform(scaleX: 1.0, y: scaleY))
|
|
||||||
transform = transform.concatenating(CGAffineTransform(rotationAngle: rotationAngle))
|
|
||||||
self.transform = transform
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1610,14 +1610,9 @@
|
||||||
[plusButtonImageView.widthAnchor constraintEqualToConstant:side].active = YES;
|
[plusButtonImageView.widthAnchor constraintEqualToConstant:side].active = YES;
|
||||||
[plusButtonImageView.heightAnchor constraintEqualToConstant:side].active = YES;
|
[plusButtonImageView.heightAnchor constraintEqualToConstant:side].active = YES;
|
||||||
|
|
||||||
if (@available(iOS 11.0, *)) {
|
// align to safe area
|
||||||
// align to safe area
|
[plusButtonImageView.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor].active = YES;
|
||||||
[plusButtonImageView.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor].active = YES;
|
[self.view.safeAreaLayoutGuide.bottomAnchor constraintEqualToAnchor:plusButtonImageView.bottomAnchor constant:9].active = YES;
|
||||||
[self.view.safeAreaLayoutGuide.bottomAnchor constraintEqualToAnchor:plusButtonImageView.bottomAnchor constant:9].active = YES;
|
|
||||||
} else {
|
|
||||||
[plusButtonImageView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor].active = YES;
|
|
||||||
[self.bottomLayoutGuide.topAnchor constraintEqualToAnchor:plusButtonImageView.bottomAnchor constant:9].active = YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
plusButtonImageView.userInteractionEnabled = YES;
|
plusButtonImageView.userInteractionEnabled = YES;
|
||||||
|
|
||||||
|
|
|
@ -100,11 +100,9 @@ static const CGFloat kInterItemsSpaceHorizontal = 8.0;
|
||||||
[super layoutSubviews];
|
[super layoutSubviews];
|
||||||
|
|
||||||
CGFloat _leftInset = 0.0, _rightInset = 0.0;
|
CGFloat _leftInset = 0.0, _rightInset = 0.0;
|
||||||
if (@available(iOS 11, *))
|
|
||||||
{
|
_leftInset += self.safeAreaInsets.left;
|
||||||
_leftInset += self.safeAreaInsets.left;
|
_rightInset += self.safeAreaInsets.right;
|
||||||
_rightInset += self.safeAreaInsets.right;
|
|
||||||
}
|
|
||||||
|
|
||||||
CGFloat leftMargin = MAX(_leftInset, _minimumLeftInset);
|
CGFloat leftMargin = MAX(_leftInset, _minimumLeftInset);
|
||||||
CGFloat rightMargin = MAX(_rightInset, _minimumRightInset);
|
CGFloat rightMargin = MAX(_rightInset, _minimumRightInset);
|
||||||
|
|
|
@ -138,50 +138,9 @@
|
||||||
|
|
||||||
self.contactAvatar.contentMode = UIViewContentModeScaleAspectFill;
|
self.contactAvatar.contentMode = UIViewContentModeScaleAspectFill;
|
||||||
self.contactAvatar.defaultBackgroundColor = [UIColor clearColor];
|
self.contactAvatar.defaultBackgroundColor = [UIColor clearColor];
|
||||||
|
|
||||||
if (@available(iOS 11.0, *))
|
|
||||||
{
|
|
||||||
// Define directly the navigation titleView with the custom title view instance. Do not use anymore a container.
|
|
||||||
self.navigationItem.titleView = contactTitleView;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self.navigationItem.titleView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 600, 40)];
|
|
||||||
|
|
||||||
// Add the title view and define edge constraints
|
// Define directly the navigation titleView with the custom title view instance. Do not use anymore a container.
|
||||||
contactTitleView.translatesAutoresizingMaskIntoConstraints = NO;
|
self.navigationItem.titleView = contactTitleView;
|
||||||
[self.navigationItem.titleView addSubview:contactTitleView];
|
|
||||||
|
|
||||||
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:contactTitleView
|
|
||||||
attribute:NSLayoutAttributeTop
|
|
||||||
relatedBy:NSLayoutRelationEqual
|
|
||||||
toItem:self.navigationItem.titleView
|
|
||||||
attribute:NSLayoutAttributeTop
|
|
||||||
multiplier:1.0f
|
|
||||||
constant:0.0f];
|
|
||||||
NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:contactTitleView
|
|
||||||
attribute:NSLayoutAttributeBottom
|
|
||||||
relatedBy:NSLayoutRelationEqual
|
|
||||||
toItem:self.navigationItem.titleView
|
|
||||||
attribute:NSLayoutAttributeBottom
|
|
||||||
multiplier:1.0f
|
|
||||||
constant:0.0f];
|
|
||||||
NSLayoutConstraint *leadingConstraint = [NSLayoutConstraint constraintWithItem:contactTitleView
|
|
||||||
attribute:NSLayoutAttributeLeading
|
|
||||||
relatedBy:NSLayoutRelationEqual
|
|
||||||
toItem:self.navigationItem.titleView
|
|
||||||
attribute:NSLayoutAttributeLeading
|
|
||||||
multiplier:1.0f
|
|
||||||
constant:0.0f];
|
|
||||||
NSLayoutConstraint *trailingConstraint = [NSLayoutConstraint constraintWithItem:contactTitleView
|
|
||||||
attribute:NSLayoutAttributeTrailing
|
|
||||||
relatedBy:NSLayoutRelationEqual
|
|
||||||
toItem:self.navigationItem.titleView
|
|
||||||
attribute:NSLayoutAttributeTrailing
|
|
||||||
multiplier:1.0f
|
|
||||||
constant:0.0f];
|
|
||||||
[NSLayoutConstraint activateConstraints:@[topConstraint, bottomConstraint, leadingConstraint, trailingConstraint]];
|
|
||||||
}
|
|
||||||
|
|
||||||
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
|
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
|
||||||
[tap setNumberOfTouchesRequired:1];
|
[tap setNumberOfTouchesRequired:1];
|
||||||
|
|
|
@ -399,14 +399,7 @@
|
||||||
|
|
||||||
CGSize fittingSize = UILayoutFittingCompressedSize;
|
CGSize fittingSize = UILayoutFittingCompressedSize;
|
||||||
CGFloat tableViewWidth = CGRectGetWidth(tableView.frame);
|
CGFloat tableViewWidth = CGRectGetWidth(tableView.frame);
|
||||||
CGFloat safeAreaWidth;
|
CGFloat safeAreaWidth = MAX(tableView.safeAreaInsets.left, tableView.safeAreaInsets.right);
|
||||||
|
|
||||||
if (@available(iOS 11.0, *)) {
|
|
||||||
// Take safe area into account
|
|
||||||
safeAreaWidth = MAX(tableView.safeAreaInsets.left, tableView.safeAreaInsets.right);
|
|
||||||
} else {
|
|
||||||
safeAreaWidth = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fittingSize.width = tableViewWidth - safeAreaWidth;
|
fittingSize.width = tableViewWidth - safeAreaWidth;
|
||||||
|
|
||||||
|
|
|
@ -411,8 +411,15 @@ NSString *const kJavascriptSendResponseToPostMessageAPI = @"riotIOS.sendResponse
|
||||||
|
|
||||||
if (navigationAction.navigationType == WKNavigationTypeLinkActivated)
|
if (navigationAction.navigationType == WKNavigationTypeLinkActivated)
|
||||||
{
|
{
|
||||||
|
NSURL *linkURL = navigationAction.request.URL;
|
||||||
|
|
||||||
// Open links outside the app
|
// Open links outside the app
|
||||||
[[UIApplication sharedApplication] openURL:navigationAction.request.URL];
|
[[UIApplication sharedApplication] vc_open:linkURL completionHandler:^(BOOL success) {
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
NSLog(@"[WidgetVC] webView:decidePolicyForNavigationAction:decisionHandler fail to open external link: %@", linkURL);
|
||||||
|
}
|
||||||
|
}];
|
||||||
decisionHandler(WKNavigationActionPolicyCancel);
|
decisionHandler(WKNavigationActionPolicyCancel);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,9 +122,12 @@ final class KeyBackupSetupSuccessFromPassphraseViewController: UIViewController
|
||||||
}
|
}
|
||||||
|
|
||||||
private func shareRecoveryKey() {
|
private func shareRecoveryKey() {
|
||||||
|
guard let recoveryKey = self.recoveryKey else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Set up activity view controller
|
// Set up activity view controller
|
||||||
let activityItems: [Any] = [ self.recoveryKey ]
|
let activityItems: [Any] = [ recoveryKey ]
|
||||||
let activityViewController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)
|
let activityViewController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)
|
||||||
|
|
||||||
// Configure source view when activity view controller is presented with a popover
|
// Configure source view when activity view controller is presented with a popover
|
||||||
|
|
|
@ -146,51 +146,9 @@
|
||||||
|
|
||||||
memberTitleView = [RoomMemberTitleView roomMemberTitleView];
|
memberTitleView = [RoomMemberTitleView roomMemberTitleView];
|
||||||
memberTitleView.delegate = self;
|
memberTitleView.delegate = self;
|
||||||
|
|
||||||
if (@available(iOS 11.0, *))
|
|
||||||
{
|
|
||||||
// Define directly the navigation titleView with the custom title view instance. Do not use anymore a container.
|
|
||||||
self.navigationItem.titleView = memberTitleView;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self.navigationItem.titleView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 600, 40)];
|
|
||||||
|
|
||||||
// Add the title view and define edge constraints
|
// Define directly the navigation titleView with the custom title view instance. Do not use anymore a container.
|
||||||
memberTitleView.translatesAutoresizingMaskIntoConstraints = NO;
|
self.navigationItem.titleView = memberTitleView;
|
||||||
[self.navigationItem.titleView addSubview:memberTitleView];
|
|
||||||
|
|
||||||
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:memberTitleView
|
|
||||||
attribute:NSLayoutAttributeTop
|
|
||||||
relatedBy:NSLayoutRelationEqual
|
|
||||||
toItem:self.navigationItem.titleView
|
|
||||||
attribute:NSLayoutAttributeTop
|
|
||||||
multiplier:1.0f
|
|
||||||
constant:0.0f];
|
|
||||||
NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:memberTitleView
|
|
||||||
attribute:NSLayoutAttributeBottom
|
|
||||||
relatedBy:NSLayoutRelationEqual
|
|
||||||
toItem:self.navigationItem.titleView
|
|
||||||
attribute:NSLayoutAttributeBottom
|
|
||||||
multiplier:1.0f
|
|
||||||
constant:0.0f];
|
|
||||||
NSLayoutConstraint *leadingConstraint = [NSLayoutConstraint constraintWithItem:memberTitleView
|
|
||||||
attribute:NSLayoutAttributeLeading
|
|
||||||
relatedBy:NSLayoutRelationEqual
|
|
||||||
toItem:self.navigationItem.titleView
|
|
||||||
attribute:NSLayoutAttributeLeading
|
|
||||||
multiplier:1.0f
|
|
||||||
constant:0.0f];
|
|
||||||
NSLayoutConstraint *trailingConstraint = [NSLayoutConstraint constraintWithItem:memberTitleView
|
|
||||||
attribute:NSLayoutAttributeTrailing
|
|
||||||
relatedBy:NSLayoutRelationEqual
|
|
||||||
toItem:self.navigationItem.titleView
|
|
||||||
attribute:NSLayoutAttributeTrailing
|
|
||||||
multiplier:1.0f
|
|
||||||
constant:0.0f];
|
|
||||||
|
|
||||||
[NSLayoutConstraint activateConstraints:@[topConstraint, bottomConstraint, leadingConstraint, trailingConstraint]];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add tap gesture on member's name
|
// Add tap gesture on member's name
|
||||||
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
|
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
|
||||||
|
|
|
@ -40,54 +40,26 @@
|
||||||
|
|
||||||
if (self.superview)
|
if (self.superview)
|
||||||
{
|
{
|
||||||
if (@available(iOS 11.0, *))
|
// Force the title view layout by adding 2 new constraints on the UINavigationBarContentView instance.
|
||||||
{
|
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:self
|
||||||
// Force the title view layout by adding 2 new constraints on the UINavigationBarContentView instance.
|
attribute:NSLayoutAttributeTop
|
||||||
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:self
|
relatedBy:NSLayoutRelationEqual
|
||||||
attribute:NSLayoutAttributeTop
|
toItem:self.superview
|
||||||
|
attribute:NSLayoutAttributeTop
|
||||||
|
multiplier:1.0f
|
||||||
|
constant:0.0f];
|
||||||
|
NSLayoutConstraint *centerXConstraint = [NSLayoutConstraint constraintWithItem:self
|
||||||
|
attribute:NSLayoutAttributeCenterX
|
||||||
relatedBy:NSLayoutRelationEqual
|
relatedBy:NSLayoutRelationEqual
|
||||||
toItem:self.superview
|
toItem:self.superview
|
||||||
attribute:NSLayoutAttributeTop
|
attribute:NSLayoutAttributeCenterX
|
||||||
multiplier:1.0f
|
multiplier:1.0f
|
||||||
constant:0.0f];
|
constant:0.0f];
|
||||||
NSLayoutConstraint *centerXConstraint = [NSLayoutConstraint constraintWithItem:self
|
|
||||||
attribute:NSLayoutAttributeCenterX
|
[NSLayoutConstraint activateConstraints:@[topConstraint, centerXConstraint]];
|
||||||
relatedBy:NSLayoutRelationEqual
|
|
||||||
toItem:self.superview
|
// Do not crop the avatar
|
||||||
attribute:NSLayoutAttributeCenterX
|
self.superview.clipsToBounds = NO;
|
||||||
multiplier:1.0f
|
|
||||||
constant:0.0f];
|
|
||||||
|
|
||||||
[NSLayoutConstraint activateConstraints:@[topConstraint, centerXConstraint]];
|
|
||||||
|
|
||||||
// Do not crop the avatar
|
|
||||||
self.superview.clipsToBounds = NO;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Center horizontally the avatar into the navigation bar
|
|
||||||
CGRect frame = self.superview.frame;
|
|
||||||
UINavigationBar *navigationBar;
|
|
||||||
UIView *superView = self;
|
|
||||||
while (superView.superview)
|
|
||||||
{
|
|
||||||
if ([superView.superview isKindOfClass:[UINavigationBar class]])
|
|
||||||
{
|
|
||||||
navigationBar = (UINavigationBar*)superView.superview;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
superView = superView.superview;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (navigationBar)
|
|
||||||
{
|
|
||||||
CGSize navBarSize = navigationBar.frame.size;
|
|
||||||
CGFloat superviewCenterX = frame.origin.x + (frame.size.width / 2);
|
|
||||||
|
|
||||||
self.memberAvatarMaskCenterXConstraint.constant = (navBarSize.width / 2) - superviewCenterX;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_delegate && [_delegate respondsToSelector:@selector(roomMemberTitleViewDidLayoutSubview:)])
|
if (_delegate && [_delegate respondsToSelector:@selector(roomMemberTitleViewDidLayoutSubview:)])
|
||||||
|
|
|
@ -4438,15 +4438,13 @@
|
||||||
|
|
||||||
if ([self.roomDataSource.mxSession.syncError.errcode isEqualToString:kMXErrCodeStringResourceLimitExceeded])
|
if ([self.roomDataSource.mxSession.syncError.errcode isEqualToString:kMXErrCodeStringResourceLimitExceeded])
|
||||||
{
|
{
|
||||||
[roomActivitiesView showResourceLimitExceededError:self.roomDataSource.mxSession.syncError.userInfo onAdminContactTapped:^(NSURL *adminContact) {
|
[roomActivitiesView showResourceLimitExceededError:self.roomDataSource.mxSession.syncError.userInfo onAdminContactTapped:^(NSURL *adminContactURL) {
|
||||||
if ([[UIApplication sharedApplication] canOpenURL:adminContact])
|
[[UIApplication sharedApplication] vc_open:adminContactURL completionHandler:^(BOOL success) {
|
||||||
{
|
if (!success)
|
||||||
[[UIApplication sharedApplication] openURL:adminContact];
|
{
|
||||||
}
|
NSLog(@"[RoomVC] refreshActivitiesViewDisplay: adminContact(%@) cannot be opened", adminContactURL);
|
||||||
else
|
}
|
||||||
{
|
}];
|
||||||
NSLog(@"[RoomVC] refreshActivitiesViewDisplay: adminContact(%@) cannot be opened", adminContact);
|
|
||||||
}
|
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
else if ([AppDelegate theDelegate].isOffline)
|
else if ([AppDelegate theDelegate].isOffline)
|
||||||
|
@ -4613,16 +4611,13 @@
|
||||||
}
|
}
|
||||||
else if (serverNotices.usageLimit && serverNotices.usageLimit.isServerNoticeUsageLimit)
|
else if (serverNotices.usageLimit && serverNotices.usageLimit.isServerNoticeUsageLimit)
|
||||||
{
|
{
|
||||||
[roomActivitiesView showResourceUsageLimitNotice:serverNotices.usageLimit onAdminContactTapped:^(NSURL *adminContact) {
|
[roomActivitiesView showResourceUsageLimitNotice:serverNotices.usageLimit onAdminContactTapped:^(NSURL *adminContactURL) {
|
||||||
|
[[UIApplication sharedApplication] vc_open:adminContactURL completionHandler:^(BOOL success) {
|
||||||
if ([[UIApplication sharedApplication] canOpenURL:adminContact])
|
if (!success)
|
||||||
{
|
{
|
||||||
[[UIApplication sharedApplication] openURL:adminContact];
|
NSLog(@"[RoomVC] refreshActivitiesViewDisplay: adminContact(%@) cannot be opened", adminContactURL);
|
||||||
}
|
}
|
||||||
else
|
}];
|
||||||
{
|
|
||||||
NSLog(@"[RoomVC] refreshActivitiesViewDisplay: adminContact(%@) cannot be opened", adminContact);
|
|
||||||
}
|
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -40,54 +40,26 @@
|
||||||
|
|
||||||
if (self.superview)
|
if (self.superview)
|
||||||
{
|
{
|
||||||
if (@available(iOS 11.0, *))
|
// Force the title view layout by adding 2 new constraints on the UINavigationBarContentView instance.
|
||||||
{
|
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:self
|
||||||
// Force the title view layout by adding 2 new constraints on the UINavigationBarContentView instance.
|
attribute:NSLayoutAttributeTop
|
||||||
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:self
|
relatedBy:NSLayoutRelationEqual
|
||||||
attribute:NSLayoutAttributeTop
|
toItem:self.superview
|
||||||
|
attribute:NSLayoutAttributeTop
|
||||||
|
multiplier:1.0f
|
||||||
|
constant:0.0f];
|
||||||
|
NSLayoutConstraint *centerXConstraint = [NSLayoutConstraint constraintWithItem:self
|
||||||
|
attribute:NSLayoutAttributeCenterX
|
||||||
relatedBy:NSLayoutRelationEqual
|
relatedBy:NSLayoutRelationEqual
|
||||||
toItem:self.superview
|
toItem:self.superview
|
||||||
attribute:NSLayoutAttributeTop
|
attribute:NSLayoutAttributeCenterX
|
||||||
multiplier:1.0f
|
multiplier:1.0f
|
||||||
constant:0.0f];
|
constant:0.0f];
|
||||||
NSLayoutConstraint *centerXConstraint = [NSLayoutConstraint constraintWithItem:self
|
|
||||||
attribute:NSLayoutAttributeCenterX
|
[NSLayoutConstraint activateConstraints:@[topConstraint, centerXConstraint]];
|
||||||
relatedBy:NSLayoutRelationEqual
|
|
||||||
toItem:self.superview
|
// Do not crop the avatar
|
||||||
attribute:NSLayoutAttributeCenterX
|
self.superview.clipsToBounds = NO;
|
||||||
multiplier:1.0f
|
|
||||||
constant:0.0f];
|
|
||||||
|
|
||||||
[NSLayoutConstraint activateConstraints:@[topConstraint, centerXConstraint]];
|
|
||||||
|
|
||||||
// Do not crop the avatar
|
|
||||||
self.superview.clipsToBounds = NO;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Center horizontally the avatar into the navigation bar
|
|
||||||
CGRect frame = self.superview.frame;
|
|
||||||
UINavigationBar *navigationBar;
|
|
||||||
UIView *superView = self;
|
|
||||||
while (superView.superview)
|
|
||||||
{
|
|
||||||
if ([superView.superview isKindOfClass:[UINavigationBar class]])
|
|
||||||
{
|
|
||||||
navigationBar = (UINavigationBar*)superView.superview;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
superView = superView.superview;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (navigationBar)
|
|
||||||
{
|
|
||||||
CGSize navBarSize = navigationBar.frame.size;
|
|
||||||
CGFloat superviewCenterX = frame.origin.x + (frame.size.width / 2);
|
|
||||||
|
|
||||||
self.roomAvatarMaskCenterXConstraint.constant = (navBarSize.width / 2) - superviewCenterX;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,59 +78,23 @@
|
||||||
|
|
||||||
if (self.superview)
|
if (self.superview)
|
||||||
{
|
{
|
||||||
if (@available(iOS 11.0, *))
|
// Force the title view layout by adding 2 new constraints on the UINavigationBarContentView instance.
|
||||||
{
|
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:self
|
||||||
// Force the title view layout by adding 2 new constraints on the UINavigationBarContentView instance.
|
attribute:NSLayoutAttributeTop
|
||||||
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:self
|
relatedBy:NSLayoutRelationEqual
|
||||||
attribute:NSLayoutAttributeTop
|
toItem:self.superview
|
||||||
|
attribute:NSLayoutAttributeTop
|
||||||
|
multiplier:1.0f
|
||||||
|
constant:0.0f];
|
||||||
|
NSLayoutConstraint *centerXConstraint = [NSLayoutConstraint constraintWithItem:self
|
||||||
|
attribute:NSLayoutAttributeCenterX
|
||||||
relatedBy:NSLayoutRelationEqual
|
relatedBy:NSLayoutRelationEqual
|
||||||
toItem:self.superview
|
toItem:self.superview
|
||||||
attribute:NSLayoutAttributeTop
|
attribute:NSLayoutAttributeCenterX
|
||||||
multiplier:1.0f
|
multiplier:1.0f
|
||||||
constant:0.0f];
|
constant:0.0f];
|
||||||
NSLayoutConstraint *centerXConstraint = [NSLayoutConstraint constraintWithItem:self
|
|
||||||
attribute:NSLayoutAttributeCenterX
|
[NSLayoutConstraint activateConstraints:@[topConstraint, centerXConstraint]];
|
||||||
relatedBy:NSLayoutRelationEqual
|
|
||||||
toItem:self.superview
|
|
||||||
attribute:NSLayoutAttributeCenterX
|
|
||||||
multiplier:1.0f
|
|
||||||
constant:0.0f];
|
|
||||||
|
|
||||||
[NSLayoutConstraint activateConstraints:@[topConstraint, centerXConstraint]];
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Center horizontally the display name into the navigation bar
|
|
||||||
CGRect frame = self.superview.frame;
|
|
||||||
|
|
||||||
// Look for the navigation bar.
|
|
||||||
UINavigationBar *navigationBar;
|
|
||||||
UIView *superView = self;
|
|
||||||
while (superView.superview)
|
|
||||||
{
|
|
||||||
if ([superView.superview isKindOfClass:[UINavigationBar class]])
|
|
||||||
{
|
|
||||||
navigationBar = (UINavigationBar*)superView.superview;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
superView = superView.superview;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (navigationBar)
|
|
||||||
{
|
|
||||||
CGSize navBarSize = navigationBar.frame.size;
|
|
||||||
CGFloat superviewCenterX = frame.origin.x + (frame.size.width / 2);
|
|
||||||
|
|
||||||
// Check whether the view is not moving away (see navigation between view controllers).
|
|
||||||
if (superviewCenterX < navBarSize.width)
|
|
||||||
{
|
|
||||||
// Center the display name
|
|
||||||
self.displayNameCenterXConstraint.constant = (navBarSize.width / 2) - superviewCenterX;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,52 +38,23 @@
|
||||||
|
|
||||||
if (self.superview)
|
if (self.superview)
|
||||||
{
|
{
|
||||||
if (@available(iOS 11.0, *))
|
// Force the title view layout by adding 2 new constraints on the UINavigationBarContentView instance.
|
||||||
{
|
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:self
|
||||||
// Force the title view layout by adding 2 new constraints on the UINavigationBarContentView instance.
|
attribute:NSLayoutAttributeTop
|
||||||
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:self
|
relatedBy:NSLayoutRelationEqual
|
||||||
attribute:NSLayoutAttributeTop
|
toItem:self.superview
|
||||||
|
attribute:NSLayoutAttributeTop
|
||||||
|
multiplier:1.0f
|
||||||
|
constant:0.0f];
|
||||||
|
NSLayoutConstraint *centerXConstraint = [NSLayoutConstraint constraintWithItem:self
|
||||||
|
attribute:NSLayoutAttributeCenterX
|
||||||
relatedBy:NSLayoutRelationEqual
|
relatedBy:NSLayoutRelationEqual
|
||||||
toItem:self.superview
|
toItem:self.superview
|
||||||
attribute:NSLayoutAttributeTop
|
attribute:NSLayoutAttributeCenterX
|
||||||
multiplier:1.0f
|
multiplier:1.0f
|
||||||
constant:0.0f];
|
constant:0.0f];
|
||||||
NSLayoutConstraint *centerXConstraint = [NSLayoutConstraint constraintWithItem:self
|
|
||||||
attribute:NSLayoutAttributeCenterX
|
[NSLayoutConstraint activateConstraints:@[topConstraint, centerXConstraint]];
|
||||||
relatedBy:NSLayoutRelationEqual
|
|
||||||
toItem:self.superview
|
|
||||||
attribute:NSLayoutAttributeCenterX
|
|
||||||
multiplier:1.0f
|
|
||||||
constant:0.0f];
|
|
||||||
|
|
||||||
[NSLayoutConstraint activateConstraints:@[topConstraint, centerXConstraint]];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Center horizontally the display name into the navigation bar
|
|
||||||
CGRect frame = self.superview.frame;
|
|
||||||
UINavigationBar *navigationBar;
|
|
||||||
UIView *superView = self;
|
|
||||||
while (superView.superview)
|
|
||||||
{
|
|
||||||
if ([superView.superview isKindOfClass:[UINavigationBar class]])
|
|
||||||
{
|
|
||||||
navigationBar = (UINavigationBar*)superView.superview;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
superView = superView.superview;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (navigationBar)
|
|
||||||
{
|
|
||||||
CGSize navBarSize = navigationBar.frame.size;
|
|
||||||
CGFloat superviewCenterX = frame.origin.x + (frame.size.width / 2);
|
|
||||||
|
|
||||||
// Center the display name
|
|
||||||
self.displayNameCenterXConstraint.constant = (navBarSize.width / 2) - superviewCenterX;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1947,16 +1947,7 @@ TableViewSectionsDelegate>
|
||||||
|
|
||||||
if (!theme)
|
if (!theme)
|
||||||
{
|
{
|
||||||
if (@available(iOS 11.0, *))
|
theme = @"auto";
|
||||||
{
|
|
||||||
// "auto" is used the default value from iOS 11
|
|
||||||
theme = @"auto";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Use "light" for older version
|
|
||||||
theme = @"light";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
theme = [NSString stringWithFormat:@"settings_ui_theme_%@", theme];
|
theme = [NSString stringWithFormat:@"settings_ui_theme_%@", theme];
|
||||||
|
@ -3506,17 +3497,14 @@ TableViewSectionsDelegate>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (@available(iOS 11.0, *))
|
// Show "auto" only from iOS 11
|
||||||
{
|
autoAction = [UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"settings_ui_theme_auto", @"Vector", nil)
|
||||||
// Show "auto" only from iOS 11
|
style:UIAlertActionStyleDefault
|
||||||
autoAction = [UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"settings_ui_theme_auto", @"Vector", nil)
|
handler:actionBlock];
|
||||||
style:UIAlertActionStyleDefault
|
|
||||||
handler:actionBlock];
|
// Explain what is "auto"
|
||||||
|
themePickerMessage = NSLocalizedStringFromTable(@"settings_ui_theme_picker_message", @"Vector", nil);
|
||||||
// Explain what is "auto"
|
|
||||||
themePickerMessage = NSLocalizedStringFromTable(@"settings_ui_theme_picker_message", @"Vector", nil);
|
|
||||||
}
|
|
||||||
|
|
||||||
lightAction = [UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"settings_ui_theme_light", @"Vector", nil)
|
lightAction = [UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"settings_ui_theme_light", @"Vector", nil)
|
||||||
style:UIAlertActionStyleDefault
|
style:UIAlertActionStyleDefault
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
@implementation AvatarGenerator
|
@implementation AvatarGenerator
|
||||||
|
|
||||||
static NSMutableDictionary *imageByKeyDict = nil;
|
static NSMutableDictionary *imageByKeyDict = nil;
|
||||||
static NSMutableArray* colorsList = nil;
|
static NSArray* colorsList = nil;
|
||||||
static UILabel* backgroundLabel = nil;
|
static UILabel* backgroundLabel = nil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -22,11 +22,14 @@ final class DataProtectionHelper {
|
||||||
/// - Parameter appGroupIdentifier: App-group identifier to be used when deciding where it'll try to write the file.
|
/// - Parameter appGroupIdentifier: App-group identifier to be used when deciding where it'll try to write the file.
|
||||||
/// - Returns: true if the state detected
|
/// - Returns: true if the state detected
|
||||||
static func isDeviceInRebootedAndLockedState(appGroupIdentifier: String? = nil) -> Bool {
|
static func isDeviceInRebootedAndLockedState(appGroupIdentifier: String? = nil) -> Bool {
|
||||||
|
|
||||||
|
let dummyString = String.unique
|
||||||
|
guard let dummyData = dummyString.data(using: .utf8) else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let dummyString = String.unique
|
var url: URL
|
||||||
let dummyData = dummyString.data(using: .utf8)!
|
|
||||||
|
|
||||||
var url: URL!
|
|
||||||
if let identifier = appGroupIdentifier,
|
if let identifier = appGroupIdentifier,
|
||||||
let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: identifier) {
|
let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: identifier) {
|
||||||
url = containerURL
|
url = containerURL
|
||||||
|
|
|
@ -161,7 +161,7 @@
|
||||||
|
|
||||||
#pragma mark - INSendMessageIntentHandling
|
#pragma mark - INSendMessageIntentHandling
|
||||||
|
|
||||||
- (void)resolveRecipientsForSendMessage:(INSendMessageIntent *)intent withCompletion:(void (^)(NSArray<INPersonResolutionResult *> * _Nonnull))completion
|
- (void)resolveRecipientsForSendMessage:(INSendMessageIntent *)intent completion:(void (^)(NSArray<INSendMessageRecipientResolutionResult *> * _Nonnull))completion
|
||||||
{
|
{
|
||||||
[self resolveContacts:intent.recipients withCompletion:completion];
|
[self resolveContacts:intent.recipients withCompletion:completion];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# ./getlogs.sh https://riot.im/bugreports/listing/2020-06-07/104229/
|
|
||||||
|
|
||||||
if [ ! $# -eq 1 ]; then
|
|
||||||
echo "Usage: ./getLogs.sh [http link]"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
LOGS_URL=$1
|
|
||||||
|
|
||||||
ID=$( basename $LOGS_URL )
|
|
||||||
|
|
||||||
echo $ID
|
|
||||||
mkdir $ID
|
|
||||||
cd $ID
|
|
||||||
|
|
||||||
wget -r -nd --user=matrix --password=a^njerkoo=les $LOGS_URL
|
|
||||||
|
|
||||||
for f in *.log.gz; do
|
|
||||||
mv -- "$f" "${f%.log.gz}.log"
|
|
||||||
done
|
|
||||||
|
|
||||||
rm *.html
|
|
||||||
|
|
Loading…
Reference in a new issue