diff --git a/package.json b/package.json index fe1434f..5ca7d4c 100644 --- a/package.json +++ b/package.json @@ -3,19 +3,18 @@ "private": true, "packageManager": "pnpm@10.18.1", "scripts": { - "swift:doctor": "tsswift doctor --path SocialIO/SocialIO.xcodeproj", - "swift:emulators": "tsswift emulators --path SocialIO/SocialIO.xcodeproj", - "swift:build": "tsswift build --path SocialIO/SocialIO.xcodeproj", - "swift:build:macos": "tsswift build --path SocialIO/SocialIO.xcodeproj --platform macos", - "swift:test": "tsswift test --path SocialIO/SocialIO.xcodeproj", - "swift:run": "tsswift run --path SocialIO/SocialIO.xcodeproj", - "swift:watch": "tsswift watch --path SocialIO/SocialIO.xcodeproj", - "swift:launch": "tsswift launch --path SocialIO/SocialIO.xcodeproj", - "swift:command:inbox": "tsswift command --path SocialIO/SocialIO.xcodeproj --route socialio://mailbox/inbox", - "swift:screenshots:ios": "tsswift screenshots --path SocialIO/SocialIO.xcodeproj --platform ios", - "swift:screenshots:ipad": "tsswift screenshots --path SocialIO/SocialIO.xcodeproj --platform ipad", - "swift:screenshots:macos": "tsswift screenshots --path SocialIO/SocialIO.xcodeproj --platform macos", - "swift:review": "tsswift review --path SocialIO/SocialIO.xcodeproj" + "swift:doctor": "tsswift doctor --path swiftapp/SocialIO.xcodeproj", + "swift:emulators": "tsswift emulators --path swiftapp/SocialIO.xcodeproj", + "swift:build": "tsswift build --path swiftapp/SocialIO.xcodeproj", + "swift:build:macos": "tsswift build --path swiftapp/SocialIO.xcodeproj --platform macos", + "swift:test": "tsswift test --path swiftapp/SocialIO.xcodeproj", + "swift:run": "tsswift run --path swiftapp/SocialIO.xcodeproj", + "swift:launch": "tsswift launch --path swiftapp/SocialIO.xcodeproj", + "swift:command:inbox": "tsswift command --path swiftapp/SocialIO.xcodeproj --route socialio://mailbox/inbox", + "swift:screenshots:ios": "tsswift screenshots --path swiftapp/SocialIO.xcodeproj --platform ios", + "swift:screenshots:ipad": "tsswift screenshots --path swiftapp/SocialIO.xcodeproj --platform ipad", + "swift:screenshots:macos": "tsswift screenshots --path swiftapp/SocialIO.xcodeproj --platform macos", + "swift:review": "tsswift review --path swiftapp/SocialIO.xcodeproj" }, "devDependencies": { "@git.zone/tsswift": "0.3.0" diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..6523845 --- /dev/null +++ b/readme.md @@ -0,0 +1,141 @@ +# SocialIO Swift App + +Multiplatform SwiftUI mail client scaffold for macOS, iPadOS, and iOS. + +## What is included + +- One shared SwiftUI app target +- Mocked mail backend with seeded conversations +- Three-column mail UI that adapts across Apple platforms +- Compose flow, search, unread filters, favorites, and message detail +- Backend-driven navigation hooks for mailboxes, threads, and compose flows +- Screenshot/test automation route IDs and accessibility identifiers + +## Open the project + +1. Install/select full Xcode on this Mac. +2. Open `swiftapp/SocialIO.xcodeproj`. +3. Build the `SocialIO` scheme for: + - `My Mac` + - an iPad simulator + - an iPhone simulator + +## tsswift workflow + +From the repo root: + +```bash +corepack pnpm install +corepack pnpm swift:doctor +corepack pnpm swift:emulators +corepack pnpm swift:build +corepack pnpm swift:test +corepack pnpm swift:run +corepack pnpm swift:launch +corepack pnpm swift:review +``` + +This repo now uses `@git.zone/tsswift` with project config in `swiftapp/.smartconfig.json`. + +- `build` targets macOS, iPhone Simulator, and iPad Simulator in parallel +- `test` targets macOS, which matches the current test bundle setup +- `run` defaults to macOS unless you pass `--platform ios` or `--platform ipad` +- `launch` starts the app with the configured control-file transport enabled +- `review` replaces the old shell-script review loop and captures screenshot sets for iPhone, iPad, and macOS + +Useful direct commands: + +```bash +corepack pnpm exec tsswift prefer-emulator --path swiftapp/SocialIO.xcodeproj --platform ios --udid +corepack pnpm exec tsswift prefer-emulator --path swiftapp/SocialIO.xcodeproj --platform ipad --udid +corepack pnpm exec tsswift command --path swiftapp/SocialIO.xcodeproj --route 'socialio://open?thread=launch-copy&message=launch-copy-2' +``` + +## App control contract + +The app can be driven in three ways: + +- Launch with `SOCIALIO_ROUTE` +- Launch with `SOCIALIO_COMMAND_JSON` +- Keep a running app subscribed to a mocked backend control file with `SOCIALIO_CONTROL_FILE` + +### Deep link examples + +```text +socialio://mailbox/inbox +socialio://mailbox/starred?unreadOnly=true +socialio://thread/launch-copy +socialio://open?thread=launch-copy&message=launch-copy-2 +socialio://compose?to=grandma@example.com&subject=Family%20Photos&body=Hi%20Grandma +``` + +### JSON command examples + +```json +{"kind":"mailbox","mailbox":"archive","search":"roadmap"} +{"kind":"thread","threadID":"launch-copy","messageID":"launch-copy-2"} +{"kind":"compose","to":"grandma@example.com","subject":"Family Photos","body":"Hi Grandma"} +``` + +### Stable mock route IDs + +- Threads: `launch-copy`, `daily-sync-status`, `investor-update`, `search-ranking-polish`, `welcome-to-socialio`, `roadmap-notes` +- Messages: `launch-copy-1`, `launch-copy-2`, `investor-update-1`, `roadmap-notes-1`, and similar seeded IDs + +## Mock backend control + +When `SOCIALIO_CONTROL_FILE` points at a text file, the running app polls it and applies the latest command whenever the file contents change. + +Examples: + +```bash +echo 'socialio://open?thread=launch-copy&message=launch-copy-2' > /tmp/socialio-control.txt +echo '{"kind":"compose","to":"grandma@example.com","subject":"Photos","body":"Hi Grandma"}' > /tmp/socialio-control.txt +``` + +That gives us a mocked backend transport now, and we can swap the same command model behind a real API later. + +## Screenshot automation + +Single-platform capture examples: + +```bash +corepack pnpm swift:screenshots:ios +corepack pnpm swift:screenshots:ipad +corepack pnpm swift:screenshots:macos +``` + +The route list now lives in `swiftapp/Automation/ui-screenshot-routes.txt`. + +## Standard UI review loop + +For UI-affecting changes, use: + +```bash +corepack pnpm swift:review +``` + +That flow now: + +- builds and captures an iPhone review pass +- builds and captures an iPad review pass +- builds and captures a macOS review pass +- saves the review set to `/tmp/socialio-ui-review/ios`, `/tmp/socialio-ui-review/ipad`, and `/tmp/socialio-ui-review/macos` + +Simulator selection is now handled through `tsswift emulators` and `tsswift prefer-emulator`, and the chosen devices are written into `swiftapp/.smartconfig.json`. + +The macOS capture path still needs Accessibility and Screen Recording permission for the terminal app that runs the command, because `tsswift` positions the app window before each screenshot. + +## UI test hooks + +Key controls now expose stable accessibility identifiers such as: + +- `mailbox.inbox` +- `filter.unread` +- `thread.launch-copy` +- `message.launch-copy-2` +- `compose.view` +- `compose.to` +- `compose.subject` +- `compose.body` +- `compose.send` diff --git a/SocialIO/.smartconfig.json b/swiftapp/.smartconfig.json similarity index 94% rename from SocialIO/.smartconfig.json rename to swiftapp/.smartconfig.json index 4aea5f6..5007b6f 100644 --- a/SocialIO/.smartconfig.json +++ b/swiftapp/.smartconfig.json @@ -7,8 +7,6 @@ "parallelTests": false, "buildPlatforms": ["macos", "ios", "ipad"], "testPlatforms": ["macos"], - "watchPlatforms": ["macos", "ios", "ipad"], - "watchDebounceMs": 1200, "defaultPlatform": "macos", "app": { "bundleId": "io.social.app" diff --git a/SocialIO/Automation/ui-screenshot-routes.txt b/swiftapp/Automation/ui-screenshot-routes.txt similarity index 100% rename from SocialIO/Automation/ui-screenshot-routes.txt rename to swiftapp/Automation/ui-screenshot-routes.txt diff --git a/SocialIO/SocialIO.xcodeproj/project.pbxproj b/swiftapp/SocialIO.xcodeproj/project.pbxproj similarity index 100% rename from SocialIO/SocialIO.xcodeproj/project.pbxproj rename to swiftapp/SocialIO.xcodeproj/project.pbxproj diff --git a/SocialIO/SocialIO.xcodeproj/xcshareddata/xcschemes/SocialIO.xcscheme b/swiftapp/SocialIO.xcodeproj/xcshareddata/xcschemes/SocialIO.xcscheme similarity index 100% rename from SocialIO/SocialIO.xcodeproj/xcshareddata/xcschemes/SocialIO.xcscheme rename to swiftapp/SocialIO.xcodeproj/xcshareddata/xcschemes/SocialIO.xcscheme diff --git a/SocialIO/Sources/App/AppControlService.swift b/swiftapp/Sources/App/AppControlService.swift similarity index 100% rename from SocialIO/Sources/App/AppControlService.swift rename to swiftapp/Sources/App/AppControlService.swift diff --git a/SocialIO/Sources/App/AppNavigationCommand.swift b/swiftapp/Sources/App/AppNavigationCommand.swift similarity index 100% rename from SocialIO/Sources/App/AppNavigationCommand.swift rename to swiftapp/Sources/App/AppNavigationCommand.swift diff --git a/SocialIO/Sources/App/AppViewModel.swift b/swiftapp/Sources/App/AppViewModel.swift similarity index 100% rename from SocialIO/Sources/App/AppViewModel.swift rename to swiftapp/Sources/App/AppViewModel.swift diff --git a/SocialIO/Sources/App/SocialIOApp.swift b/swiftapp/Sources/App/SocialIOApp.swift similarity index 100% rename from SocialIO/Sources/App/SocialIOApp.swift rename to swiftapp/Sources/App/SocialIOApp.swift diff --git a/SocialIO/Sources/Core/Models/MailModels.swift b/swiftapp/Sources/Core/Models/MailModels.swift similarity index 100% rename from SocialIO/Sources/Core/Models/MailModels.swift rename to swiftapp/Sources/Core/Models/MailModels.swift diff --git a/SocialIO/Sources/Core/Services/MockMailService.swift b/swiftapp/Sources/Core/Services/MockMailService.swift similarity index 100% rename from SocialIO/Sources/Core/Services/MockMailService.swift rename to swiftapp/Sources/Core/Services/MockMailService.swift diff --git a/SocialIO/Sources/Features/Mail/MailRootView.swift b/swiftapp/Sources/Features/Mail/MailRootView.swift similarity index 100% rename from SocialIO/Sources/Features/Mail/MailRootView.swift rename to swiftapp/Sources/Features/Mail/MailRootView.swift diff --git a/SocialIO/Tests/AppNavigationCommandTests.swift b/swiftapp/Tests/AppNavigationCommandTests.swift similarity index 100% rename from SocialIO/Tests/AppNavigationCommandTests.swift rename to swiftapp/Tests/AppNavigationCommandTests.swift diff --git a/SocialIO/Tests/AppViewModelTests.swift b/swiftapp/Tests/AppViewModelTests.swift similarity index 100% rename from SocialIO/Tests/AppViewModelTests.swift rename to swiftapp/Tests/AppViewModelTests.swift