Move the window surfaces, the palette shell and the composition root (#187)

Windows/ takes the dialog, HUD, aux-window and About code — including
AuxWindowController, which had been living at the bottom of AboutView.
Palette/ takes the panel, controller, root view, screen protocol and the
palette state types extracted from AppCore. Contents unchanged.
This commit is contained in:
Abue Ammar
2026-08-06 01:34:10 +06:00
committed by GitHub
parent 2a240436d8
commit e03bdfd653
27 changed files with 494 additions and 306 deletions
+13 -7
View File
@@ -45,7 +45,7 @@ code — come from the global `CLAUDE.md` and are not repeated here. Tinycast ad
Full detail: [`docs/architecture.md`](docs/architecture.md).
- **Single-owner core.** `AppCore.shared` (`Core/AppCore.swift`) is a `@MainActor` singleton owning
- **Single-owner core.** `AppCore.shared` (`App/AppCore.swift`) is a `@MainActor` singleton owning
every long-lived manager and the window controllers.
`AppDelegate.applicationDidFinishLaunching` calls `AppCore.shared.start()` and nothing else — that
is the one wiring point. Palette / paste / launch actions are methods on `AppCore` that views call.
@@ -206,7 +206,7 @@ Never break these without an explicit task to do so.
listen-only, installs *only* while something is bound to a double-tap, and never prompts for
Accessibility. See [hotkeys.md](docs/hotkeys.md).
- **Tinycast presents its own dialogs, never `NSAlert` / `NSSlider` / system popovers.** Every
confirmation, failure report and value prompt goes through `DialogController` (`Core/Dialog/`,
confirmation, failure report and value prompt goes through `DialogController` (`Windows/Dialog/`,
owned by `AppCore`; reachable elsewhere via `AppCore.showNotice` / `confirm`). Presentation is
`async`, so there is no nested run loop, and the presenter refuses a second dialog while one is up
— that, not a flag, is what stops a held hotkey stacking dialogs. **↵ runs the primary action,
@@ -244,7 +244,7 @@ Never break these without an explicit task to do so.
## Project Layout
- `Tinycast/Core/` — managers, stores, windows, AppKit glue (no view bodies beyond hosting).
- `Tinycast/Core/` — managers, stores and AppKit glue (no view bodies beyond hosting).
`Core/Calculator/` and `Core/Emoji/` are Foundation-only engines; `Core/Snippets/` is a
standalone-harness input in full (and owns the template engine both it and Quicklinks expand
through); `Core/WindowManagement/` is a pure geometry layer plus its one AX file; `Core/Uninstall/`
@@ -256,14 +256,20 @@ Never break these without an explicit task to do so.
`SettingsComponents`, `Scrolling/` and `Interaction/`.
- `Tinycast/Platform/` — the system shims: `Permissions`, `LaunchAtLogin`, `CursorScreen`,
`AppDisplayName`, `NotificationToken`, `AppPaths`, `Signposts` and `Images/`.
- `Tinycast/Features/` — SwiftUI views: `RootPaletteView`, `Launcher/`, `Clipboard/`, `Calculator/`,
`Emoji/`, `Quicklinks/`, `Uninstall/`, `Settings/`, `About/`, `Onboarding/`, plus
the `PaletteScreen` protocol and the harness-compiled `PaletteRowIndex`. Each
- `Tinycast/Palette/` — the palette shell: `PalettePanel`, `PaletteWindowController`,
`RootPaletteView`, the `PaletteScreen` protocol, `PaletteCoordinator` and the `PaletteViewModel` /
`PaletteMode` / `PasteTarget` state types.
- `Tinycast/Windows/` — the non-palette AppKit surfaces: `AuxWindowController` (Settings, About,
Onboarding), `Dialog/` and `HUD/`, kept separate because a dialog asks and a HUD reports, plus
`About/`.
- `Tinycast/Features/` — SwiftUI views: `Launcher/`, `Clipboard/`, `Calculator/`,
`Emoji/`, `Quicklinks/`, `Uninstall/`, `Settings/`, `Onboarding/`, plus
the harness-compiled `PaletteRowIndex`. Each
`SettingsTab` maps to
one `…SettingsView` built on the `SettingsPane` / `SettingsCard` scaffold in
`DesignSystem/SettingsComponents.swift`;
the four launcher-category panes (Applications, System Settings, System Actions, Commands) are thin
wrappers over the shared `LauncherItemsCard`.
- `Tinycast/App/` — `@main` app + delegate.
- `Tinycast/App/` — `@main` app, delegate and `AppCore`, the composition root.
- `Tools/` — standalone test harnesses and the emoji generator.
- `.github/workflows/release.yml` — the entire release pipeline (see `docs/development.md`).
+119 -115
View File
@@ -7,7 +7,6 @@
objects = {
/* Begin PBXBuildFile section */
0626264D8C719DA8366B5E28 /* VolumeHUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC6173CA658DA56245031FE6 /* VolumeHUDView.swift */; };
0674D8E1567253879EF50150 /* SnippetArgumentsPrompt.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2F919FBD5F2E0399523AA56 /* SnippetArgumentsPrompt.swift */; };
0962E9575CBF40B6F908031C /* UninstallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 59D08C3AEAFB224866F23C3E /* UninstallView.swift */; };
0CAD18A2FE3CE8C5B1C03B2E /* UninstallScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F9E18B81A4AA3358DB24FAA /* UninstallScreen.swift */; };
@@ -19,19 +18,21 @@
125A99FB5A3603488A261C6A /* UninstallRules.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EB4BA1A385F78B9C5E7EBCF /* UninstallRules.swift */; };
14712478C37E6E8760CA47EC /* HyperKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6DC5A4706854493D23FD18A /* HyperKey.swift */; };
14A5A5ACD35A572EE906769F /* CalcEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B976C84AFE60E357A346224 /* CalcEngine.swift */; };
152E4A75BD2AF9279497F5FF /* DialogController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD0A151A3B8AC682395E621D /* DialogController.swift */; };
15292937738B7CD3AE23EF73 /* VolumeSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = E27FB790A72ACD75DFCDFDDF /* VolumeSlider.swift */; };
1A899FE562A7344918CE1B44 /* QuicklinkLauncher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ECAB8490328EA3DADD05D9D /* QuicklinkLauncher.swift */; };
1AF562E00FCB98B12076F01D /* SnippetKeywordListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5051622CC6497E2151326CA /* SnippetKeywordListener.swift */; };
1B90AA42601E3AE7EEE3AD5D /* WindowLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 388A58EDB35AB0CB30EE20DE /* WindowLayout.swift */; };
1D0C2F452B3801503B70EA9E /* GeneralSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F63A3610C275E4961D60C7E /* GeneralSettingsView.swift */; };
1D322768F5E19354C41CC246 /* PaletteViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBA661399C15362ABAE13AA5 /* PaletteViewModel.swift */; };
1F39D145DBE2290532C93614 /* ClipboardSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849FF3D93960B75F341D867C /* ClipboardSettingsView.swift */; };
1F555347D7CE8F37A2C37BAF /* SnippetRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C069647C67120EBAED14422 /* SnippetRepository.swift */; };
2085C9433B7534044E0A8A7D /* PermissionsSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C36D92A5018B9A7B33775DE /* PermissionsSettingsView.swift */; };
212B9B44D7EED18A0DEF47AF /* ShellCommandRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 286B7598B81017C746558C7C /* ShellCommandRunner.swift */; };
21736CC104E158BC194B1094 /* WindowMover.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8859C0E99A2125D85B1233C /* WindowMover.swift */; };
220C7306D07B6DEA697FADC6 /* PaletteCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A2BEA44C75A8072117FE13F /* PaletteCoordinator.swift */; };
22622CB1D2F679687D5C2B03 /* SearchRelevance.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9E9B0F16CFCA5E4091178AF /* SearchRelevance.swift */; };
24842144273FF92228540DBE /* FrequentEmojiStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A228BEF62103605DE7A8F38 /* FrequentEmojiStore.swift */; };
24F4BF3EA74E8E65B2B92D6D /* VolumeHUDController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09633E6F9C37F89267341D1D /* VolumeHUDController.swift */; };
25E7E031DCF72BFF19725344 /* PaletteMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1534DB79CC23709ABC5E9D9B /* PaletteMode.swift */; };
291F17D35D98BB5700640AA7 /* QuicklinkListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D30F22CD63D23FC1808878DD /* QuicklinkListView.swift */; };
2D620B55ED68ECDF75E7155E /* UninstallRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE113DF7C07BC74AD73BC4C /* UninstallRunner.swift */; };
31E0E4E0782A79504CEB588D /* ScrollIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 622E1F1C01B954DCA2199BCD /* ScrollIntent.swift */; };
@@ -45,32 +46,34 @@
36784C964DB27B94A62EEAA3 /* tinycast.icon in Resources */ = {isa = PBXBuildFile; fileRef = 6621A88681E993D49EEF07A3 /* tinycast.icon */; };
36968DFA1E201E681F0BCD42 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1306524F57602D90FCF153C /* Theme.swift */; };
374235D358A127741447551E /* SettingsBackup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5043CD44B4B40C49BE79852A /* SettingsBackup.swift */; };
399980E533A1A83EAAA7FC6B /* AuxWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41A52665A3078BAAD151528C /* AuxWindowController.swift */; };
3B94AE7D433AB285272E6F65 /* SystemActionCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99E3714E7C617AF4A70194BD /* SystemActionCoordinator.swift */; };
3FDDE40D7AB93EE2069E8EE7 /* QuicklinkArgumentsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B3E54FBEB045D6A9866832 /* QuicklinkArgumentsScreen.swift */; };
3FEBE1C993C5BD92F1C3D95B /* LauncherRankingStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87B6E442944C99B4D1FE1C74 /* LauncherRankingStore.swift */; };
4006B894BE909BD067ED1E3A /* ShortcutRecorderPopover.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F3AA7727C7F5F511E7F1EF1 /* ShortcutRecorderPopover.swift */; };
40EC75A7BC165783128CA9E2 /* MessageHUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96F62D88E5BAC5F095E060B8 /* MessageHUDView.swift */; };
41164F539DD16E9FFEF44F8E /* DialogPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE0379921C89CA45189533B9 /* DialogPanel.swift */; };
42828BD1C5E4E6E7AA1BF103 /* CalculatorHistoryStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F793A92DD4DC73CF1D87F3FD /* CalculatorHistoryStore.swift */; };
43DBCE7B5A84D0D6322124F5 /* MessageHUDController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B2CB71671625A1F446316A1 /* MessageHUDController.swift */; };
441CF705AE1D03F6E236A61E /* ClipboardStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDC43CFF6777C11BB880F398 /* ClipboardStore.swift */; };
465B8661E7399F3AA32BD75C /* SnippetKeywordPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD3764D91B2F3170690A473A /* SnippetKeywordPolicy.swift */; };
47E13BC63F8BE11EDF25EA82 /* RootPaletteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A98172AA46F5C0C89C4AB /* RootPaletteView.swift */; };
48AB20B04EB50F9F4A68BD66 /* SnippetTemplateEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A002AC0DE601E1F65D20C4A /* SnippetTemplateEngine.swift */; };
4F3D96E59E117459153336F4 /* SettingsPaneScanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = C722D73D270A3A6CED4023F7 /* SettingsPaneScanner.swift */; };
4F740AF85545CF4133C89B82 /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4802942FF89B327A76432A9B /* AboutView.swift */; };
4F8C9F202EE37D39C1AC13EF /* CalloutShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = C24AD5CFE167900DF8B2705C /* CalloutShape.swift */; };
505D48BA4D7046FD24B45414 /* EmojiCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AC96D2469CC9D098DC4A2F2 /* EmojiCoordinator.swift */; };
52C4F57BB26F420CCD22C1D7 /* PaletteWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 209D951FDD587A040F1F76F3 /* PaletteWindowController.swift */; };
540F1433DC46BC97C9F80E06 /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 787059DAE8AB67FFE684C0D9 /* AboutView.swift */; };
57AE40420A6A5349AD092878 /* ShortcutRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 596ADD747B4546B1E3340094 /* ShortcutRecorder.swift */; };
57D7D94F9CB94B1152D44879 /* CursorScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9163FDA8F7ADDEF49A62D72C /* CursorScreen.swift */; };
5B0EFBA180AAFFBC08CC395A /* HotKeyBinding.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB5C3FDF5037F730E23E53D /* HotKeyBinding.swift */; };
5DD58D999A421873EF3F2204 /* MessageHUDController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EE6E09755C1AF3AFBA6107E /* MessageHUDController.swift */; };
5C801A9043908577FB99A555 /* DialogView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32733B27AE0BD75742D1394F /* DialogView.swift */; };
5E49E070BDBB91A2829F5321 /* SnippetTextInjector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 309908BAB8C19B67F4608DA9 /* SnippetTextInjector.swift */; };
5F107A05A7EB05204465E89D /* VolumeHUDController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6256CC7C3F15BA05A216E820 /* VolumeHUDController.swift */; };
61176B0EB91E2F82EEE3F4B9 /* SystemActionsSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29B90AEA968DD7B91A553E07 /* SystemActionsSettingsView.swift */; };
613827876C48EF88F2162C10 /* NotificationToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1FB75182A60F65BA1FB9BA8 /* NotificationToken.swift */; };
63E24116B4CCC95F4FA295E3 /* QuicklinkEditorSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAFE92DB670B2EFA79FF9FAE /* QuicklinkEditorSheet.swift */; };
649961AA51BA4D87626C27D5 /* CalcFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09093BF10EA97BDCA45A241F /* CalcFormatter.swift */; };
6590849AB537D8641C71AC71 /* UninstallPlan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4954C8003947BB16ED48E326 /* UninstallPlan.swift */; };
67686B4D7A5922D9D1E1ADE1 /* SpotlightNames.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8925E80B57FDCEAB9764C65F /* SpotlightNames.swift */; };
68537C3544E4EBC40E3ACD39 /* HUDPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BAD6EE1BA3036C4B5A3D19 /* HUDPresenter.swift */; };
68FCC30764DD44ED72EFB6BA /* TinycastApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B629EC3B716FEE881BB0075 /* TinycastApp.swift */; };
693E88D22D00CF6FD9CD7413 /* VisibilityStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 825AC18CE5DAFBEDA0CF3209 /* VisibilityStore.swift */; };
6A0C45313C7B73349C7B17E0 /* ThinScrollbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6A6748260B2DF011CCAFCEF /* ThinScrollbar.swift */; };
@@ -78,13 +81,12 @@
6C824F5B5099D36E73CF7E4C /* QuicklinkStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4A55E96BF19A8B1D71645 /* QuicklinkStore.swift */; };
6CDCE462405648998CDF1E77 /* CurrencyRateStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E6CB5CD6C0477BAC9FE383F /* CurrencyRateStore.swift */; };
6D3DBE00FCB757C67669CFBA /* CommandRegistry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D57B0AE44D21035163BD422 /* CommandRegistry.swift */; };
6F08764D6CC09E9B3FD1E05A /* RootPaletteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F50886DC766B9923C3875A5 /* RootPaletteView.swift */; };
701120BCA431BF00ABDEDBD4 /* WindowCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ECE1FA4B89326C37DF12A8C /* WindowCommand.swift */; };
72406E09AD9A33B56EA4923D /* CalcParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 423CFE8AB90484D0309F24C0 /* CalcParser.swift */; };
79EA954E3675EC25D622547B /* UninstallCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DE518F1D895CDC9681B390E /* UninstallCoordinator.swift */; };
7A2C6032E0DE0346DD10A747 /* DialogRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8745544BFC53B27B0168CA6 /* DialogRequest.swift */; };
7CB65E9238B5FC097A84CAAC /* CalculatorHistoryScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6117D83A89795049FDCD4B9A /* CalculatorHistoryScreen.swift */; };
800D542DEAB2C2F4EC8D8A11 /* CustomCommandCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB338D03EBFF94461CA42B5D /* CustomCommandCoordinator.swift */; };
8090FBE343746D9D43EE2B24 /* PalettePanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA9F3FA9925873D25EAF7D03 /* PalettePanel.swift */; };
84096D3843E674F0B12C03D4 /* UninstallSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 631D879F03A3A86553E7FFE5 /* UninstallSession.swift */; };
854C19458C8A0AE0BD757600 /* EmojiIndex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74F450E10D107C1E30EA2BC6 /* EmojiIndex.swift */; };
85A9ACCB19D9502A79F1A508 /* Snippet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05970D61D4E595D0658D0D94 /* Snippet.swift */; };
@@ -92,8 +94,10 @@
861CB0B484C44D0D9A0DB74F /* VolumeState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3499548D8C4A2FE4E7D3090B /* VolumeState.swift */; };
8631543D8E0E008E7C541345 /* BackupSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FC323070A08CD17DFFB2F8A /* BackupSettingsView.swift */; };
867B82EDC8A12BBC51592786 /* Tooltip.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADD4CE330F75BC5FE5EAD99E /* Tooltip.swift */; };
86C36C0885D5820E70184CF6 /* PaletteCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C004F2C2EFDD340A73C6AB02 /* PaletteCoordinator.swift */; };
8855C67C7EE196E3F9EDE778 /* KeyCapChip.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5BA06E4CC7E8D40E3285F16 /* KeyCapChip.swift */; };
8A75C5779712AEE0EE3DE568 /* QuicklinkArchive.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26CCC54FC861BB11AB24357E /* QuicklinkArchive.swift */; };
8D529C8F3AB579941067FE98 /* MessageHUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 976A1F05AD82DB8A04B3C3F9 /* MessageHUDView.swift */; };
8EF55652F19A1E0C5FF644B4 /* RaycastImport.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4049668745FD438D5792A2F /* RaycastImport.swift */; };
8F7431A1340D0A5783599087 /* MiscellaneousSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 297F819E291F33E43E490359 /* MiscellaneousSettingsView.swift */; };
903E82F78D3FCEF3A1AF3752 /* HotKeyManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D37B6D29E8E23C6136EBFB38 /* HotKeyManager.swift */; };
@@ -102,32 +106,32 @@
939F3944AE8D36A8C337D46F /* Signposts.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9044F107ADD5896746DBC35 /* Signposts.swift */; };
94620E1BB1049C5D8B45392E /* UninstallSearchRoot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C56920811CA9A5F0FA04441 /* UninstallSearchRoot.swift */; };
94887F8E18AB2C08A8273897 /* Permissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA7B3EB88881CEEFCE71448D /* Permissions.swift */; };
97A195E9D6480418D4944560 /* AppCore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A64EF5A07D459753998F78C /* AppCore.swift */; };
98C02FAC75A5F4F73B1BC338 /* QuicklinkCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E597EEC2DA1E88910C6C3FC7 /* QuicklinkCoordinator.swift */; };
9969E6858C4FDC5CCCDEB5D8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C45190564C9D9F1722E83943 /* Assets.xcassets */; };
99FA1235E66BDC098563957A /* LauncherScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BF4175BB6E94B42AD90660D /* LauncherScreen.swift */; };
9A15181AAF90211C807592E3 /* VisualEffectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA90C004E55AB1BBC12D9F96 /* VisualEffectView.swift */; };
9A254BEE278D7B78B76553A9 /* Scrypt.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDE0C0DC05F958A4B4DCAA8C /* Scrypt.swift */; };
9A3972BE11AE353EFBB839A0 /* PalettePanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 555E9C7EA62BDB40891A5751 /* PalettePanel.swift */; };
9EC89A6398BD075275FECC9E /* CalcUnits.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25B8A7D8DBB0CE2ACEDB3979 /* CalcUnits.swift */; };
9F82DA5A46BB39A6C6DD075D /* DialogRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28D150930C930F1FB5E2A31B /* DialogRequest.swift */; };
9F8806D46EBAF7058FC2EAEC /* PaletteRowIndex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52BD814D567DFEFD303B1750 /* PaletteRowIndex.swift */; };
A0C1BAEE55481326EEE81471 /* RaycastImportV1.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAE385AAF41C4CB276025211 /* RaycastImportV1.swift */; };
A3855695DA55ADA137630DCE /* QuicklinkArgumentSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031271DE1EEF68A443713D32 /* QuicklinkArgumentSession.swift */; };
A41C0DCB2DEBCCA46F6C4B10 /* FavoritesStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FB750D045194AE34D39D792 /* FavoritesStore.swift */; };
A66E6C662757455D3669824B /* PaletteScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97CA43885FEA5DEED2ADDC30 /* PaletteScreen.swift */; };
A500AF3BF8910B335A7A936C /* HUDPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB1752929BA1ACC0BC54865C /* HUDPanel.swift */; };
A9D8B54D88A60DE9FC1F43BF /* CalcDateTime.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0D3EBB9D877817D10D120A8 /* CalcDateTime.swift */; };
AA332C5CB997A54E7A0EA2E9 /* Memo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B61608FEDD69014907AF239 /* Memo.swift */; };
AA8050D9A547CDDD37C581C4 /* CurrencyData.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E08668A3C8418E2F0970300 /* CurrencyData.generated.swift */; };
AB1E6D5ABF74EB00B307A7D1 /* CommandsSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74868D1F22B3CEC5A2ECD668 /* CommandsSettingsView.swift */; };
AB500AC3DEBFF6EB1CE42812 /* DialogController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94507F8F095D3EBD1A9B3007 /* DialogController.swift */; };
AB9B998DB62EE2D18A058C78 /* SnippetsSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD3579618BC7FA235EBF9E93 /* SnippetsSettingsView.swift */; };
ABBB2A811EB5C69D55A93B1C /* RaycastImportSelection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BCCED95A78DC5BED117E960 /* RaycastImportSelection.swift */; };
AC6AF9FA9C6874F257D3F613 /* UninstallTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A6941F59D6E8014A22F1FF7 /* UninstallTarget.swift */; };
ACE645630E536C93CA102050 /* VolumeHUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A90559D7DB9F6F3874CAFCDE /* VolumeHUDView.swift */; };
AD2141EBF98A246BDA3BAB8E /* Gunzip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32A53295959552ED28D34960 /* Gunzip.swift */; };
AD98F015439106F0E9D32015 /* RightClick.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7EFE2C8A212D6979C43E9F7 /* RightClick.swift */; };
AE0D0C53004C65D65BE89B6F /* BackupActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9D8C2C59C2B578CFE61E004 /* BackupActions.swift */; };
B1B3F5715BE7A092F0CEFA09 /* ClipboardManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A76E4099082D59FA686C3485 /* ClipboardManager.swift */; };
B1B540309BD0EB2B36FE4641 /* SystemAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D16E927986D415F5386CDCF /* SystemAction.swift */; };
B3A213551CD73CC364476E9F /* VolumeSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFAB36FFE7E7108FB50E9134 /* VolumeSlider.swift */; };
B545BD845189EE893D8D8DE7 /* RaycastV1Decoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8B33C0EA6D52B365B82752D /* RaycastV1Decoder.swift */; };
B7274961ABF4E8F82B2D3BB7 /* DoubleTapMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = A75F40AED77119558D5FB4E4 /* DoubleTapMonitor.swift */; };
B810158281A87CBA2AB694D0 /* EmojiData.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79DB24EE452A7CA120B56FA6 /* EmojiData.generated.swift */; };
@@ -136,6 +140,7 @@
BE9EE0864C315080A4E4780F /* AppPickerPopover.swift in Sources */ = {isa = PBXBuildFile; fileRef = E874F8DFCBE0ACDD59C8664B /* AppPickerPopover.swift */; };
BEC0F4A248520C5C2B542FBC /* LauncherCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9965615AE9C3651FF020B2CA /* LauncherCoordinator.swift */; };
C0642512B709EF0517ABF4CB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C37CCD024267EB21876C7E9 /* AppDelegate.swift */; };
C215695FE671BC591DC99C2B /* DialogPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB241B179A08518424F7C1B /* DialogPanel.swift */; };
C32EA4B1F422398F96D01338 /* EmojiScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D365D33D2FE08378D999D8 /* EmojiScreen.swift */; };
C35864533DFB42DE63080ACB /* WindowManagementSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E7DD73DC688DBFAFC4B04AC /* WindowManagementSettingsView.swift */; };
C359131F793C6C6BD756B901 /* SystemSettingsSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1DE4D8B82F1D4AFB025FB24 /* SystemSettingsSettingsView.swift */; };
@@ -147,8 +152,6 @@
C8F4555ECA895F63A34A327C /* EmojiGridGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = DABCE058D38F493D58F6E072 /* EmojiGridGeometry.swift */; };
CA6BA9C381351D0B2CADFB9D /* IconCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5CBCCE63360E4590CF5884A /* IconCache.swift */; };
CB95B0CBF0DFEDFCEA837053 /* ImageThumbnail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36C6775BBA0FC6F134296606 /* ImageThumbnail.swift */; };
CC911DB8A6FB9EDA3BBA1AAC /* DialogView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72037DA506AE1A989F858C3C /* DialogView.swift */; };
CC97C121823B1DC61886BAFC /* HUDPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70D14EC2D7A6AE5F7CBB5028 /* HUDPanel.swift */; };
CDBB4E26FCABEEE8817D12B2 /* ApplicationsSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8F4B31728E49ECE0AA2636 /* ApplicationsSettingsView.swift */; };
CE15888F3C15EE2706E108A0 /* AppDisplayName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BBDB6A6CE9564ADA2D16F53 /* AppDisplayName.swift */; };
CFB516312C4694DDFD99DBCA /* SettingsRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68952539C0BD045BA175CBB6 /* SettingsRootView.swift */; };
@@ -161,18 +164,18 @@
DA2EBB18F026BD055E0270CD /* AppLauncher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A2EF9C70F8BC9571089D5EB /* AppLauncher.swift */; };
DA5BCA13045FF91B3FC8EB35 /* OnboardingState.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8A9B4E6E477C30372C85F86 /* OnboardingState.swift */; };
DB04CC2AFEDD69D0676CA1D1 /* CalculatorCardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C64C87569634E26E1BE99A91 /* CalculatorCardView.swift */; };
DB6B294B3D15B0AABCE5427E /* PaletteScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 445B0374FD5D74DBE23243CD /* PaletteScreen.swift */; };
DCC36924E538C11136CEC060 /* LauncherView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BB7C545EFD9589A77AD7BE2 /* LauncherView.swift */; };
DDFA439EA7942183414375DC /* AppPaths.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6A96350EBE68EC79497FA2D /* AppPaths.swift */; };
DEBCF434AB244DAD43DB8A6A /* LaunchAtLogin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA9F5F7226AD5A91835AF5C /* LaunchAtLogin.swift */; };
DEC660F280699E43AA028E8A /* HotKeyCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DB0D6E17E2B2D6F2CB47E0D /* HotKeyCenter.swift */; };
E4B18EBFFD009B2CAFF4BA9B /* PanelTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73E25B87C692D5FEE1FBF994 /* PanelTransition.swift */; };
E5CA6385C7A7EE754A506815 /* DoubleTapDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E24E9328F01F2EE12120C38 /* DoubleTapDetector.swift */; };
E768AC4C8A6D6A1BA6218279 /* HUDPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55D4192BC6F5A78012027488 /* HUDPresenter.swift */; };
E8B6ADBCECD7CA81BC67EE78 /* CalloutPlacement.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A1D759B8FC5A4573E401B8 /* CalloutPlacement.swift */; };
E8CB7624CCA5905AF1A4FAD9 /* AppCore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BECF24B674F9458E4A876DA /* AppCore.swift */; };
E952B659AEB905A3B233F78B /* EmojiGridView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB94F0767AE0A5855FB22BF6 /* EmojiGridView.swift */; };
EDCEE2DDCF97C354AAC72BF2 /* RaycastImportV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6999B617ECF28C9021027B9 /* RaycastImportV2.swift */; };
EE12A8ECCC5F92553B24CD0F /* QuicklinksSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C6D4DFAC1D761ECC2DE1112 /* QuicklinksSettingsView.swift */; };
F25D58ED6EF3308D38D01732 /* PaletteWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5447AEAD87BFE0E2D979B39 /* PaletteWindowController.swift */; };
F2B68DBA258D85DD5C6DC1CC /* Paster.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6185011A02366B30B48B5B6C /* Paster.swift */; };
F457EB595789DD3A25E888DF /* SnippetsStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46C3E740AA883770481A6A8C /* SnippetsStore.swift */; };
F5F3381FF70997223F8888B0 /* KeyShortcut.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C3EB07C07902C53BFD3B08B /* KeyShortcut.swift */; };
@@ -196,14 +199,16 @@
05970D61D4E595D0658D0D94 /* Snippet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Snippet.swift; sourceTree = "<group>"; };
0818D48887156CA562EF20B8 /* VolumeLevel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VolumeLevel.swift; sourceTree = "<group>"; };
09093BF10EA97BDCA45A241F /* CalcFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalcFormatter.swift; sourceTree = "<group>"; };
09633E6F9C37F89267341D1D /* VolumeHUDController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VolumeHUDController.swift; sourceTree = "<group>"; };
0C36D92A5018B9A7B33775DE /* PermissionsSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionsSettingsView.swift; sourceTree = "<group>"; };
0D16E927986D415F5386CDCF /* SystemAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemAction.swift; sourceTree = "<group>"; };
0D49F8681407A5B76393271C /* HealthTicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HealthTicker.swift; sourceTree = "<group>"; };
0F50886DC766B9923C3875A5 /* RootPaletteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootPaletteView.swift; sourceTree = "<group>"; };
1534DB79CC23709ABC5E9D9B /* PaletteMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaletteMode.swift; sourceTree = "<group>"; };
1A4B045F847659544FA182D4 /* DoubleTapModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoubleTapModifier.swift; sourceTree = "<group>"; };
1BCCED95A78DC5BED117E960 /* RaycastImportSelection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RaycastImportSelection.swift; sourceTree = "<group>"; };
1C6D4DFAC1D761ECC2DE1112 /* QuicklinksSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuicklinksSettingsView.swift; sourceTree = "<group>"; };
1DB0D6E17E2B2D6F2CB47E0D /* HotKeyCenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HotKeyCenter.swift; sourceTree = "<group>"; };
209D951FDD587A040F1F76F3 /* PaletteWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaletteWindowController.swift; sourceTree = "<group>"; };
23591B301A183579098AA019 /* OnboardingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingView.swift; sourceTree = "<group>"; };
24F31E587DD4EAA1D7BD39AF /* UninstallProtection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UninstallProtection.swift; sourceTree = "<group>"; };
2574CDD57C65CB623FC8F4C7 /* ClipboardScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClipboardScreen.swift; sourceTree = "<group>"; };
@@ -211,31 +216,35 @@
26CCC54FC861BB11AB24357E /* QuicklinkArchive.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuicklinkArchive.swift; sourceTree = "<group>"; };
2707DD82F681E75874D55E90 /* OverlayScroller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverlayScroller.swift; sourceTree = "<group>"; };
286B7598B81017C746558C7C /* ShellCommandRunner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShellCommandRunner.swift; sourceTree = "<group>"; };
28D150930C930F1FB5E2A31B /* DialogRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DialogRequest.swift; sourceTree = "<group>"; };
297F819E291F33E43E490359 /* MiscellaneousSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MiscellaneousSettingsView.swift; sourceTree = "<group>"; };
299122624B5E1BA2C5400478 /* CalcCurrency.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalcCurrency.swift; sourceTree = "<group>"; };
29B90AEA968DD7B91A553E07 /* SystemActionsSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemActionsSettingsView.swift; sourceTree = "<group>"; };
2B2CB71671625A1F446316A1 /* MessageHUDController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageHUDController.swift; sourceTree = "<group>"; };
2B629EC3B716FEE881BB0075 /* TinycastApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TinycastApp.swift; sourceTree = "<group>"; };
2BECF24B674F9458E4A876DA /* AppCore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCore.swift; sourceTree = "<group>"; };
2C3EB07C07902C53BFD3B08B /* KeyShortcut.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyShortcut.swift; sourceTree = "<group>"; };
2FC323070A08CD17DFFB2F8A /* BackupSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupSettingsView.swift; sourceTree = "<group>"; };
309908BAB8C19B67F4608DA9 /* SnippetTextInjector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnippetTextInjector.swift; sourceTree = "<group>"; };
31BAD6EE1BA3036C4B5A3D19 /* HUDPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HUDPresenter.swift; sourceTree = "<group>"; };
32733B27AE0BD75742D1394F /* DialogView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DialogView.swift; sourceTree = "<group>"; };
32A53295959552ED28D34960 /* Gunzip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Gunzip.swift; sourceTree = "<group>"; };
338EECB7D92DF7EA1E7133AA /* Quicklink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Quicklink.swift; sourceTree = "<group>"; };
3499548D8C4A2FE4E7D3090B /* VolumeState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VolumeState.swift; sourceTree = "<group>"; };
36C6775BBA0FC6F134296606 /* ImageThumbnail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageThumbnail.swift; sourceTree = "<group>"; };
388A58EDB35AB0CB30EE20DE /* WindowLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowLayout.swift; sourceTree = "<group>"; };
3A64EF5A07D459753998F78C /* AppCore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCore.swift; sourceTree = "<group>"; };
3B78A8741FA55F42BAF5D97F /* SystemActionRunner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemActionRunner.swift; sourceTree = "<group>"; };
3B976C84AFE60E357A346224 /* CalcEngine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalcEngine.swift; sourceTree = "<group>"; };
3BA9F5F7226AD5A91835AF5C /* LaunchAtLogin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchAtLogin.swift; sourceTree = "<group>"; };
3D0E4F643A5094EA0F1D46F3 /* QuicklinkDestination.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuicklinkDestination.swift; sourceTree = "<group>"; };
3ECAB8490328EA3DADD05D9D /* QuicklinkLauncher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuicklinkLauncher.swift; sourceTree = "<group>"; };
41A52665A3078BAAD151528C /* AuxWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuxWindowController.swift; sourceTree = "<group>"; };
423CFE8AB90484D0309F24C0 /* CalcParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalcParser.swift; sourceTree = "<group>"; };
445B0374FD5D74DBE23243CD /* PaletteScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaletteScreen.swift; sourceTree = "<group>"; };
45D4BA6E1BD8EB1F96A8927F /* Tinycast.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Tinycast.entitlements; sourceTree = "<group>"; };
46C3E740AA883770481A6A8C /* SnippetsStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnippetsStore.swift; sourceTree = "<group>"; };
46D365D33D2FE08378D999D8 /* EmojiScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiScreen.swift; sourceTree = "<group>"; };
4802942FF89B327A76432A9B /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = "<group>"; };
4954C8003947BB16ED48E326 /* UninstallPlan.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UninstallPlan.swift; sourceTree = "<group>"; };
4A2BEA44C75A8072117FE13F /* PaletteCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaletteCoordinator.swift; sourceTree = "<group>"; };
4B432D84D8F9C10521342199 /* RunningApps.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunningApps.swift; sourceTree = "<group>"; };
4B61608FEDD69014907AF239 /* Memo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Memo.swift; sourceTree = "<group>"; };
4B940224413903867EF5A60E /* WindowActionMemory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowActionMemory.swift; sourceTree = "<group>"; };
@@ -248,8 +257,6 @@
52ADC36002F1A5B04D61B4D3 /* ClipboardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClipboardView.swift; sourceTree = "<group>"; };
52BD814D567DFEFD303B1750 /* PaletteRowIndex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaletteRowIndex.swift; sourceTree = "<group>"; };
5392500F86E23C099D33561D /* Tinycast.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Tinycast.app; sourceTree = BUILT_PRODUCTS_DIR; };
555E9C7EA62BDB40891A5751 /* PalettePanel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PalettePanel.swift; sourceTree = "<group>"; };
55D4192BC6F5A78012027488 /* HUDPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HUDPresenter.swift; sourceTree = "<group>"; };
596ADD747B4546B1E3340094 /* ShortcutRecorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutRecorder.swift; sourceTree = "<group>"; };
59D08C3AEAFB224866F23C3E /* UninstallView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UninstallView.swift; sourceTree = "<group>"; };
5A002AC0DE601E1F65D20C4A /* SnippetTemplateEngine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnippetTemplateEngine.swift; sourceTree = "<group>"; };
@@ -262,7 +269,6 @@
6117D83A89795049FDCD4B9A /* CalculatorHistoryScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalculatorHistoryScreen.swift; sourceTree = "<group>"; };
6185011A02366B30B48B5B6C /* Paster.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Paster.swift; sourceTree = "<group>"; };
622E1F1C01B954DCA2199BCD /* ScrollIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollIntent.swift; sourceTree = "<group>"; };
6256CC7C3F15BA05A216E820 /* VolumeHUDController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VolumeHUDController.swift; sourceTree = "<group>"; };
631D879F03A3A86553E7FFE5 /* UninstallSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UninstallSession.swift; sourceTree = "<group>"; };
641A8B9F099ED1521F14D81E /* EmojiCatalog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiCatalog.swift; sourceTree = "<group>"; };
64EC07E163CE4F3D11FE7225 /* SymbolImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SymbolImage.swift; sourceTree = "<group>"; };
@@ -275,11 +281,10 @@
6E7DD73DC688DBFAFC4B04AC /* WindowManagementSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowManagementSettingsView.swift; sourceTree = "<group>"; };
6EA607D74B37C51BABA2B33A /* QuicklinkArgumentsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuicklinkArgumentsView.swift; sourceTree = "<group>"; };
6EB4BA1A385F78B9C5E7EBCF /* UninstallRules.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UninstallRules.swift; sourceTree = "<group>"; };
70D14EC2D7A6AE5F7CBB5028 /* HUDPanel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HUDPanel.swift; sourceTree = "<group>"; };
72037DA506AE1A989F858C3C /* DialogView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DialogView.swift; sourceTree = "<group>"; };
73E25B87C692D5FEE1FBF994 /* PanelTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PanelTransition.swift; sourceTree = "<group>"; };
74868D1F22B3CEC5A2ECD668 /* CommandsSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandsSettingsView.swift; sourceTree = "<group>"; };
74F450E10D107C1E30EA2BC6 /* EmojiIndex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiIndex.swift; sourceTree = "<group>"; };
787059DAE8AB67FFE684C0D9 /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = "<group>"; };
79DB24EE452A7CA120B56FA6 /* EmojiData.generated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiData.generated.swift; sourceTree = "<group>"; };
7E24E9328F01F2EE12120C38 /* DoubleTapDetector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoubleTapDetector.swift; sourceTree = "<group>"; };
825AC18CE5DAFBEDA0CF3209 /* VisibilityStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisibilityStore.swift; sourceTree = "<group>"; };
@@ -290,14 +295,13 @@
8C069647C67120EBAED14422 /* SnippetRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnippetRepository.swift; sourceTree = "<group>"; };
8D93A4CEA9FE857034D63EF7 /* CalcQuantity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalcQuantity.swift; sourceTree = "<group>"; };
8E6CB5CD6C0477BAC9FE383F /* CurrencyRateStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencyRateStore.swift; sourceTree = "<group>"; };
8EE6E09755C1AF3AFBA6107E /* MessageHUDController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageHUDController.swift; sourceTree = "<group>"; };
8F6F59F3C88C49BDED945F25 /* EdgeDissolve.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EdgeDissolve.swift; sourceTree = "<group>"; };
9163FDA8F7ADDEF49A62D72C /* CursorScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CursorScreen.swift; sourceTree = "<group>"; };
919AC64DE9C9DC3A973A0B4E /* HyperKeyTap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HyperKeyTap.swift; sourceTree = "<group>"; };
94507F8F095D3EBD1A9B3007 /* DialogController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DialogController.swift; sourceTree = "<group>"; };
95C105FED5D77A2392FDA3F0 /* CustomCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomCommand.swift; sourceTree = "<group>"; };
96A367CF8D256AA87C951F15 /* ClipboardCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClipboardCoordinator.swift; sourceTree = "<group>"; };
96F62D88E5BAC5F095E060B8 /* MessageHUDView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageHUDView.swift; sourceTree = "<group>"; };
97CA43885FEA5DEED2ADDC30 /* PaletteScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaletteScreen.swift; sourceTree = "<group>"; };
976A1F05AD82DB8A04B3C3F9 /* MessageHUDView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageHUDView.swift; sourceTree = "<group>"; };
98AD515E679D78C6F2A37E03 /* SearchScopesCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchScopesCard.swift; sourceTree = "<group>"; };
9965615AE9C3651FF020B2CA /* LauncherCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LauncherCoordinator.swift; sourceTree = "<group>"; };
99E3714E7C617AF4A70194BD /* SystemActionCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemActionCoordinator.swift; sourceTree = "<group>"; };
@@ -311,14 +315,12 @@
9ECE1FA4B89326C37DF12A8C /* WindowCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowCommand.swift; sourceTree = "<group>"; };
9FB750D045194AE34D39D792 /* FavoritesStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoritesStore.swift; sourceTree = "<group>"; };
A1306524F57602D90FCF153C /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; };
A5447AEAD87BFE0E2D979B39 /* PaletteWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaletteWindowController.swift; sourceTree = "<group>"; };
A75F40AED77119558D5FB4E4 /* DoubleTapMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoubleTapMonitor.swift; sourceTree = "<group>"; };
A76E4099082D59FA686C3485 /* ClipboardManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClipboardManager.swift; sourceTree = "<group>"; };
A8859C0E99A2125D85B1233C /* WindowMover.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowMover.swift; sourceTree = "<group>"; };
A90559D7DB9F6F3874CAFCDE /* VolumeHUDView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VolumeHUDView.swift; sourceTree = "<group>"; };
AA7B3EB88881CEEFCE71448D /* Permissions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Permissions.swift; sourceTree = "<group>"; };
AD0A151A3B8AC682395E621D /* DialogController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DialogController.swift; sourceTree = "<group>"; };
ADD4CE330F75BC5FE5EAD99E /* Tooltip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tooltip.swift; sourceTree = "<group>"; };
AE0379921C89CA45189533B9 /* DialogPanel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DialogPanel.swift; sourceTree = "<group>"; };
B14822405E8DA9531AFCD496 /* CustomCommandEditorSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomCommandEditorSheet.swift; sourceTree = "<group>"; };
B275099E59BD2531A838F7D8 /* AppSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettings.swift; sourceTree = "<group>"; };
B2CB30CE473AD75B16D8FA0E /* SnippetExpansionCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnippetExpansionCoordinator.swift; sourceTree = "<group>"; };
@@ -328,10 +330,14 @@
B6A96350EBE68EC79497FA2D /* AppPaths.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppPaths.swift; sourceTree = "<group>"; };
B8A9B4E6E477C30372C85F86 /* OnboardingState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingState.swift; sourceTree = "<group>"; };
BA7CE23482F7DF563A268806 /* AppIndex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppIndex.swift; sourceTree = "<group>"; };
BA9F3FA9925873D25EAF7D03 /* PalettePanel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PalettePanel.swift; sourceTree = "<group>"; };
BB94F0767AE0A5855FB22BF6 /* EmojiGridView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiGridView.swift; sourceTree = "<group>"; };
BBA661399C15362ABAE13AA5 /* PaletteViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaletteViewModel.swift; sourceTree = "<group>"; };
BBB5C3FDF5037F730E23E53D /* HotKeyBinding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HotKeyBinding.swift; sourceTree = "<group>"; };
BDB241B179A08518424F7C1B /* DialogPanel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DialogPanel.swift; sourceTree = "<group>"; };
BDC43CFF6777C11BB880F398 /* ClipboardStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClipboardStore.swift; sourceTree = "<group>"; };
BEDDA8820165672AF8464E25 /* SettingsComponents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsComponents.swift; sourceTree = "<group>"; };
C004F2C2EFDD340A73C6AB02 /* PaletteCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaletteCoordinator.swift; sourceTree = "<group>"; };
C1DE4D8B82F1D4AFB025FB24 /* SystemSettingsSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemSettingsSettingsView.swift; sourceTree = "<group>"; };
C24AD5CFE167900DF8B2705C /* CalloutShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalloutShape.swift; sourceTree = "<group>"; };
C45190564C9D9F1722E83943 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
@@ -346,21 +352,21 @@
CAE385AAF41C4CB276025211 /* RaycastImportV1.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RaycastImportV1.swift; sourceTree = "<group>"; };
CAFE92DB670B2EFA79FF9FAE /* QuicklinkEditorSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuicklinkEditorSheet.swift; sourceTree = "<group>"; };
CC35D5134516ECB65AABDC51 /* ShortcutCaptureSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutCaptureSession.swift; sourceTree = "<group>"; };
CC6173CA658DA56245031FE6 /* VolumeHUDView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VolumeHUDView.swift; sourceTree = "<group>"; };
CD3579618BC7FA235EBF9E93 /* SnippetsSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnippetsSettingsView.swift; sourceTree = "<group>"; };
CD3764D91B2F3170690A473A /* SnippetKeywordPolicy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnippetKeywordPolicy.swift; sourceTree = "<group>"; };
CEE113DF7C07BC74AD73BC4C /* UninstallRunner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UninstallRunner.swift; sourceTree = "<group>"; };
D23A98172AA46F5C0C89C4AB /* RootPaletteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootPaletteView.swift; sourceTree = "<group>"; };
D2A1D759B8FC5A4573E401B8 /* CalloutPlacement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalloutPlacement.swift; sourceTree = "<group>"; };
D30F22CD63D23FC1808878DD /* QuicklinkListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuicklinkListView.swift; sourceTree = "<group>"; };
D37B6D29E8E23C6136EBFB38 /* HotKeyManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HotKeyManager.swift; sourceTree = "<group>"; };
D8745544BFC53B27B0168CA6 /* DialogRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DialogRequest.swift; sourceTree = "<group>"; };
D9E9B0F16CFCA5E4091178AF /* SearchRelevance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchRelevance.swift; sourceTree = "<group>"; };
DABCE058D38F493D58F6E072 /* EmojiGridGeometry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiGridGeometry.swift; sourceTree = "<group>"; };
DB1752929BA1ACC0BC54865C /* HUDPanel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HUDPanel.swift; sourceTree = "<group>"; };
DB338D03EBFF94461CA42B5D /* CustomCommandCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomCommandCoordinator.swift; sourceTree = "<group>"; };
DBC4A55E96BF19A8B1D71645 /* QuicklinkStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuicklinkStore.swift; sourceTree = "<group>"; };
DFAB36FFE7E7108FB50E9134 /* VolumeSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VolumeSlider.swift; sourceTree = "<group>"; };
E0D3EBB9D877817D10D120A8 /* CalcDateTime.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalcDateTime.swift; sourceTree = "<group>"; };
E1FB75182A60F65BA1FB9BA8 /* NotificationToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationToken.swift; sourceTree = "<group>"; };
E27FB790A72ACD75DFCDFDDF /* VolumeSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VolumeSlider.swift; sourceTree = "<group>"; };
E2B3E54FBEB045D6A9866832 /* QuicklinkArgumentsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuicklinkArgumentsScreen.swift; sourceTree = "<group>"; };
E312F99D07F01172202478C6 /* RaycastFormat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RaycastFormat.swift; sourceTree = "<group>"; };
E5051622CC6497E2151326CA /* SnippetKeywordListener.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnippetKeywordListener.swift; sourceTree = "<group>"; };
@@ -408,15 +414,12 @@
children = (
C7693795CC6FB6188989435E /* Backup */,
E78667BC941556AB120FB562 /* Calculator */,
2B99F0414A1DE330B3B2C852 /* Dialog */,
E2E33C02FBE324BED2E84314 /* Emoji */,
CB742F7643800C43475DE213 /* HotKey */,
628C51FD0EF7D98347A4F185 /* HUD */,
C34A8B979D339766A184D225 /* Quicklinks */,
32B8FED93732983EAE729EB1 /* Snippets */,
FB939500E513D49DC165EA75 /* Uninstall */,
36FA7A5040272D524D70EC0E /* WindowManagement */,
3A64EF5A07D459753998F78C /* AppCore.swift */,
BA7CE23482F7DF563A268806 /* AppIndex.swift */,
5A2EF9C70F8BC9571089D5EB /* AppLauncher.swift */,
B275099E59BD2531A838F7D8 /* AppSettings.swift */,
@@ -434,8 +437,6 @@
87B6E442944C99B4D1FE1C74 /* LauncherRankingStore.swift */,
4B61608FEDD69014907AF239 /* Memo.swift */,
B8A9B4E6E477C30372C85F86 /* OnboardingState.swift */,
555E9C7EA62BDB40891A5751 /* PalettePanel.swift */,
A5447AEAD87BFE0E2D979B39 /* PaletteWindowController.swift */,
6185011A02366B30B48B5B6C /* Paster.swift */,
4B432D84D8F9C10521342199 /* RunningApps.swift */,
D9E9B0F16CFCA5E4091178AF /* SearchRelevance.swift */,
@@ -489,15 +490,6 @@
path = Scrolling;
sourceTree = "<group>";
};
1C15292CCE1BC823A1EFC60E /* Dialog */ = {
isa = PBXGroup;
children = (
72037DA506AE1A989F858C3C /* DialogView.swift */,
DFAB36FFE7E7108FB50E9134 /* VolumeSlider.swift */,
);
path = Dialog;
sourceTree = "<group>";
};
1DBBAD792549702C243871CD /* SystemActions */ = {
isa = PBXGroup;
children = (
@@ -522,16 +514,6 @@
path = DesignSystem;
sourceTree = "<group>";
};
2B99F0414A1DE330B3B2C852 /* Dialog */ = {
isa = PBXGroup;
children = (
AD0A151A3B8AC682395E621D /* DialogController.swift */,
AE0379921C89CA45189533B9 /* DialogPanel.swift */,
D8745544BFC53B27B0168CA6 /* DialogRequest.swift */,
);
path = Dialog;
sourceTree = "<group>";
};
32B8FED93732983EAE729EB1 /* Snippets */ = {
isa = PBXGroup;
children = (
@@ -569,14 +551,6 @@
path = WindowManagement;
sourceTree = "<group>";
};
4667598F175BCBB55CA88BEE /* About */ = {
isa = PBXGroup;
children = (
4802942FF89B327A76432A9B /* AboutView.swift */,
);
path = About;
sourceTree = "<group>";
};
486F4CE5090E1ABA5AC16451 /* CustomCommands */ = {
isa = PBXGroup;
children = (
@@ -607,15 +581,12 @@
path = Quicklinks;
sourceTree = "<group>";
};
628C51FD0EF7D98347A4F185 /* HUD */ = {
6D9D85B5CE38DEAF33B64137 /* About */ = {
isa = PBXGroup;
children = (
70D14EC2D7A6AE5F7CBB5028 /* HUDPanel.swift */,
55D4192BC6F5A78012027488 /* HUDPresenter.swift */,
8EE6E09755C1AF3AFBA6107E /* MessageHUDController.swift */,
6256CC7C3F15BA05A216E820 /* VolumeHUDController.swift */,
787059DAE8AB67FFE684C0D9 /* AboutView.swift */,
);
path = HUD;
path = About;
sourceTree = "<group>";
};
6F218021C90FC685A2DF21CE /* Interaction */ = {
@@ -647,40 +618,37 @@
path = Launcher;
sourceTree = "<group>";
};
83DF8416682FC5121DD7FD6E /* Dialog */ = {
isa = PBXGroup;
children = (
94507F8F095D3EBD1A9B3007 /* DialogController.swift */,
BDB241B179A08518424F7C1B /* DialogPanel.swift */,
28D150930C930F1FB5E2A31B /* DialogRequest.swift */,
32733B27AE0BD75742D1394F /* DialogView.swift */,
E27FB790A72ACD75DFCDFDDF /* VolumeSlider.swift */,
);
path = Dialog;
sourceTree = "<group>";
};
95CA98985928A88B33F82556 /* Features */ = {
isa = PBXGroup;
children = (
4667598F175BCBB55CA88BEE /* About */,
356F452DB0F8F9834817455B /* Calculator */,
005F026A8F7D5E209B1CE917 /* Clipboard */,
486F4CE5090E1ABA5AC16451 /* CustomCommands */,
1C15292CCE1BC823A1EFC60E /* Dialog */,
15CFCD6B1429C5F0944CBCC4 /* Emoji */,
B23CD0D2FE6389E18D45AD51 /* HUD */,
7DE06EE636C14E50EE172D9E /* Launcher */,
0ED457107377ECF8147C6B9D /* Onboarding */,
F84201058283B0EF6AD1248C /* Palette */,
60DCE6A46E636364E5C3B5B4 /* Quicklinks */,
E3202F504002B7792FC50B2F /* Settings */,
7CD438390F8FA4B3C2AE5F28 /* Snippets */,
1DBBAD792549702C243871CD /* SystemActions */,
5EC7DD3F09EBCC7AC71C230B /* Uninstall */,
52BD814D567DFEFD303B1750 /* PaletteRowIndex.swift */,
97CA43885FEA5DEED2ADDC30 /* PaletteScreen.swift */,
0F50886DC766B9923C3875A5 /* RootPaletteView.swift */,
);
path = Features;
sourceTree = "<group>";
};
B23CD0D2FE6389E18D45AD51 /* HUD */ = {
isa = PBXGroup;
children = (
96F62D88E5BAC5F095E060B8 /* MessageHUDView.swift */,
CC6173CA658DA56245031FE6 /* VolumeHUDView.swift */,
);
path = HUD;
sourceTree = "<group>";
};
BB6DB69437E85BCDB2530225 /* Tinycast */ = {
isa = PBXGroup;
children = (
@@ -688,7 +656,9 @@
07DE9E76AC9C944A7EC3F253 /* Core */,
1FC9BDBE6549F7189CB995AB /* DesignSystem */,
95CA98985928A88B33F82556 /* Features */,
BCE065D58E699AFB41A13CD3 /* Palette */,
02ADF9B2610482EE749E5C66 /* Platform */,
CACF5EC3FE229BE408F2449F /* Windows */,
C45190564C9D9F1722E83943 /* Assets.xcassets */,
4DA7B926405DAC632C056418 /* Info.plist */,
45D4BA6E1BD8EB1F96A8927F /* Tinycast.entitlements */,
@@ -700,12 +670,27 @@
BCD69CF996AA28C1A52C0D05 /* App */ = {
isa = PBXGroup;
children = (
2BECF24B674F9458E4A876DA /* AppCore.swift */,
9C37CCD024267EB21876C7E9 /* AppDelegate.swift */,
2B629EC3B716FEE881BB0075 /* TinycastApp.swift */,
);
path = App;
sourceTree = "<group>";
};
BCE065D58E699AFB41A13CD3 /* Palette */ = {
isa = PBXGroup;
children = (
C004F2C2EFDD340A73C6AB02 /* PaletteCoordinator.swift */,
1534DB79CC23709ABC5E9D9B /* PaletteMode.swift */,
BA9F3FA9925873D25EAF7D03 /* PalettePanel.swift */,
445B0374FD5D74DBE23243CD /* PaletteScreen.swift */,
BBA661399C15362ABAE13AA5 /* PaletteViewModel.swift */,
209D951FDD587A040F1F76F3 /* PaletteWindowController.swift */,
D23A98172AA46F5C0C89C4AB /* RootPaletteView.swift */,
);
path = Palette;
sourceTree = "<group>";
};
C34A8B979D339766A184D225 /* Quicklinks */ = {
isa = PBXGroup;
children = (
@@ -735,6 +720,17 @@
path = Backup;
sourceTree = "<group>";
};
CACF5EC3FE229BE408F2449F /* Windows */ = {
isa = PBXGroup;
children = (
6D9D85B5CE38DEAF33B64137 /* About */,
83DF8416682FC5121DD7FD6E /* Dialog */,
E33AE5825517FE9F2777C810 /* HUD */,
41A52665A3078BAAD151528C /* AuxWindowController.swift */,
);
path = Windows;
sourceTree = "<group>";
};
CB742F7643800C43475DE213 /* HotKey */ = {
isa = PBXGroup;
children = (
@@ -801,6 +797,19 @@
path = Settings;
sourceTree = "<group>";
};
E33AE5825517FE9F2777C810 /* HUD */ = {
isa = PBXGroup;
children = (
DB1752929BA1ACC0BC54865C /* HUDPanel.swift */,
31BAD6EE1BA3036C4B5A3D19 /* HUDPresenter.swift */,
2B2CB71671625A1F446316A1 /* MessageHUDController.swift */,
976A1F05AD82DB8A04B3C3F9 /* MessageHUDView.swift */,
09633E6F9C37F89267341D1D /* VolumeHUDController.swift */,
A90559D7DB9F6F3874CAFCDE /* VolumeHUDView.swift */,
);
path = HUD;
sourceTree = "<group>";
};
E78667BC941556AB120FB562 /* Calculator */ = {
isa = PBXGroup;
children = (
@@ -817,14 +826,6 @@
path = Calculator;
sourceTree = "<group>";
};
F84201058283B0EF6AD1248C /* Palette */ = {
isa = PBXGroup;
children = (
4A2BEA44C75A8072117FE13F /* PaletteCoordinator.swift */,
);
path = Palette;
sourceTree = "<group>";
};
FB939500E513D49DC165EA75 /* Uninstall */ = {
isa = PBXGroup;
children = (
@@ -920,8 +921,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4F740AF85545CF4133C89B82 /* AboutView.swift in Sources */,
97A195E9D6480418D4944560 /* AppCore.swift in Sources */,
540F1433DC46BC97C9F80E06 /* AboutView.swift in Sources */,
E8CB7624CCA5905AF1A4FAD9 /* AppCore.swift in Sources */,
C0642512B709EF0517ABF4CB /* AppDelegate.swift in Sources */,
CE15888F3C15EE2706E108A0 /* AppDisplayName.swift in Sources */,
D322804853973E1C19F2A408 /* AppIndex.swift in Sources */,
@@ -930,6 +931,7 @@
BE9EE0864C315080A4E4780F /* AppPickerPopover.swift in Sources */,
FEA05585E8AA58506D378CAF /* AppSettings.swift in Sources */,
CDBB4E26FCABEEE8817D12B2 /* ApplicationsSettingsView.swift in Sources */,
399980E533A1A83EAAA7FC6B /* AuxWindowController.swift in Sources */,
AE0D0C53004C65D65BE89B6F /* BackupActions.swift in Sources */,
8631543D8E0E008E7C541345 /* BackupSettingsView.swift in Sources */,
D3D2ACD2D94588786C2185AE /* CalcCurrency.swift in Sources */,
@@ -961,10 +963,10 @@
C526BEAA60A62E9BC78F309E /* CustomCommand.swift in Sources */,
800D542DEAB2C2F4EC8D8A11 /* CustomCommandCoordinator.swift in Sources */,
333BCB9C66380985400CD1E2 /* CustomCommandEditorSheet.swift in Sources */,
152E4A75BD2AF9279497F5FF /* DialogController.swift in Sources */,
41164F539DD16E9FFEF44F8E /* DialogPanel.swift in Sources */,
7A2C6032E0DE0346DD10A747 /* DialogRequest.swift in Sources */,
CC911DB8A6FB9EDA3BBA1AAC /* DialogView.swift in Sources */,
AB500AC3DEBFF6EB1CE42812 /* DialogController.swift in Sources */,
C215695FE671BC591DC99C2B /* DialogPanel.swift in Sources */,
9F82DA5A46BB39A6C6DD075D /* DialogRequest.swift in Sources */,
5C801A9043908577FB99A555 /* DialogView.swift in Sources */,
E5CA6385C7A7EE754A506815 /* DoubleTapDetector.swift in Sources */,
D8704A9F0BC1A55B7BE4D717 /* DoubleTapModifier.swift in Sources */,
B7274961ABF4E8F82B2D3BB7 /* DoubleTapMonitor.swift in Sources */,
@@ -981,8 +983,8 @@
24842144273FF92228540DBE /* FrequentEmojiStore.swift in Sources */,
1D0C2F452B3801503B70EA9E /* GeneralSettingsView.swift in Sources */,
AD2141EBF98A246BDA3BAB8E /* Gunzip.swift in Sources */,
CC97C121823B1DC61886BAFC /* HUDPanel.swift in Sources */,
E768AC4C8A6D6A1BA6218279 /* HUDPresenter.swift in Sources */,
A500AF3BF8910B335A7A936C /* HUDPanel.swift in Sources */,
68537C3544E4EBC40E3ACD39 /* HUDPresenter.swift in Sources */,
D58522DE2928F8087815D6BE /* HealthTicker.swift in Sources */,
5B0EFBA180AAFFBC08CC395A /* HotKeyBinding.swift in Sources */,
DEC660F280699E43AA028E8A /* HotKeyCenter.swift in Sources */,
@@ -1000,18 +1002,20 @@
99FA1235E66BDC098563957A /* LauncherScreen.swift in Sources */,
DCC36924E538C11136CEC060 /* LauncherView.swift in Sources */,
AA332C5CB997A54E7A0EA2E9 /* Memo.swift in Sources */,
5DD58D999A421873EF3F2204 /* MessageHUDController.swift in Sources */,
40EC75A7BC165783128CA9E2 /* MessageHUDView.swift in Sources */,
43DBCE7B5A84D0D6322124F5 /* MessageHUDController.swift in Sources */,
8D529C8F3AB579941067FE98 /* MessageHUDView.swift in Sources */,
8F7431A1340D0A5783599087 /* MiscellaneousSettingsView.swift in Sources */,
613827876C48EF88F2162C10 /* NotificationToken.swift in Sources */,
DA5BCA13045FF91B3FC8EB35 /* OnboardingState.swift in Sources */,
0DD808F80666846F4E74BAD8 /* OnboardingView.swift in Sources */,
D12A5F39377C352077FE85BF /* OverlayScroller.swift in Sources */,
220C7306D07B6DEA697FADC6 /* PaletteCoordinator.swift in Sources */,
9A3972BE11AE353EFBB839A0 /* PalettePanel.swift in Sources */,
86C36C0885D5820E70184CF6 /* PaletteCoordinator.swift in Sources */,
25E7E031DCF72BFF19725344 /* PaletteMode.swift in Sources */,
8090FBE343746D9D43EE2B24 /* PalettePanel.swift in Sources */,
9F8806D46EBAF7058FC2EAEC /* PaletteRowIndex.swift in Sources */,
A66E6C662757455D3669824B /* PaletteScreen.swift in Sources */,
F25D58ED6EF3308D38D01732 /* PaletteWindowController.swift in Sources */,
DB6B294B3D15B0AABCE5427E /* PaletteScreen.swift in Sources */,
1D322768F5E19354C41CC246 /* PaletteViewModel.swift in Sources */,
52C4F57BB26F420CCD22C1D7 /* PaletteWindowController.swift in Sources */,
E4B18EBFFD009B2CAFF4BA9B /* PanelTransition.swift in Sources */,
F2B68DBA258D85DD5C6DC1CC /* Paster.swift in Sources */,
94887F8E18AB2C08A8273897 /* Permissions.swift in Sources */,
@@ -1038,7 +1042,7 @@
C3C45B2E5F0D05CD6E27D34C /* RaycastSnippetImport.swift in Sources */,
B545BD845189EE893D8D8DE7 /* RaycastV1Decoder.swift in Sources */,
AD98F015439106F0E9D32015 /* RightClick.swift in Sources */,
6F08764D6CC09E9B3FD1E05A /* RootPaletteView.swift in Sources */,
47E13BC63F8BE11EDF25EA82 /* RootPaletteView.swift in Sources */,
C7DD1345A6BFB1D9EB22FCEE /* RunningApps.swift in Sources */,
31E0E4E0782A79504CEB588D /* ScrollIntent.swift in Sources */,
9A254BEE278D7B78B76553A9 /* Scrypt.swift in Sources */,
@@ -1089,10 +1093,10 @@
0962E9575CBF40B6F908031C /* UninstallView.swift in Sources */,
693E88D22D00CF6FD9CD7413 /* VisibilityStore.swift in Sources */,
9A15181AAF90211C807592E3 /* VisualEffectView.swift in Sources */,
5F107A05A7EB05204465E89D /* VolumeHUDController.swift in Sources */,
0626264D8C719DA8366B5E28 /* VolumeHUDView.swift in Sources */,
24F4BF3EA74E8E65B2B92D6D /* VolumeHUDController.swift in Sources */,
ACE645630E536C93CA102050 /* VolumeHUDView.swift in Sources */,
F7D26DE09844A5A38787CDD2 /* VolumeLevel.swift in Sources */,
B3A213551CD73CC364476E9F /* VolumeSlider.swift in Sources */,
15292937738B7CD3AE23EF73 /* VolumeSlider.swift in Sources */,
861CB0B484C44D0D9A0DB74F /* VolumeState.swift in Sources */,
C7D8BB669C3DBC0D26EB6E32 /* WindowActionMemory.swift in Sources */,
701120BCA431BF00ABDEDBD4 /* WindowCommand.swift in Sources */,
@@ -1,103 +1,5 @@
import AppKit
enum PaletteMode: String, CaseIterable, Identifiable {
case launcher
case clipboard
case calculatorHistory
case emoji
case uninstall
case quicklinks
/// Collects a quicklink's `{argument}` values before it opens; the pending request lives on
/// `AppCore.quicklinkArguments`, the way `.uninstall`'s target lives on `UninstallSession`.
case quicklinkArguments
var id: String { rawValue }
var title: String {
switch self {
case .launcher: return "Apps"
case .clipboard: return "Clipboard"
case .calculatorHistory: return "Calculator History"
case .emoji: return "Emoji & Symbols"
case .uninstall: return "Uninstall Application"
case .quicklinks: return "Quicklinks"
case .quicklinkArguments: return "Open Quicklink"
}
}
var systemImage: String {
switch self {
case .launcher: return "magnifyingglass"
case .clipboard: return "doc.on.doc"
case .calculatorHistory: return "plus.forwardslash.minus"
case .emoji: return "face.smiling"
case .uninstall: return "trash"
case .quicklinks, .quicklinkArguments: return Quicklink.sfSymbol
}
}
var placeholder: String {
switch self {
case .launcher: return "Search for apps and commands…"
case .clipboard: return "Type to filter entries…"
case .calculatorHistory: return "Do math, convert units, or search your past calculations…"
case .emoji: return "Search emoji and symbols…"
case .uninstall: return "Filter files and folders by name…"
case .quicklinks: return "Search quicklinks…"
// Replaced by the pending argument's name; only reached if the session vanished mid-render.
case .quicklinkArguments: return "Enter a value…"
}
}
}
/// The app a paste will land in, resolved once per palette show so the footer pill and menu rows can name it without re-reading `NSWorkspace` on every render.
struct PasteTarget: Equatable {
let name: String
/// Bundle path for `IconCache` — nil for a target with no on-disk bundle.
let iconPath: String?
init?(app: NSRunningApplication?) {
guard let app, let name = app.localizedName else { return nil }
self.name = name
iconPath = app.bundleURL?.path
}
var pasteTitle: String { "Paste to \(name)" }
}
/// View-model shared between the panel's SwiftUI tree and the coordinator.
@MainActor
@Observable
final class PaletteViewModel {
var mode: PaletteMode = .launcher
var query: String = ""
var selection: Int = 0
/// Changes every time the palette is shown so the search field can re-focus.
var focusToken = UUID()
/// Changes only when `prepare` resets the palette, so the lists snap their scroll to the top even when query/mode were already at their defaults (`focusToken` can't serve: it bumps on every reopen, which must preserve a within-timeout scroll).
var resetToken = UUID()
/// Changes when an action reorders the list under the selection (pinning a clip lifts it into the Pinned section), so the list scrolls the highlight back into view.
var followToken = UUID()
/// Set by the compact bar's "…" overflow to expand into the full launcher without a query; cleared on every `prepare`.
var forceExpanded = false
/// The app a paste would land in, mirrored from `PaletteWindowController.previousApp` on every show. Deliberately *not* cleared by `prepare` — pop-to-root resets the screen, not the paste target.
var pasteTarget: PasteTarget?
/// Gates the mouse-hover highlight: true only while the pointer is physically moving (armed on `.mouseMoved`, disarmed on any `.keyDown` in `PalettePanel.sendEvent`). Untracked — read at hover time, never drives a re-render.
@ObservationIgnored var hoverHighlightArmed = false
/// True while a footer popover menu (⌘K Actions or the app menu) is open, so `PalettePanel.sendEvent` swallows text-editing keystrokes the field editor would otherwise consume — the query must stay frozen while a menu owns the keyboard (matches Raycast). Untracked — read at event time, mirrored from the view's menu state.
@ObservationIgnored var menuOpen = false { didSet { onMenuOpenChanged?(menuOpen) } }
/// Fired when `menuOpen` flips so `PalettePanel` can hide/show the search field's caret while it keeps first-responder status (no focus swap, so the placeholder never reflows).
@ObservationIgnored var onMenuOpenChanged: ((Bool) -> Void)?
func prepare(mode: PaletteMode) {
self.mode = mode
query = ""
selection = 0
forceExpanded = false
hoverHighlightArmed = false
menuOpen = false
focusToken = UUID()
resetToken = UUID()
}
}
/// Single owner of every long-lived manager. Wired up once from the app delegate.
@MainActor
@Observable
+63
View File
@@ -0,0 +1,63 @@
import AppKit
enum PaletteMode: String, CaseIterable, Identifiable {
case launcher
case clipboard
case calculatorHistory
case emoji
case uninstall
case quicklinks
/// Collects a quicklink's `{argument}` values before it opens; the pending request lives on
/// `AppCore.quicklinkArguments`, the way `.uninstall`'s target lives on `UninstallSession`.
case quicklinkArguments
var id: String { rawValue }
var title: String {
switch self {
case .launcher: return "Apps"
case .clipboard: return "Clipboard"
case .calculatorHistory: return "Calculator History"
case .emoji: return "Emoji & Symbols"
case .uninstall: return "Uninstall Application"
case .quicklinks: return "Quicklinks"
case .quicklinkArguments: return "Open Quicklink"
}
}
var systemImage: String {
switch self {
case .launcher: return "magnifyingglass"
case .clipboard: return "doc.on.doc"
case .calculatorHistory: return "plus.forwardslash.minus"
case .emoji: return "face.smiling"
case .uninstall: return "trash"
case .quicklinks, .quicklinkArguments: return Quicklink.sfSymbol
}
}
var placeholder: String {
switch self {
case .launcher: return "Search for apps and commands…"
case .clipboard: return "Type to filter entries…"
case .calculatorHistory: return "Do math, convert units, or search your past calculations…"
case .emoji: return "Search emoji and symbols…"
case .uninstall: return "Filter files and folders by name…"
case .quicklinks: return "Search quicklinks…"
// Replaced by the pending argument's name; only reached if the session vanished mid-render.
case .quicklinkArguments: return "Enter a value…"
}
}
}
/// The app a paste will land in, resolved once per palette show so the footer pill and menu rows can name it without re-reading `NSWorkspace` on every render.
struct PasteTarget: Equatable {
let name: String
/// Bundle path for `IconCache` — nil for a target with no on-disk bundle.
let iconPath: String?
init?(app: NSRunningApplication?) {
guard let app, let name = app.localizedName else { return nil }
self.name = name
iconPath = app.bundleURL?.path
}
var pasteTitle: String { "Paste to \(name)" }
}
+37
View File
@@ -0,0 +1,37 @@
import Foundation
/// View-model shared between the panel's SwiftUI tree and the coordinator.
@MainActor
@Observable
final class PaletteViewModel {
var mode: PaletteMode = .launcher
var query: String = ""
var selection: Int = 0
/// Changes every time the palette is shown so the search field can re-focus.
var focusToken = UUID()
/// Changes only when `prepare` resets the palette, so the lists snap their scroll to the top even when query/mode were already at their defaults (`focusToken` can't serve: it bumps on every reopen, which must preserve a within-timeout scroll).
var resetToken = UUID()
/// Changes when an action reorders the list under the selection (pinning a clip lifts it into the Pinned section), so the list scrolls the highlight back into view.
var followToken = UUID()
/// Set by the compact bar's "…" overflow to expand into the full launcher without a query; cleared on every `prepare`.
var forceExpanded = false
/// The app a paste would land in, mirrored from `PaletteWindowController.previousApp` on every show. Deliberately *not* cleared by `prepare` — pop-to-root resets the screen, not the paste target.
var pasteTarget: PasteTarget?
/// Gates the mouse-hover highlight: true only while the pointer is physically moving (armed on `.mouseMoved`, disarmed on any `.keyDown` in `PalettePanel.sendEvent`). Untracked — read at hover time, never drives a re-render.
@ObservationIgnored var hoverHighlightArmed = false
/// True while a footer popover menu (⌘K Actions or the app menu) is open, so `PalettePanel.sendEvent` swallows text-editing keystrokes the field editor would otherwise consume — the query must stay frozen while a menu owns the keyboard (matches Raycast). Untracked — read at event time, mirrored from the view's menu state.
@ObservationIgnored var menuOpen = false { didSet { onMenuOpenChanged?(menuOpen) } }
/// Fired when `menuOpen` flips so `PalettePanel` can hide/show the search field's caret while it keeps first-responder status (no focus swap, so the placeholder never reflows).
@ObservationIgnored var onMenuOpenChanged: ((Bool) -> Void)?
func prepare(mode: PaletteMode) {
self.mode = mode
query = ""
selection = 0
forceExpanded = false
hoverHighlightArmed = false
menuOpen = false
focusToken = UUID()
resetToken = UUID()
}
}
@@ -190,82 +190,3 @@ private struct AboutLinkRow: View {
}
}
}
/// Hosts auxiliary SwiftUI windows (About, Settings), torn down on close so their SwiftUI trees deallocate instead of lingering, and rebuilt instantly on reopen from live state.
@MainActor
final class AuxWindowController: NSObject, NSWindowDelegate {
private var windows: [String: NSWindow] = [:]
/// Returns `true` when a new window was created, `false` when an existing one was re-raised.
@discardableResult
func show<Content: View>(
id: String, title: String, size: CGSize, seamlessTitleBar: Bool = false,
@ViewBuilder content: () -> Content
) -> Bool {
let window: NSWindow
let isNew: Bool
if let existing = windows[id] {
window = existing
isNew = false
} else {
isNew = true
var style: NSWindow.StyleMask = [.titled, .closable]
if seamlessTitleBar { style.insert(.fullSizeContentView) }
window = NSWindow(
contentRect: NSRect(origin: .zero, size: size),
styleMask: style,
backing: .buffered,
defer: false
)
window.title = title
// Let the content run edge-to-edge under a transparent titlebar so the window reads as one continuous surface — the modern inspector look.
if seamlessTitleBar {
window.titlebarAppearsTransparent = true
window.titleVisibility = .hidden
window.isMovableByWindowBackground = true
}
window.isReleasedWhenClosed = false
let hosting = NSHostingView(rootView: content())
// Let the window keep its requested size instead of resizing to the SwiftUI fitting size (an unconstrained fill would otherwise blow the window up); the content fills the fixed frame.
hosting.sizingOptions = []
window.contentView = hosting
window.delegate = self
window.center()
windows[id] = window
}
// Promote to a regular app so the window gets a Dock icon and normal layering; demoted back to accessory when the last aux window closes.
NSApp.setActivationPolicy(.regular)
NSApp.activate(ignoringOtherApps: true)
window.makeKeyAndOrderFront(nil)
// A plain `NSWindow` only becomes key while the app is active, but `NSApp.activate` from the menu bar is async, so the synchronous `makeKeyAndOrderFront` above can land first; re-asserting key on the next runloop makes the window truly key up front.
DispatchQueue.main.async {
window.makeKeyAndOrderFront(nil)
}
return isNew
}
/// Re-focus an open aux window on reopen (Dock-icon click); returns false when none is open. `windows` only holds live windows (`windowWillClose` prunes them).
@discardableResult
func focusExisting() -> Bool {
guard let window = windows.values.first(where: { $0.isVisible }) ?? windows.values.first
else { return false }
NSApp.setActivationPolicy(.regular)
NSApp.activate(ignoringOtherApps: true)
window.makeKeyAndOrderFront(nil)
return true
}
/// Close a window programmatically; `windowWillClose` handles the dict/teardown so the SwiftUI tree deallocates.
func close(id: String) {
windows[id]?.close()
}
func windowWillClose(_ notification: Notification) {
guard let window = notification.object as? NSWindow,
let id = windows.first(where: { $0.value === window })?.key
else { return }
windows.removeValue(forKey: id)
if windows.isEmpty { NSApp.setActivationPolicy(.accessory) }
}
}
@@ -0,0 +1,81 @@
import AppKit
import SwiftUI
/// Hosts auxiliary SwiftUI windows (About, Settings), torn down on close so their SwiftUI trees deallocate instead of lingering, and rebuilt instantly on reopen from live state.
@MainActor
final class AuxWindowController: NSObject, NSWindowDelegate {
private var windows: [String: NSWindow] = [:]
/// Returns `true` when a new window was created, `false` when an existing one was re-raised.
@discardableResult
func show<Content: View>(
id: String, title: String, size: CGSize, seamlessTitleBar: Bool = false,
@ViewBuilder content: () -> Content
) -> Bool {
let window: NSWindow
let isNew: Bool
if let existing = windows[id] {
window = existing
isNew = false
} else {
isNew = true
var style: NSWindow.StyleMask = [.titled, .closable]
if seamlessTitleBar { style.insert(.fullSizeContentView) }
window = NSWindow(
contentRect: NSRect(origin: .zero, size: size),
styleMask: style,
backing: .buffered,
defer: false
)
window.title = title
// Let the content run edge-to-edge under a transparent titlebar so the window reads as one continuous surface — the modern inspector look.
if seamlessTitleBar {
window.titlebarAppearsTransparent = true
window.titleVisibility = .hidden
window.isMovableByWindowBackground = true
}
window.isReleasedWhenClosed = false
let hosting = NSHostingView(rootView: content())
// Let the window keep its requested size instead of resizing to the SwiftUI fitting size (an unconstrained fill would otherwise blow the window up); the content fills the fixed frame.
hosting.sizingOptions = []
window.contentView = hosting
window.delegate = self
window.center()
windows[id] = window
}
// Promote to a regular app so the window gets a Dock icon and normal layering; demoted back to accessory when the last aux window closes.
NSApp.setActivationPolicy(.regular)
NSApp.activate(ignoringOtherApps: true)
window.makeKeyAndOrderFront(nil)
// A plain `NSWindow` only becomes key while the app is active, but `NSApp.activate` from the menu bar is async, so the synchronous `makeKeyAndOrderFront` above can land first; re-asserting key on the next runloop makes the window truly key up front.
DispatchQueue.main.async {
window.makeKeyAndOrderFront(nil)
}
return isNew
}
/// Re-focus an open aux window on reopen (Dock-icon click); returns false when none is open. `windows` only holds live windows (`windowWillClose` prunes them).
@discardableResult
func focusExisting() -> Bool {
guard let window = windows.values.first(where: { $0.isVisible }) ?? windows.values.first
else { return false }
NSApp.setActivationPolicy(.regular)
NSApp.activate(ignoringOtherApps: true)
window.makeKeyAndOrderFront(nil)
return true
}
/// Close a window programmatically; `windowWillClose` handles the dict/teardown so the SwiftUI tree deallocates.
func close(id: String) {
windows[id]?.close()
}
func windowWillClose(_ notification: Notification) {
guard let window = notification.object as? NSWindow,
let id = windows.first(where: { $0.value === window })?.key
else { return }
windows.removeValue(forKey: id)
if windows.isEmpty { NSApp.setActivationPolicy(.accessory) }
}
}
+4 -4
View File
@@ -9,7 +9,7 @@ System-action catalog, launcher integration and permission behavior are document
## Single-owner core
`AppCore.shared` (`Core/AppCore.swift`) is a `@MainActor` singleton that owns every long-lived
`AppCore.shared` (`App/AppCore.swift`) is a `@MainActor` singleton that owns every long-lived
manager — `AppIndex`, `ClipboardStore`, `ClipboardManager`, `SnippetsStore`,
`SnippetKeywordListener`, `SnippetTextInjector`, `HotKeyManager`, `AppSettings`, `FavoritesStore`,
`VisibilityStore`, `LauncherRankingStore`, `CustomCommandStore`, `CalculatorHistoryStore`,
@@ -25,7 +25,7 @@ launch actions are methods on `AppCore` that the SwiftUI views call.
`TinycastApp` (`@main`) declares only a `MenuBarExtra` scene; everything else visible is driven
imperatively from AppKit.
- **Command palette** — a borderless floating `NSPanel` (`Core/PalettePanel.swift`) hosting SwiftUI
- **Command palette** — a borderless floating `NSPanel` (`Palette/PalettePanel.swift`) hosting SwiftUI
via `NSHostingView`, managed by `PaletteWindowController`. It toggles between a compact bar and the
full launcher by resizing the window. `PaletteWindowController` solely owns the frame (resolved once
per show to a top-left anchor so it grows downward), and the hosting view sets `sizingOptions = []`
@@ -33,11 +33,11 @@ imperatively from AppKit.
content and the top edge drifts on the compact↔expanded swap. The panel auto-dismisses on
`windowDidResignKey`.
- **Settings / About** — plain `NSWindow`s via `AuxWindowController` (in
`Features/About/AboutView.swift`). SwiftUI `Settings` / `Window` scenes are unreliable for accessory
`Windows/AuxWindowController.swift`). SwiftUI `Settings` / `Window` scenes are unreliable for accessory
apps, so this is deliberate.
- **Dialogs** borderless `DialogPanel`s driven by `DialogController`, the app's only
presenter for confirmations, failure reports and value prompts. **HUDs** are separate:
`MessageHUDController` and `VolumeHUDController` (`Core/HUD/`), both over a shared `HUDPresenter`. `NSAlert` is deliberately unused: its
`MessageHUDController` and `VolumeHUDController` (`Windows/HUD/`), both over a shared `HUDPresenter`. `NSAlert` is deliberately unused: its
`runModal` nested run loop lets Carbon hotkeys stack dialogs, and an Aqua alert clashes with the
forced-dark surface. Presentation is `async`, so nothing blocks the main actor. See
[ui.md](ui.md#dialogs--hud).
+1 -1
View File
@@ -211,7 +211,7 @@ Update this table as phases land. `Blocked` requires a note in the phase's progr
| 25b | Complete | `refactor/25b-palette-action-coordinators` | 2026-08-06 | **M4's DoD is now literally true** — `AppCore` orchestrates no feature: 746 → 618 (−128), four coordinators, 6 → 10. Every hard gate holds — **`launch` is still one method** (`grep -c "func launch"` = 1) dispatching on `app.kind`, `PaletteWindowController` **and** `Paster` are both **absent from the diff**, `DialogController()` stays **1** with **no new façade** (the first coordinator phase since 24 that needed none), `AppCore.shared` greps empty in all five files, and `runWindowCommand` / the façade / `start()` stay put. Moves proven by direct body diff against `HEAD` as in 24 and 25, run **order-preserving rather than sorted** — sorting would hide exactly the reordering AC6 and AC9 exist to catch. Both pinned sequences byte-identical: snippets' guard → early-return → `NSApp.activate` → `confirm` → set flag → `ensureAccessibility()`, and `togglePinned` → `selectClip` → `followToken`. **AC2 not met — 618, not ~560, and the phase doc contradicts itself** the same way 25's did: its "net −195" budget ignores the forwarders it itself mandates (~51 lines) plus 4 properties, so −128 is the ceiling. But **no "no phase owns this" row remains** — of the 618, ~99 are the three palette types **28** extracts by name and ~144 are forwarders **32** deletes, leaving ~375 of composition root (class body alone: 518). `SnippetExpansionCoordinator` gained `unowned core` for the consent dialog, **abandoning 24's deliberate no-`AppCore`-reference shape**; its `showMessage` closure was left in place so every phase-24 body stays byte-identical, leaving two paths to `AppCore` for 29 or 32 to collapse. Debug **and** Release clean, 0 → 0 warnings, all 17 harnesses green, `palette-selection-test` 111,684 unchanged. **`regression.md` waived** — AC5–AC9 structural only, including all three runs the kickoff names (pinned-clip follow, skin-toned emoji, consent-before-Accessibility). **Unblocks 26, 29 and 32**; 29's feature table now needs the four new files named. |
| 26 | Complete | `refactor/26-dependency-inversions` | 2026-08-06 | **M4 closes.** All three inversions gone — `HotKeyManager` takes a `(HotKeyAction) -> String?` resolver (keeping its five static-catalog fallbacks), `collapsedModifierSymbols` is pure, `SystemActionRunner` reports through `onAsyncFailure`; three closures, no protocol, all wired once in `start()`. **AC1 not met — the grep is 6, not 0**: `Core/Backup/BackupActions.swift` is a **fourth** inversion the phase names nowhere (it postdates review §2.3), and two of its six references are the `confirm`/`showNotice` façade every coordinator since 24 deliberately keeps — operator scoped this phase to the three named sites; 29 relocates the file anyway. Two forced deviations: `collapsedModifierSymbols` needs a **fourth** `includesShift:` argument (the doc's three can't reproduce the ✦ set), and `keycaps` reads an injected `@MainActor static` **closure** rather than parameters, because `HotKeyBinding.swift` is must-not-change — a closure, not a snapshot, so a Settings toggle still re-renders every keycap. Debug **and** Release clean, 0 → 0 warnings; the three named harnesses green. Diff +60/−22 against an expected +60/−45; `project.pbxproj` unchanged. **`regression.md` waived** — AC4–AC7 structural only, including the six-owner conflict sweep the kickoff calls the one check that catches a half-wired resolver. **Unblocks 27.** |
| 27 | Complete | `refactor/27-extract-designsystem-and-platform` | 2026-08-06 | **M5 opens.** `Core/` 50 → 32 files; `DesignSystem/` (13) and `Platform/` (9) exist. **19 of 20 renames at 100 % similarity**, `EdgeDissolve` and `ThinScrollbar` among them — moved, never opened. The two extractions are byte-identical to their source hunks (`diff` against `HEAD`, not by eye) and both parent files' diffs contain **zero `+` lines**, so no `Theme` token and no cache behaviour changed; `Theme.swift`'s 85 % is the one authorised exception, and the `AppIndex`/`IconCache` pair falls below git's rename threshold so AC2's column cannot show it. `project.yml` needed no edit — XcodeGen derives sources from the directory. **AC4 unmeetable as worded**: `AGENTS.md` holds no harness command lines, so its four stale *paths* and the Project Layout section were fixed instead; the real duplicates live in `docs/snippets.md` and **`ci.yml`**, both updated — a stale path in CI is a red suite, not a stale doc. `checklists/testing.md` updated too (phase 29 requires it; 27 omits it). Debug **and** Release clean, 0 compile warnings either side, `xcodegen` idempotent, all 17 harnesses green under `set -e`, `palette-selection-test` 111,684 unchanged. Comment delta **0**. **`regression.md` waived** — AC7 structural only, including the pixel-identical screenshot pair this phase's whole claim rests on. Pre-existing defect found: `ci.yml`'s `snippets-test` line lacks `HealthTicker.swift` and has been failing since phase 10. **Unblocks 28.** |
| 28 | Not started | | | |
| 28 | Complete | `refactor/28-extract-windows-palette-and-app` | 2026-08-06 | **`Windows/` (13) and `Palette/` (7) exist; `App/` holds the composition root.** `Core/` 32 → 24 files. **16 of 16 pure moves at 100 % similarity**, `PaletteWindowController` and `PalettePanel` among them — moved, never opened; the only non-100 % entries are the two extraction parents (`AppCore` 81 %, `AboutView` 66 %), each having lost a type. All three extractions proven by `diff` against `git show HEAD:…` rather than by eye: `AuxWindowController`'s body, `AboutView`'s 192-line remainder, `PaletteMode`+`PasteTarget`, `PaletteViewModel` and `AppCore`'s 543-line remainder are **each byte-identical**, so the `DispatchQueue.main.async` key re-assertion and `windowWillClose`'s `.accessory` restore demonstrably survived. `Dialog/` and `HUD/` kept separate. `AppCore` 642 → 543. The "no harness references any file in this phase" claim was **checked before being relied on** — `ci.yml` and every harness command line unchanged. Doc paths fixed in `AGENTS.md` (2 + the Project Layout section, now carrying `Palette/` and `Windows/` bullets), `docs/architecture.md` (4) and `docs/ui.md` (2), though no AC asked; `architecture-review.md` left stale on purpose (rank 5, historical). Debug **and** Release clean, 0 → 0 warnings, `xcodegen` idempotent, all 17 harnesses green under `set -e`, `palette-selection-test` 111,684 unchanged. Comment delta **0**. **Two gaps recorded rather than papered over:** `regression.md` **not run — operator waived further testing**, and unlike 25–27 the waiver is not free here, because this phase's risks are runtime (the three aux-window focus / Dock-icon checks) rather than structural; and **AC7's pixel-identity is argued from byte-identity, not observed**. `OnboardingState.swift` **not moved** — its row is annotated "(with its view, in phase 29)", so 29 must take it to clear `Core/`. **Unblocks 29.** |
| 29 | Not started | | | |
| 30 | Not started | | | |
| 31 | Not started | | | |
@@ -0,0 +1,174 @@
# Phase 28 — Extract `Windows/`, `Palette/` and `App/`
---
## Status
| Field | Value |
| ----------------------------- | ------------------------------------------------- |
| **Status** | Complete |
| **Started** | 2026-08-06 |
| **Completed** | 2026-08-06 |
| **Operator** | abue-ammar |
| **Branch** | `refactor/28-extract-windows-palette-and-app` |
| **Commit** | single commit on the branch |
| **Claude conversations used** | 1 |
| **Actual effort** | ~15 min vs. estimate of M (2–4 h) |
---
## Completed tasks
- [x] Objective 1 — `Tinycast/Windows/` created; `Dialog/` (5 files), `HUD/` (6 files), `About/` (1) and
`AuxWindowController.swift` moved into it
- [x] Objective 2 — `Tinycast/Palette/` created; panel, controller, root view, screen protocol,
coordinator and the two extracted state files moved into it
- [x] Objective 3 — `Tinycast/App/` consolidated: `AppCore.swift` joins `TinycastApp` and `AppDelegate`
- [x] `AuxWindowController` cut out of `AboutView.swift` into `Windows/AuxWindowController.swift`
- [x] `PaletteViewModel` cut out of `AppCore.swift` into `Palette/PaletteViewModel.swift`
- [x] `PaletteMode` + `PasteTarget` cut out of `AppCore.swift` into `Palette/PaletteMode.swift`
- [x] Six emptied directories pruned
- [x] `xcodegen generate` re-run and the regenerated `project.pbxproj` staged
## Acceptance criteria
- [x] AC1 — every listed file at its new path — verified by: `git diff -M --cached --summary` shows 16
renames plus 3 creates. See _Deviations_ for `OnboardingState.swift`
- [x] AC2 — 100 % similarity for every pure move — verified by:
`git diff -M --cached --summary` shows **16 of 16** pure moves at `(100%)`; the only non-100 %
entries are the two extraction parents, `AppCore.swift (81%)` and `AboutView.swift (66%)`, which
lost a type each
- [x] AC3 — `AuxWindowController` is its own file and `AboutView.swift` no longer declares it —
verified by: `grep -c AuxWindowController` in `AboutView.swift` is 0; `AboutLink` and
`AboutLinkRow` are still there and still `private`
- [x] AC4 — the three types are out of `AppCore.swift`, which is shorter — verified by: 642 → 543 lines
- [x] AC5 — `PaletteWindowController` byte-identical — verified by:
`rename Tinycast/{Core => Palette}/PaletteWindowController.swift (100%)`. The file was never
opened. `PalettePanel.swift` is likewise 100 %
- [x] AC6 — all 17 harnesses pass, no command line changed — verified by: the `## Tests` fence of
`docs/development.md` run under `bash -e`, exit 0; `palette-selection-test` 111,684, unchanged.
The phase's "no harness references any file in this phase" claim was **checked before being
relied on** — every harness input lives in `Core/`, `DesignSystem/`, `Platform/` or
`Features/PaletteRowIndex.swift`, none of which this phase touches. `ci.yml` likewise unchanged
- [~] AC7 — Debug and Release succeed; UI pixel-identical — **builds met, pixel-identity argued not
observed.** Both configurations build clean at 0 compile warnings against a pre-phase Debug
baseline of 0. Pixel-identity was **not** visually verified: every view and panel file moved at
100 % similarity and the three extraction diffs are byte-identical to `HEAD`, so no view body,
layout token or animation curve can have changed — but no screenshot pair was taken
---
## Verification
| Checklist | Result | Notes |
| -------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `checklists/build.md` | PASS | Debug **and** Release, `CODE_SIGNING_ALLOWED=NO`. 0 → 0 compile warnings against a pre-phase Debug baseline. `xcodegen generate` twice → `project.pbxproj` identical |
| `checklists/testing.md` | PASS | All 17 harnesses, `bash -e`, exit 0. `palette-selection-test` 111,684 unchanged |
| `checklists/regression.md` | NOT RUN | **Waived by the operator**, who declined further testing. See _Issues encountered_ — this is the one gap in this phase's record and the three aux-window runtime checks are in it |
| `checklists/review.md` | PASS | Content delta proven by `diff` against `git show HEAD:…` rather than by eye, on all three extractions and both parents. Comment delta 0 |
### Measurements
Not a performance or size phase. Content delta is near zero by construction: 16 files moved with zero
changed lines, and the three extractions are byte-identical cut-and-paste.
---
## Failed tasks
None.
---
## Issues encountered
- **`regression.md` was waived, and unlike phases 25–27 that waiver is not free here.** Those phases'
waivers were sound because their acceptance criteria were structural. This phase's regression risks
are **runtime**: the `DispatchQueue.main.async` re-assertion of key status, and `windowWillClose`
restoring `.accessory`. Both survive in source verbatim — the extracted body `diff`s clean against
`HEAD`, so nothing can have been dropped — but the phase document asks for three runtime checks and
none was performed:
- open Settings **from the menu bar** and confirm you can type in it immediately
- close the last aux window and confirm the Dock icon disappears
- open Settings, then click the Dock icon, and confirm the existing window is focused, not duplicated
The byte-identity argument is strong (the failure mode this guards against is a *lost* re-assertion,
and it demonstrably was not lost) but it is not the same as having watched the window take focus.
Anyone who trips over an aux-window focus bug later should start here.
- **The emoji generator ran by accident and proved something useful.** Extracting the `## Tests` fence
of `docs/development.md` by `awk` picks up the `node Tools/gen-emoji.js` line that follows the
harnesses, so `EmojiData.generated.swift` was regenerated mid-run. It came back **byte-identical** to
the committed file, so nothing was staged — but the generator is not idempotent by contract, only in
fact, and a Unicode revision upstream would have silently dirtied the diff. Slice the fence at the
last `swiftc` line, not by `head -n`.
- **`git mv` leaves the emptied directories on disk.** Six of them (`Core/Dialog`, `Core/HUD`,
`Features/About`, `Features/Dialog`, `Features/HUD`, `Features/Palette`). Git does not track them so
nothing complains, but XcodeGen derives sources from the directory tree and a stray empty group is
noise. `find Tinycast -type d -empty -delete`.
---
## Deviations from the phase document
- **`Core/OnboardingState.swift` was not moved.** The phase's `App/` table lists it going to
`Features/Onboarding/OnboardingState.swift`, annotated _"(with its view, in phase 29)"_. Read as: the
destination is recorded here, the move happens in 29 — which is also what "Do not reorganise
`Features/` — phase 29" requires. It stays in `Core/`. **Phase 29 must move it**; it is one of the
files AC6 there depends on to delete `Core/`.
- **`Palette/PaletteViewModel.swift` imports `Foundation`, not `AppKit`.** The source file imported
`AppKit` because `PasteTarget` needs `NSRunningApplication`; the view-model needs only `UUID`. The
narrower import is the honest one and `PaletteMode.swift`, which carries `PasteTarget`, keeps
`AppKit`.
- **`Windows/AuxWindowController.swift` imports both `AppKit` and `SwiftUI`.** `show` is generic over
`View`, takes a `@ViewBuilder` and constructs an `NSHostingView`, so neither import is droppable.
- **Doc paths were updated although no acceptance criterion asked.** Phase 27 established this and its
progress note flagged stale paths as the real cost: `AGENTS.md` (2 inline paths + the Project Layout
section, which gained `Palette/` and `Windows/` bullets), `docs/architecture.md` (4) and `docs/ui.md`
(2 section headings). `docs/architecture-review.md` carries four now-stale paths and was **left
alone** deliberately — it is the historical review, rank 5 on the precedence ladder, never an
instruction.
- **The `Windows/` file count differs from the phase's table arithmetic.** The table lists
`Features/About/AboutView.swift → Windows/About/AboutView.swift` and `AuxWindowController` as
separate rows, which is what was done: `Windows/About/` holds the view, `AuxWindowController.swift`
sits at `Windows/` root next to `Dialog/` and `HUD/`. `Dialog/` and `HUD/` were **not** merged.
---
## Follow-up work
| Observation | Where | Suggested phase |
| --------------------------------------------------------------------------------------- | --------------------------------------- | ------------------------- |
| `OnboardingState.swift` still in `Core/`, by this phase's reading of its own move table | `Tinycast/Core/OnboardingState.swift` | 29 (already required) |
| `Tinycast/Core/` still holds 24 files | `Tinycast/Core/` | 29 — its AC6 deletes it |
| Four stale paths in the architecture review | `docs/architecture-review.md` 251, 643, 649, 903 | 34, with the docs pass |
| The three aux-window runtime checks this phase skipped | Settings / About / Onboarding windows | Fold into 29's regression |
---
## Rollback notes
- **Revert command:** `git revert <sha>`
- **Is a plain revert sufficient?** Yes. Pure moves plus three cut-and-paste extractions; no storage,
no persisted format, no behaviour. Re-run `xcodegen generate` after reverting.
- **Dependent phases that must also be reverted:** none yet. **29 hard-depends on this**, so reverting
after 29 lands means reverting 29 too.
- **Data risk on revert:** none.
---
## Sign-off
- [x] All acceptance criteria met — AC7 partially: builds verified, pixel-identity argued from
byte-identity rather than observed
- [ ] All four checklists passed — **three of four.** `regression.md` not run; waived by the operator
- [x] `ROADMAP.md` status table updated
- [x] Follow-ups recorded above, not fixed in this phase
- [ ] Merged to `main` — branch pushed, not merged
- [x] **Stopped.** Next phase is a separate session.
+2 -2
View File
@@ -106,7 +106,7 @@ the forced-dark environment). **Selection always beats hover** when a row is bot
---
## Panel structure — `Core/PalettePanel.swift`, `Features/RootPaletteView.swift`
## Panel structure — `Palette/PalettePanel.swift`, `Palette/RootPaletteView.swift`
- **`PalettePanel`** is a borderless `NSPanel`: `isOpaque = false`, `backgroundColor = .clear`, `.floating` level, `hasShadow`, `animationBehavior = .none`. It hosts SwiftUI via `NSHostingView`. `PaletteWindowController` centers it slightly above screen center (`+8%`) and dismisses it on `windowDidResignKey`.
- **The results layer fills the whole panel.** The header and bottom bar attach via `.safeAreaInset(edge: .top/.bottom)` as transparent overlays that float _over_ the list. The list underlaps them and dissolves at the edges.
@@ -170,7 +170,7 @@ Glass is **only** for floating controls, never the main surface.
---
## Dialogs & HUD `Core/Dialog/`, `Features/Dialog/`, `Core/HUD/`, `Features/HUD/`
## Dialogs & HUD `Windows/Dialog/`, `Windows/HUD/`
Tinycast owns its dialogs; `NSAlert` is never used. `DialogController` is owned by `AppCore` (the
sole owner rule) and is the only presenter, so every confirmation in the app looks and behaves alike.