Skip to content

feat: Add native iOS download support using URLSession - #7

Merged
yokuze merged 14 commits into
silvermine:masterfrom
velocitysystems:feature/ios
May 13, 2025
Merged

feat: Add native iOS download support using URLSession#7
yokuze merged 14 commits into
silvermine:masterfrom
velocitysystems:feature/ios

Conversation

@velocitysystems

Copy link
Copy Markdown
Contributor

This PR introduces native iOS download support using URLSession splitting the original shared code into platform-specific modules (desktop and mobile). It utilises a new Swift package DownloadManagerKit which is integrated with the Tauri plugin architecture.

Key Changes

  • build.rs: Added ios_path("ios") to the tauri_plugin builder to include the iOS implementation
  • guest-js/index.ts: Added addPluginListener to handle events from the iOS plugin
  • ios-src/DownloadManagerKit: Created a Swift package containing the core download logic
  • ios-src/DownloadManagerExample: Created an example iOS app that utilizes the DownloadManagerKit package.

Impact

  • Behavioral changes: Introduces iOS support for the download plugin, using a native Swift implementation. The JS API now supports listening to plugin events from both desktop and mobile platforms.
  • Dependencies affected: Adds a dependency on the new DownloadManagerKit Swift package for iOS builds, and Tauri package.
  • Splits plugin implementation into platform-specific modules, requiring conditional compilation.

Maintenance

  • Updated all Tauri packages to latest
  • Updated generated iOS example project to fix arm64-sim bug with Xcode 16.3
  • Updated package.json to add new run targets for iOS and Android

Comment thread ios-src/tauri-api/Sources/Tauri/Plugin/Plugin.swift
@velocitysystems
velocitysystems force-pushed the feature/ios branch 3 times, most recently from 40881bd to a9b84de Compare May 2, 2025 11:58

@jjhafer jjhafer left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@velocitysystems Finished my initial review and offered suggestions. We can certainly discuss which suggestions are actually necessary before this can be merged.

Comment thread ios-src/DownloadManagerKit/Package.swift Outdated
Comment thread ios-src/DownloadManagerKit/Sources/DownloadManagerKit/DownloadItem.swift Outdated
Comment thread ios-src/DownloadManagerKit/Sources/DownloadManagerKit/DownloadItem.swift Outdated
Comment thread ios-src/DownloadManagerKit/Sources/DownloadManagerKit/DownloadItem.swift Outdated
Comment thread ios-src/DownloadManagerKit/Sources/DownloadManagerKit/DownloadManager.swift Outdated
Comment thread ios-src/DownloadManagerKit/Sources/DownloadManagerKit/DownloadManager.swift Outdated
Comment thread ios-src/DownloadManagerKit/Sources/DownloadManagerKit/DownloadManager.swift Outdated
Comment thread ios-src/DownloadManagerKit/Sources/DownloadManagerKit/DownloadManager.swift Outdated
Comment thread ios-src/DownloadManagerKit/Sources/DownloadManagerKit/DownloadManager.swift Outdated
@velocitysystems
velocitysystems force-pushed the feature/ios branch 4 times, most recently from 041ac8c to 1d9699c Compare May 7, 2025 11:37
@velocitysystems
velocitysystems marked this pull request as ready for review May 7, 2025 12:36
@velocitysystems
velocitysystems requested a review from yokuze May 7, 2025 12:36
}
}

func getDownloadTask(_ key: String) -> URLSessionDownloadTask? {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jjhafer With async/await this could be simplified to:

   func getDownloadTask(_ key: String) async -> URLSessionDownloadTask? {
       guard let session = session else { return nil }
       let tasks = await withCheckedContinuation { continuation in
           session.getAllTasks { tasks in
               continuation.resume(returning: tasks)
           }
       }
       
       return tasks.compactMap { $0 as? URLSessionDownloadTask }.first { $0.taskDescription == key }
   }

However from testing I ran into issues with invoking the commands from Tauri's IPC when either:

  • Decorated with async
  • Using an embedded Task { } wrapper

Will do some further research and may revisit this in a future PR.

Comment thread src/commands.rs
}

#[tauri::command(rename_all = "snake_case")]
pub(crate) async fn is_native<R: Runtime>(_app: AppHandle<R>) -> Result<bool> {

@velocitysystems velocitysystems May 7, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This command allows the JS API to determine whether to register a plugin listener for iOS or a global listener for Android/desktop. Adding this command was a low-cost alternative to bringing in an external dependency such as the OS information plugin.

@yokuze yokuze left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for all of the great work here! A few questions/suggestions there for you.

Comment thread guest-js/index.ts Outdated
Comment thread guest-js/index.ts
Comment thread ios/Sources/DownloadPlugin.swift
Comment thread permissions/schemas/schema.json
Comment thread src/mobile.rs
Comment thread guest-js/index.ts Outdated
@velocitysystems

Copy link
Copy Markdown
Contributor Author

Thank you for all of the great work here! A few questions/suggestions there for you.

Thanks @yokuze. I've addressed all of your feedback in the PR.

@velocitysystems
velocitysystems requested a review from yokuze May 13, 2025 11:37
@yokuze
yokuze merged commit 970642e into silvermine:master May 13, 2025
@velocitysystems
velocitysystems deleted the feature/ios branch May 13, 2025 12:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants