From 6886f8efbe8f8a9b6e914405e0aa9fffb984fb2e Mon Sep 17 00:00:00 2001 From: westlandnigel Date: Fri, 13 Nov 2026 22:37:17 +0800 Subject: [PATCH 1/7] feat(dylib): add skip account --- src/dylib/Patches/SkipAccount/Code.m | 36 +++++++++ src/dylib/Patches/SkipAccount/Menu.m | 56 ++++++++++++++ src/dylib/Patches/SkipAccount/Settings.m | 24 ++++++ src/dylib/Patches/SkipAccount/SkipAccount.m | 81 +++++++++++++++++++++ src/dylib/Patches/SkipAccount/Startup.h | 11 +++ src/dylib/Patches/SkipAccount/Startup.m | 52 +++++++++++++ 6 files changed, 260 insertions(+) create mode 100644 src/dylib/Patches/SkipAccount/Code.m create mode 100644 src/dylib/Patches/SkipAccount/Menu.m create mode 100644 src/dylib/Patches/SkipAccount/Settings.m create mode 100644 src/dylib/Patches/SkipAccount/SkipAccount.m create mode 100644 src/dylib/Patches/SkipAccount/Startup.h create mode 100644 src/dylib/Patches/SkipAccount/Startup.m diff --git a/src/dylib/Patches/SkipAccount/Code.m b/src/dylib/Patches/SkipAccount/Code.m new file mode 100644 index 00000000..b5e1501f --- /dev/null +++ b/src/dylib/Patches/SkipAccount/Code.m @@ -0,0 +1,36 @@ +#import "Startup.h" +#import +#import +#import +#import + +uint32_t *DPSkipFindCode(const DPSkipInstruction *signature, NSUInteger length) { + const struct mach_header_64 *header = NULL; + for (uint32_t i = 0; i < _dyld_image_count(); i++) + if (_dyld_get_image_header(i)->filetype == MH_EXECUTE) header = (const struct mach_header_64 *)_dyld_get_image_header(i); + if (!header) return NULL; + unsigned long size = 0; + const uint32_t *text = (const uint32_t *)getsectiondata(header, "__TEXT", "__text", &size); + uint32_t *found = NULL; + for (NSUInteger i = 0; text && i + length <= size / sizeof *text; i++) { + NSUInteger j = 0; + while (j < length && (text[i + j] & signature[j].mask) == signature[j].value) j++; + if (j != length) continue; + if (found) return NULL; + found = (uint32_t *)(text + i); + } + return found; +} + +BOOL DPSkipWriteCode(uint32_t *site, uint32_t expected, uint32_t value) { + if (*site != expected) return NO; + mach_vm_address_t page = (mach_vm_address_t)site & ~((mach_vm_address_t)vm_page_size - 1); + if (mach_vm_protect(mach_task_self(), page, vm_page_size, FALSE, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY)) return NO; + *site = value; + sys_icache_invalidate(site, sizeof *site); + if (!mach_vm_protect(mach_task_self(), page, vm_page_size, FALSE, VM_PROT_READ | VM_PROT_EXECUTE)) return YES; + *site = expected; + sys_icache_invalidate(site, sizeof *site); + mach_vm_protect(mach_task_self(), page, vm_page_size, FALSE, VM_PROT_READ | VM_PROT_EXECUTE); + return NO; +} diff --git a/src/dylib/Patches/SkipAccount/Menu.m b/src/dylib/Patches/SkipAccount/Menu.m new file mode 100644 index 00000000..2a733160 --- /dev/null +++ b/src/dylib/Patches/SkipAccount/Menu.m @@ -0,0 +1,56 @@ +#import "Startup.h" + +static BOOL DPIsSignIn(NSMenuItem *item) { + return item.menu && item.menu == NSApp.mainMenu.itemArray.firstObject.submenu + && [@[ @"Sign In…", @"Sign In..." ] containsObject:item.title]; +} + +static BOOL DPIsLocalAction(NSMenuItem *item) { + if (!item.menu) return NO; + NSMenu *bar = NSApp.mainMenu; + if (item.menu == bar.itemArray.firstObject.submenu) + return [@[ @"Settings…", @"Settings...", @"Set as Default Browser", @"Import from Another Browser…" ] containsObject:item.title]; + return item.menu && item.menu == [bar itemWithTitle:@"File"].submenu + && [@[ @"New Window", @"New Incognito Window" ] containsObject:item.title]; +} + +static void DPItem_setEnabled(NSMenuItem *self, SEL _cmd, BOOL enabled) { + DPCallOriginal(DPItem_setEnabled, self, enabled || DPIsLocalAction(self)); +} + +static void DPUpdateMenu(NSMenu *menu) { + for (NSMenuItem *item in menu.itemArray) { + if (DPIsSignIn(item)) item.hidden = YES; + if (DPIsLocalAction(item)) item.enabled = YES; + } +} + +static void DPItem_setHidden(NSMenuItem *self, SEL _cmd, BOOL hidden) { + DPCallOriginal(DPItem_setHidden, self, hidden || DPIsSignIn(self)); +} + +static void DPMenu_addItem(NSMenu *self, SEL _cmd, NSMenuItem *item) { + DPCallOriginal(DPMenu_addItem, self, item); + if (DPIsSignIn(item)) item.hidden = YES; + if (DPIsLocalAction(item)) item.enabled = YES; +} + +static void DPMenu_insertItem(NSMenu *self, SEL _cmd, NSMenuItem *item, NSInteger index) { + DPCallOriginal(DPMenu_insertItem, self, item, index); + if (DPIsSignIn(item)) item.hidden = YES; + if (DPIsLocalAction(item)) item.enabled = YES; +} + +static void DPMenu_update(NSMenu *self, SEL _cmd) { + DPCallOriginal(DPMenu_update, self); + DPUpdateMenu(self); +} + +void DPSkipAccountMenus(void) { + DPHookClass(NSMenuItem.class, @selector(setHidden:), (IMP)DPItem_setHidden); + DPHookClass(NSMenuItem.class, @selector(setEnabled:), (IMP)DPItem_setEnabled); + DPHookClass(NSMenu.class, @selector(addItem:), (IMP)DPMenu_addItem); + DPHookClass(NSMenu.class, @selector(insertItem:atIndex:), (IMP)DPMenu_insertItem); + DPHookClass(NSMenu.class, @selector(update), (IMP)DPMenu_update); + DPOnLaunch(^{ DPUpdateMenu(NSApp.mainMenu.itemArray.firstObject.submenu); }); +} diff --git a/src/dylib/Patches/SkipAccount/Settings.m b/src/dylib/Patches/SkipAccount/Settings.m new file mode 100644 index 00000000..cd482b8d --- /dev/null +++ b/src/dylib/Patches/SkipAccount/Settings.m @@ -0,0 +1,24 @@ +#import "Startup.h" + +static BOOL DPIsAccountHeader(NSView *header) { + NSTextField *title = (NSTextField *)DPFindView(header, ^BOOL(NSView *view) { return [view isKindOfClass:NSTextField.class]; }); + return [title.stringValue isEqual:@"Account"]; +} + +static void DPHeader_layout(NSView *self, SEL _cmd) { + DPCallOriginal(DPHeader_layout, self); + // The arranged stack contains the heading, Name/Email card, and account options row. + if (DPIsAccountHeader(self)) self.superview.hidden = YES; +} + +void DPSkipAccountSettings(void) { + DPHook(DPSkipAccountHeader, @selector(layout), (IMP)DPHeader_layout); +} + +NSString *DPSkipVerifyAccountSettings(void) { + for (NSView *header in DPFindViews(DPSkipAccountHeader)) + if (DPIsAccountHeader(header) && !header.isHiddenOrHasHiddenAncestor) return @"Account settings section is visible"; + for (NSView *button in DPFindViews("NSButton")) + if (DPHasLabel(button, @"More account options") && !button.isHiddenOrHasHiddenAncestor) return @"account options button is visible"; + return nil; +} diff --git a/src/dylib/Patches/SkipAccount/SkipAccount.m b/src/dylib/Patches/SkipAccount/SkipAccount.m new file mode 100644 index 00000000..7cc9264a --- /dev/null +++ b/src/dylib/Patches/SkipAccount/SkipAccount.m @@ -0,0 +1,81 @@ +#import "Startup.h" +#import "Updates/Updates.h" + +extern DPPatch DPSkipAccount; +static BOOL gSkipping; + +static id DPDefaults_objectForKey(NSUserDefaults *self, SEL _cmd, NSString *key) { + return [key isEqual:@"hasPresentedOnboardingIntro"] ? @YES : DPCallOriginal(DPDefaults_objectForKey, self, key); +} + +static BOOL DPDefaults_boolForKey(NSUserDefaults *self, SEL _cmd, NSString *key) { + return [key isEqual:@"hasPresentedOnboardingIntro"] ? YES : DPCallOriginal(DPDefaults_boolForKey, self, key); +} + +static void DPWaitForBrowser(void) { + __block NSUInteger polls = 0; + [NSTimer scheduledTimerWithTimeInterval:0.5 repeats:YES block:^(NSTimer *timer) { + void **slot = DPIvar(NSApp.delegate, "controller"); + id controller = slot ? (__bridge id)*slot : nil; + BOOL restored = [DPSwiftValue(controller, @"hasFinishedRestoringWindows") boolValue]; + if (!restored && ++polls < 120) return; + [timer invalidate]; + if (!restored) return; + for (NSWindow *window in NSApp.windows) if (DPIsKind(window, DPDiaWindow)) return; + // The File item carries the default profile even before any windows have been opened. + NSMenu *file = [NSApp.mainMenu itemWithTitle:@"File"].submenu; + for (NSMenuItem *item in file.itemArray) { + if (![item.title hasPrefix:@"New Window"]) continue; + [NSApp sendAction:item.action to:item.target from:item]; + break; + } + }]; +} + +static void DPInstallSkipAccount(void) { + if (!DPSkipAccount.on) return; + gSkipping = DPSkipAccountStartup(); + if (gSkipping) { + DPHookClass(NSUserDefaults.class, @selector(objectForKey:), (IMP)DPDefaults_objectForKey); + DPHookClass(NSUserDefaults.class, @selector(boolForKey:), (IMP)DPDefaults_boolForKey); + DPSkipAccountMenus(); + DPSkipAccountSettings(); + DPOnLaunch(^{ DPWaitForBrowser(); }); + return; + } + DPSkipAccount.unavailable = YES; + DPSkipAccount.on = NO; + NSLog(@"DiaPatches: Skip Account doesn't know this Dia's startup code, so it stays off"); +} + +static void DPApplySkipAccount(DPPatch *patch) { + if (patch->on == gSkipping || patch->on != DPSavedOn(patch)) return; + NSAlert *alert = [NSAlert new]; + alert.messageText = patch->on ? @"Relaunch Dia to skip account sign-in" : @"Relaunch Dia to use account sign-in"; + [alert addButtonWithTitle:@"Relaunch"]; + [alert addButtonWithTitle:@"Later"]; + if ([alert runModal] == NSAlertFirstButtonReturn) DPHandOffAndQuit(@[ @"apply" ]); +} + +static NSString *DPVerifySkipAccount(DPPatch *patch) { + if (!gSkipping || !patch->on) return nil; // Startup changes need separate launches, not the self-test's unsaved toggles. + for (NSMenuItem *item in NSApp.mainMenu.itemArray.firstObject.submenu.itemArray) + if ([item.title hasPrefix:@"Sign In"] && !item.hidden) return @"sign-in menu item is visible"; + NSString *settings = DPSkipVerifyAccountSettings(); + if (settings) return settings; + return DPFindViews(DPDiaContentPane).count ? nil : @"no browser page opened after skipping sign-in"; +} + +DP_PATCH(DPSkipAccount) { + .key = @"skipAccount", + .order = 120, + .title = @"Skip Account", + .detail = @"Open Dia without signing in or creating a Dia account. Relaunch to apply. Account services still need an account. Use Turn Off AI too for plain browsing. May need an update after some Dia releases.", + .symbol = @"person.crop.circle.badge.minus person.crop.circle", + .tint = @"systemBrownColor", + .section = @"Window", + .classes = DPClasses(DPDiaAppDelegate, DPSkipAccountHeader), + .install = DPInstallSkipAccount, + .apply = DPApplySkipAccount, + .verify = DPVerifySkipAccount, +}; diff --git a/src/dylib/Patches/SkipAccount/Startup.h b/src/dylib/Patches/SkipAccount/Startup.h new file mode 100644 index 00000000..6699d838 --- /dev/null +++ b/src/dylib/Patches/SkipAccount/Startup.h @@ -0,0 +1,11 @@ +#import "StdPatch/StdPatch.h" + +#define DPSkipAccountHeader "_TtC11Preferences25SettingsSectionHeaderView" + +typedef struct { uint32_t value, mask; } DPSkipInstruction; +uint32_t *DPSkipFindCode(const DPSkipInstruction *signature, NSUInteger length); +BOOL DPSkipWriteCode(uint32_t *site, uint32_t expected, uint32_t value); +BOOL DPSkipAccountStartup(void); +void DPSkipAccountMenus(void); +void DPSkipAccountSettings(void); +NSString *DPSkipVerifyAccountSettings(void); diff --git a/src/dylib/Patches/SkipAccount/Startup.m b/src/dylib/Patches/SkipAccount/Startup.m new file mode 100644 index 00000000..028fc7d1 --- /dev/null +++ b/src/dylib/Patches/SkipAccount/Startup.m @@ -0,0 +1,52 @@ +#import "Startup.h" + +// Dia 1.57.1 (90935), arm64. Unknown or ambiguous code stays untouched. +// initializeAuth() has finished initializing auth here. With no user it waits for sign-in; otherwise it returns .restored. +static const DPSkipInstruction DPLaunch[] = { + {0xb24403bd, 0xffffffff}, + {0xd10083ff, 0xffffffff}, + {0xa9017bfd, 0xffffffff}, + {0xf90007f6, 0xffffffff}, + {0x910043fd, 0xffffffff}, + {0x3944e6c8, 0xffffffff}, + {0x7100051f, 0xffffffff}, + {0x540001a1, 0xffffffff}, + {0xf940b2c0, 0xffffffff}, + {0xf940aad4, 0xffffffff}, + {0x94000000, 0xfc000000}, + {0x528000e0, 0xffffffff}, + {0x94000000, 0xfc000000}, + {0xf94006c1, 0xffffffff}, + {0x52800040, 0xffffffff}, + {0xd2800014, 0xffffffff}, + {0xa9417bfd, 0xffffffff}, + {0x9243fbbd, 0xffffffff}, + {0x910083ff, 0xffffffff}, + {0xd61f0020, 0xffffffff}, +}; + +// Window creation separately rejects a signed-out user. Keep the readiness and termination checks around it. +static const DPSkipInstruction DPWindow[] = { + {0xf947bd14, 0xffffffff}, + {0xb4000014, 0xff00001f}, + {0xaa1403e0, 0xffffffff}, + {0x94000000, 0xfc000000}, + {0x94000000, 0xfc000000}, + {0xaa0003f3, 0xffffffff}, + {0xaa1403e0, 0xffffffff}, + {0x94000000, 0xfc000000}, + {0x36002133, 0xffffffff}, + {0xf946eed4, 0xffffffff}, + {0xf946eac0, 0xffffffff}, + {0x52800021, 0xffffffff}, +}; + +BOOL DPSkipAccountStartup(void) { + uint32_t *launch = DPSkipFindCode(DPLaunch, sizeof DPLaunch / sizeof *DPLaunch); + uint32_t *window = DPSkipFindCode(DPWindow, sizeof DPWindow / sizeof *DPWindow); + if (!launch || !window) return NO; + if (!DPSkipWriteCode(launch + 7, DPLaunch[7].value, 0xd503201f)) return NO; + if (DPSkipWriteCode(window + 8, DPWindow[8].value, 0xd503201f)) return YES; + DPSkipWriteCode(launch + 7, 0xd503201f, DPLaunch[7].value); + return NO; +} From 60fdee2fcaa651897fd6c3aae76bee496ecfab3e Mon Sep 17 00:00:00 2001 From: westlandnigel Date: Fri, 13 Nov 2026 23:24:32 +0800 Subject: [PATCH 2/7] fix(dylib): hide account-only settings when skipping sign-in --- src/dylib/Patches/SkipAccount/Settings.m | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/dylib/Patches/SkipAccount/Settings.m b/src/dylib/Patches/SkipAccount/Settings.m index cd482b8d..2b594c30 100644 --- a/src/dylib/Patches/SkipAccount/Settings.m +++ b/src/dylib/Patches/SkipAccount/Settings.m @@ -1,23 +1,33 @@ #import "Startup.h" +static NSHashTable *DPAccountSections; + static BOOL DPIsAccountHeader(NSView *header) { NSTextField *title = (NSTextField *)DPFindView(header, ^BOOL(NSView *view) { return [view isKindOfClass:NSTextField.class]; }); - return [title.stringValue isEqual:@"Account"]; + return title.stringValue && [@[ @"Account", @"Morning Brief", @"Sync" ] containsObject:title.stringValue]; +} + +static void DPSection_setHidden(NSView *self, SEL _cmd, BOOL hidden) { + DPCallOriginal(DPSection_setHidden, self, hidden || [DPAccountSections containsObject:self]); } static void DPHeader_layout(NSView *self, SEL _cmd) { DPCallOriginal(DPHeader_layout, self); - // The arranged stack contains the heading, Name/Email card, and account options row. - if (DPIsAccountHeader(self)) self.superview.hidden = YES; + // Hide the arranged section, including its heading, controls, and any account error message. + if (!DPIsAccountHeader(self) || ![self.superview isKindOfClass:NSStackView.class]) return; + [DPAccountSections addObject:self.superview]; + self.superview.hidden = YES; } void DPSkipAccountSettings(void) { + DPAccountSections = [NSHashTable weakObjectsHashTable]; + DPHookClass(NSStackView.class, @selector(setHidden:), (IMP)DPSection_setHidden); DPHook(DPSkipAccountHeader, @selector(layout), (IMP)DPHeader_layout); } NSString *DPSkipVerifyAccountSettings(void) { for (NSView *header in DPFindViews(DPSkipAccountHeader)) - if (DPIsAccountHeader(header) && !header.isHiddenOrHasHiddenAncestor) return @"Account settings section is visible"; + if (DPIsAccountHeader(header) && !header.isHiddenOrHasHiddenAncestor) return @"account-only settings section is visible"; for (NSView *button in DPFindViews("NSButton")) if (DPHasLabel(button, @"More account options") && !button.isHiddenOrHasHiddenAncestor) return @"account options button is visible"; return nil; From 9f0a75779466c8731ffd8c2cc1d49d1d3159814c Mon Sep 17 00:00:00 2001 From: Jace Date: Sat, 14 Nov 2026 01:31:47 +0100 Subject: [PATCH 3/7] fix(dylib): match Skip Account's window check when its offset moves --- src/dylib/Patches/SkipAccount/Startup.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dylib/Patches/SkipAccount/Startup.m b/src/dylib/Patches/SkipAccount/Startup.m index 028fc7d1..027b632e 100644 --- a/src/dylib/Patches/SkipAccount/Startup.m +++ b/src/dylib/Patches/SkipAccount/Startup.m @@ -26,8 +26,9 @@ }; // Window creation separately rejects a signed-out user. Keep the readiness and termination checks around it. +// The first load's field offset changes in every Dia release (0xf28, 0xf78, 0xf68), so only its registers are matched. static const DPSkipInstruction DPWindow[] = { - {0xf947bd14, 0xffffffff}, + {0xf9400114, 0xffc003ff}, {0xb4000014, 0xff00001f}, {0xaa1403e0, 0xffffffff}, {0x94000000, 0xfc000000}, From ca1a67ce065edee7156a6ef5cb878a02b379f25d Mon Sep 17 00:00:00 2001 From: Jace Date: Sat, 14 Nov 2026 01:31:47 +0100 Subject: [PATCH 4/7] fix(dylib): refuse Skip Account on a Dia that has signed in before --- src/dylib/Patches/SkipAccount/SkipAccount.m | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/dylib/Patches/SkipAccount/SkipAccount.m b/src/dylib/Patches/SkipAccount/SkipAccount.m index 7cc9264a..2fc5c33a 100644 --- a/src/dylib/Patches/SkipAccount/SkipAccount.m +++ b/src/dylib/Patches/SkipAccount/SkipAccount.m @@ -32,8 +32,13 @@ static void DPWaitForBrowser(void) { }]; } +static NSString *DPSkipAccountProblem(DPPatch *patch) { + if (gSkipping || ![NSUserDefaults.standardUserDefaults boolForKey:@"hasUserAuthenticated"]) return nil; + return @"This Dia has signed in to an account before. Skip Account only works on a Dia that never has."; +} + static void DPInstallSkipAccount(void) { - if (!DPSkipAccount.on) return; + if (!DPSkipAccount.on || DPSkipAccountProblem(&DPSkipAccount)) return; gSkipping = DPSkipAccountStartup(); if (gSkipping) { DPHookClass(NSUserDefaults.class, @selector(objectForKey:), (IMP)DPDefaults_objectForKey); @@ -49,7 +54,7 @@ static void DPInstallSkipAccount(void) { } static void DPApplySkipAccount(DPPatch *patch) { - if (patch->on == gSkipping || patch->on != DPSavedOn(patch)) return; + if (patch->on == gSkipping || patch->on != DPSavedOn(patch) || DPSkipAccountProblem(patch)) return; NSAlert *alert = [NSAlert new]; alert.messageText = patch->on ? @"Relaunch Dia to skip account sign-in" : @"Relaunch Dia to use account sign-in"; [alert addButtonWithTitle:@"Relaunch"]; @@ -78,4 +83,5 @@ static void DPApplySkipAccount(DPPatch *patch) { .install = DPInstallSkipAccount, .apply = DPApplySkipAccount, .verify = DPVerifySkipAccount, + .ready = DPSkipAccountProblem, }; From fde8f7b22d5d2b0de80b03f91cca49acb537bb46 Mon Sep 17 00:00:00 2001 From: Jace Date: Sat, 14 Nov 2026 01:31:47 +0100 Subject: [PATCH 5/7] refactor(dylib): share the settings header class name with Turn Off AI --- src/dylib/Patches/SkipAccount/Settings.m | 4 ++-- src/dylib/Patches/SkipAccount/SkipAccount.m | 2 +- src/dylib/Patches/SkipAccount/Startup.h | 2 -- src/dylib/Patches/TurnOffAI/TurnOffAI.m | 1 - src/dylib/StdPatch/Dia.h | 1 + 5 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/dylib/Patches/SkipAccount/Settings.m b/src/dylib/Patches/SkipAccount/Settings.m index 2b594c30..b000191d 100644 --- a/src/dylib/Patches/SkipAccount/Settings.m +++ b/src/dylib/Patches/SkipAccount/Settings.m @@ -22,11 +22,11 @@ static void DPHeader_layout(NSView *self, SEL _cmd) { void DPSkipAccountSettings(void) { DPAccountSections = [NSHashTable weakObjectsHashTable]; DPHookClass(NSStackView.class, @selector(setHidden:), (IMP)DPSection_setHidden); - DPHook(DPSkipAccountHeader, @selector(layout), (IMP)DPHeader_layout); + DPHook(DPDiaSettingsHeader, @selector(layout), (IMP)DPHeader_layout); } NSString *DPSkipVerifyAccountSettings(void) { - for (NSView *header in DPFindViews(DPSkipAccountHeader)) + for (NSView *header in DPFindViews(DPDiaSettingsHeader)) if (DPIsAccountHeader(header) && !header.isHiddenOrHasHiddenAncestor) return @"account-only settings section is visible"; for (NSView *button in DPFindViews("NSButton")) if (DPHasLabel(button, @"More account options") && !button.isHiddenOrHasHiddenAncestor) return @"account options button is visible"; diff --git a/src/dylib/Patches/SkipAccount/SkipAccount.m b/src/dylib/Patches/SkipAccount/SkipAccount.m index 2fc5c33a..17a098e7 100644 --- a/src/dylib/Patches/SkipAccount/SkipAccount.m +++ b/src/dylib/Patches/SkipAccount/SkipAccount.m @@ -79,7 +79,7 @@ static void DPApplySkipAccount(DPPatch *patch) { .symbol = @"person.crop.circle.badge.minus person.crop.circle", .tint = @"systemBrownColor", .section = @"Window", - .classes = DPClasses(DPDiaAppDelegate, DPSkipAccountHeader), + .classes = DPClasses(DPDiaAppDelegate, DPDiaSettingsHeader), .install = DPInstallSkipAccount, .apply = DPApplySkipAccount, .verify = DPVerifySkipAccount, diff --git a/src/dylib/Patches/SkipAccount/Startup.h b/src/dylib/Patches/SkipAccount/Startup.h index 6699d838..2f77bf7e 100644 --- a/src/dylib/Patches/SkipAccount/Startup.h +++ b/src/dylib/Patches/SkipAccount/Startup.h @@ -1,7 +1,5 @@ #import "StdPatch/StdPatch.h" -#define DPSkipAccountHeader "_TtC11Preferences25SettingsSectionHeaderView" - typedef struct { uint32_t value, mask; } DPSkipInstruction; uint32_t *DPSkipFindCode(const DPSkipInstruction *signature, NSUInteger length); BOOL DPSkipWriteCode(uint32_t *site, uint32_t expected, uint32_t value); diff --git a/src/dylib/Patches/TurnOffAI/TurnOffAI.m b/src/dylib/Patches/TurnOffAI/TurnOffAI.m index 23f30c36..18b06495 100644 --- a/src/dylib/Patches/TurnOffAI/TurnOffAI.m +++ b/src/dylib/Patches/TurnOffAI/TurnOffAI.m @@ -3,7 +3,6 @@ #define DPDiaCapabilitiesToolbar "_TtC23AssistantCapabilitiesUI32AssistantCapabilitiesToolbarView" #define DPDiaTabCardActions "_TtC5TabUI21TabPopoverActionsView" -#define DPDiaSettingsHeader "_TtC11Preferences25SettingsSectionHeaderView" #define DPDiaPlaceholderText "_TtC5ARCUI23TextViewWithPlaceholder" #define DPDiaChatSidebar "_TtC6Window30AssistantSidebarViewController" diff --git a/src/dylib/StdPatch/Dia.h b/src/dylib/StdPatch/Dia.h index e121efb2..cb066d9b 100644 --- a/src/dylib/StdPatch/Dia.h +++ b/src/dylib/StdPatch/Dia.h @@ -37,6 +37,7 @@ #define DPDiaTabSwitcher "_TtC10RecentTabs26RecentTabsWindowController" #define DPDiaTabSwitcherList "_TtC10RecentTabs24RecentTabsViewController" #define DPDiaSettingsController "_TtC11Preferences38SidebarPreferencesWindowViewController" +#define DPDiaSettingsHeader "_TtC11Preferences25SettingsSectionHeaderView" #define DPDiaSettingsSidebar "_TtC11Preferences15SidebarListView" #define DPDiaSpaceSwitcher "_TtC10TabSidebar17SpaceSwitcherView" #define DPDiaSpaceSwitcherItem "_TtC10TabSidebar21SpaceSwitcherItemView" From b133a8132c03454155c2cb7cf1ab66b6233d3b4f Mon Sep 17 00:00:00 2001 From: Jace Date: Sat, 14 Nov 2026 01:31:48 +0100 Subject: [PATCH 6/7] fix(dylib): mark Skip Account experimental and say what it hides --- src/dylib/Patches/SkipAccount/SkipAccount.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dylib/Patches/SkipAccount/SkipAccount.m b/src/dylib/Patches/SkipAccount/SkipAccount.m index 17a098e7..95b19225 100644 --- a/src/dylib/Patches/SkipAccount/SkipAccount.m +++ b/src/dylib/Patches/SkipAccount/SkipAccount.m @@ -75,7 +75,7 @@ static void DPApplySkipAccount(DPPatch *patch) { .key = @"skipAccount", .order = 120, .title = @"Skip Account", - .detail = @"Open Dia without signing in or creating a Dia account. Relaunch to apply. Account services still need an account. Use Turn Off AI too for plain browsing. May need an update after some Dia releases.", + .detail = @"Use Dia without signing in. Relaunch to apply. Hides Sign In and the Account, Morning Brief and Sync settings. Only works on a Dia that has never signed in. Chat needs an account, so pair it with Turn Off AI. Experimental.", .symbol = @"person.crop.circle.badge.minus person.crop.circle", .tint = @"systemBrownColor", .section = @"Window", From d10b13071f50fa798e5d89d62562bb44de76b815 Mon Sep 17 00:00:00 2001 From: Jace Date: Sat, 14 Nov 2026 01:31:57 +0100 Subject: [PATCH 7/7] chore(github): list Skip Account in the bug report form --- .github/ISSUE_TEMPLATE/bug.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 1cd73164..febb553b 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -69,6 +69,7 @@ body: - Window Corners - App Icon - Hide Window Controls + - Skip Account - Allow 1Password - Allow Bitwarden - Allow iCloud Passkeys