Skip to content

feat(ios): background sync, Cmd+F search focus, scene-restored search text, regex literal highlighter#1170

Merged
datlechin merged 2 commits into
mainfrom
feat/ios-polish-state-bg-shortcuts
May 9, 2026
Merged

feat(ios): background sync, Cmd+F search focus, scene-restored search text, regex literal highlighter#1170
datlechin merged 2 commits into
mainfrom
feat/ios-polish-state-bg-shortcuts

Conversation

@datlechin

Copy link
Copy Markdown
Member

Summary

Bundle of four small iOS polish items from the audit backlog. Each one stands alone; bundling because total LOC is small and review surfaces are independent.

D. Background sync via BGAppRefreshTask

  • TableProMobileApp declares static let backgroundSyncIdentifier = "com.TablePro.sync" and uses .backgroundTask(.appRefresh(_:)) (iOS 17 SwiftUI native API) to register the sync handler
  • On .background scenePhase, schedule the next BGAppRefreshTaskRequest with earliestBeginDate = +30min. iOS picks the actual fire time based on usage and battery
  • The handler reschedules first (so the loop continues) then runs syncCoordinator.sync(...) if AppPreferences.isCloudSyncEnabled
  • Logged via os.Logger("com.TablePro", "BackgroundSync")
  • Info.plist gains UIBackgroundModes (fetch, processing) and BGTaskSchedulerPermittedIdentifiers array

E. Cmd+F focuses search

  • DataBrowserView and TableListView add @FocusState searchFocused: Bool, apply .searchFocused($searchFocused) on the searchable, and place a hidden Cmd+F button in .background that sets searchFocused = true
  • iPad with external keyboard: Cmd+F snaps focus to the search field (canonical macOS-style)

C. State restoration via @SceneStorage

  • searchText in DataBrowserView and TableListView switches from @State to @SceneStorage("dataBrowser.searchText") and @SceneStorage("tableList.searchText")
  • Survives process kill; per-scene on iPad multi-window
  • Tradeoff: cross-table search text persists within a scene (key is not table-scoped). User clearing or retyping is the natural reset; full table-scoping needs explicit init plumbing not worth the complexity here

F. SQL syntax highlighter Regex literals

  • 4 static patterns (number, line comment, block comment, string) become Regex<Substring> literals (#/.../#) — compile-time validated, no try!
  • 2 dynamic patterns (keyword and function lists built from arrays) keep the runtime-built pattern but typed as Regex<Substring> via Regex(_:as:) instead of NSRegularExpression
  • 6 repeated enumerateMatches blocks consolidate into a single apply(_ regex:color:scanText:in:on:protected:recordsProtection:) generic helper. The helper takes any Regex<Output> so static and dynamic patterns share one code path
  • Bridges Swift Range<String.Index> to NSRange once via NSRange(_:in:) for NSTextStorage.addAttribute

Test plan

  • Open the SQL editor, type a query with comments, strings, keywords, functions, numbers - colors match before/after this PR
  • Type a long block comment with embedded keywords - keyword inside comment stays gray (protected range logic works)
  • iPad with keyboard: in Tables list, press Cmd+F - search field gains focus and the keyboard appears. Same in Data Browser
  • Type "users" in Data Browser search, force-quit the app from Recents, relaunch - search field still shows "users"
  • Settings -> iCloud Sync off -> background the app -> wait 30+ minutes (or trigger via Xcode e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.TablePro.sync"]) - sync handler runs but exits early because of the gate
  • Settings -> iCloud Sync on -> same trigger - sync runs, log shows "Background sync starting" then "Background sync completed"

@datlechin datlechin merged commit 97f399b into main May 9, 2026
2 checks passed
@datlechin datlechin deleted the feat/ios-polish-state-bg-shortcuts branch May 9, 2026 19:39
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.

1 participant