Compare commits

..
2 changed files with 159 additions and 24 deletions
+64 -24
View File
@@ -5,39 +5,79 @@ import ShotdeckCore
struct SettingsView: View {
@Environment(AppModel.self) private var model
private let labelWidth: CGFloat = 104
var body: some View {
Form {
Section("Hotkey") {
LabeledContent("Capture", value: "⌥⇧2 — fixed in this version")
Grid(alignment: .leading, horizontalSpacing: 12, verticalSpacing: 10) {
GridRow {
Text("Hotkey")
.font(.headline)
.frame(maxWidth: .infinity, alignment: .leading)
.gridCellColumns(2)
}
Section("Folders") {
LabeledContent("Watch folder") {
HStack(spacing: 8) {
Text(model.watchFolderURL.path)
.lineLimit(1)
.truncationMode(.middle)
.foregroundStyle(.secondary)
Button("Choose…") { model.chooseWatchFolder() }
}
}
LabeledContent("Output folder") {
HStack(spacing: 8) {
Text(model.outboxURL.path)
.lineLimit(1)
.truncationMode(.middle)
.foregroundStyle(.secondary)
Button("Choose…") { model.chooseOutboxFolder() }
}
GridRow(alignment: .firstTextBaseline) {
fieldLabel("Capture")
Text("⌥⇧2 — fixed in this version")
.foregroundStyle(.secondary)
.lineLimit(1)
.frame(maxWidth: .infinity, alignment: .leading)
.frame(minHeight: 22, alignment: .leading)
}
GridRow {
Text("Folders")
.font(.headline)
.frame(maxWidth: .infinity, alignment: .leading)
.gridCellColumns(2)
.padding(.top, 6)
}
GridRow(alignment: .center) {
fieldLabel("Watch folder")
folderValue(path: model.watchFolderURL.path) {
model.chooseWatchFolder()
}
}
Section {
GridRow(alignment: .center) {
fieldLabel("Output folder")
folderValue(path: model.outboxURL.path) {
model.chooseOutboxFolder()
}
}
GridRow {
Button("Reveal spool folder") { model.openSpoolFolder() }
.gridCellColumns(2)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.top, 4)
}
}
.padding()
.frame(width: 360)
.padding(16)
.frame(minWidth: 320, idealWidth: 360, maxWidth: 360, alignment: .leading)
.controlSize(.small)
}
private func fieldLabel(_ title: String) -> some View {
Text(title)
.lineLimit(1)
.frame(width: labelWidth, alignment: .trailing)
.gridColumnAlignment(.trailing)
.frame(minHeight: 22, alignment: .trailing)
}
private func folderValue(path: String, choose: @escaping () -> Void) -> some View {
HStack(spacing: 8) {
Text(path)
.lineLimit(1)
.truncationMode(.middle)
.foregroundStyle(.secondary)
.frame(maxWidth: .infinity, alignment: .leading)
Button("Choose…") { choose() }
}
.frame(minHeight: 22)
}
}
extension AppModel: SettingsWindowPresenting {
+95
View File
@@ -0,0 +1,95 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"
APP_BUNDLE="${ROOT}/.build/Shotdeck.app"
STAGING="${ROOT}/.build/dmg-staging"
DMG="${ROOT}/.build/Shotdeck.dmg"
MOUNT_POINT="${ROOT}/.build/dmg-mnt"
SKIP_SIGN=0
for arg in "$@"; do
case "${arg}" in
--skip-sign)
SKIP_SIGN=1
;;
*)
echo "Unknown argument: ${arg}" >&2
echo "Usage: $0 [--skip-sign]" >&2
exit 1
;;
esac
done
echo "==> Building Shotdeck.app"
if [[ "${SKIP_SIGN}" -eq 1 ]]; then
./scripts/build-app.sh --skip-sign
else
./scripts/build-app.sh
fi
if [[ ! -d "${APP_BUNDLE}" ]]; then
echo "App bundle not found at ${APP_BUNDLE}" >&2
exit 1
fi
echo "==> Staging DMG contents"
rm -rf "${STAGING}"
mkdir -p "${STAGING}"
ditto "${APP_BUNDLE}" "${STAGING}/Shotdeck.app"
ln -s /Applications "${STAGING}/Applications"
echo "==> Creating ${DMG}"
mkdir -p "$(dirname "${DMG}")"
hdiutil create -volname "Shotdeck" -srcfolder "${STAGING}" -ov -format UDZO "${DMG}"
MOUNTED=0
detach_dmg() {
if [[ "${MOUNTED}" -eq 1 ]]; then
hdiutil detach "${MOUNT_POINT}" || hdiutil detach "${MOUNT_POINT}" -force || true
MOUNTED=0
fi
}
trap detach_dmg EXIT
if [[ -d "${MOUNT_POINT}" ]] && /sbin/mount | grep -F -q "${MOUNT_POINT}"; then
hdiutil detach "${MOUNT_POINT}" || hdiutil detach "${MOUNT_POINT}" -force
fi
rm -rf "${MOUNT_POINT}"
mkdir -p "${MOUNT_POINT}"
echo "==> Verifying ${DMG}"
hdiutil attach "${DMG}" -nobrowse -readonly -mountpoint "${MOUNT_POINT}"
MOUNTED=1
echo "==> Mount contents"
ls -la "${MOUNT_POINT}"
if [[ ! -d "${MOUNT_POINT}/Shotdeck.app" ]]; then
echo "Verification failed: Shotdeck.app missing from mounted DMG" >&2
exit 1
fi
if [[ ! -L "${MOUNT_POINT}/Applications" ]]; then
echo "Verification failed: Applications symlink missing from mounted DMG" >&2
exit 1
fi
if [[ "$(readlink "${MOUNT_POINT}/Applications")" != "/Applications" ]]; then
echo "Verification failed: Applications does not point at /Applications" >&2
exit 1
fi
echo "==> codesign --verify --deep"
codesign --verify --deep --verbose=2 "${MOUNT_POINT}/Shotdeck.app"
echo "==> Detaching ${MOUNT_POINT}"
hdiutil detach "${MOUNT_POINT}"
MOUNTED=0
trap - EXIT
SHA256="$(shasum -a 256 "${DMG}" | awk '{print $1}')"
echo
echo "DMG path: ${DMG}"
echo "SHA256: ${SHA256}"