Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/build-dmg.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Build DMG

on:
workflow_dispatch:
pull_request:
push:
branches:
- main

permissions:
contents: read

jobs:
build-dmg:
runs-on: macos-15

steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "22"

- name: Build DMG
run: make dmg

- name: Upload DMG artifact
uses: actions/upload-artifact@v4
with:
name: CroPDF-dmg
path: dist/CroPDF.dmg
if-no-files-found: error
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.DS_Store
/.build
/dist
/Packages
xcuserdata/
DerivedData/
Expand Down
30 changes: 30 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
APP_NAME := CroPDF
EXECUTABLE := CroPDFMacOS
CONFIGURATION ?= release
DIST_DIR := $(CURDIR)/dist
APP_DIR := $(DIST_DIR)/$(APP_NAME).app
CONTENTS_DIR := $(APP_DIR)/Contents
MACOS_DIR := $(CONTENTS_DIR)/MacOS
RESOURCES_DIR := $(CONTENTS_DIR)/Resources
DMG_PATH := $(DIST_DIR)/$(APP_NAME).dmg
CREATE_DMG_VERSION ?= 8.0.0

.PHONY: dmg clean

dmg:
@set -euo pipefail; \
swift build --disable-sandbox -c "$(CONFIGURATION)"; \
BIN_DIR="$$(swift build --disable-sandbox -c "$(CONFIGURATION)" --show-bin-path)"; \
rm -rf "$(APP_DIR)"; \
mkdir -p "$(MACOS_DIR)" "$(RESOURCES_DIR)"; \
cp "$$BIN_DIR/$(EXECUTABLE)" "$(MACOS_DIR)/$(EXECUTABLE)"; \
cp -R "$$BIN_DIR/$(EXECUTABLE)_$(EXECUTABLE).bundle" "$(RESOURCES_DIR)/$(EXECUTABLE)_$(EXECUTABLE).bundle"; \
cp "$(CURDIR)/src/Resources/$(APP_NAME).icns" "$(RESOURCES_DIR)/$(APP_NAME).icns"; \
cp "$(CURDIR)/scripts/Info.plist" "$(CONTENTS_DIR)/Info.plist"; \
rm -f "$(DMG_PATH)"; \
npx --yes "create-dmg@$(CREATE_DMG_VERSION)" --overwrite --no-version-in-filename --no-code-sign "$(APP_DIR)" "$(DIST_DIR)"; \
rm -rf "$(APP_DIR)"; \
echo "Built $(DMG_PATH)"

clean:
rm -rf "$(DIST_DIR)"
5 changes: 4 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ let package = Package(
targets: [
.executableTarget(
name: "CroPDFMacOS",
path: "src"
path: "src",
resources: [
.process("Resources"),
]
),
]
)
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,17 @@ swift run CroPDFMacOS /path/to/file.pdf --page 12
```

You can also open the package directly in Xcode and run it as a macOS app target.

## Package As .app

There is no dedicated `.app` packaging command anymore. The supported packaging output is the DMG.

## Package As .dmg

```bash
make dmg
```

This builds a temporary app bundle, packages it with `create-dmg`, and leaves you with `dist/CroPDF.dmg`. The intermediate `dist/CroPDF.app` is removed automatically.

`Node.js` and `npm` are required for the DMG step because the script downloads `create-dmg` on demand.
120 changes: 120 additions & 0 deletions assets/CroPDF.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 30 additions & 0 deletions scripts/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>CroPDFMacOS</string>
<key>CFBundleIconFile</key>
<string>CroPDF</string>
<key>CFBundleIdentifier</key>
<string>com.ericceglie.CroPDF</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>CroPDF</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>14.0</string>
<key>NSHighResolutionCapable</key>
<true/>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>
20 changes: 20 additions & 0 deletions src/CroPDFMacOSApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,30 @@ import SwiftUI

final class CroPDFAppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ notification: Notification) {
if let iconImage = appIconImage() {
NSApp.applicationIconImage = iconImage
}

NSApp.setActivationPolicy(.regular)
NSApp.activate(ignoringOtherApps: true)
NSApp.windows.first?.makeKeyAndOrderFront(nil)
}

private func appIconImage() -> NSImage? {
let candidates = [
("CroPDF", "icns"),
("CroPDFIcon", "png"),
]

for (name, ext) in candidates {
if let iconURL = Bundle.module.url(forResource: name, withExtension: ext),
let iconImage = NSImage(contentsOf: iconURL) {
return iconImage
}
}

return nil
}
}

@main
Expand Down
Binary file added src/Resources/CroPDF.icns
Binary file not shown.
Binary file added src/Resources/CroPDFIcon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading