From 4447ea63e2f4a5c7c4689c8e953328d5eee9d302 Mon Sep 17 00:00:00 2001 From: Cory McWilliams Date: Sun, 9 Nov 2025 11:54:37 -0500 Subject: [PATCH] ios: Fix exporting/downloading to file. --- GNUmakefile | 4 +-- src/ios.m | 71 +++++++++++++++++++++++++++++++++++++++++++++- src/ios/Info.plist | 6 ++-- src/log.h | 3 ++ 4 files changed, 79 insertions(+), 5 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 22645cef..2ec9a083 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -21,7 +21,7 @@ VERSION_CODE_IOS := 20 VERSION_NUMBER := 0.2026.11-wip VERSION_NAME := This program kills fascists. -IPHONEOS_VERSION_MIN=14.0 +IPHONEOS_VERSION_MIN=14.5 SQLITE_URL := https://www.sqlite.org/2025/sqlite-amalgamation-3510000.zip BUNDLETOOL_URL := https://github.com/google/bundletool/releases/download/1.17.0/bundletool-all-1.17.0.jar @@ -1181,7 +1181,7 @@ ios%go: out/tildefriends-ios%.app/tildefriends iossimdebuggo: out/tildefriends-iossimdebug.app/tildefriends ## Build, install, and run an iOS debug build. xcrun simctl install booted out/tildefriends-iossimdebug.app/ - xcrun simctl launch booted com.unprompted.tildefriends + xcrun simctl launch --console booted com.unprompted.tildefriends .PHONY: iossimdebuggo out/macos%/tildefriends: out/macos%-arm/tildefriends out/macos%-x86_64/tildefriends diff --git a/src/ios.m b/src/ios.m index 8971920f..ac4e9478 100644 --- a/src/ios.m +++ b/src/ios.m @@ -1,5 +1,9 @@ #import +#import +#import +#import #import +#import #import #import #import @@ -11,9 +15,10 @@ void tf_run_thread_start(const char* zip_path); -@interface ViewController : UINavigationController +@interface ViewController : UINavigationController @property (strong, nonatomic) WKWebView* web_view; @property bool initial_load_complete; +@property (retain) NSURL* download_url; @end static void _start_initial_load(WKWebView* web_view) @@ -133,6 +138,70 @@ static void _start_initial_load(WKWebView* web_view) [alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction* action) { completionHandler(nil); }]]; [self presentViewController:alertController animated:YES completion:^ {}]; } + +- (void)webView:(WKWebView*)webView + decidePolicyForNavigationAction:(WKNavigationAction*)navigationAction + decisionHandler:(void (^)(enum WKNavigationActionPolicy)) decisionHandler +{ + decisionHandler(navigationAction.shouldPerformDownload ? WKNavigationActionPolicyDownload : WKNavigationActionPolicyAllow); +} + +- (void)webView:(WKWebView*)webView + decidePolicyForNavigationResponse:(WKNavigationResponse*)navigationResponse + decisionHandler:(void (^)(enum WKNavigationResponsePolicy)) decisionHandler +{ + decisionHandler(navigationResponse.canShowMIMEType ? WKNavigationResponsePolicyAllow : WKNavigationResponsePolicyDownload); +} + +- (void)webView:(WKWebView*)webView + navigationAction:(WKNavigationAction*)navigationAction + didBecomeDownload:(WKDownload*)download +{ + download.delegate = self; +} + +- (void)webView:(WKWebView*)webView + navigationResponse:(WKNavigationResponse*)navigationResponse + didBecomeDownload:(WKDownload*)download +{ + download.delegate = self; +} + +- (void)download:(WKDownload*)download + decideDestinationUsingResponse:(NSURLResponse*)response + suggestedFilename:(NSString*)suggestedFilename + completionHandler:(void (^)(NSURL*))completionHandler +{ + self.download_url = [[NSURL fileURLWithPath:NSTemporaryDirectory()] URLByAppendingPathComponent:suggestedFilename]; + completionHandler(self.download_url); +} + +- (void)downloadDidFinish:(WKDownload*)download +{ + UIDocumentPickerViewController* picker = [[UIDocumentPickerViewController alloc] initForExportingURLs:@[self.download_url]]; + picker.delegate = self; + [self presentViewController:picker animated:YES completion:nil]; +} + +- (void)download:(WKDownload*)download + didFailWithError:(NSError*)error + resumeData:(NSData*)resumeData +{ + tf_printf("didFailWithError:%s\n", [error.localizedDescription UTF8String]); +} + +- (void)documentPicker:(UIDocumentPickerViewController*)controller + didPickDocumentAtURLs:(NSArray*)urls +{ + tf_printf("did pick!\n"); + [[NSFileManager defaultManager] removeItemAtURL:self.download_url error:nil]; +} + +- (void)documentPickerWasCancelled:(UIDocumentPickerViewController*)controller +{ + tf_printf("no pick!\n"); + [[NSFileManager defaultManager] removeItemAtURL:self.download_url error:nil]; +} @end @interface AppDelegate : UIResponder diff --git a/src/ios/Info.plist b/src/ios/Info.plist index 070346cc..32ecfc55 100644 --- a/src/ios/Info.plist +++ b/src/ios/Info.plist @@ -25,7 +25,7 @@ LSRequiresIPhoneOS MinimumOSVersion - 14.0 + 14.5 UIDeviceFamily 1 @@ -88,6 +88,8 @@ NSMicrophoneUsageDescription Microphone access is used to capture audio to add to posts. NSPhotoLibraryUsageDescription - Photo library access is userd to select images to add to posts. + Photo library access is used to select images to add to posts. + NSDownlodasFolderUsageDescription + Downloads folder access is used to export and import apps. diff --git a/src/log.h b/src/log.h index cfbe7261..bc7672cb 100644 --- a/src/log.h +++ b/src/log.h @@ -17,12 +17,15 @@ #include #if TARGET_OS_IPHONE #include +#include #define tf_printf(...) \ do \ { \ char buffer##__LINE__[2048]; \ snprintf(buffer##__LINE__, sizeof(buffer##__LINE__), __VA_ARGS__); \ os_log(OS_LOG_DEFAULT, "%{public}s", buffer##__LINE__); \ + fputs(buffer##__LINE__, stdout); \ + fflush(stdout); \ } while (0) #else #include