Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions ios/Internxt/FileProviderDomainManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,20 @@ enum FileProviderDomainManager {
}
}

static func signalEnumeration(completion: @escaping (Error?) -> Void) {
guard let manager = NSFileProviderManager(for: domain) else {
completion(NSError(
domain: "FileProviderDomainManager",
code: -1,
userInfo: [NSLocalizedDescriptionKey: "No NSFileProviderManager for domain \(domainIdentifier.rawValue)"]
))
return
}
manager.signalEnumerator(for: .workingSet) { error in
completion(error)
}
}

private static func isAlreadyExists(_ error: Error?) -> Bool {
guard let error = error as NSError? else { return false }
return error.domain == NSCocoaErrorDomain && error.code == NSFileWriteFileExistsError
Expand Down
8 changes: 7 additions & 1 deletion ios/Internxt/InternxtAuthCredentialsModule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ class InternxtAuthCredentialsModule: NSObject {
rejecter("E_REGISTER_DOMAIN", error.localizedDescription, error as NSError)
return
}
resolver(nil)
FileProviderDomainManager.signalEnumeration { signalError in
if let signalError = signalError {
NSLog("InternxtAuthCredentialsModule: signalEnumeration failed (ignored): \(signalError.localizedDescription)")
}
resolver(nil)
}
}
}

Expand Down Expand Up @@ -56,6 +61,7 @@ class InternxtAuthCredentialsModule: NSObject {
writeIfPresent(creds["rootFolderUuid"], to: SharedAuthKeychain.rootFolderIdKey)
writeIfPresent(creds["bridgeUser"], to: SharedAuthKeychain.bridgeUserKey)
writeIfPresent(creds["userId"], to: SharedAuthKeychain.userIdKey)
writeIfPresent(creds["driveBaseUrl"], to: SharedAuthKeychain.driveBaseUrlKey)
}

private func writeIfPresent(_ value: Any?, to sharedKey: String) {
Expand Down
61 changes: 50 additions & 11 deletions ios/InternxtFileProvider/FileProviderExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,70 @@
import InternxtSwiftCore

class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension {
private let rootDisplayName: String

required init(domain: NSFileProviderDomain) {
self.rootDisplayName = domain.displayName
super.init()
}

private func currentAuthToken() -> String? {
guard let data = SharedAuthKeychain.read(SharedAuthKeychain.photosTokenKey) else { return nil }
return String(data: data, encoding: .utf8)
}

func invalidate() {
// TODO: cleanup any resources
}

func item(for identifier: NSFileProviderItemIdentifier, request: NSFileProviderRequest, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) -> Progress {
_ = currentAuthToken()
if identifier == .rootContainer {
let rootItem = FileProviderItem.root(displayName: rootDisplayName)
completionHandler(rootItem, nil)
return Progress()
}

// TODO: implement the actual lookup using the auth token
guard let decoded = FileProviderItemID.decode(identifier) else {
completionHandler(nil, NSFileProviderError(.noSuchItem))
return Progress()
}

completionHandler(FileProviderItem(identifier: identifier), nil)
return Progress()
guard let driveAPI = DriveAPIFactory.make() else {
completionHandler(nil, NSFileProviderError(.notAuthenticated))
return Progress()
}

let progress = Progress(totalUnitCount: 1)
Task {
do {
let item = try await resolveItem(decoded, identifier: identifier, driveAPI: driveAPI)
progress.completedUnitCount = 1
completionHandler(item, nil)
} catch {
completionHandler(nil, lookupError(from: error))
}
}
return progress
}

func fetchContents(for itemIdentifier: NSFileProviderItemIdentifier, version requestedVersion: NSFileProviderItemVersion?, request: NSFileProviderRequest, completionHandler: @escaping (URL?, NSFileProviderItem?, Error?) -> Void) -> Progress {
_ = currentAuthToken()
private func resolveItem(
_ decoded: (kind: DriveItemKind, uuid: String),
identifier: NSFileProviderItemIdentifier,
driveAPI: DriveAPI
) async throws -> FileProviderItem {
switch decoded.kind {
case .folder:
let meta = try await driveAPI.getFolderMetaByUuid(uuid: decoded.uuid)
return FileProviderItem(folderMeta: meta, identifier: identifier)
case .file:
let meta = try await driveAPI.getFileMetaByUuid(uuid: decoded.uuid)
return FileProviderItem(fileMeta: meta, identifier: identifier)
}
}

private func lookupError(from error: Error) -> Error {
if let apiError = error as? APIClientError, apiError.statusCode == 401 {
return NSFileProviderError(.notAuthenticated)
}
return error
}

func fetchContents(for itemIdentifier: NSFileProviderItemIdentifier, version requestedVersion: NSFileProviderItemVersion?, request: NSFileProviderRequest, completionHandler: @escaping (URL?, NSFileProviderItem?, Error?) -> Void) -> Progress {

Check warning on line 75 in ios/InternxtFileProvider/FileProviderExtension.swift

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the unused function parameter "request" or name it "_".

See more on https://sonarcloud.io/project/issues?id=internxt_drive-mobile&issues=AZ65rT1Y6-8DAyAuaDCn&open=AZ65rT1Y6-8DAyAuaDCn&pullRequest=493

Check warning on line 75 in ios/InternxtFileProvider/FileProviderExtension.swift

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the unused function parameter "itemIdentifier" or name it "_".

See more on https://sonarcloud.io/project/issues?id=internxt_drive-mobile&issues=AZ65rT1Y6-8DAyAuaDCl&open=AZ65rT1Y6-8DAyAuaDCl&pullRequest=493

Check warning on line 75 in ios/InternxtFileProvider/FileProviderExtension.swift

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the unused function parameter "requestedVersion" or name it "_".

See more on https://sonarcloud.io/project/issues?id=internxt_drive-mobile&issues=AZ65rT1Y6-8DAyAuaDCm&open=AZ65rT1Y6-8DAyAuaDCm&pullRequest=493
// TODO: implement fetching of the contents for the itemIdentifier at the specified version

completionHandler(nil, nil, NSError(domain: NSCocoaErrorDomain, code: NSFeatureUnsupportedError, userInfo:[:]))
Expand Down
8 changes: 8 additions & 0 deletions src/services/native/InternxtAuthCredentialsModule.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ describe('InternxtAuthCredentialsModule wrapper', () => {
expect(setCredentials).toHaveBeenCalledWith(credentials);
});

it('when on iOS with the module present, then setCredentials forwards driveBaseUrl to the native module', async () => {
const { wrapper, setCredentials } = arrangePresentNative('ios');

await wrapper.setCredentials(credentials);

expect(setCredentials.mock.calls[0][0]).toMatchObject({ driveBaseUrl: 'https://drive.example' });
});

it('when on iOS with the module present, then clearCredentials delegates to the native module', async () => {
const { wrapper, clearCredentials } = arrangePresentNative('ios');

Expand Down
Loading