From 50b2c0c7f42edb2b3424601e02cab32e9ad70a9f Mon Sep 17 00:00:00 2001 From: Cory McWilliams Date: Tue, 11 Nov 2025 21:40:17 -0500 Subject: [PATCH] ios: Expose post text to Core Spotlight search. --- GNUmakefile | 3 +++ src/ios.m | 42 +++++++++++++++++++++++++++++++++++++++--- src/ssb.db.c | 23 +++++++++++++++++++++++ 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 19141d57..e6ea86d2 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -815,7 +815,9 @@ $(MACOS_TARGETS) $(IOS_TARGETS) $(IOSSIM_TARGETS): CFLAGS += \ $(IOS_TARGETS) $(IOSSIM_TARGETS): LDFLAGS += \ -framework Foundation \ -framework CoreFoundation \ + -framework CoreSpotlight \ -framework UIKit \ + -framework UniformTypeIdentifiers \ -framework WebKit ## @@ -1180,6 +1182,7 @@ ios%go: out/tildefriends-ios%.app/tildefriends ideviceinstaller -i $(realpath $(dir $<)) iossimdebuggo: out/tildefriends-iossimdebug.app/tildefriends ## Build, install, and run an iOS debug build. + xcrun -sdk iphoneos codesign -f -s 'Apple Distribution' --entitlements src/ios/Entitlements.plist --generate-entitlement-der out/tildefriends-iossimdebug.app xcrun simctl install booted out/tildefriends-iossimdebug.app/ xcrun simctl launch --console booted com.unprompted.tildefriends .PHONY: iossimdebuggo diff --git a/src/ios.m b/src/ios.m index 7072d072..24a2146b 100644 --- a/src/ios.m +++ b/src/ios.m @@ -1,3 +1,6 @@ +#import +#import +#import #import #import #import @@ -9,6 +12,7 @@ #import #include "log.h" +#include "util.js.h" #include #include @@ -90,6 +94,7 @@ static void _start_initial_load(WKWebView* web_view) - (void)webView:(WKWebView*)webView didFinishNavigation:(WKNavigation*)navigation { self.initial_load_complete = true; + tf_printf("initial load complete\n"); } - (void)webView:(WKWebView*)webView didFailProvisionalNavigation:(WKNavigation*)navigation withError:(NSError*)error @@ -179,18 +184,16 @@ static void _start_initial_load(WKWebView* web_view) - (void)download:(WKDownload*)download didFailWithError:(NSError*)error resumeData:(NSData*)resumeData { - tf_printf("didFailWithError:%s\n", [error.localizedDescription UTF8String]); + tf_printf("download 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 @@ -208,8 +211,41 @@ static void _start_initial_load(WKWebView* web_view) [self.window makeKeyAndVisible]; return YES; } + +- (BOOL)application:(UIApplication*)application continueUserActivity:(NSUserActivity*)activity restorationHandler:(void (^)(NSArray>*))restorationHandler +{ + if ([activity.activityType isEqual:CSSearchableItemActionType]) { + const char* identifier = [[activity.userInfo valueForKey:CSSearchableItemActivityIdentifier] UTF8String]; + tf_printf("Jumping to search result: %s.\n", identifier); + + char url[1024]; + snprintf(url, sizeof(url), "http://localhost:12345/~core/ssb/#%s", identifier); + tf_printf("Navigating to %s.", url); + ViewController* view_controller = (ViewController*)self.window.rootViewController; + [view_controller.web_view loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithUTF8String:url]]]]; + } else { + tf_printf("no search\n"); + } + return NO; +} @end +void tf_notify_message_added_ios(const char* identifier, const char* title, const char* content) +{ + tf_printf("indexing: identifier=%s title=%s content=%s\n", identifier, title, content); + CSSearchableItemAttributeSet* attribute_set = [[CSSearchableItemAttributeSet alloc] initWithContentType:UTTypeText]; + attribute_set.title = [NSString stringWithUTF8String:content]; + attribute_set.contentDescription = [NSString stringWithUTF8String:title]; + CSSearchableItem* item = [[CSSearchableItem alloc] initWithUniqueIdentifier:[NSString stringWithUTF8String:identifier] domainIdentifier:@"com.unprompted.tildefriends.messages" attributeSet:attribute_set]; + [[CSSearchableIndex defaultSearchableIndex] indexSearchableItems:@[item] completionHandler:^(NSError* _Nullable error) { + if (error) { + tf_printf("indexing error: %s.\n", [error.localizedDescription UTF8String]); + } else { + tf_printf("indexed successfully.\n"); + } + }]; +} + int main(int argc, char* argv[]) { NSFileManager* file_manager = [NSFileManager defaultManager]; diff --git a/src/ssb.db.c b/src/ssb.db.c index 6f800293..9e62316b 100644 --- a/src/ssb.db.c +++ b/src/ssb.db.c @@ -716,6 +716,29 @@ static void _tf_ssb_db_store_message_after_work(tf_ssb_t* ssb, int status, void* tf_trace_end(trace); } +#if TARGET_OS_IPHONE + JSContext* context = tf_ssb_get_context(ssb); + JSValue content = JS_ParseJSON(context, store->content, strlen(store->content), NULL); + if (JS_IsObject(content)) + { + JSValue type_value = JS_GetPropertyStr(context, content, "type"); + const char* type = JS_ToCString(context, type_value); + if (type && strcmp(type, "post") == 0) + { + JSValue text_value = JS_GetPropertyStr(context, content, "text"); + const char* text = JS_ToCString(context, text_value); + + void tf_notify_message_added_ios(const char* identifier, const char* title, const char* content); + tf_notify_message_added_ios(store->id, type, text); + JS_FreeCString(context, text); + JS_FreeValue(context, text_value); + } + JS_FreeCString(context, type); + JS_FreeValue(context, type_value); + } + JS_FreeValue(context, content); +#endif + if (store->callback) { store->callback(store->id, store->out_stored, store->user_data);