Native macOS rebuild (Phase 1): Electron → SwiftUI - #70
Open
stefansl wants to merge 23 commits into
Open
Conversation
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JWaXeE5W5tCBX41AmYtRxW
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JWaXeE5W5tCBX41AmYtRxW
Read stderr/stdout on background queues started before proc.run()/ waitUntilExit(), joining after exit via DispatchGroup. Prevents a classic Process/Pipe deadlock when a child writes more than the OS pipe buffer before exiting. Adds a regression test exercising the failure path (non-image input) to prove stderr is still captured.
…odel Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JWaXeE5W5tCBX41AmYtRxW
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JWaXeE5W5tCBX41AmYtRxW
Replace the interim x86_64-only cjpeg and pngquant with universal
(arm64 + x86_64), statically-linked, self-contained builds so the app
runs natively on Apple Silicon without Rosetta. gifsicle was already
universal and self-contained (npm-vendored) and is carried over as-is.
- cjpeg: built from mozjpeg @ 08265790 with BUILD_SHARED_LIBS=OFF
(cjpeg-static target); links only /usr/lib/libSystem.
- pngquant: built from pngquant 3.0.3 (Rust) with PNG_STATIC=1
LCMS2_STATIC=1 to force static libpng/lcms2 on both cargo targets,
avoiding a Homebrew dylib dependency on the native arm64 slice;
links only /usr/lib/{libz,libiconv,libSystem}.
See build-tools/fetch-binaries.md for exact source commits and
rebuild commands. Verified via `swift test` against the new
binaries (all optimizer tests pass) plus lipo/otool checks.
…/bin) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JWaXeE5W5tCBX41AmYtRxW
Rewrite README build/install section for the native SwiftUI/Xcode workflow (xcodegen, build-svgo.sh, xcodebuild, swift test) and mark signing/notarization/DMG/auto-update as not yet wired up. Remove the obsolete Electron sources (main.js, renderer.js, index.html, menu/, lib/, .eslintrc.json, package.json) now that the app has no runtime npm dependency; package-lock.json was already gitignored and deleted from disk.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 1: Electron → native SwiftUI (macOS)
Rebuilds Image Shrinker as a native macOS app, replacing the Electron 11 stack. macOS-only, deployment target macOS 14, Swift/SwiftUI. Design + plan under
docs/superpowers/.Architecture
ImageShrinkerCore— a pure-logic Swift package (fully unit-tested, 14 tests, exercises the real binaries on fixtures):ImageOptimizerprotocol +ProcessRunner(shared subprocess helper, concurrent pipe draining to avoid deadlock)JpegOptimizer(cjpeg),PngOptimizer(pngquant),GifOptimizer(gifsicle) — exact legacy args preservedSvgOptimizer— svgo v3 running in JavaScriptCore (no Node; bundle built viabuild-tools/build-svgo.sh)OutputPathBuilder,OptimizerSettings,OptimizerService(dispatch by extension)project.ymlvia XcodeGen): drop zone + results list,SettingsStore(UserDefaults, legacy keys), notifications, Finder open-file + recent documents (AppModel/AppDelegate), universal binaries bundled intoContents/Resources/bin.Engines
build-tools/fetch-binaries.md). No Rosetta.Notable fixes caught in review
ProcessRunnerpipe-buffer deadlock (concurrent draining).#54guard: JPEG in-place optimize no longer truncates the original when output == input (temp-copy). Covered by a regression test.Deliberately deferred (not in this PR)
Code signing, notarization, DMG, and Sparkle auto-update — plus the optional Phase-2 native-lib swaps. TouchBar intentionally dropped.
Verification
swift test→ 14/14 pass (real binaries on fixtures).xcodegen generate && xcodebuild … build→ BUILD SUCCEEDED; app bundles the binaries, launches, and shrinks real images via the app's own paths/args.🤖 Generated with Claude Code