Create notification service extension

Signed-off-by: ismailgulek <gulekismail@gmail.com>
This commit is contained in:
ismailgulek
2020-05-22 14:27:30 +03:00
parent ff09e18abf
commit eb2d572e91
12 changed files with 1004 additions and 144 deletions

View File

@@ -93,6 +93,10 @@ abstract_target 'RiotPods' do
import_MatrixKitAppExtension
end
target "RiotNSE" do
import_MatrixKitAppExtension
end
end

View File

@@ -684,6 +684,7 @@
B1E5368D21FB7245001F3AFF /* KeyBackupRecoverFromPassphraseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1E5368C21FB7245001F3AFF /* KeyBackupRecoverFromPassphraseViewController.swift */; };
B1E5368F21FB7258001F3AFF /* KeyBackupRecoverFromPassphraseViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B1E5368E21FB7258001F3AFF /* KeyBackupRecoverFromPassphraseViewController.storyboard */; };
B1FDF56021F5FE5500BA3834 /* KeyBackupSetupPassphraseViewAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1FDF55F21F5FE5500BA3834 /* KeyBackupSetupPassphraseViewAction.swift */; };
DB1392A2332C3CAF6C9962EF /* Pods_RiotPods_RiotNSE.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E4D418D054E4032F2CFA8B51 /* Pods_RiotPods_RiotNSE.framework */; };
EC85D6AE2477DC89002C44C9 /* RoundedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC85D6AD2477DC89002C44C9 /* RoundedButton.swift */; };
EC85D7142477DCD7002C44C9 /* KeyVerificationScanConfirmationViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC85D70C2477DCD7002C44C9 /* KeyVerificationScanConfirmationViewState.swift */; };
EC85D7152477DCD7002C44C9 /* KeyVerificationScanConfirmationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC85D70D2477DCD7002C44C9 /* KeyVerificationScanConfirmationViewController.swift */; };
@@ -706,6 +707,9 @@
EC85D7372477DD97002C44C9 /* LocalContactsSectionHeaderContainerView.m in Sources */ = {isa = PBXBuildFile; fileRef = EC85D7352477DD97002C44C9 /* LocalContactsSectionHeaderContainerView.m */; };
EC85D73A2477DDB8002C44C9 /* DirectorySectionHeaderContainerView.m in Sources */ = {isa = PBXBuildFile; fileRef = EC85D7392477DDB8002C44C9 /* DirectorySectionHeaderContainerView.m */; };
EC85D73E2477DDD0002C44C9 /* PushNotificationService.m in Sources */ = {isa = PBXBuildFile; fileRef = EC85D73D2477DDD0002C44C9 /* PushNotificationService.m */; };
EC85D7462477E5F7002C44C9 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC85D7452477E5F7002C44C9 /* NotificationService.swift */; };
EC85D74A2477E5F7002C44C9 /* RiotNSE.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = EC85D7432477E5F7002C44C9 /* RiotNSE.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
EC85D74F2477E8EB002C44C9 /* RiotSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1B5597F20EFC3DF00210D55 /* RiotSettings.swift */; };
ECB101302477CFDB00CF8C11 /* UITableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECB1012C2477CFDB00CF8C11 /* UITableView.swift */; };
ECB101312477CFDB00CF8C11 /* UILabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECB1012D2477CFDB00CF8C11 /* UILabel.swift */; };
ECB101322477CFDB00CF8C11 /* UIDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECB1012E2477CFDB00CF8C11 /* UIDevice.swift */; };
@@ -751,6 +755,13 @@
remoteGlobalIDString = 92726A421F58737A004AD26F;
remoteInfo = SiriIntents;
};
EC85D7482477E5F7002C44C9 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F094A99A1B78D8F000B1FBBF /* Project object */;
proxyType = 1;
remoteGlobalIDString = EC85D7422477E5F7002C44C9;
remoteInfo = RiotNSE;
};
F094A9BF1B78D8F000B1FBBF /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F094A99A1B78D8F000B1FBBF /* Project object */;
@@ -769,6 +780,7 @@
files = (
24CBEC591F0EAD310093EABB /* RiotShareExtension.appex in Embed App Extensions */,
92726A4B1F58737A004AD26F /* SiriIntents.appex in Embed App Extensions */,
EC85D74A2477E5F7002C44C9 /* RiotNSE.appex in Embed App Extensions */,
);
name = "Embed App Extensions";
runOnlyForDeploymentPostprocessing = 0;
@@ -779,6 +791,7 @@
129EB7E27E7E4AC3F5F098F5 /* Pods_RiotTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RiotTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
1ACF09217ADF1D7E7A35BC02 /* Pods_RiotPods_Riot.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RiotPods_Riot.framework; sourceTree = BUILT_PRODUCTS_DIR; };
24CBEC4E1F0EAD310093EABB /* RiotShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = RiotShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
2B582BE9B2A98BCF5F740873 /* Pods-RiotPods-RiotNSE.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RiotPods-RiotNSE.debug.xcconfig"; path = "Target Support Files/Pods-RiotPods-RiotNSE/Pods-RiotPods-RiotNSE.debug.xcconfig"; sourceTree = "<group>"; };
3209451121F1C1430088CAA2 /* BlackTheme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlackTheme.swift; sourceTree = "<group>"; };
32242F0821E8B05F00725742 /* UIColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIColor.swift; sourceTree = "<group>"; };
32242F0C21E8FBA900725742 /* ThemeService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ThemeService.m; sourceTree = "<group>"; };
@@ -912,6 +925,7 @@
43C2962BE367F59220F517FA /* Pods-RiotPods-Riot.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RiotPods-Riot.debug.xcconfig"; path = "Target Support Files/Pods-RiotPods-Riot/Pods-RiotPods-Riot.debug.xcconfig"; sourceTree = "<group>"; };
4FC6A5D63FAD1B27C2F57AFA /* Pods-RiotPods-RiotShareExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RiotPods-RiotShareExtension.release.xcconfig"; path = "Target Support Files/Pods-RiotPods-RiotShareExtension/Pods-RiotPods-RiotShareExtension.release.xcconfig"; sourceTree = "<group>"; };
51187E952D5CECF6D6F5A28E /* Pods_RiotPods_SiriIntents.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RiotPods_SiriIntents.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8A61E94F88EA96AFE1CFD9D3 /* Pods-RiotPods-RiotNSE.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RiotPods-RiotNSE.release.xcconfig"; path = "Target Support Files/Pods-RiotPods-RiotNSE/Pods-RiotPods-RiotNSE.release.xcconfig"; sourceTree = "<group>"; };
926FA53D1F4C132000F826C2 /* MXSession+Riot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MXSession+Riot.h"; sourceTree = "<group>"; };
926FA53E1F4C132000F826C2 /* MXSession+Riot.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MXSession+Riot.m"; sourceTree = "<group>"; };
92726A431F58737A004AD26F /* SiriIntents.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = SiriIntents.appex; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -1673,6 +1687,7 @@
B43DC75D1590BB8A4243BD4D /* Pods-RiotPods-Riot.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RiotPods-Riot.release.xcconfig"; path = "Target Support Files/Pods-RiotPods-Riot/Pods-RiotPods-Riot.release.xcconfig"; sourceTree = "<group>"; };
BABB6681FBD79219B1213D6C /* Pods-RiotTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RiotTests.debug.xcconfig"; path = "Target Support Files/Pods-RiotTests/Pods-RiotTests.debug.xcconfig"; sourceTree = "<group>"; };
E2599D0ECB8DD206624E450B /* Pods-RiotPods-SiriIntents.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RiotPods-SiriIntents.release.xcconfig"; path = "Target Support Files/Pods-RiotPods-SiriIntents/Pods-RiotPods-SiriIntents.release.xcconfig"; sourceTree = "<group>"; };
E4D418D054E4032F2CFA8B51 /* Pods_RiotPods_RiotNSE.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RiotPods_RiotNSE.framework; sourceTree = BUILT_PRODUCTS_DIR; };
EC85D6AD2477DC89002C44C9 /* RoundedButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoundedButton.swift; sourceTree = "<group>"; };
EC85D70C2477DCD7002C44C9 /* KeyVerificationScanConfirmationViewState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyVerificationScanConfirmationViewState.swift; sourceTree = "<group>"; };
EC85D70D2477DCD7002C44C9 /* KeyVerificationScanConfirmationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyVerificationScanConfirmationViewController.swift; sourceTree = "<group>"; };
@@ -1700,6 +1715,10 @@
EC85D7392477DDB8002C44C9 /* DirectorySectionHeaderContainerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DirectorySectionHeaderContainerView.m; sourceTree = "<group>"; };
EC85D73C2477DDD0002C44C9 /* PushNotificationService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PushNotificationService.h; sourceTree = "<group>"; };
EC85D73D2477DDD0002C44C9 /* PushNotificationService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PushNotificationService.m; sourceTree = "<group>"; };
EC85D7432477E5F7002C44C9 /* RiotNSE.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = RiotNSE.appex; sourceTree = BUILT_PRODUCTS_DIR; };
EC85D7452477E5F7002C44C9 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = "<group>"; };
EC85D7472477E5F7002C44C9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
EC85D74E2477E614002C44C9 /* RiotNSE.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RiotNSE.entitlements; sourceTree = "<group>"; };
ECB1012C2477CFDB00CF8C11 /* UITableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UITableView.swift; sourceTree = "<group>"; };
ECB1012D2477CFDB00CF8C11 /* UILabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UILabel.swift; sourceTree = "<group>"; };
ECB1012E2477CFDB00CF8C11 /* UIDevice.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIDevice.swift; sourceTree = "<group>"; };
@@ -1763,6 +1782,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
EC85D7402477E5F7002C44C9 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
DB1392A2332C3CAF6C9962EF /* Pods_RiotPods_RiotNSE.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F094A99F1B78D8F000B1FBBF /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -2111,6 +2138,8 @@
E2599D0ECB8DD206624E450B /* Pods-RiotPods-SiriIntents.release.xcconfig */,
BABB6681FBD79219B1213D6C /* Pods-RiotTests.debug.xcconfig */,
AC34BF67FD21A9D01C16AE5D /* Pods-RiotTests.release.xcconfig */,
2B582BE9B2A98BCF5F740873 /* Pods-RiotPods-RiotNSE.debug.xcconfig */,
8A61E94F88EA96AFE1CFD9D3 /* Pods-RiotPods-RiotNSE.release.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
@@ -2123,6 +2152,7 @@
97151D7F0F892081250D50A3 /* Pods_RiotPods_RiotShareExtension.framework */,
51187E952D5CECF6D6F5A28E /* Pods_RiotPods_SiriIntents.framework */,
129EB7E27E7E4AC3F5F098F5 /* Pods_RiotTests.framework */,
E4D418D054E4032F2CFA8B51 /* Pods_RiotPods_RiotNSE.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@@ -4247,6 +4277,16 @@
path = PushNotification;
sourceTree = "<group>";
};
EC85D7442477E5F7002C44C9 /* RiotNSE */ = {
isa = PBXGroup;
children = (
EC85D74E2477E614002C44C9 /* RiotNSE.entitlements */,
EC85D7452477E5F7002C44C9 /* NotificationService.swift */,
EC85D7472477E5F7002C44C9 /* Info.plist */,
);
path = RiotNSE;
sourceTree = "<group>";
};
F083BB021E7005FD00A9B29C /* RiotTests */ = {
isa = PBXGroup;
children = (
@@ -4407,6 +4447,7 @@
F083BB021E7005FD00A9B29C /* RiotTests */,
24CBEC4F1F0EAD310093EABB /* RiotShareExtension */,
92726A441F58737A004AD26F /* SiriIntents */,
EC85D7442477E5F7002C44C9 /* RiotNSE */,
F094A9A31B78D8F000B1FBBF /* Products */,
5FC42FA41F5186AFFB6A2404 /* Frameworks */,
3232AAFE22564D9100AD6A5C /* Tools */,
@@ -4422,6 +4463,7 @@
F094A9BE1B78D8F000B1FBBF /* RiotTests.xctest */,
24CBEC4E1F0EAD310093EABB /* RiotShareExtension.appex */,
92726A431F58737A004AD26F /* SiriIntents.appex */,
EC85D7432477E5F7002C44C9 /* RiotNSE.appex */,
);
name = Products;
sourceTree = "<group>";
@@ -4465,6 +4507,24 @@
productReference = 92726A431F58737A004AD26F /* SiriIntents.appex */;
productType = "com.apple.product-type.app-extension";
};
EC85D7422477E5F7002C44C9 /* RiotNSE */ = {
isa = PBXNativeTarget;
buildConfigurationList = EC85D74D2477E5F7002C44C9 /* Build configuration list for PBXNativeTarget "RiotNSE" */;
buildPhases = (
E96A5016582B740FB3EABBB3 /* [CP] Check Pods Manifest.lock */,
EC85D73F2477E5F7002C44C9 /* Sources */,
EC85D7402477E5F7002C44C9 /* Frameworks */,
EC85D7412477E5F7002C44C9 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = RiotNSE;
productName = RiotNSE;
productReference = EC85D7432477E5F7002C44C9 /* RiotNSE.appex */;
productType = "com.apple.product-type.app-extension";
};
F094A9A11B78D8F000B1FBBF /* Riot */ = {
isa = PBXNativeTarget;
buildConfigurationList = F094A9C81B78D8F000B1FBBF /* Build configuration list for PBXNativeTarget "Riot" */;
@@ -4483,6 +4543,7 @@
dependencies = (
242661F61F12B1BA00D3FC08 /* PBXTargetDependency */,
92726A4A1F58737A004AD26F /* PBXTargetDependency */,
EC85D7492477E5F7002C44C9 /* PBXTargetDependency */,
);
name = Riot;
productName = Vector;
@@ -4514,6 +4575,8 @@
F094A99A1B78D8F000B1FBBF /* Project object */ = {
isa = PBXProject;
attributes = {
DefaultBuildSystemTypeForWorkspace = Original;
LastSwiftUpdateCheck = 1130;
LastUpgradeCheck = 0940;
ORGANIZATIONNAME = matrix.org;
TargetAttributes = {
@@ -4538,6 +4601,9 @@
};
};
};
EC85D7422477E5F7002C44C9 = {
CreatedOnToolsVersion = 11.3.1;
};
F094A9A11B78D8F000B1FBBF = {
CreatedOnToolsVersion = 6.2;
DevelopmentTeam = 7J4U792NQT;
@@ -4599,6 +4665,7 @@
F094A9BD1B78D8F000B1FBBF /* RiotTests */,
24CBEC4D1F0EAD310093EABB /* RiotShareExtension */,
92726A421F58737A004AD26F /* SiriIntents */,
EC85D7422477E5F7002C44C9 /* RiotNSE */,
);
};
/* End PBXProject section */
@@ -4625,6 +4692,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
EC85D7412477E5F7002C44C9 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
F094A9A01B78D8F000B1FBBF /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@@ -4934,6 +5008,28 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
E96A5016582B740FB3EABBB3 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-RiotPods-RiotNSE-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
FF06981FDA0DB688B8C52A41 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -4997,6 +5093,15 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
EC85D73F2477E5F7002C44C9 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
EC85D74F2477E8EB002C44C9 /* RiotSettings.swift in Sources */,
EC85D7462477E5F7002C44C9 /* NotificationService.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F094A99E1B78D8F000B1FBBF /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -5540,6 +5645,11 @@
target = 92726A421F58737A004AD26F /* SiriIntents */;
targetProxy = 92726A491F58737A004AD26F /* PBXContainerItemProxy */;
};
EC85D7492477E5F7002C44C9 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = EC85D7422477E5F7002C44C9 /* RiotNSE */;
targetProxy = EC85D7482477E5F7002C44C9 /* PBXContainerItemProxy */;
};
F094A9C01B78D8F000B1FBBF /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = F094A9A11B78D8F000B1FBBF /* Riot */;
@@ -5791,6 +5901,83 @@
};
name = Release;
};
EC85D74B2477E5F7002C44C9 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 2B582BE9B2A98BCF5F740873 /* Pods-RiotPods-RiotNSE.debug.xcconfig */;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = RiotNSE/RiotNSE.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 0.11.5;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 7J4U792NQT;
ENABLE_BITCODE = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = RiotNSE/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 0.11.5;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = im.vector.app.nse;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
EC85D74C2477E5F7002C44C9 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 8A61E94F88EA96AFE1CFD9D3 /* Pods-RiotPods-RiotNSE.release.xcconfig */;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = RiotNSE/RiotNSE.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 0.11.5;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = 7J4U792NQT;
ENABLE_BITCODE = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = RiotNSE/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 0.11.5;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = im.vector.app.nse;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
F094A9C61B78D8F000B1FBBF /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -6041,6 +6228,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
EC85D74D2477E5F7002C44C9 /* Build configuration list for PBXNativeTarget "RiotNSE" */ = {
isa = XCConfigurationList;
buildConfigurations = (
EC85D74B2477E5F7002C44C9 /* Debug */,
EC85D74C2477E5F7002C44C9 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
F094A99D1B78D8F000B1FBBF /* Build configuration list for PBXProject "Riot" */ = {
isa = XCConfigurationList;
buildConfigurations = (

View File

@@ -273,6 +273,28 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
[self.pushNotificationService registerForRemoteNotificationsWithCompletion:completion];
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
[self.pushNotificationService didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
NSString * deviceTokenString = [[[[deviceToken description]
stringByReplacingOccurrencesOfString: @"<" withString: @""]
stringByReplacingOccurrencesOfString: @">" withString: @""]
stringByReplacingOccurrencesOfString: @" " withString: @""];
NSLog(@"The generated device token string is : %@",deviceTokenString);
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
[self.pushNotificationService didFailToRegisterForRemoteNotificationsWithError:error];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
[self.pushNotificationService didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
#pragma mark -
- (NSString*)appVersion
@@ -484,6 +506,9 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
[MXSDKOptions sharedInstance].analyticsDelegate = [Analytics sharedInstance];
[DecryptionFailureTracker sharedInstance].delegate = [Analytics sharedInstance];
[[Analytics sharedInstance] start];
// Disable CallKit
[MXKAppSettings standardAppSettings].enableCallKit = NO;
self.pushNotificationService = [PushNotificationService new];
self.pushNotificationService.delegate = self;
@@ -1953,7 +1978,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
if (isPushRegistered)
{
// Enable push notifications by default on new added account
[account enablePushKitNotifications:YES success:nil failure:nil];
[account enablePushNotifications:YES success:nil failure:nil];
}
else
{
@@ -2034,13 +2059,13 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
accountManager.storeClass = [MXFileStore class];
// Disable APNS use.
if (accountManager.apnsDeviceToken)
{
// We use now Pushkit, unregister for all remote notifications received via Apple Push Notification service.
[[UIApplication sharedApplication] unregisterForRemoteNotifications];
[accountManager setApnsDeviceToken:nil];
}
// if (accountManager.apnsDeviceToken)
// {
// // We use now Pushkit, unregister for all remote notifications received via Apple Push Notification service.
// [[UIApplication sharedApplication] unregisterForRemoteNotifications];
// [accountManager setApnsDeviceToken:nil];
// }
// Observers have been defined, we can start a matrix session for each enabled accounts.
NSLog(@"[AppDelegate] initMatrixSessions: prepareSessionForActiveAccounts (app state: %tu)", [[UIApplication sharedApplication] applicationState]);
[accountManager prepareSessionForActiveAccounts];
@@ -4541,6 +4566,11 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
NSDictionary *defaults = [NSDictionary dictionaryWithContentsOfFile:defaultsPathFromApp];
[[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
if (!RiotSettings.shared.isUserDefaultsMigrated)
{
[RiotSettings.shared migrate];
}
// Now use RiotSettings and NSUserDefaults to store `showDecryptedContentInNotifications` setting option
// Migrate this information from main MXKAccount to RiotSettings, if value is not in UserDefaults

View File

@@ -12,6 +12,10 @@
<string>im.vector.app.ios.voip.prod</string>
<key>pushKitAppIdDev</key>
<string>im.vector.app.ios.voip.dev</string>
<key>pusherAppIdDev</key>
<string>im.vector.app.ios.dev</string>
<key>pusherAppIdProd</key>
<string>im.vector.app.ios.prod</string>
<key>identityserverurl</key>
<string>https://vector.im</string>
<key>homeserverurl</key>

View File

@@ -34,6 +34,8 @@ internal enum RiotDefaults {
internal static let pushGatewayURL: String = _document["pushGatewayURL"]
internal static let pushKitAppIdDev: String = _document["pushKitAppIdDev"]
internal static let pushKitAppIdProd: String = _document["pushKitAppIdProd"]
internal static let pusherAppIdDev: String = _document["pusherAppIdDev"]
internal static let pusherAppIdProd: String = _document["pusherAppIdProd"]
internal static let roomDirectoryServers: [String: Any] = _document["roomDirectoryServers"]
internal static let showAllEventsInRoomHistory: Bool = _document["showAllEventsInRoomHistory"]
internal static let showLeftMembersInRoomMemberList: Bool = _document["showLeftMembersInRoomMemberList"]

View File

@@ -15,16 +15,19 @@
limitations under the License.
*/
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <PushKit/PushKit.h>
#import <UserNotifications/UserNotifications.h>
@class MXSession;
@class MXEvent;
@class MXPushRule;
@class MXKAccount;
@protocol PushNotificationServiceDelegate;
NS_ASSUME_NONNULL_BEGIN
@interface PushNotificationService : NSObject <PKPushRegistryDelegate, UNUserNotificationCenterDelegate>
@interface PushNotificationService : NSObject <UNUserNotificationCenterDelegate>
/**
Is push really registered.
@@ -48,6 +51,13 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)registerForRemoteNotificationsWithCompletion:(nullable void (^)(NSError *))completion;
- (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken;
- (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error;
- (void)didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler;
/**
Perform deregistration for remote notifications.
*/

View File

@@ -46,7 +46,7 @@
NSMutableDictionary <NSNumber *, MXOnNotification> *notificationListenerBlocks;
}
@property (nonatomic, strong) PKPushRegistry *pushRegistry;
//@property (nonatomic, strong) PKPushRegistry *pushRegistry;
@property (nonatomic) NSMutableDictionary <NSNumber *, NSMutableArray <NSString *> *> *incomingPushEventIds;
@@ -110,16 +110,83 @@
- (void)registerForRemoteNotificationsWithCompletion:(nullable void (^)(NSError *))completion
{
self.pushRegistry = [[PKPushRegistry alloc] initWithQueue:nil];
self.pushRegistry.delegate = self;
self.pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
self.registrationForRemoteNotificationsCompletion = completion;
dispatch_async(dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] registerForRemoteNotifications];
});
}
- (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
MXKAccountManager* accountManager = [MXKAccountManager sharedManager];
[accountManager setApnsDeviceToken:deviceToken];
// remove PushKit pusher if exists
if (accountManager.pushDeviceToken)
{
[accountManager setPushDeviceToken:nil withPushOptions:nil];
}
// Sanity check: Make sure the Pushkit push token is deleted
NSParameterAssert(!accountManager.isPushAvailable);
NSParameterAssert(!accountManager.pushDeviceToken);
_isPushRegistered = YES;
if (self.registrationForRemoteNotificationsCompletion)
{
self.registrationForRemoteNotificationsCompletion(nil);
self.registrationForRemoteNotificationsCompletion = nil;
}
}
- (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
[self clearPushNotificationToken];
if (self.registrationForRemoteNotificationsCompletion)
{
self.registrationForRemoteNotificationsCompletion(error);
self.registrationForRemoteNotificationsCompletion = nil;
}
}
- (void)didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
// NSLog(@"[PushNotificationService][Push] didReceiveRemoteNotification: applicationState: %tu - payload: %@", [UIApplication sharedApplication].applicationState, userInfo);
//
// // Display local notifications only when the app is running in background.
// if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground)
// {
// NSLog(@"[PushNotificationService][Push] didReceiveRemoteNotification while app is in background");
//
// // Check whether an event id is provided.
// NSString *eventId = userInfo[@"event_id"];
// if (eventId)
// {
// // Add this event identifier in the pending push array for each session.
// for (NSMutableArray *array in self.incomingPushEventIds.allValues)
// {
// [array addObject:eventId];
// }
//
// // Cache payload for further usage
// incomingPushPayloads[eventId] = userInfo;
// }
// else
// {
// NSLog(@"[PushNotificationService][Push] didReceiveRemoteNotification - Unexpected payload %@", userInfo);
// }
//
// // Trigger a background sync to handle notifications.
// [self launchBackgroundSync];
// }
//
completionHandler(UIBackgroundFetchResultNewData);
}
- (void)deregisterRemoteNotifications
{
self.pushRegistry = nil;
_isPushRegistered = NO;
}
@@ -259,64 +326,64 @@
}
}
#pragma mark - PKPushRegistryDelegate
//#pragma mark - PKPushRegistryDelegate
//
//- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(PKPushType)type
//{
// NSData *token = credentials.token;
//
// NSLog(@"[PushNotificationService][Push] didUpdatePushCredentials: Got Push token: %@. Type: %@", [MXKTools logForPushToken:token], type);
//
// MXKAccountManager* accountManager = [MXKAccountManager sharedManager];
// [accountManager setPushDeviceToken:token withPushOptions:@{@"format": @"event_id_only"}];
//
// _isPushRegistered = YES;
//
// if (self.registrationForRemoteNotificationsCompletion)
// {
// self.registrationForRemoteNotificationsCompletion(nil);
// self.registrationForRemoteNotificationsCompletion = nil;
// }
//}
//
//- (void)pushRegistry:(PKPushRegistry *)registry didInvalidatePushTokenForType:(PKPushType)type
//{
// NSLog(@"[PushNotificationService][Push] didInvalidatePushTokenForType: Type: %@", type);
//
// [self clearPushNotificationToken];
//}
- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(PKPushType)type
{
NSData *token = credentials.token;
NSLog(@"[PushNotificationService][Push] didUpdatePushCredentials: Got Push token: %@. Type: %@", [MXKTools logForPushToken:token], type);
MXKAccountManager* accountManager = [MXKAccountManager sharedManager];
[accountManager setPushDeviceToken:token withPushOptions:@{@"format": @"event_id_only"}];
_isPushRegistered = YES;
if (self.registrationForRemoteNotificationsCompletion)
{
self.registrationForRemoteNotificationsCompletion(nil);
self.registrationForRemoteNotificationsCompletion = nil;
}
}
- (void)pushRegistry:(PKPushRegistry *)registry didInvalidatePushTokenForType:(PKPushType)type
{
NSLog(@"[PushNotificationService][Push] didInvalidatePushTokenForType: Type: %@", type);
[self clearPushNotificationToken];
}
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type
{
NSLog(@"[PushNotificationService][Push] didReceiveIncomingPushWithPayload: applicationState: %tu - type: %@ - payload: %@", [UIApplication sharedApplication].applicationState, payload.type, payload.dictionaryPayload);
// Display local notifications only when the app is running in background.
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground)
{
NSLog(@"[PushNotificationService][Push] didReceiveIncomingPushWithPayload while app is in background");
// Check whether an event id is provided.
NSString *eventId = payload.dictionaryPayload[@"event_id"];
if (eventId)
{
// Add this event identifier in the pending push array for each session.
for (NSMutableArray *array in self.incomingPushEventIds.allValues)
{
[array addObject:eventId];
}
// Cache payload for further usage
incomingPushPayloads[eventId] = payload.dictionaryPayload;
}
else
{
NSLog(@"[PushNotificationService][Push] didReceiveIncomingPushWithPayload - Unexpected payload %@", payload.dictionaryPayload);
}
// Trigger a background sync to handle notifications.
[self launchBackgroundSync];
}
}
//- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type
//{
// NSLog(@"[PushNotificationService][Push] didReceiveIncomingPushWithPayload: applicationState: %tu - type: %@ - payload: %@", [UIApplication sharedApplication].applicationState, payload.type, payload.dictionaryPayload);
//
// // Display local notifications only when the app is running in background.
// if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground)
// {
// NSLog(@"[PushNotificationService][Push] didReceiveIncomingPushWithPayload while app is in background");
//
// // Check whether an event id is provided.
// NSString *eventId = payload.dictionaryPayload[@"event_id"];
// if (eventId)
// {
// // Add this event identifier in the pending push array for each session.
// for (NSMutableArray *array in self.incomingPushEventIds.allValues)
// {
// [array addObject:eventId];
// }
//
// // Cache payload for further usage
// incomingPushPayloads[eventId] = payload.dictionaryPayload;
// }
// else
// {
// NSLog(@"[PushNotificationService][Push] didReceiveIncomingPushWithPayload - Unexpected payload %@", payload.dictionaryPayload);
// }
//
// // Trigger a background sync to handle notifications.
// [self launchBackgroundSync];
// }
//}
#pragma mark - UNUserNotificationCenterDelegate
@@ -374,12 +441,13 @@
}
// iOS 10+, this is called when a notification is about to display in foreground.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
NSLog(@"[PushNotificationService][Push] willPresentNotification: applicationState: %@", @([UIApplication sharedApplication].applicationState));
completionHandler(UNNotificationPresentationOptionNone);
}
//- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
//{
// NSLog(@"[PushNotificationService][Push] willPresentNotification: applicationState: %@", @([UIApplication sharedApplication].applicationState));
//
//// completionHandler(UNNotificationPresentationOptionNone);
// completionHandler(UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert);
//}
#pragma mark - Other Methods
@@ -607,7 +675,7 @@
}
// iOS 10+, does the same thing as notificationBodyForEvent:pushRule:inAccount:onComplete:, except with more features
- (void)notificationContentForEvent:(MXEvent *)event pushRule:(MXPushRule *)rule inAccount:(MXKAccount *)account onComplete:(void (^)(UNNotificationContent * _Nullable notificationContent))onComplete;
- (void)notificationContentForEvent:(MXEvent *)event pushRule:(MXPushRule *)rule inAccount:(MXKAccount *)account onComplete:(void (^)(UNNotificationContent * _Nullable notificationContent))onComplete
{
if (!event.content || !event.content.count)
{

View File

@@ -38,39 +38,61 @@ final class RiotSettings: NSObject {
static let shared = RiotSettings()
/// UserDefaults to be used on reads and writes.
private lazy var defaults: UserDefaults = {
return UserDefaults(suiteName: "group.im.vector")!
}()
// MARK: - Public
// MARK: Notifications
/// Indicate if `showDecryptedContentInNotifications` settings has been set once.
var isShowDecryptedContentInNotificationsHasBeenSetOnce: Bool {
return UserDefaults.standard.object(forKey: UserDefaultsKeys.notificationsShowDecryptedContent) != nil
return defaults.object(forKey: UserDefaultsKeys.notificationsShowDecryptedContent) != nil
}
/// Indicate if UserDefaults suite has been migrated once.
var isUserDefaultsMigrated: Bool {
return defaults.object(forKey: UserDefaultsKeys.notificationsShowDecryptedContent) != nil
}
func migrate() {
// read all values from standard
let dictionary = UserDefaults.standard.dictionaryRepresentation()
// write values to suite
// remove redundant values from standard
for (key, value) in dictionary {
defaults.set(value, forKey: key)
UserDefaults.standard.removeObject(forKey: key)
}
}
/// Indicate if encrypted messages content should be displayed in notifications.
var showDecryptedContentInNotifications: Bool {
get {
return UserDefaults.standard.bool(forKey: UserDefaultsKeys.notificationsShowDecryptedContent)
return defaults.bool(forKey: UserDefaultsKeys.notificationsShowDecryptedContent)
} set {
UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.notificationsShowDecryptedContent)
defaults.set(newValue, forKey: UserDefaultsKeys.notificationsShowDecryptedContent)
}
}
/// Indicate if rooms with missed notifications should be displayed first on home screen.
var pinRoomsWithMissedNotificationsOnHome: Bool {
get {
return UserDefaults.standard.bool(forKey: UserDefaultsKeys.pinRoomsWithMissedNotifications)
return defaults.bool(forKey: UserDefaultsKeys.pinRoomsWithMissedNotifications)
} set {
UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.pinRoomsWithMissedNotifications)
defaults.set(newValue, forKey: UserDefaultsKeys.pinRoomsWithMissedNotifications)
}
}
/// Indicate if rooms with unread messages should be displayed first on home screen.
var pinRoomsWithUnreadMessagesOnHome: Bool {
get {
return UserDefaults.standard.bool(forKey: UserDefaultsKeys.pinRoomsWithUnreadMessages)
return defaults.bool(forKey: UserDefaultsKeys.pinRoomsWithUnreadMessages)
} set {
UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.pinRoomsWithUnreadMessages)
defaults.set(newValue, forKey: UserDefaultsKeys.pinRoomsWithUnreadMessages)
}
}
@@ -78,9 +100,9 @@ final class RiotSettings: NSObject {
var userInterfaceTheme: String? {
get {
return UserDefaults.standard.string(forKey: UserDefaultsKeys.userInterfaceTheme)
return defaults.string(forKey: UserDefaultsKeys.userInterfaceTheme)
} set {
UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.userInterfaceTheme)
defaults.set(newValue, forKey: UserDefaultsKeys.userInterfaceTheme)
}
}
@@ -88,22 +110,22 @@ final class RiotSettings: NSObject {
/// Indicate if `enableCrashReport` settings has been set once.
var isEnableCrashReportHasBeenSetOnce: Bool {
return UserDefaults.standard.object(forKey: UserDefaultsKeys.enableCrashReport) != nil
return defaults.object(forKey: UserDefaultsKeys.enableCrashReport) != nil
}
var enableCrashReport: Bool {
get {
return UserDefaults.standard.bool(forKey: UserDefaultsKeys.enableCrashReport)
return defaults.bool(forKey: UserDefaultsKeys.enableCrashReport)
} set {
UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.enableCrashReport)
defaults.set(newValue, forKey: UserDefaultsKeys.enableCrashReport)
}
}
var enableRageShake: Bool {
get {
return UserDefaults.standard.bool(forKey: UserDefaultsKeys.enableRageShake)
return defaults.bool(forKey: UserDefaultsKeys.enableRageShake)
} set {
UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.enableRageShake)
defaults.set(newValue, forKey: UserDefaultsKeys.enableRageShake)
}
}
@@ -111,9 +133,9 @@ final class RiotSettings: NSObject {
var createConferenceCallsWithJitsi: Bool {
get {
return UserDefaults.standard.bool(forKey: UserDefaultsKeys.createConferenceCallsWithJitsi)
return defaults.bool(forKey: UserDefaultsKeys.createConferenceCallsWithJitsi)
} set {
UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.createConferenceCallsWithJitsi)
defaults.set(newValue, forKey: UserDefaultsKeys.createConferenceCallsWithJitsi)
}
}
@@ -121,36 +143,36 @@ final class RiotSettings: NSObject {
/// Indicate if `allowStunServerFallback` settings has been set once.
var isAllowStunServerFallbackHasBeenSetOnce: Bool {
return UserDefaults.standard.object(forKey: UserDefaultsKeys.allowStunServerFallback) != nil
return defaults.object(forKey: UserDefaultsKeys.allowStunServerFallback) != nil
}
var allowStunServerFallback: Bool {
get {
return UserDefaults.standard.bool(forKey: UserDefaultsKeys.allowStunServerFallback)
return defaults.bool(forKey: UserDefaultsKeys.allowStunServerFallback)
} set {
UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.allowStunServerFallback)
defaults.set(newValue, forKey: UserDefaultsKeys.allowStunServerFallback)
}
}
var stunServerFallback: String? {
return UserDefaults.standard.string(forKey: UserDefaultsKeys.stunServerFallback)
return defaults.string(forKey: UserDefaultsKeys.stunServerFallback)
}
// MARK: Key verification
var hideVerifyThisSessionAlert: Bool {
get {
return UserDefaults.standard.bool(forKey: UserDefaultsKeys.hideVerifyThisSessionAlert)
return defaults.bool(forKey: UserDefaultsKeys.hideVerifyThisSessionAlert)
} set {
UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.hideVerifyThisSessionAlert)
defaults.set(newValue, forKey: UserDefaultsKeys.hideVerifyThisSessionAlert)
}
}
var hideReviewSessionsAlert: Bool {
get {
return UserDefaults.standard.bool(forKey: UserDefaultsKeys.hideReviewSessionsAlert)
return defaults.bool(forKey: UserDefaultsKeys.hideReviewSessionsAlert)
} set {
UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.hideReviewSessionsAlert)
defaults.set(newValue, forKey: UserDefaultsKeys.hideReviewSessionsAlert)
}
}
}

View File

@@ -87,9 +87,9 @@ enum
enum
{
CALLS_ENABLE_CALLKIT_INDEX = 0,
CALLS_CALLKIT_DESCRIPTION_INDEX,
CALLS_ENABLE_STUN_SERVER_FALLBACK_INDEX,
//CALLS_ENABLE_CALLKIT_INDEX = 0,
//CALLS_CALLKIT_DESCRIPTION_INDEX,
CALLS_ENABLE_STUN_SERVER_FALLBACK_INDEX=0,
CALLS_STUN_SERVER_FALLBACK_DESCRIPTION_INDEX,
CALLS_COUNT
};
@@ -1731,39 +1731,40 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
}
else if (section == SETTINGS_SECTION_CALLS_INDEX)
{
if (row == CALLS_ENABLE_CALLKIT_INDEX)
{
MXKTableViewCellWithLabelAndSwitch* labelAndSwitchCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath];
labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_enable_callkit", @"Vector", nil);
labelAndSwitchCell.mxkSwitch.on = [MXKAppSettings standardAppSettings].isCallKitEnabled;
labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor;
labelAndSwitchCell.mxkSwitch.enabled = YES;
[labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleCallKit:) forControlEvents:UIControlEventTouchUpInside];
if (![MXCallKitAdapter callKitAvailable])
{
labelAndSwitchCell.mxkSwitch.on = NO;
labelAndSwitchCell.mxkSwitch.enabled = NO;
labelAndSwitchCell.mxkLabel.enabled = NO;
}
cell = labelAndSwitchCell;
}
else if (row == CALLS_CALLKIT_DESCRIPTION_INDEX)
{
MXKTableViewCell *globalInfoCell = [self getDefaultTableViewCell:tableView];
globalInfoCell.textLabel.text = NSLocalizedStringFromTable(@"settings_callkit_info", @"Vector", nil);
globalInfoCell.textLabel.numberOfLines = 0;
globalInfoCell.selectionStyle = UITableViewCellSelectionStyleNone;
if (![MXCallKitAdapter callKitAvailable])
{
globalInfoCell.textLabel.enabled = NO;
}
cell = globalInfoCell;
}
else if (row == CALLS_ENABLE_STUN_SERVER_FALLBACK_INDEX)
// if (row == CALLS_ENABLE_CALLKIT_INDEX)
// {
// MXKTableViewCellWithLabelAndSwitch* labelAndSwitchCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath];
// labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_enable_callkit", @"Vector", nil);
// labelAndSwitchCell.mxkSwitch.on = [MXKAppSettings standardAppSettings].isCallKitEnabled;
// labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor;
// labelAndSwitchCell.mxkSwitch.enabled = YES;
// [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleCallKit:) forControlEvents:UIControlEventTouchUpInside];
//
// if (![MXCallKitAdapter callKitAvailable])
// {
// labelAndSwitchCell.mxkSwitch.on = NO;
// labelAndSwitchCell.mxkSwitch.enabled = NO;
// labelAndSwitchCell.mxkLabel.enabled = NO;
// }
//
// cell = labelAndSwitchCell;
// }
// else if (row == CALLS_CALLKIT_DESCRIPTION_INDEX)
// {
// MXKTableViewCell *globalInfoCell = [self getDefaultTableViewCell:tableView];
// globalInfoCell.textLabel.text = NSLocalizedStringFromTable(@"settings_callkit_info", @"Vector", nil);
// globalInfoCell.textLabel.numberOfLines = 0;
// globalInfoCell.selectionStyle = UITableViewCellSelectionStyleNone;
//
// if (![MXCallKitAdapter callKitAvailable])
// {
// globalInfoCell.textLabel.enabled = NO;
// }
//
// cell = globalInfoCell;
// }
// else
if (row == CALLS_ENABLE_STUN_SERVER_FALLBACK_INDEX)
{
MXKTableViewCellWithLabelAndSwitch* labelAndSwitchCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath];
labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_calls_stun_server_fallback_button", @"Vector", nil);
@@ -2848,10 +2849,10 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
MXKAccountManager *accountManager = [MXKAccountManager sharedManager];
MXKAccount* account = accountManager.activeAccounts.firstObject;
if (accountManager.pushDeviceToken)
if (accountManager.apnsDeviceToken)
{
[account enablePushKitNotifications:!account.isPushKitNotificationActive success:^{
[account enablePushNotifications:!account.pushNotificationServiceIsActive success:^{
[self stopActivityIndicator];
} failure:^(NSError *error) {
[self stopActivityIndicator];
@@ -2868,7 +2869,7 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
}
else
{
[account enablePushKitNotifications:YES success:^{
[account enablePushNotifications:YES success:^{
[self stopActivityIndicator];
} failure:^(NSError *error) {
[self stopActivityIndicator];

31
RiotNSE/Info.plist Normal file
View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>RiotNSE</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.usernotifications.service</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).NotificationService</string>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,482 @@
/*
Copyright 2020 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import UserNotifications
import MatrixKit
class NotificationService: UNNotificationServiceExtension {
var requestIdentifier: String?
var contentHandler: ((UNNotificationContent) -> Void)?
var originalContent: UNMutableNotificationContent?
var userAccount: MXKAccount?
var store: MXFileStore?
var showDecryptedContentInNotifications: Bool {
return RiotSettings.shared.showDecryptedContentInNotifications
}
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
requestIdentifier = request.identifier
// save this content as fallback content
originalContent = request.content.mutableCopy() as? UNMutableNotificationContent
// check if this is a Matrix notification
if let content = originalContent {
let userInfo = content.userInfo
NSLog("[NotificationService] Payload came: \(userInfo) with identifier: \(requestIdentifier!)")
let roomId = userInfo["room_id"] as? String
let eventId = userInfo["event_id"] as? String
guard roomId != nil, eventId != nil else {
// it's not a Matrix notification, do not change the content
NSLog("[NotificationService] Fallback case 7")
contentHandler(content)
return
}
}
// setup user account
setup()
// fetch the event first
fetchEvent()
}
override func serviceExtensionTimeWillExpire() {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
NSLog("[NotificationService] Fallback case 5")
fallbackToOriginalContent()
}
func setup() {
let sdkOptions = MXSDKOptions.sharedInstance()
sdkOptions.applicationGroupIdentifier = "group.im.vector"
sdkOptions.disableIdenticonUseForUserAvatar = true
sdkOptions.enableCryptoWhenStartingMXSession = true
sdkOptions.backgroundModeHandler = MXUIKitBackgroundModeHandler()
Bundle.mxk_customizeLocalizedStringTableName("Vector")
if isatty(STDERR_FILENO) == 0 {
// MXLogger.setSubLogName("nse")
// MXLogger.redirectNSLog(toFiles: true)
}
userAccount = MXKAccountManager.shared()?.activeAccounts.first
if let theUserAccount = userAccount {
store = MXFileStore(credentials: theUserAccount.mxCredentials)
if theUserAccount.mxSession == nil {
theUserAccount.openSession(with: store!)
}
}
}
func fetchEvent() {
if let content = originalContent, let theUserAccount = self.userAccount {
let userInfo = content.userInfo
let roomId = userInfo["room_id"] as? String
let eventId = userInfo["event_id"] as? String
guard let theRoomId = roomId, let theEventId = eventId else {
// it's not a Matrix notification, do not change the content
NSLog("[NotificationService] Fallback case 1")
contentHandler?(content)
return
}
theUserAccount.mxSession.event(withEventId: theEventId, inRoom: theRoomId, success: { [weak self] (event) in
guard let strongSelf = self else {
NSLog("[NotificationService] Fallback case 9")
return
}
guard let theEvent = event else {
return
}
if theEvent.isEncrypted {
// encrypted
if strongSelf.showDecryptedContentInNotifications {
// should show decrypted content in notification
if theEvent.clear == nil {
// should decrypt it first
if theUserAccount.mxSession.decryptEvent(theEvent, inTimeline: nil) {
// decryption succeeded
strongSelf.processEvent(theEvent)
} else {
// decryption failed
NSLog("[NotificationService] Event needs to be decrpyted, but we don't have the keys to decrypt it. Launching a background sync.")
strongSelf.launchBackgroundSync()
}
} else {
// already decrypted
strongSelf.processEvent(theEvent)
}
} else {
// do not show decrypted content in notification
strongSelf.fallbackToOriginalContent()
}
} else {
// not encrypted, go on
strongSelf.processEvent(theEvent)
}
}) { [weak self] (error) in
guard let strongSelf = self else {
NSLog("[NotificationService] Fallback case 10")
return
}
NSLog("[NotificationService] Fallback case 3")
strongSelf.fallbackToOriginalContent()
}
} else {
// there is something wrong, do not change the content
NSLog("[NotificationService] Fallback case 4")
fallbackToOriginalContent()
}
}
func launchBackgroundSync() {
guard let theUserAccount = userAccount else { return }
guard let theFileStore = store else { return }
if theUserAccount.mxSession == nil {
theUserAccount.openSession(with: theFileStore)
}
let sessionState = theUserAccount.mxSession.state
if sessionState == MXSessionStateInitialised || sessionState == MXSessionStatePaused {
theUserAccount.initialBackgroundSync(20000, success: { [weak self] in
guard let strongSelf = self else {
NSLog("[NotificationService] Fallback case 12")
return
}
strongSelf.fetchEvent()
}) { [weak self] (error) in
guard let strongSelf = self else {
NSLog("[NotificationService] Fallback case 11")
return
}
NSLog("[NotificationService] Fallback case 6")
strongSelf.fallbackToOriginalContent()
}
} else {
NSLog("[NotificationService] Fallback case 8")
fallbackToOriginalContent()
}
}
func processEvent(_ event: MXEvent) {
if let content = originalContent, let theUserAccount = userAccount {
self.notificationContent(forEvent: event, inAccount: theUserAccount) { (notificationContent) in
self.store?.close()
// Modify the notification content here...
guard let newContent = notificationContent else {
// remove
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [self.requestIdentifier!])
return
}
content.title = newContent.title
content.subtitle = newContent.subtitle
content.body = newContent.body
content.threadIdentifier = newContent.threadIdentifier
content.categoryIdentifier = newContent.categoryIdentifier
content.userInfo = newContent.userInfo
content.sound = newContent.sound
self.contentHandler?(content)
}
}
}
func fallbackToOriginalContent() {
store?.close()
if let content = originalContent {
contentHandler?(content)
} else {
NSLog("[NotificationService] Fallback case 13")
}
}
func notificationContent(forEvent event: MXEvent, inAccount account: MXKAccount, onComplete: @escaping (UNNotificationContent?) -> Void) {
if event.content == nil || event.content!.count == 0 {
NSLog("[NotificationService][Push] notificationContentForEvent: empty event content")
onComplete(nil)
return
}
guard let room = account.mxSession.room(withRoomId: event.roomId) else {
NSLog("[NotificationService][Push] notificationBodyForEvent: Unknown room")
onComplete(nil)
return
}
let pushRule = room.getRoomPushRule()
room.state({ (roomState:MXRoomState!) in
var notificationTitle: String?
var notificationBody: String?
var threadIdentifier = room.roomId
let eventSenderName = roomState.members.memberName(event.sender)
let currentUserId = account.mxCredentials.userId
if event.eventType == .roomMessage || event.eventType == .roomEncrypted {
if room.isMentionsOnly {
// A local notification will be displayed only for highlighted notification.
var isHighlighted:Bool = false
// Check whether is there an highlight tweak on it
for ruleAction in pushRule?.actions ?? [] {
guard let action = ruleAction as? MXPushRuleAction else { continue }
if action.actionType == MXPushRuleActionTypeSetTweak {
if action.parameters["set_tweak"] as? String == "highlight" {
// Check the highlight tweak "value"
// If not present, highlight. Else check its value before highlighting
if nil == action.parameters["value"] || true == (action.parameters["value"] as? Bool) {
isHighlighted = true
break
}
}
}
}
if !isHighlighted {
// Ignore this notif.
NSLog("[NotificationService][Push] notificationBodyForEvent: Ignore non highlighted notif in mentions only room")
onComplete(nil)
return
}
}
var msgType = event.content["msgtype"] as? String
let messageContent = event.content["body"] as? String
if event.isEncrypted && !self.showDecryptedContentInNotifications {
// Hide the content
msgType = nil
}
let roomDisplayName = room.summary.displayname
let myUserId:String! = account.mxSession.myUser.userId
let isIncomingEvent:Bool = !(event.sender == myUserId)
// Display the room name only if it is different than the sender name
if roomDisplayName != nil && !(roomDisplayName == eventSenderName) {
notificationTitle = NSString.localizedUserNotificationString(forKey: "MSG_FROM_USER_IN_ROOM_TITLE", arguments:[eventSenderName as Any, roomDisplayName as Any])
if (msgType == "m.text") {
notificationBody = messageContent
} else if (msgType == "m.emote") {
notificationBody = NSString.localizedUserNotificationString(forKey: "ACTION_FROM_USER", arguments:[eventSenderName as Any, messageContent as Any])
} else if (msgType == "m.image") {
notificationBody = NSString.localizedUserNotificationString(forKey: "IMAGE_FROM_USER", arguments:[eventSenderName as Any, messageContent as Any])
} else if room.isDirect && isIncomingEvent && (msgType == kMXMessageTypeKeyVerificationRequest) {
account.mxSession.crypto.keyVerificationManager.keyVerification(fromKeyVerificationEvent: event,
success:{ (keyVerification) in
if keyVerification.request != nil && keyVerification.request!.state == MXKeyVerificationRequestStatePending {
// TODO: Add accept and decline actions to notification
let body:String! = NSString.localizedUserNotificationString(forKey: "KEY_VERIFICATION_REQUEST_FROM_USER", arguments:[eventSenderName as Any])
let notificationContent:UNNotificationContent! = self.notificationContent(withTitle: notificationTitle,
body: body,
threadIdentifier: threadIdentifier,
userId: currentUserId,
event: event,
pushRule: pushRule)
onComplete(notificationContent)
} else {
onComplete(nil)
}
}, failure:{ (error) in
NSLog("[NotificationService][Push] notificationContentForEvent: failed to fetch key verification with error: \(error)")
onComplete(nil)
})
} else {
// Encrypted messages falls here
notificationBody = NSString.localizedUserNotificationString(forKey: "MSG_FROM_USER", arguments:[eventSenderName as Any])
}
} else {
notificationTitle = eventSenderName
if (msgType == "m.text") {
notificationBody = messageContent
} else if (msgType == "m.emote") {
notificationBody = NSString.localizedUserNotificationString(forKey: "ACTION_FROM_USER", arguments:[eventSenderName as Any, messageContent as Any])
} else if (msgType == "m.image") {
notificationBody = NSString.localizedUserNotificationString(forKey: "IMAGE_FROM_USER", arguments:[eventSenderName as Any, messageContent as Any])
} else {
// Encrypted messages falls here
notificationBody = NSString.localizedUserNotificationString(forKey: "MSG_FROM_USER", arguments:[eventSenderName as Any])
}
}
} else if event.eventType == .callInvite {
let offer = event.content["offer"] as? [AnyHashable: Any]
let sdp = offer?["sdp"] as? String
let isVideoCall = sdp?.contains("m=video") ?? false
if isVideoCall {
notificationBody = NSString.localizedUserNotificationString(forKey: "VIDEO_CALL_FROM_USER", arguments:[eventSenderName as Any])
} else {
notificationBody = NSString.localizedUserNotificationString(forKey: "VOICE_CALL_FROM_USER", arguments:[eventSenderName as Any])
}
// call notifications should stand out from normal messages, so we don't stack them
threadIdentifier = nil
} else if event.eventType == .roomMember {
let roomDisplayName:String! = room.summary.displayname
if roomDisplayName != nil && !(roomDisplayName == eventSenderName) {
notificationBody = NSString.localizedUserNotificationString(forKey: "USER_INVITE_TO_NAMED_ROOM", arguments:[eventSenderName as Any, roomDisplayName as Any])
} else {
notificationBody = NSString.localizedUserNotificationString(forKey: "USER_INVITE_TO_CHAT", arguments:[eventSenderName as Any])
}
} else if event.eventType == .sticker {
let roomDisplayName:String! = room.summary.displayname
if roomDisplayName != nil && !(roomDisplayName == eventSenderName) {
notificationTitle = NSString.localizedUserNotificationString(forKey: "MSG_FROM_USER_IN_ROOM_TITLE", arguments:[eventSenderName as Any, roomDisplayName as Any])
} else {
notificationTitle = eventSenderName
}
notificationBody = NSString.localizedUserNotificationString(forKey: "STICKER_FROM_USER", arguments:[eventSenderName as Any])
}
if (notificationBody != nil) {
let notificationContent = self.notificationContent(withTitle: notificationTitle,
body: notificationBody,
threadIdentifier: threadIdentifier,
userId: currentUserId,
event: event,
pushRule: pushRule)
onComplete(notificationContent)
} else {
onComplete(nil)
}
})
}
func notificationContent(withTitle title: String?, body: String?, threadIdentifier: String?, userId: String?, event: MXEvent, pushRule: MXPushRule?) -> UNNotificationContent {
let notificationContent = UNMutableNotificationContent()
if let title = title {
notificationContent.title = title
}
if let body = body {
notificationContent.body = body
}
if let threadIdentifier = threadIdentifier {
notificationContent.threadIdentifier = threadIdentifier
}
if let categoryIdentifier = self.notificationCategoryIdentifier(forEvent: event) {
notificationContent.categoryIdentifier = categoryIdentifier
}
if let soundName = notificationSoundName(fromPushRule: pushRule) {
notificationContent.sound = UNNotificationSound(named: UNNotificationSoundName(rawValue: soundName))
} else {
notificationContent.sound = UNNotificationSound.default
}
notificationContent.userInfo = notificationUserInfo(forEvent: event, andUserId: userId)
return notificationContent
}
func notificationUserInfo(forEvent event: MXEvent, andUserId userId: String?) -> [AnyHashable: Any] {
var notificationUserInfo: [AnyHashable: Any] = [
"type": "full",
"room_id": event.roomId as Any,
"event_id": event.eventId as Any
]
if let userId = userId {
notificationUserInfo["user_id"] = userId
}
return notificationUserInfo
}
func notificationSoundName(fromPushRule pushRule: MXPushRule?) -> String? {
var soundName: String?
// Set sound name based on the value provided in action of MXPushRule
for ruleAction in pushRule?.actions ?? [] {
guard let action = ruleAction as? MXPushRuleAction else { continue }
if action.actionType == MXPushRuleActionTypeSetTweak {
if (action.parameters["set_tweak"] as? String == "sound") {
soundName = action.parameters["value"] as? String
if (soundName == "default") {
soundName = "message.caf"
}
}
}
}
return soundName
}
func notificationCategoryIdentifier(forEvent event: MXEvent) -> String? {
let isNotificationContentShown = !event.isEncrypted || self.showDecryptedContentInNotifications
var categoryIdentifier: String?
if (event.eventType == .roomMessage || event.eventType == .roomEncrypted) && isNotificationContentShown {
categoryIdentifier = "QUICK_REPLY"
}
return categoryIdentifier
}
}
extension MXRoom {
func getRoomPushRule() -> MXPushRule? {
if let rules = self.mxSession.notificationCenter.rules.global.room {
for rule in rules {
guard let pushRule = rule as? MXPushRule else { continue }
// the rule id is the room Id
// it is the server trick to avoid duplicated rule on the same room.
if (pushRule.ruleId == self.roomId) {
return pushRule
}
}
}
return nil
}
var isMentionsOnly: Bool {
// Check push rules at room level
if let rule = self.getRoomPushRule() {
for ruleAction in rule.actions {
guard let action = ruleAction as? MXPushRuleAction else { continue }
if action.actionType == MXPushRuleActionTypeDontNotify {
return rule.enabled
}
}
}
return false
}
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.im.vector</string>
</array>
</dict>
</plist>