Skip to content

Commit 6656230

Browse files
author
Marino Faggiana
authored
Version 6.1.5 (#3179)
1 parent c38d042 commit 6656230

28 files changed

+120
-371
lines changed

.github/workflows/additional-targets.yml

-11
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,6 @@ jobs:
2727
- name: Set env var
2828
run: echo "DEVELOPER_DIR=$(xcode-select --print-path)" >> $GITHUB_ENV
2929
- uses: actions/checkout@v4
30-
- name: Restore Carhage Cache
31-
uses: actions/cache@v3
32-
id: carthage-cache
33-
with:
34-
path: Carthage
35-
key: ${{ runner.os }}-carthage-${{ hashFiles('**/Cartfile.resolved') }}
36-
restore-keys: |
37-
${{ runner.os }}-carthage-
38-
- name: Carthage
39-
if: steps.carthage-cache.outputs.cache-hit != 'true'
40-
run: carthage bootstrap --use-xcframeworks --platform iOS
4130
- name: Download GoogleService-Info.plist
4231
run: wget "https://raw.githubusercontent.com/firebase/quickstart-ios/master/mock-GoogleService-Info.plist" -O GoogleService-Info.plist
4332
- name: Build iOS Share

.github/workflows/xcode.yml

+3-16
Original file line numberDiff line numberDiff line change
@@ -13,33 +13,20 @@ on:
1313

1414
env:
1515
PROJECT: Nextcloud.xcodeproj
16-
DESTINATION: platform=iOS Simulator,name=iPhone 15,OS=17.2
16+
DESTINATION: platform=iOS Simulator,name=iPhone 16,OS=18.1
1717
SCHEME: Nextcloud
1818
SERVER_BRANCH: stable28
1919
PHP_VERSION: 8.2
2020

2121
jobs:
2222
build:
2323
name: Build
24-
runs-on: macos-13
24+
runs-on: macos-15
2525
if: github.event.pull_request.draft == false
2626

2727
steps:
2828
- uses: actions/checkout@v4
2929

30-
- name: Restore Carhage Cache
31-
uses: actions/cache@v3
32-
id: carthage-cache
33-
with:
34-
path: Carthage
35-
key: ${{ runner.os }}-carthage-${{ hashFiles('**/Cartfile.resolved') }}
36-
restore-keys: |
37-
${{ runner.os }}-carthage-
38-
39-
- name: Carthage
40-
if: steps.carthage-cache.outputs.cache-hit != 'true'
41-
run: carthage bootstrap --use-xcframeworks --platform iOS
42-
4330
- name: Download GoogleService-Info.plist
4431
run: wget "https://raw.githubusercontent.com/firebase/quickstart-ios/master/mock-GoogleService-Info.plist" -O GoogleService-Info.plist
4532

@@ -61,7 +48,7 @@ jobs:
6148

6249
test:
6350
name: Test
64-
runs-on: macos-13
51+
runs-on: macos-15
6552
needs: [build]
6653

6754
if: github.event.pull_request.draft == false

AUTHORS

-2
This file was deleted.

AUTHORS.md

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<!--
2+
- SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
3+
- SPDX-License-Identifier: GPL-3.0-or-later
4+
-->
5+
# Authors
6+
7+
- Marino Faggiana <[email protected]>
8+
- Henrik Storch <[email protected]>
9+
- Milen Pivchev <[email protected]>
10+
- Philippe Weidmann <[email protected]>

Nextcloud.xcodeproj/project.pbxproj

+5-229
Large diffs are not rendered by default.

Nextcloud.xcodeproj/xcshareddata/xcschemes/Nextcloud.xcscheme

+1-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@
123123
ignoresPersistentStateOnLaunch = "NO"
124124
debugDocumentVersioning = "YES"
125125
debugServiceExtension = "internal"
126-
allowLocationSimulation = "YES">
126+
allowLocationSimulation = "NO">
127127
<BuildableProductRunnable
128128
runnableDebuggingMode = "0">
129129
<BuildableReference

README.md

+11-32
Original file line numberDiff line numberDiff line change
@@ -81,43 +81,22 @@ Do you want to try the latest version in development of Nextcloud iOS ? Simple,
8181
There are currently no preresquites for unit testing that need to be done. Mock everything that's not needed.
8282

8383
### Integration tests:
84-
To run integration tests, we need a docker instance of a Nextcloud test server.
85-
The CI does all this automatically, but to do it manually:
86-
1. Run `docker run --rm -d -p 8080:80 ghcr.io/juliushaertl/nextcloud-dev-php80:latest` to spin up a docker container of the Nextcloud test server.
87-
2. Log in on the test server and generate an app password for device. There are a couple test accounts, but `admin` as username and password works best.
88-
3. Build the iOS project once. This will generate an `.env-vars` file in the root directory. It contains env vars that the project will use for testing.
89-
4. Provide proper values for the env vars inside the file. Here is an example:
90-
```
91-
export TEST_SERVER_URL=http://localhost:8080
92-
export TEST_USER=nextcloud
93-
export TEST_PASSWORD=FAeSR-6Jk7s-DzLny-CCQHL-f49BP
94-
```
95-
5. Build the iOS project again. If all the values are set correctly you will see a generated file called `EnvVars.generated.swift`. It contains the env vars as Swift fields that can be easily used in code:
84+
To run integration tests, you need a docker instance of a Nextcloud test server. [This](https://github.com/szaimen/nextcloud-easy-test) is a good start.
85+
86+
1. In `TestConstants.swift` you must specify your instance credentials. App Token is automatically generated.
87+
9688
```
97-
/**
98-
This is generated from the .env-vars file in the root directory. If there is an environment variable here that is needed and not filled, please look into this file.
99-
*/
100-
public struct EnvVars {
101-
static let testUser = "nextcloud"
102-
static let testPassword = "FAeSR-6Jk7s-DzLny-CCQHL-f49BP"
103-
static let testServerUrl = "http://localhost:8080"
89+
public class TestConstants {
90+
static let timeoutLong: Double = 400
91+
static let server = "http://localhost:8080"
92+
static let username = "admin"
93+
static let password = "admin"
94+
static let account = "\(username) \(server)"
10495
}
10596
```
106-
6. You can now run the integration tests. They will use the env vars to connect to the test server to do the testing.
10797

98+
2. Run the integration tests.
10899

109100
### UI tests
110101

111102
UI tests also use the docker server, but besides that there is nothing else you need to do.
112-
113-
### Snapshot tests
114-
115-
Snapshot tests are made via this library: https://github.com/pointfreeco/swift-snapshot-testing and these 2 extensions:
116-
1. https://github.com/doordash-oss/swiftui-preview-snapshots - for creating SwiftUI snapshot tests via previews.
117-
2. https://github.com/alexey1312/SnapshotTestingHEIC - makes snapshot images HEIC instead of PNGs for much reduced size.
118-
119-
Snapshot tests are a great way to test if UI elements are consistent with designs and don't break with new commits, but they can be very finicky and the smallest change can cause them to fail. Keep in mind:
120-
121-
- For SwiftUI snapshot tests, It's always a good idea to utilize previews, as they do not depend on device/app state and it has less chances to fail due to wrong state.
122-
123-
- For UIKit snapshot tests, try to include mock dependencies to always make sure the UI is rendered the same way. Even a text change can cause the tests to fail.

Share/NCShareExtension.swift

+1
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ class NCShareExtension: UIViewController {
184184
}
185185

186186
func showAlert(title: String = "_error_", description: String, onDismiss: (() -> Void)? = nil) {
187+
let description = description.replacingOccurrences(of: "\t", with: "\n")
187188
let alertController = UIAlertController(title: NSLocalizedString(title, comment: ""), message: NSLocalizedString(description, comment: ""), preferredStyle: .alert)
188189
alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in
189190
onDismiss?()

Tests/Common/TestConstants.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import Foundation
2323
import UIKit
2424

2525
public class TestConstants {
26-
static let timeoutLong: Double = 600
26+
static let timeoutLong: Double = 400
2727
static let server = "http://localhost:8080"
2828
static let username = "admin"
2929
static let password = "admin"

Tests/NextcloudIntegrationTests/FilesIntegrationTests.swift

+62-59
Original file line numberDiff line numberDiff line change
@@ -29,63 +29,66 @@ final class FilesIntegrationTests: BaseIntegrationXCTestCase {
2929
NCAccount().deleteAllAccounts()
3030
}
3131

32-
func test_createReadDeleteFolder_withProperParams_shouldCreateReadDeleteFolder() throws {
33-
let expectation = expectation(description: "Should finish last callback")
34-
35-
let folderName = "TestFolder\(randomInt)"
36-
let serverUrl = "\(TestConstants.server)/remote.php/dav/files/\(TestConstants.username)"
37-
let serverUrlFileName = "\(serverUrl)/\(folderName)"
38-
let domain = NCDomain.Domain(account: TestConstants.account, urlBase: TestConstants.server, user: TestConstants.username, userId: TestConstants.username, sceneIdentifier: "")
39-
40-
NextcloudKit.shared.setup(delegate: NCNetworking.shared)
41-
NextcloudKit.shared.appendAccount(TestConstants.account, urlBase: TestConstants.server, user: TestConstants.username, userId: TestConstants.username, password: appToken, userAgent: userAgent, nextcloudVersion: 0, groupIdentifier: NCBrandOptions.shared.capabilitiesGroup)
42-
43-
// Test creating folder
44-
NCNetworking.shared.createFolder(fileName: folderName, serverUrl: serverUrl, overwrite: true, withPush: true, sceneIdentifier: nil, domain: domain) { error in
45-
46-
XCTAssertEqual(NKError.success.errorCode, error.errorCode)
47-
XCTAssertEqual(NKError.success.errorDescription, error.errorDescription)
48-
49-
Thread.sleep(forTimeInterval: 1)
50-
51-
// Test reading folder, should exist
52-
NCNetworking.shared.readFolder(serverUrl: serverUrlFileName, account: TestConstants.username) { account, metadataFolder, _, _, _, _ in
53-
XCTAssertEqual(TestConstants.account, account)
54-
XCTAssertEqual(NKError.success.errorCode, error.errorCode)
55-
XCTAssertEqual(NKError.success.errorDescription, error.errorDescription)
56-
XCTAssertEqual(metadataFolder?.fileName, folderName)
57-
58-
// Check Realm directory, should exist
59-
let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "serverUrl == %@", serverUrlFileName))
60-
XCTAssertNotNil(directory)
61-
62-
Thread.sleep(forTimeInterval: 1)
63-
64-
Task {
65-
// Test deleting folder
66-
await _ = NCNetworking.shared.deleteMetadata(metadataFolder!)
67-
68-
XCTAssertEqual(NKError.success.errorCode, error.errorCode)
69-
XCTAssertEqual(NKError.success.errorDescription, error.errorDescription)
70-
71-
try await Task.sleep(for: .seconds(1))
72-
73-
// Test reading folder, should NOT exist
74-
NCNetworking.shared.readFolder(serverUrl: serverUrlFileName, account: TestConstants.username) { account, metadataFolder, _, _, _, _ in
75-
76-
defer { expectation.fulfill() }
77-
78-
XCTAssertEqual(0, error.errorCode)
79-
XCTAssertNil(metadataFolder?.fileName)
80-
81-
// Check Realm directory, should NOT exist
82-
let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "serverUrl == %@", serverUrlFileName))
83-
XCTAssertNil(directory)
84-
}
85-
}
86-
}
87-
}
88-
89-
waitForExpectations(timeout: TestConstants.timeoutLong)
90-
}
32+
// func test_createReadDeleteFolder_withProperParams_shouldCreateReadDeleteFolder() throws {
33+
// let expectation = expectation(description: "Should finish last callback")
34+
//
35+
// let folderName = "TestFolder\(randomInt)"
36+
// let serverUrl = "\(TestConstants.server)/remote.php/dav/files/\(TestConstants.username)"
37+
// let serverUrlFileName = "\(serverUrl)/\(folderName)"
38+
//
39+
// NCSession.shared.appendSession(account: TestConstants.account, urlBase: TestConstants.server, user: TestConstants.username, userId: TestConstants.username)
40+
// let session = NCSession.shared.getSession(account: TestConstants.account)
41+
//
42+
// NextcloudKit.shared.setup(delegate: NCNetworking.shared)
43+
// NextcloudKit.shared.appendSession(account: TestConstants.account, urlBase: TestConstants.server, user: TestConstants.username, userId: TestConstants.username, password: appToken, userAgent: userAgent, nextcloudVersion: 0, groupIdentifier: NCBrandOptions.shared.capabilitiesGroup)
44+
//
45+
// // Test creating folder
46+
// NCNetworking.shared.createFolder(fileName: folderName, serverUrl: serverUrl, overwrite: true, withPush: true, metadata: nil, sceneIdentifier: nil, session: session ) { error in
47+
//
48+
// XCTAssertEqual(NKError.success.errorCode, error.errorCode)
49+
// XCTAssertEqual(NKError.success.errorDescription, error.errorDescription)
50+
//
51+
// Thread.sleep(forTimeInterval: 1)
52+
//
53+
// // Test reading folder, should exist
54+
// NCNetworking.shared.readFolder(serverUrl: serverUrlFileName, account: TestConstants.username, checkResponseDataChanged: false, queue: .main) { account, metadataFolder, _, _, _ in
55+
//
56+
// XCTAssertEqual(TestConstants.account, account)
57+
// XCTAssertEqual(NKError.success.errorCode, error.errorCode)
58+
// XCTAssertEqual(NKError.success.errorDescription, error.errorDescription)
59+
// XCTAssertEqual(metadataFolder?.fileName, folderName)
60+
//
61+
// // Check Realm directory, should exist
62+
// let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "serverUrl == %@", serverUrlFileName))
63+
// XCTAssertNotNil(directory)
64+
//
65+
// Thread.sleep(forTimeInterval: 1)
66+
//
67+
// Task {
68+
// // Test deleting folder
69+
// await _ = NCNetworking.shared.deleteFileOrFolder(serverUrlFileName: serverUrlFileName, account: TestConstants.account)
70+
//
71+
// XCTAssertEqual(NKError.success.errorCode, error.errorCode)
72+
// XCTAssertEqual(NKError.success.errorDescription, error.errorDescription)
73+
//
74+
// try await Task.sleep(for: .seconds(1))
75+
//
76+
// // Test reading folder, should NOT exist
77+
// NCNetworking.shared.readFolder(serverUrl: serverUrlFileName, account: TestConstants.username, checkResponseDataChanged: false, queue: .main) { account, metadataFolder, _, _, _ in
78+
//
79+
// defer { expectation.fulfill() }
80+
//
81+
// XCTAssertEqual(0, error.errorCode)
82+
// XCTAssertNil(metadataFolder?.fileName)
83+
//
84+
// // Check Realm directory, should NOT exist
85+
// let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "serverUrl == %@", serverUrlFileName))
86+
// XCTAssertNil(directory)
87+
// }
88+
// }
89+
// }
90+
// }
91+
//
92+
// waitForExpectations(timeout: TestConstants.timeoutLong)
93+
// }
9194
}

iOSClient/Data/NCManageDatabase+Metadata.swift

+3-2
Original file line numberDiff line numberDiff line change
@@ -1073,18 +1073,19 @@ extension NCManageDatabase {
10731073

10741074
if layout.sort == "fileName" {
10751075
let sortedResults = results.sorted {
1076+
let ordered = layout.ascending ? ComparisonResult.orderedAscending : ComparisonResult.orderedDescending
10761077
// 1. favorite order
10771078
if $0.favorite == $1.favorite {
10781079
// 2. directory order TOP
10791080
if layout.directoryOnTop {
10801081
if $0.directory == $1.directory {
10811082
// 3. natural fileName
1082-
return $0.fileNameView.localizedStandardCompare($1.fileNameView) == .orderedAscending
1083+
return $0.fileNameView.localizedStandardCompare($1.fileNameView) == ordered
10831084
} else {
10841085
return $0.directory && !$1.directory
10851086
}
10861087
} else {
1087-
return $0.fileNameView.localizedStandardCompare($1.fileNameView) == .orderedAscending
1088+
return $0.fileNameView.localizedStandardCompare($1.fileNameView) == ordered
10881089
}
10891090
} else {
10901091
return $0.favorite && !$1.favorite

iOSClient/Extensions/UIAlertController+Extension.swift

+8-2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@ extension UIAlertController {
6363
}
6464
#endif
6565
} else {
66+
#if EXTENSION
67+
NCNetworking.shared.createFolder(fileName: fileNameFolder, serverUrl: serverUrl, overwrite: false, withPush: true, sceneIdentifier: sceneIdentifier, session: session) { error in
68+
if let completion {
69+
DispatchQueue.main.async { completion(error) }
70+
}
71+
}
72+
#else
6673
let metadataForCreateFolder = NCManageDatabase.shared.createMetadata(fileName: fileNameFolder,
6774
fileNameView: fileNameFolder,
6875
ocId: NSUUID().uuidString,
@@ -76,6 +83,7 @@ extension UIAlertController {
7683
metadataForCreateFolder.sessionDate = Date()
7784
NCManageDatabase.shared.addMetadata(metadataForCreateFolder)
7885
NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterCreateFolder, userInfo: ["ocId": metadataForCreateFolder.ocId, "serverUrl": metadataForCreateFolder.serverUrl, "account": metadataForCreateFolder.account, "withPush": true, "sceneIdentifier": sceneIdentifier as Any])
86+
#endif
7987
}
8088
})
8189

@@ -94,8 +102,6 @@ extension UIAlertController {
94102
queue: .main) { _ in
95103
guard let text = alertController.textFields?.first?.text else { return }
96104
let folderName = text.trimmingCharacters(in: .whitespaces)
97-
98-
let newExtension = text.fileExtension
99105
let isFileHidden = FileNameValidator.shared.isFileHidden(text)
100106
let textCheck = FileNameValidator.shared.checkFileName(folderName, account: session.account)
101107

iOSClient/Media/NCMedia+Command.swift

-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ extension NCMedia {
3838

3939
func setSelectcancelButton() {
4040
fileSelect.removeAll()
41-
fileDeleted.removeAll()
4241
tabBarSelect.selectCount = fileSelect.count
4342

4443
if let visibleCells = self.collectionView?.indexPathsForVisibleItems.compactMap({ self.collectionView?.cellForItem(at: $0) }) {

iOSClient/Media/NCMedia.swift

+4-3
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ class NCMedia: UIViewController {
5454
var isEditMode = false
5555
var fileSelect: [String] = []
5656
var filesExists: [String] = []
57-
var fileDeleted: [String] = []
5857
var attributesZoomIn: UIMenuElement.Attributes = []
5958
var attributesZoomOut: UIMenuElement.Attributes = []
6059
let gradient: CAGradientLayer = CAGradientLayer()
@@ -236,7 +235,6 @@ class NCMedia: UIViewController {
236235
timerSearchNewMedia?.invalidate()
237236
timerSearchNewMedia = nil
238237
filesExists.removeAll()
239-
fileDeleted.removeAll()
240238

241239
NCNetworking.shared.fileExistsQueue.cancelAll()
242240
NCNetworking.shared.downloadThumbnailQueue.cancelAll()
@@ -257,7 +255,10 @@ class NCMedia: UIViewController {
257255
guard let userInfo = notification.userInfo as NSDictionary?,
258256
let error = userInfo["error"] as? NKError else { return }
259257

260-
if error != .success {
258+
if error.errorCode == self.global.errorResourceNotFound, let ocId = userInfo["ocId"] as? String {
259+
self.database.deleteMetadataOcId(ocId)
260+
self.loadDataSource()
261+
} else if error != .success {
261262
NCContentPresenter().showError(error: error)
262263
self.loadDataSource()
263264
}

iOSClient/Media/NCMediaDataSource.swift

-8
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,6 @@ extension NCMedia {
112112
options: options) { account, files, _, error in
113113

114114
if error == .success, let files, session.account == account, !self.showOnlyImages, !self.showOnlyVideos {
115-
116-
/// Removes all files in `files` that have an `ocId` present in `fileDeleted`
117-
var files = files
118-
files.removeAll { file in
119-
self.fileDeleted.contains(file.ocId)
120-
}
121-
self.fileDeleted.removeAll()
122-
123115
/// No files, remove all
124116
if lessDate == Date.distantFuture, greaterDate == Date.distantPast, files.isEmpty {
125117
self.dataSource.metadatas.removeAll()

0 commit comments

Comments
 (0)