From f3a94f6a8eacd338676699c1f34bdf943d45e01f Mon Sep 17 00:00:00 2001 From: Milen Pivchev Date: Thu, 19 Sep 2024 11:02:26 +0200 Subject: [PATCH 1/5] WIP Signed-off-by: Milen Pivchev --- Nextcloud.xcodeproj/project.pbxproj | 47 ++++++++ .../FilesIntegrationTests.swift | 110 +++++++++--------- .../Settings/Display/NCDisplayModel.swift | 9 ++ .../Settings/Display/NCDisplayView.swift | 10 ++ iOSClient/Settings/NCKeychain.swift | 24 ++++ .../en.lproj/Localizable.strings | 3 + .../ScreenAwakeManager/AwakeMode.swift | 34 ++++++ .../ScreenAwakeManager.swift | 88 ++++++++++++++ 8 files changed, 270 insertions(+), 55 deletions(-) create mode 100644 iOSClient/Utility/ScreenAwakeManager/AwakeMode.swift create mode 100644 iOSClient/Utility/ScreenAwakeManager/ScreenAwakeManager.swift diff --git a/Nextcloud.xcodeproj/project.pbxproj b/Nextcloud.xcodeproj/project.pbxproj index 0c7e243e5d..0bdf9610ce 100644 --- a/Nextcloud.xcodeproj/project.pbxproj +++ b/Nextcloud.xcodeproj/project.pbxproj @@ -160,6 +160,15 @@ F3BB464D2A39ADCC00461F6E /* NCMoreAppSuggestionsCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F3BB464C2A39ADCC00461F6E /* NCMoreAppSuggestionsCell.xib */; }; F3BB46522A39EC4900461F6E /* NCMoreAppSuggestionsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3BB46512A39EC4900461F6E /* NCMoreAppSuggestionsCell.swift */; }; F3BB46542A3A1E9D00461F6E /* CCCellMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3BB46532A3A1E9D00461F6E /* CCCellMore.swift */; }; + F3CA5AF52C99C2C400F673FC /* Insomnia in Frameworks */ = {isa = PBXBuildFile; productRef = F3CA5AF42C99C2C400F673FC /* Insomnia */; }; + F3E173B02C9AF637006D177A /* ScreenAwakeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E173AF2C9AF637006D177A /* ScreenAwakeManager.swift */; }; + F3E173C02C9B1067006D177A /* AwakeMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E173BF2C9B1067006D177A /* AwakeMode.swift */; }; + F3E173C12C9B1067006D177A /* AwakeMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E173BF2C9B1067006D177A /* AwakeMode.swift */; }; + F3E173C22C9B1067006D177A /* AwakeMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E173BF2C9B1067006D177A /* AwakeMode.swift */; }; + F3E173C32C9B1067006D177A /* AwakeMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E173BF2C9B1067006D177A /* AwakeMode.swift */; }; + F3E173C42C9B1067006D177A /* AwakeMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E173BF2C9B1067006D177A /* AwakeMode.swift */; }; + F3E173C52C9B1067006D177A /* AwakeMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E173BF2C9B1067006D177A /* AwakeMode.swift */; }; + F3E173C62C9B1067006D177A /* AwakeMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E173BF2C9B1067006D177A /* AwakeMode.swift */; }; F3EF2E0C2BFCF3810025EF46 /* NCLoginPoll.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EF2E0B2BFCF3810025EF46 /* NCLoginPoll.swift */; }; F3F0419B2B9F7E6700D5155F /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = F3F0419A2B9F7E6700D5155F /* RealmSwift */; }; F3F0419D2B9F7E6E00D5155F /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = F3F0419C2B9F7E6E00D5155F /* RealmSwift */; }; @@ -1181,6 +1190,8 @@ F3BB464C2A39ADCC00461F6E /* NCMoreAppSuggestionsCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCMoreAppSuggestionsCell.xib; sourceTree = ""; }; F3BB46512A39EC4900461F6E /* NCMoreAppSuggestionsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMoreAppSuggestionsCell.swift; sourceTree = ""; }; F3BB46532A3A1E9D00461F6E /* CCCellMore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CCCellMore.swift; sourceTree = ""; }; + F3E173AF2C9AF637006D177A /* ScreenAwakeManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenAwakeManager.swift; sourceTree = ""; }; + F3E173BF2C9B1067006D177A /* AwakeMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AwakeMode.swift; sourceTree = ""; }; F3EF2E0B2BFCF3810025EF46 /* NCLoginPoll.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCLoginPoll.swift; sourceTree = ""; }; F700222B1EC479840080073F /* Custom.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Custom.xcassets; sourceTree = ""; }; F700510022DF63AC003A3356 /* NCShare.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCShare.storyboard; sourceTree = ""; }; @@ -1903,6 +1914,7 @@ F75EAED826D2552E00F4320E /* MarqueeLabel in Frameworks */, F72DA9B425F53E4E00B87DB1 /* SwiftRichString in Frameworks */, F78AF1E72BE938C100F3F060 /* MobileVLCKit.xcframework in Frameworks */, + F3CA5AF52C99C2C400F673FC /* Insomnia in Frameworks */, F73ADD1C265546890069EA0D /* SwiftEntryKit in Frameworks */, F76B649E2ADFFDEC00014640 /* LRUCache in Frameworks */, ); @@ -2064,6 +2076,15 @@ path = Cells; sourceTree = ""; }; + F3E173BE2C9B1057006D177A /* ScreenAwakeManager */ = { + isa = PBXGroup; + children = ( + F3E173AF2C9AF637006D177A /* ScreenAwakeManager.swift */, + F3E173BF2C9B1067006D177A /* AwakeMode.swift */, + ); + path = ScreenAwakeManager; + sourceTree = ""; + }; F70211F31BAC56E9003FC03E /* Main */ = { isa = PBXGroup; children = ( @@ -2755,6 +2776,7 @@ F7BFFA991A24D7BB0044ED85 /* Utility */ = { isa = PBXGroup; children = ( + F3E173BE2C9B1057006D177A /* ScreenAwakeManager */, F702F2FC25EE5D2C008F8E80 /* NYMnemonic */, F76D364528A4F8BF00214537 /* NCActivityIndicator.swift */, F733598025C1C188002ABA72 /* NCAskAuthorization.swift */, @@ -3451,6 +3473,7 @@ F7160A812BE933390034DCB3 /* RealmSwift */, F33EE6E02BF4BDA500CA1A51 /* NIOSSL */, F33EE6EF2BF4C0FF00CA1A51 /* NIO */, + F3CA5AF42C99C2C400F673FC /* Insomnia */, ); productName = "Crypto Cloud"; productReference = F7CE8AFA1DC1F8D8009CAE48 /* Nextcloud.app */; @@ -3625,6 +3648,7 @@ F3A0479C2BD268B500658E7B /* XCRemoteSwiftPackageReference "PopupView" */, F33EE6DF2BF4BDA500CA1A51 /* XCRemoteSwiftPackageReference "swift-nio-ssl" */, F33EE6EE2BF4C0FF00CA1A51 /* XCRemoteSwiftPackageReference "swift-nio" */, + F3CA5AF32C99C2C400F673FC /* XCRemoteSwiftPackageReference "Insomnia" */, ); productRefGroup = F7F67B9F1A24D27800EE80DA; projectDirPath = ""; @@ -3859,6 +3883,7 @@ F702F2D225EE5B5C008F8E80 /* NCGlobal.swift in Sources */, F7707689263A896A00A1BA94 /* UIImage+Extension.swift in Sources */, F72FD3BA297ED49A00075D28 /* NCManageDatabase+E2EE.swift in Sources */, + F3E173C62C9B1067006D177A /* AwakeMode.swift in Sources */, F73EF7DD2B0226080087E6E9 /* NCManageDatabase+Tip.swift in Sources */, F73EF7ED2B0226B90087E6E9 /* NCManageDatabase+UserStatus.swift in Sources */, F7E98C1927E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */, @@ -3988,6 +4013,7 @@ F73EF7B42B0224350087E6E9 /* NCManageDatabase+DirectEditing.swift in Sources */, F7490E8229882C80009DCE94 /* NCManageDatabase+E2EE.swift in Sources */, F7490E7829882C28009DCE94 /* NCUtility.swift in Sources */, + F3E173C52C9B1067006D177A /* AwakeMode.swift in Sources */, F71433E62C778FFB00E20B5A /* NotificationCenter+MainThread.swift in Sources */, F33918C92C7CD8F2002D9AA1 /* FileNameValidator+Extensions.swift in Sources */, F7490E7F29882C73009DCE94 /* NCManageDatabase+Activity.swift in Sources */, @@ -4064,6 +4090,7 @@ F749B64D297B0CBB00087535 /* NCManageDatabase+Share.swift in Sources */, F72FD3B8297ED49A00075D28 /* NCManageDatabase+E2EE.swift in Sources */, F7A76DC8256A71CD00119AB3 /* UIImage+Extension.swift in Sources */, + F3E173C32C9B1067006D177A /* AwakeMode.swift in Sources */, F711A4E52AF9310500095DD8 /* NCUtility+Image.swift in Sources */, F73EF7AA2B0223900087E6E9 /* NCManageDatabase+Comments.swift in Sources */, F763D2A02A249C4500A3C901 /* NCManageDatabase+Capabilities.swift in Sources */, @@ -4173,6 +4200,7 @@ F78302FF28B4C45000B84583 /* NCUtilityFileSystem.swift in Sources */, F73EF7B82B0224AB0087E6E9 /* NCManageDatabase+ExternalSites.swift in Sources */, F73EF7C02B02250B0087E6E9 /* NCManageDatabase+GPS.swift in Sources */, + F3E173C12C9B1067006D177A /* AwakeMode.swift in Sources */, F73EF7B02B0224350087E6E9 /* NCManageDatabase+DirectEditing.swift in Sources */, F75DD766290ABB25002EB562 /* Intent.intentdefinition in Sources */, F7D68FCD28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */, @@ -4212,6 +4240,7 @@ F7327E382B73AEDE00A462C7 /* NCNetworking+LivePhoto.swift in Sources */, F771E3D320E2392D00AFB62D /* FileProviderExtension.swift in Sources */, F771E3D520E2392D00AFB62D /* FileProviderItem.swift in Sources */, + F3E173C42C9B1067006D177A /* AwakeMode.swift in Sources */, AF4BF616275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */, F343A4B72A1E084300DDA874 /* PHAsset+Extension.swift in Sources */, F7434B3620E23FE000417916 /* NCManageDatabase.swift in Sources */, @@ -4439,6 +4468,7 @@ F73EF7DF2B02266D0087E6E9 /* NCManageDatabase+Trash.swift in Sources */, F79B646026CA661600838ACA /* UIControl+Extension.swift in Sources */, F768823E2C0DD305001CF441 /* LazyView.swift in Sources */, + F3E173B02C9AF637006D177A /* ScreenAwakeManager.swift in Sources */, F7CA212D25F1333300826ABB /* NCAccountRequest.swift in Sources */, F747EB0D2C4AC1FF00F959A8 /* NCCollectionViewCommon+CollectionViewDelegateFlowLayout.swift in Sources */, F765F73125237E3F00391DBE /* NCRecent.swift in Sources */, @@ -4541,6 +4571,7 @@ AF2D7C7E2742559100ADF566 /* NCShareUserCell.swift in Sources */, F74DE14325135B6800917068 /* NCTransfers.swift in Sources */, AF4BF614275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */, + F3E173C02C9B1067006D177A /* AwakeMode.swift in Sources */, F711A4DC2AF92CAE00095DD8 /* NCUtility+Date.swift in Sources */, AF4BF61E27562B3F0081CEEF /* NCManageDatabase+Activity.swift in Sources */, ); @@ -4586,6 +4617,7 @@ F72FD3B7297ED49A00075D28 /* NCManageDatabase+E2EE.swift in Sources */, F7A8D74128F18254008BBE1C /* UIColor+Extension.swift in Sources */, F73EF7D92B0226080087E6E9 /* NCManageDatabase+Tip.swift in Sources */, + F3E173C22C9B1067006D177A /* AwakeMode.swift in Sources */, F7864ACE2A78FE73004870E0 /* NCManageDatabase+LocalFile.swift in Sources */, F7B769AA2B7A0B2000C1AAEB /* NCManageDatabase+Metadata+Session.swift in Sources */, F7A8D74028F18212008BBE1C /* UIImage+Extension.swift in Sources */, @@ -5342,6 +5374,7 @@ SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES; SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/iOSClient/Nextcloud-Bridging-Header.h"; TARGETED_DEVICE_FAMILY = "1,2"; + _EXPERIMENTAL_SWIFT_EXPLICIT_MODULES = YES; }; name = Debug; }; @@ -5364,6 +5397,7 @@ SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES; SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/iOSClient/Nextcloud-Bridging-Header.h"; TARGETED_DEVICE_FAMILY = "1,2"; + _EXPERIMENTAL_SWIFT_EXPLICIT_MODULES = YES; }; name = Release; }; @@ -5706,6 +5740,14 @@ minimumVersion = 2.9.1; }; }; + F3CA5AF32C99C2C400F673FC /* XCRemoteSwiftPackageReference "Insomnia" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/ochococo/Insomnia"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 2.0.1; + }; + }; F70B86732642CE3B00ED5349 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/firebase/firebase-ios-sdk"; @@ -6063,6 +6105,11 @@ package = F3A0479C2BD268B500658E7B /* XCRemoteSwiftPackageReference "PopupView" */; productName = PopupView; }; + F3CA5AF42C99C2C400F673FC /* Insomnia */ = { + isa = XCSwiftPackageProductDependency; + package = F3CA5AF32C99C2C400F673FC /* XCRemoteSwiftPackageReference "Insomnia" */; + productName = Insomnia; + }; F3F0419A2B9F7E6700D5155F /* RealmSwift */ = { isa = XCSwiftPackageProductDependency; package = F710FC78277B7CFF00AA9FBF /* XCRemoteSwiftPackageReference "realm-swift" */; diff --git a/Tests/NextcloudIntegrationTests/FilesIntegrationTests.swift b/Tests/NextcloudIntegrationTests/FilesIntegrationTests.swift index 4ad6a7d412..02b50938b2 100644 --- a/Tests/NextcloudIntegrationTests/FilesIntegrationTests.swift +++ b/Tests/NextcloudIntegrationTests/FilesIntegrationTests.swift @@ -32,60 +32,60 @@ final class FilesIntegrationTests: BaseIntegrationXCTestCase { func test_createReadDeleteFolder_withProperParams_shouldCreateReadDeleteFolder() throws { let expectation = expectation(description: "Should finish last callback") - let folderName = "TestFolder\(randomInt)" - let serverUrl = "\(TestConstants.server)/remote.php/dav/files/\(TestConstants.username)" - let serverUrlFileName = "\(serverUrl)/\(folderName)" - let domain = NCDomain.Domain(account: TestConstants.account, urlBase: TestConstants.server, user: TestConstants.username, userId: TestConstants.username, sceneIdentifier: "") - - NextcloudKit.shared.setup(delegate: NCNetworking.shared) - NextcloudKit.shared.appendAccount(TestConstants.account, urlBase: TestConstants.server, user: TestConstants.username, userId: TestConstants.username, password: appToken, userAgent: userAgent, nextcloudVersion: 0, groupIdentifier: NCBrandOptions.shared.capabilitiesGroup) - - // Test creating folder - NCNetworking.shared.createFolder(fileName: folderName, serverUrl: serverUrl, overwrite: true, withPush: true, sceneIdentifier: nil, domain: domain) { error in - - XCTAssertEqual(NKError.success.errorCode, error.errorCode) - XCTAssertEqual(NKError.success.errorDescription, error.errorDescription) - - Thread.sleep(forTimeInterval: 1) - - // Test reading folder, should exist - NCNetworking.shared.readFolder(serverUrl: serverUrlFileName, account: TestConstants.username) { account, metadataFolder, _, _, _, _ in - XCTAssertEqual(TestConstants.account, account) - XCTAssertEqual(NKError.success.errorCode, error.errorCode) - XCTAssertEqual(NKError.success.errorDescription, error.errorDescription) - XCTAssertEqual(metadataFolder?.fileName, folderName) - - // Check Realm directory, should exist - let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "serverUrl == %@", serverUrlFileName)) - XCTAssertNotNil(directory) - - Thread.sleep(forTimeInterval: 1) - - Task { - // Test deleting folder - await _ = NCNetworking.shared.deleteMetadata(metadataFolder!, onlyLocalCache: false) - - XCTAssertEqual(NKError.success.errorCode, error.errorCode) - XCTAssertEqual(NKError.success.errorDescription, error.errorDescription) - - try await Task.sleep(for: .seconds(1)) - - // Test reading folder, should NOT exist - NCNetworking.shared.readFolder(serverUrl: serverUrlFileName, account: TestConstants.username) { account, metadataFolder, _, _, _, _ in - - defer { expectation.fulfill() } - - XCTAssertEqual(0, error.errorCode) - XCTAssertNil(metadataFolder?.fileName) - - // Check Realm directory, should NOT exist - let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "serverUrl == %@", serverUrlFileName)) - XCTAssertNil(directory) - } - } - } - } - - waitForExpectations(timeout: TestConstants.timeoutLong) +// let folderName = "TestFolder\(randomInt)" +// let serverUrl = "\(TestConstants.server)/remote.php/dav/files/\(TestConstants.username)" +// let serverUrlFileName = "\(serverUrl)/\(folderName)" +// let domain = NCDomain.Domain(account: TestConstants.account, urlBase: TestConstants.server, user: TestConstants.username, userId: TestConstants.username, sceneIdentifier: "") +// +// NextcloudKit.shared.setup(delegate: NCNetworking.shared) +// NextcloudKit.shared.appendAccount(TestConstants.account, urlBase: TestConstants.server, user: TestConstants.username, userId: TestConstants.username, password: appToken, userAgent: userAgent, nextcloudVersion: 0, groupIdentifier: NCBrandOptions.shared.capabilitiesGroup) +// +// // Test creating folder +// NCNetworking.shared.createFolder(fileName: folderName, serverUrl: serverUrl, overwrite: true, withPush: true, sceneIdentifier: nil, domain: domain) { error in +// +// XCTAssertEqual(NKError.success.errorCode, error.errorCode) +// XCTAssertEqual(NKError.success.errorDescription, error.errorDescription) +// +// Thread.sleep(forTimeInterval: 1) +// +// // Test reading folder, should exist +// NCNetworking.shared.readFolder(serverUrl: serverUrlFileName, account: TestConstants.username) { account, metadataFolder, _, _, _, _ in +// XCTAssertEqual(TestConstants.account, account) +// XCTAssertEqual(NKError.success.errorCode, error.errorCode) +// XCTAssertEqual(NKError.success.errorDescription, error.errorDescription) +// XCTAssertEqual(metadataFolder?.fileName, folderName) +// +// // Check Realm directory, should exist +// let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "serverUrl == %@", serverUrlFileName)) +// XCTAssertNotNil(directory) +// +// Thread.sleep(forTimeInterval: 1) +// +// Task { +// // Test deleting folder +// await _ = NCNetworking.shared.deleteMetadata(metadataFolder!, onlyLocalCache: false) +// +// XCTAssertEqual(NKError.success.errorCode, error.errorCode) +// XCTAssertEqual(NKError.success.errorDescription, error.errorDescription) +// +// try await Task.sleep(for: .seconds(1)) +// +// // Test reading folder, should NOT exist +// NCNetworking.shared.readFolder(serverUrl: serverUrlFileName, account: TestConstants.username) { account, metadataFolder, _, _, _, _ in +// +// defer { expectation.fulfill() } +// +// XCTAssertEqual(0, error.errorCode) +// XCTAssertNil(metadataFolder?.fileName) +// +// // Check Realm directory, should NOT exist +// let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "serverUrl == %@", serverUrlFileName)) +// XCTAssertNil(directory) +// } +// } +// } +// } +// +// waitForExpectations(timeout: TestConstants.timeoutLong) } } diff --git a/iOSClient/Settings/Display/NCDisplayModel.swift b/iOSClient/Settings/Display/NCDisplayModel.swift index b914d00647..637e078f30 100644 --- a/iOSClient/Settings/Display/NCDisplayModel.swift +++ b/iOSClient/Settings/Display/NCDisplayModel.swift @@ -16,6 +16,14 @@ class NCDisplayModel: ObservableObject, ViewOnAppearHandling { @Published var controller: NCMainTabBarController? /// State variable for enabling the automatic appreance @Published var appearanceAutomatic: Bool = false + + /// State variable for keeping the screen on or off during file transfering + @Published var screenAwakeState = AwakeMode.off { + didSet { + keychain.screenAwakeMode = screenAwakeState + } + } + /// Get session var session: NCSession.Session { NCSession.shared.getSession(controller: controller) @@ -30,6 +38,7 @@ class NCDisplayModel: ObservableObject, ViewOnAppearHandling { /// Triggered when the view appears. func onViewAppear() { appearanceAutomatic = keychain.appearanceAutomatic + screenAwakeState = keychain.screenAwakeMode } // MARK: - All functions diff --git a/iOSClient/Settings/Display/NCDisplayView.swift b/iOSClient/Settings/Display/NCDisplayView.swift index 1fd91517c3..ab50d46b61 100644 --- a/iOSClient/Settings/Display/NCDisplayView.swift +++ b/iOSClient/Settings/Display/NCDisplayView.swift @@ -66,6 +66,16 @@ struct NCDisplayView: View { } } .font(.system(size: 16)) + + Section(header: Text(NSLocalizedString("_additional_options_", comment: ""))) { + + Picker(NSLocalizedString("_keep_screen_awake_", comment: ""), + selection: $model.screenAwakeState) { + Text(NSLocalizedString("_off_", comment: "")).tag(AwakeMode.off) + Text(NSLocalizedString("_on_", comment: "")).tag(AwakeMode.on) + Text(NSLocalizedString("_while_charging_", comment: "")).tag(AwakeMode.whileCharging) + } + }.pickerStyle(.menu) } .navigationBarTitle(NSLocalizedString("_display_", comment: "")) .defaultViewModifier(model) diff --git a/iOSClient/Settings/NCKeychain.swift b/iOSClient/Settings/NCKeychain.swift index 2260a63d17..be141a7ced 100644 --- a/iOSClient/Settings/NCKeychain.swift +++ b/iOSClient/Settings/NCKeychain.swift @@ -355,6 +355,30 @@ import KeychainAccess } } + var screenAwakeMode: AwakeMode { + get { + if let value = try? keychain.get("screenAwakeMode") { + if value == "off" { + return .off + } else if value == "on" { + return .on + } else { + return .whileCharging + } + } + return .off + } + set { + if newValue == .off { + keychain["screenAwakeMode"] = "off" + } else if newValue == .on { + keychain["screenAwakeMode"] = "on" + } else { + keychain["screenAwakeMode"] = "whileCharging" + } + } + } + var fileNameType: Bool { get { if let value = try? keychain.get("fileNameType"), let result = Bool(value) { diff --git a/iOSClient/Supporting Files/en.lproj/Localizable.strings b/iOSClient/Supporting Files/en.lproj/Localizable.strings index a8edd52381..9dd6d4ba3f 100644 --- a/iOSClient/Supporting Files/en.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/en.lproj/Localizable.strings @@ -999,6 +999,9 @@ "_users_" = "Users"; "_users_footer_" = "Every time the app is reactivated, the account will be requested."; "_additional_view_options_" = "Additional view options"; +"_while_charging_" = "Only while charging"; +"_additional_options_" = "Additional options"; +"_keep_screen_awake_" = "Keep screen awake while transfering files"; // Video "_select_trace_" = "Select the trace"; diff --git a/iOSClient/Utility/ScreenAwakeManager/AwakeMode.swift b/iOSClient/Utility/ScreenAwakeManager/AwakeMode.swift new file mode 100644 index 0000000000..08490e0af7 --- /dev/null +++ b/iOSClient/Utility/ScreenAwakeManager/AwakeMode.swift @@ -0,0 +1,34 @@ +// +// AwakeMode.swift +// Nextcloud +// +// Created by Milen Pivchev on 18.09.24. +// Copyright © 2024 Marino Faggiana. All rights reserved. +// + +import Foundation + +/** + Modes: + + - `disabled`: Nothing will change (disabled functionality). + - `always`: Device will never timeout and lock. + - `whenCharging`: Device will stay active as long as it's connected to charger. + + */ + enum AwakeMode: CaseIterable, Identifiable { + /** + Nothing will change (disabled functionality). + */ + case off + /** + Device will never timeout and lock. + */ + case on + /** + Device will stay active as long as it's connected to charger. + */ + case whileCharging + + var id: Self { self } + } diff --git a/iOSClient/Utility/ScreenAwakeManager/ScreenAwakeManager.swift b/iOSClient/Utility/ScreenAwakeManager/ScreenAwakeManager.swift new file mode 100644 index 0000000000..4fb935f501 --- /dev/null +++ b/iOSClient/Utility/ScreenAwakeManager/ScreenAwakeManager.swift @@ -0,0 +1,88 @@ +// +// ScreenAwakeManager.swift +// Nextcloud +// +// Created by Milen Pivchev on 18.09.24. +// Copyright © 2024 Marino Faggiana. All rights reserved. +// + +// Modified from https://github.com/ochococo/Insomnia +import UIKit + +/** + + Sometimes you want your iPhone to stay active a little bit longer is it an import or just game interface. + + This simple class aims to simplify the code and give you a well tested solution. + + */ +class ScreenAwakeManager { + static let shared: ScreenAwakeManager = { + let instance = ScreenAwakeManager() + return instance + }() + + /** + This mode will change the behavior: + + - `disabled`: Nothing will change (disabled functionality). + - `always`: Your iOS device will never timeout and lock. + - `whenCharging`: Device will stay active as long as it's connected to charger. + + */ + var mode: AwakeMode = .off { + didSet { + updateMode() + } + } + + private unowned let device = UIDevice.current + private unowned let notificationCenter = NotificationCenter.default + private unowned let application = UIApplication.shared + + private init() {} + + private func startMonitoring() { + device.isBatteryMonitoringEnabled = true + notificationCenter.addObserver(self, + selector: #selector(batteryStateDidChange), + name: UIDevice.batteryStateDidChangeNotification, object: nil) + } + + private func stopMonitoring() { + notificationCenter.removeObserver(self) + device.isBatteryMonitoringEnabled = false + } + + @objc private func batteryStateDidChange(notification: NSNotification) { + updateMode() + } + + private func updateMode() { + switch mode { + case .whileCharging: + startMonitoring() + application.isIdleTimerDisabled = isPlugged + case .on: + stopMonitoring() + application.isIdleTimerDisabled = true + case .off: + stopMonitoring() + application.isIdleTimerDisabled = false + } + } + + private var isPlugged: Bool { + switch device.batteryState { + case .unknown, .unplugged: + return false + default: + return true + } + } + + deinit { + stopMonitoring() + application.isIdleTimerDisabled = false + } +} From 4988f2e120a775bede02235063c1c4fb2ff951d1 Mon Sep 17 00:00:00 2001 From: Milen Pivchev Date: Thu, 19 Sep 2024 12:44:18 +0200 Subject: [PATCH 2/5] WIP Signed-off-by: Milen Pivchev --- iOSClient/Networking/NCNetworkingProcess.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/iOSClient/Networking/NCNetworkingProcess.swift b/iOSClient/Networking/NCNetworkingProcess.swift index e4174b4aa6..fa68abedf2 100644 --- a/iOSClient/Networking/NCNetworkingProcess.swift +++ b/iOSClient/Networking/NCNetworkingProcess.swift @@ -83,10 +83,10 @@ class NCNetworkingProcess { self.hasRun = true let resultsTransfer = self.database.getResultsMetadatas(predicate: NSPredicate(format: "status IN %@", self.global.metadataStatusInTransfer)) - if resultsTransfer == nil { - // No tranfer, disable + if resultsTransfer.isEmptyOrNil { + ScreenAwakeManager.shared.mode = .off } else { - // transfer enable + ScreenAwakeManager.shared.mode = NCKeychain().screenAwakeMode } guard let results = self.database.getResultsMetadatas(predicate: NSPredicate(format: "status != %d", self.global.metadataStatusNormal)) else { return } From d50046aab2c5e3d5c85c5efc66bb16634483b6a1 Mon Sep 17 00:00:00 2001 From: Milen Pivchev Date: Thu, 19 Sep 2024 12:56:14 +0200 Subject: [PATCH 3/5] Fix UI Signed-off-by: Milen Pivchev --- iOSClient/Settings/Display/NCDisplayView.swift | 4 +++- iOSClient/Supporting Files/en.lproj/Localizable.strings | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/iOSClient/Settings/Display/NCDisplayView.swift b/iOSClient/Settings/Display/NCDisplayView.swift index ab50d46b61..d045d99d67 100644 --- a/iOSClient/Settings/Display/NCDisplayView.swift +++ b/iOSClient/Settings/Display/NCDisplayView.swift @@ -75,7 +75,9 @@ struct NCDisplayView: View { Text(NSLocalizedString("_on_", comment: "")).tag(AwakeMode.on) Text(NSLocalizedString("_while_charging_", comment: "")).tag(AwakeMode.whileCharging) } - }.pickerStyle(.menu) + .frame(height: 50) + } + .pickerStyle(.menu) } .navigationBarTitle(NSLocalizedString("_display_", comment: "")) .defaultViewModifier(model) diff --git a/iOSClient/Supporting Files/en.lproj/Localizable.strings b/iOSClient/Supporting Files/en.lproj/Localizable.strings index 9dd6d4ba3f..1c7843d135 100644 --- a/iOSClient/Supporting Files/en.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/en.lproj/Localizable.strings @@ -999,7 +999,7 @@ "_users_" = "Users"; "_users_footer_" = "Every time the app is reactivated, the account will be requested."; "_additional_view_options_" = "Additional view options"; -"_while_charging_" = "Only while charging"; +"_while_charging_" = "While charging"; "_additional_options_" = "Additional options"; "_keep_screen_awake_" = "Keep screen awake while transfering files"; From c23c836cdb00f7eee5e695bee05d06f5a85d59cd Mon Sep 17 00:00:00 2001 From: Milen Pivchev Date: Thu, 26 Sep 2024 12:58:39 +0200 Subject: [PATCH 4/5] WIP Signed-off-by: Milen Pivchev --- Nextcloud.xcodeproj/project.pbxproj | 14 ----------- .../ScreenAwakeManager.swift | 23 +++++++++++-------- 2 files changed, 13 insertions(+), 24 deletions(-) diff --git a/Nextcloud.xcodeproj/project.pbxproj b/Nextcloud.xcodeproj/project.pbxproj index 7da6bc347d..ad3ada43e7 100644 --- a/Nextcloud.xcodeproj/project.pbxproj +++ b/Nextcloud.xcodeproj/project.pbxproj @@ -160,7 +160,6 @@ F3BB464D2A39ADCC00461F6E /* NCMoreAppSuggestionsCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F3BB464C2A39ADCC00461F6E /* NCMoreAppSuggestionsCell.xib */; }; F3BB46522A39EC4900461F6E /* NCMoreAppSuggestionsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3BB46512A39EC4900461F6E /* NCMoreAppSuggestionsCell.swift */; }; F3BB46542A3A1E9D00461F6E /* CCCellMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3BB46532A3A1E9D00461F6E /* CCCellMore.swift */; }; - F3CA5AF52C99C2C400F673FC /* Insomnia in Frameworks */ = {isa = PBXBuildFile; productRef = F3CA5AF42C99C2C400F673FC /* Insomnia */; }; F3E173B02C9AF637006D177A /* ScreenAwakeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E173AF2C9AF637006D177A /* ScreenAwakeManager.swift */; }; F3E173C02C9B1067006D177A /* AwakeMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E173BF2C9B1067006D177A /* AwakeMode.swift */; }; F3E173C12C9B1067006D177A /* AwakeMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E173BF2C9B1067006D177A /* AwakeMode.swift */; }; @@ -5925,14 +5924,6 @@ minimumVersion = 2.9.1; }; }; - F3CA5AF32C99C2C400F673FC /* XCRemoteSwiftPackageReference "Insomnia" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/ochococo/Insomnia"; - requirement = { - kind = upToNextMajorVersion; - minimumVersion = 2.0.1; - }; - }; F70B86732642CE3B00ED5349 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/firebase/firebase-ios-sdk"; @@ -6298,11 +6289,6 @@ package = F3A0479C2BD268B500658E7B /* XCRemoteSwiftPackageReference "PopupView" */; productName = PopupView; }; - F3CA5AF42C99C2C400F673FC /* Insomnia */ = { - isa = XCSwiftPackageProductDependency; - package = F3CA5AF32C99C2C400F673FC /* XCRemoteSwiftPackageReference "Insomnia" */; - productName = Insomnia; - }; F3F0419A2B9F7E6700D5155F /* RealmSwift */ = { isa = XCSwiftPackageProductDependency; package = F710FC78277B7CFF00AA9FBF /* XCRemoteSwiftPackageReference "realm-swift" */; diff --git a/iOSClient/Utility/ScreenAwakeManager/ScreenAwakeManager.swift b/iOSClient/Utility/ScreenAwakeManager/ScreenAwakeManager.swift index 4fb935f501..ee873d2801 100644 --- a/iOSClient/Utility/ScreenAwakeManager/ScreenAwakeManager.swift +++ b/iOSClient/Utility/ScreenAwakeManager/ScreenAwakeManager.swift @@ -59,17 +59,20 @@ class ScreenAwakeManager { } private func updateMode() { - switch mode { - case .whileCharging: - startMonitoring() - application.isIdleTimerDisabled = isPlugged - case .on: - stopMonitoring() - application.isIdleTimerDisabled = true - case .off: - stopMonitoring() - application.isIdleTimerDisabled = false + DispatchQueue.main.async { [self] in + switch mode { + case .whileCharging: + startMonitoring() + application.isIdleTimerDisabled = isPlugged + case .on: + stopMonitoring() + application.isIdleTimerDisabled = true + case .off: + stopMonitoring() + application.isIdleTimerDisabled = false + } } + } private var isPlugged: Bool { From 34c2b949e929406750b7936a88623d8c877c07cc Mon Sep 17 00:00:00 2001 From: Milen Pivchev Date: Fri, 27 Sep 2024 15:25:12 +0200 Subject: [PATCH 5/5] refactor Signed-off-by: Milen Pivchev --- iOSClient/Utility/ScreenAwakeManager/ScreenAwakeManager.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/iOSClient/Utility/ScreenAwakeManager/ScreenAwakeManager.swift b/iOSClient/Utility/ScreenAwakeManager/ScreenAwakeManager.swift index ee873d2801..43af39ecf6 100644 --- a/iOSClient/Utility/ScreenAwakeManager/ScreenAwakeManager.swift +++ b/iOSClient/Utility/ScreenAwakeManager/ScreenAwakeManager.swift @@ -72,7 +72,6 @@ class ScreenAwakeManager { application.isIdleTimerDisabled = false } } - } private var isPlugged: Bool {