Copycat: iOS Copyparty Client
(Approx. 5 min read)
Copyparty is a genuinely great file server that I like using, and it’s played an important role in many smaller projects I’ve done throughout the year when something like scp or AirDrop just won’t do. The one area where it’s still really lacking is in user-friendly GUI and a native experience on mobile: while there is a pile of iOS shortcuts that allow for uploading to a copyparty server (and a small Android app that does roughly the same thing), it’s nothing quite like a full native app in terms of speed and ease of use.
Astute readers might realize that I really like Swift and programming for Apple platforms; in fact, this is the third project I’ve done in Swift as of the time of writing. So what will I do differently this time?
Note: I am currently working on Copycat, so this page is sort of a work-in-progress. I’m collecting ideas about what would be cool for the project and what I should try out. What actually goes into the final release might be wildly different.
Also, the first release will probably just do
up2kstyle uploads and nothing more, to match the existing Android client. These ideas are more about future releases than anything else.
Rough Ideas Right Now
Dynamic Island
No network transfer software provides status updates like this. For long-running transfers, this would be a nice way to both keep the long-living background task alive while also providing status updates in a very intuitive format. Copyparty does something similar with its favicon in-browser.
Triple-Plane Design
The truly cross-platform way to write SwiftUI apps looks something like this. On each platform, this conforms to something different (think about how Mail.app looks on separate platforms):
1NavigationSplitView {
2 SidebarView(selection: $selectedCategory)
3} content: {
4 if let category = selectedCategory {
5 ItemListView(category: category, selection: $selectedItem)
6 }
7} detail: {
8 if let item = selectedItem {
9 DetailView(item: item)
10 }
11}
I’ve never used this design style before because none of my apps naturally fit it, but trying to design against this design pattern usually results in designs that work great on iOS but fit terribly on macOS. Most first-party Apple apps follow this pattern to maximize code re-use. It’s probably unrealistic (many small differences to account for), but getting an iPadOS app and maybe a macOS app for free alongside iOS development would be fantastic.
For Copyparty, I think this looks like a server management and settings pane in the SidebarView, a list of files and folders (or options) in the ItemListView with breadcrumbs at the top (like Copyparty WebUI), and the DetailView lets you see the files contents & details.
File Picker Extension
True backwards compatibility with every app that uses files requires building our own NSFileProviderReplicatedExtension. This is tedious and basically requires implementing our own FUSE-like interface to Copyparty although it comes with some massive benefits:
- See files in Files.app as a separate network device
- Works cross-platform (and maybe on macOS too?)
- Any app that can open files can open one on this device (it just sees an
NSURLthat’s sandboxed, it doesn’t know what physical block device it’s on) - It can be a lot faster than something like share sheets, since you don’t need to download the whole file until the application needs it (so it’s more intuitive to use)
I’m taking a filesystems class in the fall where we’ll get into FUSE to implement our own FAT driver for Linux (but since it’s FUSE it will work on any Unix including with macFUSE). Hopefully that will give me the needed experience to make implementing this not-painful (although the pain with FAT is a different kind than a networked filesystem).
Easy Encryption
Consider this: you’ve got a Copyparty instance shared to you by someone you don’t fully trust. How do you store data there? Obviously you’d like to use per-file encryption like gocryptfs, but doing this manually before uploading is tedious. What if our client could transparently encrypt and decrypt for us?
This is more of a long-shot idea, but the workflow looks something like:
- iOS already lets us spawn files with
completeFileProtection, which we can store user keyfiles with - Then use those keyfiles to encrypt the data with something stronger (exactly which algorithm would ideally be user-selectable)
- Scramble the filenames as well and encrypt them, too
In a better world I might just link against something like gocryptfs, although I fear linking Swift with anything else because it’s annoying to sign in practice. This would be a great feature if it could be built though!
WebDAV Support
Copyparty can be thought of (incorrectly) as a set of extensions to a stock WebDAV server. I should probably find and test this app against more diverse WebDAV server implementations so that this could be used against those as well, since that would be extremely useful (can’t deploy Copyparty everywhere).
Copyparty Hosting
Swift FFI should allow for managing a Python process inside of our app, so we could technically deploy it internally and use a nested WebKitView to interact, but this is probably a bad idea since it requires you to have the phone on and actively running. Background rules on iOS mean that it’s likely to be killed and restarted many times during normal iPhone usage, so while this would be a cool feature I’m probably unlikely to add it unless something changes at Apple (maybe they’ll announce some feature at a future WWDC that makes this more viable).