diff --git a/.gitignore b/.gitignore
index c564a37..c299087 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,6 @@
*.tmproj
.DS_Store
-*.app.log
+*.log
+**/xcuserdata/**
+buck-out
+.build
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..eba966a
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,5 @@
+{
+ "[plist]": {
+ "editor.formatOnSave": false
+ }
+}
diff --git a/Appify UI 2011.app/Contents/Info.plist b/Create Appify UI.app/Contents/Info.plist
similarity index 100%
rename from Appify UI 2011.app/Contents/Info.plist
rename to Create Appify UI.app/Contents/Info.plist
diff --git a/Appify UI 2011 Demo.app/Contents/MacOS/apache-callback-mac b/Create Appify UI.app/Contents/MacOS/apache-callback-mac
similarity index 100%
rename from Appify UI 2011 Demo.app/Contents/MacOS/apache-callback-mac
rename to Create Appify UI.app/Contents/MacOS/apache-callback-mac
diff --git a/Appify UI 2011.app/Contents/MacOS/appify-ui.sh b/Create Appify UI.app/Contents/MacOS/appify-ui.sh
similarity index 100%
rename from Appify UI 2011.app/Contents/MacOS/appify-ui.sh
rename to Create Appify UI.app/Contents/MacOS/appify-ui.sh
diff --git a/Appify AI.app/Contents/Resources/English.lproj/MainMenu.nib b/Create Appify UI.app/Contents/Resources/English.lproj/MainMenu.nib
similarity index 100%
rename from Appify AI.app/Contents/Resources/English.lproj/MainMenu.nib
rename to Create Appify UI.app/Contents/Resources/English.lproj/MainMenu.nib
diff --git a/Create Appify UI.app/Contents/Resources/index.html b/Create Appify UI.app/Contents/Resources/index.html
new file mode 100644
index 0000000..3a69c85
--- /dev/null
+++ b/Create Appify UI.app/Contents/Resources/index.html
@@ -0,0 +1,66 @@
+
+
Appify
+
+
+
+
+
+
+
+
diff --git a/Appify AI.app/Contents/Info.plist b/Example Apps/Appify AI.app/Contents/Info.plist
similarity index 100%
rename from Appify AI.app/Contents/Info.plist
rename to Example Apps/Appify AI.app/Contents/Info.plist
diff --git a/Appify AI.app/Contents/MacOS/appify-ui-webview b/Example Apps/Appify AI.app/Contents/MacOS/appify-ui-webview
similarity index 100%
rename from Appify AI.app/Contents/MacOS/appify-ui-webview
rename to Example Apps/Appify AI.app/Contents/MacOS/appify-ui-webview
diff --git a/Appify AI.app/Contents/MacOS/main.sh b/Example Apps/Appify AI.app/Contents/MacOS/main.sh
similarity index 100%
rename from Appify AI.app/Contents/MacOS/main.sh
rename to Example Apps/Appify AI.app/Contents/MacOS/main.sh
diff --git a/Appify UI 2011 Demo.app/Contents/Resources/English.lproj/MainMenu.nib b/Example Apps/Appify AI.app/Contents/Resources/English.lproj/MainMenu.nib
similarity index 100%
rename from Appify UI 2011 Demo.app/Contents/Resources/English.lproj/MainMenu.nib
rename to Example Apps/Appify AI.app/Contents/Resources/English.lproj/MainMenu.nib
diff --git a/Appify AI.app/Contents/Resources/Node not found Error.html b/Example Apps/Appify AI.app/Contents/Resources/Node not found Error.html
similarity index 100%
rename from Appify AI.app/Contents/Resources/Node not found Error.html
rename to Example Apps/Appify AI.app/Contents/Resources/Node not found Error.html
diff --git a/Appify AI.app/Contents/Resources/app/lib/http-webview.js b/Example Apps/Appify AI.app/Contents/Resources/app/lib/http-webview.js
similarity index 100%
rename from Appify AI.app/Contents/Resources/app/lib/http-webview.js
rename to Example Apps/Appify AI.app/Contents/Resources/app/lib/http-webview.js
diff --git a/Appify AI.app/Contents/Resources/app/lib/webview.js b/Example Apps/Appify AI.app/Contents/Resources/app/lib/webview.js
similarity index 100%
rename from Appify AI.app/Contents/Resources/app/lib/webview.js
rename to Example Apps/Appify AI.app/Contents/Resources/app/lib/webview.js
diff --git a/Appify AI.app/Contents/Resources/app/main.js b/Example Apps/Appify AI.app/Contents/Resources/app/main.js
similarity index 100%
rename from Appify AI.app/Contents/Resources/app/main.js
rename to Example Apps/Appify AI.app/Contents/Resources/app/main.js
diff --git a/Appify UI 2011 Demo.app/Contents/Info.plist b/Example Apps/Appify UI 2011 Demo.app/Contents/Info.plist
similarity index 100%
rename from Appify UI 2011 Demo.app/Contents/Info.plist
rename to Example Apps/Appify UI 2011 Demo.app/Contents/Info.plist
diff --git a/Appify UI 2011.app/Contents/MacOS/apache-callback-mac b/Example Apps/Appify UI 2011 Demo.app/Contents/MacOS/apache-callback-mac
similarity index 100%
rename from Appify UI 2011.app/Contents/MacOS/apache-callback-mac
rename to Example Apps/Appify UI 2011 Demo.app/Contents/MacOS/apache-callback-mac
diff --git a/Appify UI 2011 Demo.app/Contents/MacOS/app.sh b/Example Apps/Appify UI 2011 Demo.app/Contents/MacOS/app.sh
similarity index 100%
rename from Appify UI 2011 Demo.app/Contents/MacOS/app.sh
rename to Example Apps/Appify UI 2011 Demo.app/Contents/MacOS/app.sh
diff --git a/Appify UI 2011 Deno Demo.app/Contents/Resources/English.lproj/MainMenu.nib b/Example Apps/Appify UI 2011 Demo.app/Contents/Resources/English.lproj/MainMenu.nib
similarity index 100%
rename from Appify UI 2011 Deno Demo.app/Contents/Resources/English.lproj/MainMenu.nib
rename to Example Apps/Appify UI 2011 Demo.app/Contents/Resources/English.lproj/MainMenu.nib
diff --git a/Appify UI 2011 Demo.app/Contents/Resources/index.html b/Example Apps/Appify UI 2011 Demo.app/Contents/Resources/index.html
similarity index 100%
rename from Appify UI 2011 Demo.app/Contents/Resources/index.html
rename to Example Apps/Appify UI 2011 Demo.app/Contents/Resources/index.html
diff --git a/Appify UI 2011 Deno Demo.app/Contents/.vscode/settings.json b/Example Apps/Appify UI 2011 Deno Demo.app/Contents/.vscode/settings.json
similarity index 100%
rename from Appify UI 2011 Deno Demo.app/Contents/.vscode/settings.json
rename to Example Apps/Appify UI 2011 Deno Demo.app/Contents/.vscode/settings.json
diff --git a/Appify UI 2011 Deno Demo.app/Contents/Info.plist b/Example Apps/Appify UI 2011 Deno Demo.app/Contents/Info.plist
similarity index 100%
rename from Appify UI 2011 Deno Demo.app/Contents/Info.plist
rename to Example Apps/Appify UI 2011 Deno Demo.app/Contents/Info.plist
diff --git a/Appify UI 2011 Deno Demo.app/Contents/MacOS/appify-ui-webview b/Example Apps/Appify UI 2011 Deno Demo.app/Contents/MacOS/appify-ui-webview
similarity index 100%
rename from Appify UI 2011 Deno Demo.app/Contents/MacOS/appify-ui-webview
rename to Example Apps/Appify UI 2011 Deno Demo.app/Contents/MacOS/appify-ui-webview
diff --git a/Appify UI 2011 Deno Demo.app/Contents/MacOS/main.sh b/Example Apps/Appify UI 2011 Deno Demo.app/Contents/MacOS/main.sh
similarity index 100%
rename from Appify UI 2011 Deno Demo.app/Contents/MacOS/main.sh
rename to Example Apps/Appify UI 2011 Deno Demo.app/Contents/MacOS/main.sh
diff --git a/Appify UI 2011 Deno Demo.app/Contents/Resources/Deno not found Error.html b/Example Apps/Appify UI 2011 Deno Demo.app/Contents/Resources/Deno not found Error.html
similarity index 100%
rename from Appify UI 2011 Deno Demo.app/Contents/Resources/Deno not found Error.html
rename to Example Apps/Appify UI 2011 Deno Demo.app/Contents/Resources/Deno not found Error.html
diff --git a/Appify UI 2011 Node Demo.app/Contents/Resources/English.lproj/MainMenu.nib b/Example Apps/Appify UI 2011 Deno Demo.app/Contents/Resources/English.lproj/MainMenu.nib
similarity index 100%
rename from Appify UI 2011 Node Demo.app/Contents/Resources/English.lproj/MainMenu.nib
rename to Example Apps/Appify UI 2011 Deno Demo.app/Contents/Resources/English.lproj/MainMenu.nib
diff --git a/Appify UI 2011 Deno Demo.app/Contents/Resources/app/lib/html.ts b/Example Apps/Appify UI 2011 Deno Demo.app/Contents/Resources/app/lib/html.ts
similarity index 100%
rename from Appify UI 2011 Deno Demo.app/Contents/Resources/app/lib/html.ts
rename to Example Apps/Appify UI 2011 Deno Demo.app/Contents/Resources/app/lib/html.ts
diff --git a/Appify UI 2011 Deno Demo.app/Contents/Resources/app/lib/http-webview.ts b/Example Apps/Appify UI 2011 Deno Demo.app/Contents/Resources/app/lib/http-webview.ts
similarity index 94%
rename from Appify UI 2011 Deno Demo.app/Contents/Resources/app/lib/http-webview.ts
rename to Example Apps/Appify UI 2011 Deno Demo.app/Contents/Resources/app/lib/http-webview.ts
index d55af77..b4ecf12 100644
--- a/Appify UI 2011 Deno Demo.app/Contents/Resources/app/lib/http-webview.ts
+++ b/Example Apps/Appify UI 2011 Deno Demo.app/Contents/Resources/app/lib/http-webview.ts
@@ -1,8 +1,8 @@
const __filename = decodeURIComponent(new URL(import.meta.url).pathname)
const __dirname = __filename.slice(0, __filename.lastIndexOf("/"))
-import { open } from "./webview.ts"
import { type Handler, Server } from "https://deno.land/std@0.182.0/http/server.ts"
+import { open } from "./webview.ts"
export function create(handler: Handler) {
let port = 8444
@@ -22,7 +22,7 @@ export function create(handler: Handler) {
return server
}
-import { html, css } from "./html.ts"
+import { css, html } from "./html.ts"
if (import.meta.main) {
console.log("webview works?")
@@ -32,6 +32,7 @@ if (import.meta.main) {
const styles = css`
:root {
+ color-scheme: light dark;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans",
"Helvetica Neue", sans-serif;
}
diff --git a/Appify UI 2011 Deno Demo.app/Contents/Resources/app/lib/webview.html b/Example Apps/Appify UI 2011 Deno Demo.app/Contents/Resources/app/lib/webview.html
similarity index 100%
rename from Appify UI 2011 Deno Demo.app/Contents/Resources/app/lib/webview.html
rename to Example Apps/Appify UI 2011 Deno Demo.app/Contents/Resources/app/lib/webview.html
diff --git a/Appify UI 2011 Deno Demo.app/Contents/Resources/app/lib/webview.ts b/Example Apps/Appify UI 2011 Deno Demo.app/Contents/Resources/app/lib/webview.ts
similarity index 100%
rename from Appify UI 2011 Deno Demo.app/Contents/Resources/app/lib/webview.ts
rename to Example Apps/Appify UI 2011 Deno Demo.app/Contents/Resources/app/lib/webview.ts
diff --git a/Appify UI 2011 Deno Demo.app/Contents/Resources/app/main.ts b/Example Apps/Appify UI 2011 Deno Demo.app/Contents/Resources/app/main.ts
similarity index 96%
rename from Appify UI 2011 Deno Demo.app/Contents/Resources/app/main.ts
rename to Example Apps/Appify UI 2011 Deno Demo.app/Contents/Resources/app/main.ts
index ed0731f..402d07c 100644
--- a/Appify UI 2011 Deno Demo.app/Contents/Resources/app/main.ts
+++ b/Example Apps/Appify UI 2011 Deno Demo.app/Contents/Resources/app/main.ts
@@ -1,14 +1,15 @@
const __filename = decodeURIComponent(new URL(import.meta.url).pathname)
const __dirname = __filename.slice(0, __filename.lastIndexOf("/"))
+import { css, html } from "./lib/html.ts"
import * as webviewServer from "./lib/http-webview.ts"
-import { html, css } from "./lib/html.ts"
const handlerMainView = (_req: Request): Response => {
console.log("webview works!")
const styles = css`
:root {
+ color-scheme: light dark;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans",
"Helvetica Neue", sans-serif;
}
diff --git a/Appify UI 2011 Node Demo.app/Contents/Info.plist b/Example Apps/Appify UI 2011 Node Demo.app/Contents/Info.plist
similarity index 100%
rename from Appify UI 2011 Node Demo.app/Contents/Info.plist
rename to Example Apps/Appify UI 2011 Node Demo.app/Contents/Info.plist
diff --git a/Appify UI 2011 Node Demo.app/Contents/MacOS/appify-ui-webview b/Example Apps/Appify UI 2011 Node Demo.app/Contents/MacOS/appify-ui-webview
similarity index 100%
rename from Appify UI 2011 Node Demo.app/Contents/MacOS/appify-ui-webview
rename to Example Apps/Appify UI 2011 Node Demo.app/Contents/MacOS/appify-ui-webview
diff --git a/Appify UI 2011 Node Demo.app/Contents/MacOS/main.sh b/Example Apps/Appify UI 2011 Node Demo.app/Contents/MacOS/main.sh
similarity index 100%
rename from Appify UI 2011 Node Demo.app/Contents/MacOS/main.sh
rename to Example Apps/Appify UI 2011 Node Demo.app/Contents/MacOS/main.sh
diff --git a/Appify UI 2011.app/Contents/Resources/English.lproj/MainMenu.nib b/Example Apps/Appify UI 2011 Node Demo.app/Contents/Resources/English.lproj/MainMenu.nib
similarity index 100%
rename from Appify UI 2011.app/Contents/Resources/English.lproj/MainMenu.nib
rename to Example Apps/Appify UI 2011 Node Demo.app/Contents/Resources/English.lproj/MainMenu.nib
diff --git a/Appify UI 2011 Node Demo.app/Contents/Resources/Node not found Error.html b/Example Apps/Appify UI 2011 Node Demo.app/Contents/Resources/Node not found Error.html
similarity index 100%
rename from Appify UI 2011 Node Demo.app/Contents/Resources/Node not found Error.html
rename to Example Apps/Appify UI 2011 Node Demo.app/Contents/Resources/Node not found Error.html
diff --git a/Appify UI 2011 Node Demo.app/Contents/Resources/app/lib/http-webview.js b/Example Apps/Appify UI 2011 Node Demo.app/Contents/Resources/app/lib/http-webview.js
similarity index 100%
rename from Appify UI 2011 Node Demo.app/Contents/Resources/app/lib/http-webview.js
rename to Example Apps/Appify UI 2011 Node Demo.app/Contents/Resources/app/lib/http-webview.js
diff --git a/Appify UI 2011 Node Demo.app/Contents/Resources/app/lib/webview.js b/Example Apps/Appify UI 2011 Node Demo.app/Contents/Resources/app/lib/webview.js
similarity index 100%
rename from Appify UI 2011 Node Demo.app/Contents/Resources/app/lib/webview.js
rename to Example Apps/Appify UI 2011 Node Demo.app/Contents/Resources/app/lib/webview.js
diff --git a/Appify UI 2011 Node Demo.app/Contents/Resources/app/main.js b/Example Apps/Appify UI 2011 Node Demo.app/Contents/Resources/app/main.js
similarity index 100%
rename from Appify UI 2011 Node Demo.app/Contents/Resources/app/main.js
rename to Example Apps/Appify UI 2011 Node Demo.app/Contents/Resources/app/main.js
diff --git a/Example Apps/Appify UI 2011.app/Contents/Info.plist b/Example Apps/Appify UI 2011.app/Contents/Info.plist
new file mode 100644
index 0000000..4a87b48
--- /dev/null
+++ b/Example Apps/Appify UI 2011.app/Contents/Info.plist
@@ -0,0 +1,14 @@
+CFBundlePackageTypeAPPLCFBundleInfoDictionaryVersion6.0
+
+ CFBundleName Appify UI
+ CFBundleExecutable appify-ui.sh
+ CFBundleIdentifier com.SubtleGradient.AppifyUI
+
+ CFBundleVersion 1.0
+ CFBundleGetInfoString 1.0 Appified by Thomas Aylott on Sat Dec 3 2011
+ CFBundleShortVersionString 1.0
+
+ NSPrincipalClassNSApplication
+ NSMainNibFileMainMenu
+
+
diff --git a/Example Apps/Appify UI 2011.app/Contents/MacOS/apache-callback-mac b/Example Apps/Appify UI 2011.app/Contents/MacOS/apache-callback-mac
new file mode 100755
index 0000000..51f3d97
Binary files /dev/null and b/Example Apps/Appify UI 2011.app/Contents/MacOS/apache-callback-mac differ
diff --git a/Example Apps/Appify UI 2011.app/Contents/MacOS/appify-ui.sh b/Example Apps/Appify UI 2011.app/Contents/MacOS/appify-ui.sh
new file mode 100755
index 0000000..7aa4c55
--- /dev/null
+++ b/Example Apps/Appify UI 2011.app/Contents/MacOS/appify-ui.sh
@@ -0,0 +1,140 @@
+#!/usr/bin/env bash
+#
+# MIT License
+#
+# Created By
+# Thomas Aylott
+#
+# Special Thanks
+# Mathias Bynens
+# Shazron Abdullah
+# Apache Callback Mac (heavily modified)
+# Marc Wäckerlin
+
+
+# Decodes an URL-string
+# an URL encoding has "+" instead of spaces
+# and no special characters but "%HEX"
+function urlDec() {
+ local value=${*//+/%20} # replace +-spaces by %20 (hex)
+ for part in ${value//%/ \\x}; do # split at % prepend \x for printf
+ printf "%b%s" "${part:0:4}" "${part:4}" # output decoded char
+ done
+}
+
+# For all given query strings
+# parse them an set shell variables
+function setQueryVars() {
+ local vars="$(cat)"
+ local vars="${vars//\*/%2A}" # escape * as %2A
+ for var in ${vars//&/ }; do # split at &
+ local value=$(urlDec "${var#*=}") # decode value after =
+ value=${value//\\/\\\\} # change \ to \\ for later
+ eval "CGI_${var%=*}=\"${value//\"/\\\"}\"" # evaluate assignment
+ done
+}
+
+function handleForm () {
+ appify
+}
+
+function appify () {
+ setQueryVars
+
+ cd "$HOME/Desktop"
+
+ # Options
+ local appify_FILE="$CGI_CFBundleExecutable"
+ local appify_NAME="$CGI_CFBundleName"
+ local appify_ROOT="$appify_NAME.appify/Contents/MacOS"
+ local appify_INFO="$appify_ROOT/../Info.plist"
+
+ if [[ "$appify_FILE" == "" ]]; then
+ echo "CFBundleExecutable is required. Aborting" 1>&2
+ exit 1
+ fi
+
+ # Create the bundle
+ if [[ -a "$appify_NAME.appify" ]]; then
+ echo "$PWD/$appify_NAME.appify already exists :(" 1>&2
+ exit 1
+ fi
+ mkdir -p "$appify_ROOT"
+
+
+ # Create a new blank CFBundleExecutable
+ cat <<-EOF > "$appify_ROOT/$appify_FILE"
+#!/usr/bin/env bash
+# launch the cocoa app
+cd "\$(dirname "\$0")"
+./apache-callback-mac -url "file://\$(dirname "\$0")/../Resources/index.html"
+EOF
+ echo "Created blank '$appify_ROOT/$appify_FILE' be sure to edit this file to make it do things and stuff" 1>&2
+
+ chmod +x "$appify_ROOT/$appify_FILE"
+
+ cp "$(dirname "$0")/apache-callback-mac" "$appify_ROOT/"
+ mkdir -p "$appify_ROOT/../Resources/English.lproj"
+ cp "$(dirname "$0")/../Resources/English.lproj/MainMenu.nib" "$appify_ROOT/../Resources/English.lproj/MainMenu.nib"
+ cat <<-EOF > "$appify_ROOT/../Resources/index.html"
+
+
+$appify_NAME
+
+$appify_NAME
+EOF
+
+ # Create the Info.plist
+ cat <<-EOF > "$appify_INFO"
+CFBundlePackageTypeAPPLCFBundleInfoDictionaryVersion6.0
+
+ CFBundleIconFile $CGI_CFBundleIconFile
+
+ CFBundleName $CGI_CFBundleName
+ CFBundleExecutable $CGI_CFBundleExecutable
+ CFBundleIdentifier $CGI_CFBundleIdentifier
+
+ CFBundleVersion $CGI_CFBundleVersion
+ NSHumanReadableCopyright $CGI_NSHumanReadableCopyright
+ CFBundleShortVersionString $CGI_CFBundleShortVersionString
+
+
+ NSPrincipalClassNSApplication
+ NSMainNibFileMainMenu
+
+
+EOF
+
+ # Appify!
+ if [[ -a "$appify_NAME.app" ]]; then
+ echo "$appify_NAME.app already exists :(" 1>&2
+ exit 1
+ fi
+ mv "$appify_NAME.appify" "$appify_NAME.app"
+
+ exit
+}
+
+function waitForFormData () {
+ cat < /dev/null
diff --git a/Example Apps/Appify UI 2011.app/Contents/Resources/English.lproj/MainMenu.nib b/Example Apps/Appify UI 2011.app/Contents/Resources/English.lproj/MainMenu.nib
new file mode 100644
index 0000000..68c6207
Binary files /dev/null and b/Example Apps/Appify UI 2011.app/Contents/Resources/English.lproj/MainMenu.nib differ
diff --git a/Appify UI 2011.app/Contents/Resources/index.html b/Example Apps/Appify UI 2011.app/Contents/Resources/index.html
similarity index 100%
rename from Appify UI 2011.app/Contents/Resources/index.html
rename to Example Apps/Appify UI 2011.app/Contents/Resources/index.html
diff --git a/Example Apps/Appify UI 2023 Bun.app/Contents/.gitignore b/Example Apps/Appify UI 2023 Bun.app/Contents/.gitignore
new file mode 100644
index 0000000..9b1ee42
--- /dev/null
+++ b/Example Apps/Appify UI 2023 Bun.app/Contents/.gitignore
@@ -0,0 +1,175 @@
+# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
+
+# Logs
+
+logs
+_.log
+npm-debug.log_
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+.pnpm-debug.log*
+
+# Caches
+
+.cache
+
+# Diagnostic reports (https://nodejs.org/api/report.html)
+
+report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
+
+# Runtime data
+
+pids
+_.pid
+_.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+
+lib-cov
+
+# Coverage directory used by tools like istanbul
+
+coverage
+*.lcov
+
+# nyc test coverage
+
+.nyc_output
+
+# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
+
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+
+bower_components
+
+# node-waf configuration
+
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+
+build/Release
+
+# Dependency directories
+
+node_modules/
+jspm_packages/
+
+# Snowpack dependency directory (https://snowpack.dev/)
+
+web_modules/
+
+# TypeScript cache
+
+*.tsbuildinfo
+
+# Optional npm cache directory
+
+.npm
+
+# Optional eslint cache
+
+.eslintcache
+
+# Optional stylelint cache
+
+.stylelintcache
+
+# Microbundle cache
+
+.rpt2_cache/
+.rts2_cache_cjs/
+.rts2_cache_es/
+.rts2_cache_umd/
+
+# Optional REPL history
+
+.node_repl_history
+
+# Output of 'npm pack'
+
+*.tgz
+
+# Yarn Integrity file
+
+.yarn-integrity
+
+# dotenv environment variable files
+
+.env
+.env.development.local
+.env.test.local
+.env.production.local
+.env.local
+
+# parcel-bundler cache (https://parceljs.org/)
+
+.parcel-cache
+
+# Next.js build output
+
+.next
+out
+
+# Nuxt.js build / generate output
+
+.nuxt
+dist
+
+# Gatsby files
+
+# Comment in the public line in if your project uses Gatsby and not Next.js
+
+# https://nextjs.org/blog/next-9-1#public-directory-support
+
+# public
+
+# vuepress build output
+
+.vuepress/dist
+
+# vuepress v2.x temp and cache directory
+
+.temp
+
+# Docusaurus cache and generated files
+
+.docusaurus
+
+# Serverless directories
+
+.serverless/
+
+# FuseBox cache
+
+.fusebox/
+
+# DynamoDB Local files
+
+.dynamodb/
+
+# TernJS port file
+
+.tern-port
+
+# Stores VSCode versions used for testing VSCode extensions
+
+.vscode-test
+
+# yarn v2
+
+.yarn/cache
+.yarn/unplugged
+.yarn/build-state.yml
+.yarn/install-state.gz
+.pnp.*
+
+# IntelliJ based IDEs
+.idea
+
+# Finder (MacOS) folder config
+.DS_Store
diff --git a/Example Apps/Appify UI 2023 Bun.app/Contents/.vscode/settings.json b/Example Apps/Appify UI 2023 Bun.app/Contents/.vscode/settings.json
new file mode 100644
index 0000000..974a2b4
--- /dev/null
+++ b/Example Apps/Appify UI 2023 Bun.app/Contents/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "deno.enable": false
+}
diff --git a/Hello AI.app/Contents/Info.plist b/Example Apps/Appify UI 2023 Bun.app/Contents/Info.plist
similarity index 80%
rename from Hello AI.app/Contents/Info.plist
rename to Example Apps/Appify UI 2023 Bun.app/Contents/Info.plist
index fd4edb4..d972ea1 100644
--- a/Hello AI.app/Contents/Info.plist
+++ b/Example Apps/Appify UI 2023 Bun.app/Contents/Info.plist
@@ -4,12 +4,12 @@
CFBundlePackageTypeAPPL
CFBundleInfoDictionaryVersion6.0
- CFBundleIconFileHello-AI.icns
- CFBundleNameHello AI
+ CFBundleIconFileAppify-Bun.icns
+ CFBundleNameAppify Bun
CFBundleExecutablemain.sh
- CFBundleIdentifiercom.ThingsThatDoStuff.Appify.Hello-AI
+ CFBundleIdentifiercom.ThingsThatDoStuff.Appify-Bun
- NSHumanReadableCopyright© Copyright 2023 Things That So Stuff, LLC
+ NSHumanReadableCopyright© Copyright 2024 Things That So Stuff, LLC
CFBundleVersion0.1.0
CFBundleShortVersionString0.1.0
diff --git a/Appify UI 2023 Deno.app/Contents/MacOS/Appify UI 23.app/Contents/Info.plist b/Example Apps/Appify UI 2023 Bun.app/Contents/MacOS/Appify UI 23.app/Contents/Info.plist
similarity index 100%
rename from Appify UI 2023 Deno.app/Contents/MacOS/Appify UI 23.app/Contents/Info.plist
rename to Example Apps/Appify UI 2023 Bun.app/Contents/MacOS/Appify UI 23.app/Contents/Info.plist
diff --git a/Appify UI 2023 Deno.app/Contents/MacOS/Appify UI 23.app/Contents/MacOS/Appify UI 23 b/Example Apps/Appify UI 2023 Bun.app/Contents/MacOS/Appify UI 23.app/Contents/MacOS/Appify UI 23
similarity index 100%
rename from Appify UI 2023 Deno.app/Contents/MacOS/Appify UI 23.app/Contents/MacOS/Appify UI 23
rename to Example Apps/Appify UI 2023 Bun.app/Contents/MacOS/Appify UI 23.app/Contents/MacOS/Appify UI 23
diff --git a/Appify UI 2023 Deno.app/Contents/MacOS/Appify UI 23.app/Contents/PkgInfo b/Example Apps/Appify UI 2023 Bun.app/Contents/MacOS/Appify UI 23.app/Contents/PkgInfo
similarity index 100%
rename from Appify UI 2023 Deno.app/Contents/MacOS/Appify UI 23.app/Contents/PkgInfo
rename to Example Apps/Appify UI 2023 Bun.app/Contents/MacOS/Appify UI 23.app/Contents/PkgInfo
diff --git a/Appify UI 2023 Deno.app/Contents/MacOS/Appify UI 23.app/Contents/_CodeSignature/CodeResources b/Example Apps/Appify UI 2023 Bun.app/Contents/MacOS/Appify UI 23.app/Contents/_CodeSignature/CodeResources
similarity index 100%
rename from Appify UI 2023 Deno.app/Contents/MacOS/Appify UI 23.app/Contents/_CodeSignature/CodeResources
rename to Example Apps/Appify UI 2023 Bun.app/Contents/MacOS/Appify UI 23.app/Contents/_CodeSignature/CodeResources
diff --git a/Example Apps/Appify UI 2023 Bun.app/Contents/MacOS/main.sh b/Example Apps/Appify UI 2023 Bun.app/Contents/MacOS/main.sh
new file mode 100755
index 0000000..4c583e7
--- /dev/null
+++ b/Example Apps/Appify UI 2023 Bun.app/Contents/MacOS/main.sh
@@ -0,0 +1,38 @@
+#!/usr/bin/env bash
+
+App="$(dirname "$0")/../.."
+cd "$App"
+App="$PWD"
+AppName="$(basename "$App")"
+
+bunNotFound() {
+ echo "bun not found. Show error" >&2
+ URL="file://$App/Contents/Resources/Bun not found Error.html"
+ URL="${URL// /%20}"
+ "$App/Contents/MacOS/Appify UI 23.app/Contents/MacOS/Appify UI 23" --url "${URL}"
+ exit 1
+}
+
+installBun() {
+ echo "Installing bun..." >&2
+ curl -fsSL https://bun.sh/install | bash
+}
+
+bun_run() {
+ local bun="$App/Contents/MacOS/bun" # for packaging bun with the app
+ [[ -f "$bun" ]] || bun="$HOME/.bun/bin/bun" # default install location
+ [[ -f "$bun" ]] || bun="$(which bun)" # in PATH
+ [[ -f "$bun" ]] || installBun # install bun if not found
+ [[ -f "$bun" ]] || bun="$HOME/.bun/bin/bun" # default install location?!
+ [[ -f "$bun" ]] || bun="$(which bun)" # in PATH?!
+ [[ -f "$bun" ]] || bunNotFound # give up :(
+
+ "$bun" run "$@"
+}
+
+main() {
+ MAIN="$App/Contents/app/main.ts"
+ bun_run "$MAIN" "$@"
+}
+
+main "$@" >"$App/../.$AppName.$$.log" 2>&1
diff --git a/Example Apps/Appify UI 2023 Bun.app/Contents/Resources/Bun not found Error.html b/Example Apps/Appify UI 2023 Bun.app/Contents/Resources/Bun not found Error.html
new file mode 100644
index 0000000..c4fa7c4
--- /dev/null
+++ b/Example Apps/Appify UI 2023 Bun.app/Contents/Resources/Bun not found Error.html
@@ -0,0 +1,20 @@
+
+
+
+
+Can't find Bun
+
+Bun not found
+This app requires Bun
+
+Please install Bun and try again.
+
+
+ - Install the latest Bun: https://bun.sh
+
diff --git a/Example Apps/Appify UI 2023 Bun.app/Contents/app/lib/hotness.ts b/Example Apps/Appify UI 2023 Bun.app/Contents/app/lib/hotness.ts
new file mode 100644
index 0000000..d095547
--- /dev/null
+++ b/Example Apps/Appify UI 2023 Bun.app/Contents/app/lib/hotness.ts
@@ -0,0 +1,74 @@
+type RefObject = { readonly current: T }
+declare global {
+ var hotness: undefined | RefObject
+}
+
+type HotDisposable = T & {
+ [Symbol.dispose](this: T, last: T, next: T): void
+}
+
+export class Hotness {
+ static version = "hotness 2.13"
+ version = Hotness.version
+
+ count = -1
+
+ disposables = new Map>()
+ listeners: (null | (() => void))[] = [];
+
+ [Symbol.dispose]() {
+ this.listeners.forEach((it, i, them) => ((them[i] = null), it?.()))
+ this.listeners = []
+ }
+
+ using>>(meta: ImportMeta, map: T): T {
+ for (const [id, current] of Object.entries(map)) this.usingOne(meta, id, current)
+ return map
+ }
+
+ usingOne>({ filename }: ImportMeta, id: string, current: T): T {
+ const key = `${filename}#${id}`
+ const old = this.disposables.get(key)
+ this.disposables.set(key, current)
+ try {
+ old?.[Symbol.dispose]?.(old, current)
+ } catch (error) {
+ console.warn("Hotness.using", "error disposing", { key, error })
+ }
+ return current
+ }
+
+ static get current(): Hotness {
+ const old = globalThis.hotness?.current
+ if (old?.version === Hotness.version) return old
+
+ globalThis.hotness = { current: new Hotness() }
+ return globalThis.hotness!.current
+ }
+
+ static onHotReload(listener: (old: Hotness, current: Hotness) => void): void {
+ const old = { ...Hotness.current } as Hotness
+ Hotness.current.listeners.push(() => listener(old, Hotness.current))
+ }
+}
+
+Hotness.current.count++
+Hotness.current[Symbol.dispose]()
+
+if (import.meta.main) {
+ console.log(``, import.meta.filename)
+ setImmediate(() => Hotness.onHotReload(({ count }) => console.log(`\n`)))
+
+ const testObject: HotDisposable<{ id: string }> = {
+ id: new Date().toLocaleTimeString() + " " + Hotness.current.count,
+ [Symbol.dispose]: function ({ id: OLD }, { id: NEW }): void {
+ console.log("Hot reloaded! disposed of old object.", { OLD, NEW })
+ },
+ }
+
+ Hotness.current.using(import.meta, { testObject })
+
+ Hotness.onHotReload(({ count, version }) => {
+ console.log("onHotReload, Hot reloaded! ran once listener. ", { count, version })
+ })
+}
diff --git a/Example Apps/Appify UI 2023 Bun.app/Contents/app/lib/html.ts b/Example Apps/Appify UI 2023 Bun.app/Contents/app/lib/html.ts
new file mode 100644
index 0000000..d9420db
--- /dev/null
+++ b/Example Apps/Appify UI 2023 Bun.app/Contents/app/lib/html.ts
@@ -0,0 +1,57 @@
+export function html(strings: TemplateStringsArray, ...values: unknown[]): string {
+ return strings
+ .map((string, index) => {
+ let value = values[index]
+ if (value === undefined) return string
+ if (typeof value === "function") value = value()
+ return string + htmlEscape(value)
+ })
+ .join("")
+}
+
+function htmlEscape(value: unknown): string {
+ if (typeof value === "string") {
+ return value.replace(/[&<>"']/g, char => {
+ switch (char) {
+ case "&":
+ return "&"
+ case "<":
+ return "<"
+ case ">":
+ return ">"
+ case '"':
+ return """
+ case "'":
+ return "'"
+ default:
+ return char
+ }
+ })
+ }
+ return String(value)
+}
+
+function raw(strings: TemplateStringsArray, ...values: unknown[]): string {
+ return strings
+ .map((string, index) => {
+ let value = values[index]
+ if (value === undefined) return string
+ if (typeof value === "function") value = value()
+ return string + value
+ })
+ .join("")
+}
+
+export const css = raw
+
+export function js(strings: TemplateStringsArray, ...values: unknown[]): string {
+ return strings
+ .map((string, index) => {
+ let value = values[index]
+ if (value === undefined) return string
+ if (typeof value === "function") value = value()
+ if (typeof value !== "string") value = JSON.stringify(value)
+ return string + value
+ })
+ .join("")
+}
diff --git a/Example Apps/Appify UI 2023 Bun.app/Contents/app/lib/serve-webview.ts b/Example Apps/Appify UI 2023 Bun.app/Contents/app/lib/serve-webview.ts
new file mode 100644
index 0000000..96e4046
--- /dev/null
+++ b/Example Apps/Appify UI 2023 Bun.app/Contents/app/lib/serve-webview.ts
@@ -0,0 +1,54 @@
+import type { ServeOptions, Server } from "bun"
+import { css, html } from "./html.ts"
+import { webviewOpen } from "./webview.ts"
+
+function serveToAnyPort({ port, ...options }: ServeOptions): Server {
+ port = Number(port) || 8444
+ while (port < 9999) {
+ try {
+ return Bun.serve({ ...options, port: port })
+ } catch (error) {
+ console.warn("Port", port, "is in use")
+ if ((error as any).code !== "EADDRINUSE") throw error
+ port++
+ }
+ }
+ throw new Error("Could not start server")
+}
+
+export function create(options: ServeOptions) {
+ const server = serveToAnyPort(options)
+ const window = webviewOpen(server.url.href)
+ window.exited.then(() => server.stop())
+ return server
+}
+
+if (import.meta.main) {
+ test()
+ function test() {
+ console.log("webview works?")
+
+ const fetcher = (request: Request): Response => {
+ console.log("webview works!")
+
+ const styles = css`
+ :root {
+ color-scheme: light dark;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans",
+ "Helvetica Neue", sans-serif;
+ }
+ `
+ const body = html`
+
+
+ lulz 1
+ `
+ return new Response(body, { status: 200, headers: { "content-type": "text/html" } })
+ }
+
+ create({ fetch: fetcher })
+ create({ fetch: fetcher })
+ }
+}
diff --git a/Example Apps/Appify UI 2023 Bun.app/Contents/app/lib/webview.ts b/Example Apps/Appify UI 2023 Bun.app/Contents/app/lib/webview.ts
new file mode 100644
index 0000000..a669203
--- /dev/null
+++ b/Example Apps/Appify UI 2023 Bun.app/Contents/app/lib/webview.ts
@@ -0,0 +1,38 @@
+import type { Subprocess } from "bun"
+
+const [APP_ROOT] = __dirname.split("/Contents/")
+
+const WEBVIEW_BIN = Bun.file(`${APP_ROOT}/Contents/MacOS/Appify UI 23.app/Contents/MacOS/Appify UI 23`)
+
+export function webviewOpen(url: URL | string) {
+ if (typeof url === "string") url = new URL(url)
+
+ console.log(__filename, "open", url.href)
+
+ const webview = Bun.spawn([WEBVIEW_BIN.name!, "--url", url.href], {
+ stdio: ["ignore", "inherit", "inherit"],
+ cwd: APP_ROOT,
+ })
+ // const webview = Bun.spawn(["open", "--wait-apps", `${APP_ROOT}/Contents/MacOS/webview.app`], {
+ // stdio: ["ignore", "inherit", "inherit"],
+ // cwd: APP_ROOT,
+ // })
+
+ console.log("webview pid", webview.pid)
+
+ webview.exited.then(status => console.log("webview exited", { status }))
+
+ return webview
+}
+
+declare global {
+ var webviewRef: undefined | { current?: Subprocess }
+}
+
+if (import.meta.main) {
+ ;(globalThis.webviewRef ??= {}).current?.kill()
+ const webview = (webviewRef!.current = webviewOpen(
+ Bun.serve({ port: 9873, fetch: () => Response.json({ success: true }) }).url.href,
+ ))
+ webview.exited.then(() => webviewRef!.current === webview && process.exit(0))
+}
diff --git a/Example Apps/Appify UI 2023 Bun.app/Contents/app/main.ts b/Example Apps/Appify UI 2023 Bun.app/Contents/app/main.ts
new file mode 100644
index 0000000..27cadc8
--- /dev/null
+++ b/Example Apps/Appify UI 2023 Bun.app/Contents/app/main.ts
@@ -0,0 +1,111 @@
+import type { ServeOptions } from "bun"
+import { css, html, js } from "./lib/html.ts"
+import * as webviewServer from "./lib/serve-webview.ts"
+
+const styles = css`
+ :root {
+ color-scheme: light dark;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans",
+ "Helvetica Neue", sans-serif;
+ }
+`
+
+const routes: Record = {}
+
+class FakeServerAction {
+ constructor(public readonly pathname: string, public readonly fetch: ServeOptions["fetch"]) {
+ routes[this.pathname] = this.fetch
+ }
+ onClick(params: P) {
+ return js`fetch(${JSON.stringify(this.pathname)}, {
+ method: "POST",
+ body: ${JSON.stringify(params)},
+ headers: { "Content-Type": "application/json" }
+ }).then(response => response.text()).then(alert)`
+ }
+}
+
+const editAction = new FakeServerAction("/edit", async (req: Request) => {
+ const body = await req.json()
+ const { wantsInsiders } = body
+
+ console.log("handlerEdit")
+ if (req.method !== "POST") {
+ console.warn("Error; Endpoint requires POST")
+ return new Response("Error; Endpoint requires POST", { status: 401, headers: { "content-type": "text/html" } })
+ }
+ console.log("Opening VSCode…")
+ const result = await Bun.$`/usr/local/bin/code${wantsInsiders ? "-insiders" : ""} ${__dirname}/../..`
+
+ return Response.json(
+ { result: result.text() },
+ { status: result.exitCode === 0 ? 200 : 500, statusText: result.exitCode === 0 ? "OK" : "Error" },
+ )
+})
+
+const handlerMainView = (request: Request): Response => {
+ console.log("webview works!")
+
+ const body = html`
+
+
+ ${request.url}
+
+
Appify UI (powered by Bun)
+
+
+ Edit this app
+
+
+
+ `
+ return new Response(body, { status: 200, headers: { "content-type": "text/html" } })
+}
+
+const handlerEdit = async (req: Request): Promise => {
+ const url = new URL(req.url)
+ const wantsInsiders = url.searchParams.get("insiders") === "1"
+
+ console.log("handlerEdit")
+ if (req.method !== "POST") {
+ console.warn("Error; Endpoint requires POST")
+ return new Response("Error; Endpoint requires POST", { status: 400, headers: { "content-type": "text/html" } })
+ }
+ // if (??? !== "darwin") {
+ // console.warn("NOT IMPLEMENTED")
+ // return new Response("NOT IMPLEMENTED", { status: 400, headers: { "content-type": "text/html" } })
+ // } else
+ {
+ console.log("Opening VSCode…")
+ // const vscode = Bun.run({
+ // cmd: ["/usr/local/bin/code" + (wantsInsiders ? "-insiders" : ""), `${__dirname}/../..`],
+ // stdout: "piped",
+ // stderr: "piped",
+ // })
+ Bun.$`/usr/local/bin/code${wantsInsiders ? "-insiders" : ""} ${__dirname}/../..`
+ // const { code } = await vscode.status()
+ // console.log("VSCode exited with code", code)
+ // if (code !== 0) {
+ // const rawError = await vscode.stderrOutput()
+ // const errorString = new TextDecoder().decode(rawError)
+ // return new Response(errorString, { status: 500, headers: { "content-type": "text/html" } })
+ // }
+ return new Response("Done", { status: 200, headers: { "content-type": "text/html" } })
+ }
+}
+
+export const router: ServeOptions["fetch"] = async (req, server) => {
+ const url = new URL(req.url)
+ if (url.pathname in routes) return await routes[url.pathname].call(server, req, server)
+
+ console.log("handlerRouter", req.url)
+ if (url.pathname === "/edit") return await handlerEdit(req)
+ return handlerMainView(req)
+}
+
+if (import.meta.main) {
+ console.log("starting webview server…")
+ webviewServer.create({ fetch: router })
+}
diff --git a/Example Apps/Appify UI 2023 Bun.app/Contents/bun.lockb b/Example Apps/Appify UI 2023 Bun.app/Contents/bun.lockb
new file mode 100755
index 0000000..51ac237
Binary files /dev/null and b/Example Apps/Appify UI 2023 Bun.app/Contents/bun.lockb differ
diff --git a/Example Apps/Appify UI 2023 Bun.app/Contents/package.json b/Example Apps/Appify UI 2023 Bun.app/Contents/package.json
new file mode 100644
index 0000000..4a0ce7e
--- /dev/null
+++ b/Example Apps/Appify UI 2023 Bun.app/Contents/package.json
@@ -0,0 +1,11 @@
+{
+ "name": "appify-ui-bun",
+ "module": "main.ts",
+ "type": "module",
+ "devDependencies": {
+ "@types/bun": "latest"
+ },
+ "peerDependencies": {
+ "typescript": "^5"
+ }
+}
diff --git a/Example Apps/Appify UI 2023 Bun.app/Contents/tsconfig.json b/Example Apps/Appify UI 2023 Bun.app/Contents/tsconfig.json
new file mode 100644
index 0000000..238655f
--- /dev/null
+++ b/Example Apps/Appify UI 2023 Bun.app/Contents/tsconfig.json
@@ -0,0 +1,27 @@
+{
+ "compilerOptions": {
+ // Enable latest features
+ "lib": ["ESNext", "DOM"],
+ "target": "ESNext",
+ "module": "ESNext",
+ "moduleDetection": "force",
+ "jsx": "react-jsx",
+ "allowJs": true,
+
+ // Bundler mode
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "noEmit": true,
+
+ // Best practices
+ "strict": true,
+ "skipLibCheck": true,
+ "noFallthroughCasesInSwitch": true,
+
+ // Some stricter flags (disabled by default)
+ "noUnusedLocals": false,
+ "noUnusedParameters": false,
+ "noPropertyAccessFromIndexSignature": false
+ }
+}
diff --git a/Appify UI 2023 Deno.app/Contents/.vscode/settings.json b/Example Apps/Appify UI 2023 Deno.app/Contents/.vscode/settings.json
similarity index 100%
rename from Appify UI 2023 Deno.app/Contents/.vscode/settings.json
rename to Example Apps/Appify UI 2023 Deno.app/Contents/.vscode/settings.json
diff --git a/Appify UI 2023 Deno.app/Contents/Info.plist b/Example Apps/Appify UI 2023 Deno.app/Contents/Info.plist
similarity index 100%
rename from Appify UI 2023 Deno.app/Contents/Info.plist
rename to Example Apps/Appify UI 2023 Deno.app/Contents/Info.plist
diff --git a/Appify UI 2023.app/Contents/Info.plist b/Example Apps/Appify UI 2023 Deno.app/Contents/MacOS/Appify UI 23.app/Contents/Info.plist
similarity index 100%
rename from Appify UI 2023.app/Contents/Info.plist
rename to Example Apps/Appify UI 2023 Deno.app/Contents/MacOS/Appify UI 23.app/Contents/Info.plist
diff --git a/Appify UI 2023.app/Contents/MacOS/Appify UI 23 b/Example Apps/Appify UI 2023 Deno.app/Contents/MacOS/Appify UI 23.app/Contents/MacOS/Appify UI 23
similarity index 100%
rename from Appify UI 2023.app/Contents/MacOS/Appify UI 23
rename to Example Apps/Appify UI 2023 Deno.app/Contents/MacOS/Appify UI 23.app/Contents/MacOS/Appify UI 23
diff --git a/Appify UI 2023.app/Contents/PkgInfo b/Example Apps/Appify UI 2023 Deno.app/Contents/MacOS/Appify UI 23.app/Contents/PkgInfo
similarity index 100%
rename from Appify UI 2023.app/Contents/PkgInfo
rename to Example Apps/Appify UI 2023 Deno.app/Contents/MacOS/Appify UI 23.app/Contents/PkgInfo
diff --git a/Appify UI 2023.app/Contents/_CodeSignature/CodeResources b/Example Apps/Appify UI 2023 Deno.app/Contents/MacOS/Appify UI 23.app/Contents/_CodeSignature/CodeResources
similarity index 100%
rename from Appify UI 2023.app/Contents/_CodeSignature/CodeResources
rename to Example Apps/Appify UI 2023 Deno.app/Contents/MacOS/Appify UI 23.app/Contents/_CodeSignature/CodeResources
diff --git a/Appify UI 2023 Deno.app/Contents/MacOS/main.sh b/Example Apps/Appify UI 2023 Deno.app/Contents/MacOS/main.sh
similarity index 100%
rename from Appify UI 2023 Deno.app/Contents/MacOS/main.sh
rename to Example Apps/Appify UI 2023 Deno.app/Contents/MacOS/main.sh
diff --git a/Appify UI 2023 Deno.app/Contents/Resources/Deno not found Error.html b/Example Apps/Appify UI 2023 Deno.app/Contents/Resources/Deno not found Error.html
similarity index 100%
rename from Appify UI 2023 Deno.app/Contents/Resources/Deno not found Error.html
rename to Example Apps/Appify UI 2023 Deno.app/Contents/Resources/Deno not found Error.html
diff --git a/Appify UI 2023 Deno.app/Contents/Resources/app/lib/html.ts b/Example Apps/Appify UI 2023 Deno.app/Contents/Resources/app/lib/html.ts
similarity index 100%
rename from Appify UI 2023 Deno.app/Contents/Resources/app/lib/html.ts
rename to Example Apps/Appify UI 2023 Deno.app/Contents/Resources/app/lib/html.ts
diff --git a/Appify UI 2023 Deno.app/Contents/Resources/app/lib/http-webview.ts b/Example Apps/Appify UI 2023 Deno.app/Contents/Resources/app/lib/http-webview.ts
similarity index 97%
rename from Appify UI 2023 Deno.app/Contents/Resources/app/lib/http-webview.ts
rename to Example Apps/Appify UI 2023 Deno.app/Contents/Resources/app/lib/http-webview.ts
index d4118dd..a0104cc 100644
--- a/Appify UI 2023 Deno.app/Contents/Resources/app/lib/http-webview.ts
+++ b/Example Apps/Appify UI 2023 Deno.app/Contents/Resources/app/lib/http-webview.ts
@@ -32,6 +32,7 @@ if (import.meta.main) {
const styles = css`
:root {
+ color-scheme: light dark;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans",
"Helvetica Neue", sans-serif;
}
diff --git a/Appify UI 2023 Deno.app/Contents/Resources/app/lib/webview.html b/Example Apps/Appify UI 2023 Deno.app/Contents/Resources/app/lib/webview.html
similarity index 100%
rename from Appify UI 2023 Deno.app/Contents/Resources/app/lib/webview.html
rename to Example Apps/Appify UI 2023 Deno.app/Contents/Resources/app/lib/webview.html
diff --git a/Appify UI 2023 Deno.app/Contents/Resources/app/lib/webview.ts b/Example Apps/Appify UI 2023 Deno.app/Contents/Resources/app/lib/webview.ts
similarity index 100%
rename from Appify UI 2023 Deno.app/Contents/Resources/app/lib/webview.ts
rename to Example Apps/Appify UI 2023 Deno.app/Contents/Resources/app/lib/webview.ts
diff --git a/Appify UI 2023 Deno.app/Contents/Resources/app/main.ts b/Example Apps/Appify UI 2023 Deno.app/Contents/Resources/app/main.ts
similarity index 98%
rename from Appify UI 2023 Deno.app/Contents/Resources/app/main.ts
rename to Example Apps/Appify UI 2023 Deno.app/Contents/Resources/app/main.ts
index b197927..ee82c01 100644
--- a/Appify UI 2023 Deno.app/Contents/Resources/app/main.ts
+++ b/Example Apps/Appify UI 2023 Deno.app/Contents/Resources/app/main.ts
@@ -9,6 +9,7 @@ import * as webviewServer from "./lib/http-webview.ts"
const styles = css`
:root {
+ color-scheme: light dark;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans",
"Helvetica Neue", sans-serif;
}
diff --git a/Hello AI.app/Contents/MacOS/Appify UI 23.app/Contents/Info.plist b/Example Apps/Appify UI 2023.app/Contents/Info.plist
similarity index 100%
rename from Hello AI.app/Contents/MacOS/Appify UI 23.app/Contents/Info.plist
rename to Example Apps/Appify UI 2023.app/Contents/Info.plist
diff --git a/Hello AI.app/Contents/MacOS/Appify UI 23.app/Contents/MacOS/Appify UI 23 b/Example Apps/Appify UI 2023.app/Contents/MacOS/Appify UI 23
similarity index 100%
rename from Hello AI.app/Contents/MacOS/Appify UI 23.app/Contents/MacOS/Appify UI 23
rename to Example Apps/Appify UI 2023.app/Contents/MacOS/Appify UI 23
diff --git a/Hello AI.app/Contents/MacOS/Appify UI 23.app/Contents/PkgInfo b/Example Apps/Appify UI 2023.app/Contents/PkgInfo
similarity index 100%
rename from Hello AI.app/Contents/MacOS/Appify UI 23.app/Contents/PkgInfo
rename to Example Apps/Appify UI 2023.app/Contents/PkgInfo
diff --git a/Hello AI.app/Contents/MacOS/Appify UI 23.app/Contents/_CodeSignature/CodeResources b/Example Apps/Appify UI 2023.app/Contents/_CodeSignature/CodeResources
similarity index 100%
rename from Hello AI.app/Contents/MacOS/Appify UI 23.app/Contents/_CodeSignature/CodeResources
rename to Example Apps/Appify UI 2023.app/Contents/_CodeSignature/CodeResources
diff --git a/Example Apps/Appify UI 2024 Bun.app/Contents/Info.plist b/Example Apps/Appify UI 2024 Bun.app/Contents/Info.plist
new file mode 100644
index 0000000..b7cd828
--- /dev/null
+++ b/Example Apps/Appify UI 2024 Bun.app/Contents/Info.plist
@@ -0,0 +1,46 @@
+
+
+
+
+ BuildMachineOSBuild
+ 23A344
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ Appify_UI_23
+ CFBundleIdentifier
+ com.ThingsThatDoStuff.Appify-UI-23
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ Appify UI 23
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSupportedPlatforms
+
+ MacOSX
+
+ CFBundleVersion
+ 2
+ DTCompiler
+ com.apple.compilers.llvm.clang.1_0
+ DTPlatformBuild
+
+ DTPlatformName
+ macosx
+ DTPlatformVersion
+ 14.5
+ DTSDKBuild
+ 23F73
+ DTSDKName
+ macosx14.5
+ DTXcode
+ 1540
+ DTXcodeBuild
+ 15F31d
+ LSMinimumSystemVersion
+ 13.0
+
+
diff --git a/Example Apps/Appify UI 2024 Bun.app/Contents/MacOS/Appify_UI_23 b/Example Apps/Appify UI 2024 Bun.app/Contents/MacOS/Appify_UI_23
new file mode 100755
index 0000000..94450b3
Binary files /dev/null and b/Example Apps/Appify UI 2024 Bun.app/Contents/MacOS/Appify_UI_23 differ
diff --git a/Example Apps/Frens Devtools.app/Contents/.gitignore b/Example Apps/Frens Devtools.app/Contents/.gitignore
new file mode 100644
index 0000000..9b1ee42
--- /dev/null
+++ b/Example Apps/Frens Devtools.app/Contents/.gitignore
@@ -0,0 +1,175 @@
+# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
+
+# Logs
+
+logs
+_.log
+npm-debug.log_
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+.pnpm-debug.log*
+
+# Caches
+
+.cache
+
+# Diagnostic reports (https://nodejs.org/api/report.html)
+
+report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
+
+# Runtime data
+
+pids
+_.pid
+_.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+
+lib-cov
+
+# Coverage directory used by tools like istanbul
+
+coverage
+*.lcov
+
+# nyc test coverage
+
+.nyc_output
+
+# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
+
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+
+bower_components
+
+# node-waf configuration
+
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+
+build/Release
+
+# Dependency directories
+
+node_modules/
+jspm_packages/
+
+# Snowpack dependency directory (https://snowpack.dev/)
+
+web_modules/
+
+# TypeScript cache
+
+*.tsbuildinfo
+
+# Optional npm cache directory
+
+.npm
+
+# Optional eslint cache
+
+.eslintcache
+
+# Optional stylelint cache
+
+.stylelintcache
+
+# Microbundle cache
+
+.rpt2_cache/
+.rts2_cache_cjs/
+.rts2_cache_es/
+.rts2_cache_umd/
+
+# Optional REPL history
+
+.node_repl_history
+
+# Output of 'npm pack'
+
+*.tgz
+
+# Yarn Integrity file
+
+.yarn-integrity
+
+# dotenv environment variable files
+
+.env
+.env.development.local
+.env.test.local
+.env.production.local
+.env.local
+
+# parcel-bundler cache (https://parceljs.org/)
+
+.parcel-cache
+
+# Next.js build output
+
+.next
+out
+
+# Nuxt.js build / generate output
+
+.nuxt
+dist
+
+# Gatsby files
+
+# Comment in the public line in if your project uses Gatsby and not Next.js
+
+# https://nextjs.org/blog/next-9-1#public-directory-support
+
+# public
+
+# vuepress build output
+
+.vuepress/dist
+
+# vuepress v2.x temp and cache directory
+
+.temp
+
+# Docusaurus cache and generated files
+
+.docusaurus
+
+# Serverless directories
+
+.serverless/
+
+# FuseBox cache
+
+.fusebox/
+
+# DynamoDB Local files
+
+.dynamodb/
+
+# TernJS port file
+
+.tern-port
+
+# Stores VSCode versions used for testing VSCode extensions
+
+.vscode-test
+
+# yarn v2
+
+.yarn/cache
+.yarn/unplugged
+.yarn/build-state.yml
+.yarn/install-state.gz
+.pnp.*
+
+# IntelliJ based IDEs
+.idea
+
+# Finder (MacOS) folder config
+.DS_Store
diff --git a/Example Apps/Frens Devtools.app/Contents/Info.plist b/Example Apps/Frens Devtools.app/Contents/Info.plist
new file mode 100644
index 0000000..275588c
--- /dev/null
+++ b/Example Apps/Frens Devtools.app/Contents/Info.plist
@@ -0,0 +1,33 @@
+
+
+
+ CFBundlePackageType
+ APPL
+ CFBundleInfoDictionaryVersion
+ 6.0
+
+ CFBundleIconFile
+ FrensDevtools.icns
+
+ CFBundleName
+ Frens Devtools
+ CFBundleExecutable
+ frens-devtools.appify.sh
+ CFBundleIdentifier
+ lol.frens.devtools
+
+ CFBundleVersion
+ 1
+ NSHumanReadableCopyright
+ © Copyright 2024 Friendly Labs Inc.
+ CFBundleShortVersionString
+ 0.0.1
+
+
+ NSPrincipalClass
+ NSApplication
+ NSMainNibFile
+ MainMenu
+
+
+
diff --git a/Example Apps/Frens Devtools.app/Contents/MacOS/apache-callback-mac b/Example Apps/Frens Devtools.app/Contents/MacOS/apache-callback-mac
new file mode 100755
index 0000000..51f3d97
Binary files /dev/null and b/Example Apps/Frens Devtools.app/Contents/MacOS/apache-callback-mac differ
diff --git a/Example Apps/Frens Devtools.app/Contents/MacOS/frens-devtools.appify.sh b/Example Apps/Frens Devtools.app/Contents/MacOS/frens-devtools.appify.sh
new file mode 100755
index 0000000..c97de7b
--- /dev/null
+++ b/Example Apps/Frens Devtools.app/Contents/MacOS/frens-devtools.appify.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+cd "$(dirname "$0")/../.."
+APP_ROOT="$PWD"
+
+export BUN_INSTALL="$HOME/.bun"
+export PATH="$BUN_INSTALL/bin:$PATH"
+
+"$APP_ROOT/Contents/src/frens-devtools.appify.bun.ts" >"${APP_ROOT}.log" 2>&1
diff --git a/Example Apps/Frens Devtools.app/Contents/README.md b/Example Apps/Frens Devtools.app/Contents/README.md
new file mode 100644
index 0000000..88711cd
--- /dev/null
+++ b/Example Apps/Frens Devtools.app/Contents/README.md
@@ -0,0 +1,15 @@
+# frens-devtools-macos
+
+To install dependencies:
+
+```bash
+bun install
+```
+
+To run:
+
+```bash
+bun run index.ts
+```
+
+This project was created using `bun init` in bun v1.1.8. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
diff --git a/Example Apps/Frens Devtools.app/Contents/Resources/English.lproj/MainMenu.nib b/Example Apps/Frens Devtools.app/Contents/Resources/English.lproj/MainMenu.nib
new file mode 100644
index 0000000..68c6207
Binary files /dev/null and b/Example Apps/Frens Devtools.app/Contents/Resources/English.lproj/MainMenu.nib differ
diff --git a/Example Apps/Frens Devtools.app/Contents/bun.lockb b/Example Apps/Frens Devtools.app/Contents/bun.lockb
new file mode 100755
index 0000000..d62122d
Binary files /dev/null and b/Example Apps/Frens Devtools.app/Contents/bun.lockb differ
diff --git a/Example Apps/Frens Devtools.app/Contents/index.ts b/Example Apps/Frens Devtools.app/Contents/index.ts
new file mode 100644
index 0000000..f67b2c6
--- /dev/null
+++ b/Example Apps/Frens Devtools.app/Contents/index.ts
@@ -0,0 +1 @@
+console.log("Hello via Bun!");
\ No newline at end of file
diff --git a/Example Apps/Frens Devtools.app/Contents/package.json b/Example Apps/Frens Devtools.app/Contents/package.json
new file mode 100644
index 0000000..470ee8e
--- /dev/null
+++ b/Example Apps/Frens Devtools.app/Contents/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "frens-devtools-macos",
+ "module": "src/frens-devtools.appify.bun.ts",
+ "type": "module",
+ "devDependencies": {
+ "@types/bun": "latest",
+ "@types/react": "^18.3.1",
+ "@types/react-dom": "^18.3.0"
+ },
+ "peerDependencies": {
+ "typescript": "latest"
+ },
+ "dependencies": {
+ "react": "^19.0.0-beta-04b058868c-20240508",
+ "react-dom": "^19.0.0-beta-04b058868c-20240508"
+ }
+}
diff --git a/Example Apps/Frens Devtools.app/Contents/src/frens-devtools.appify.bun.ts b/Example Apps/Frens Devtools.app/Contents/src/frens-devtools.appify.bun.ts
new file mode 100755
index 0000000..fe6724b
--- /dev/null
+++ b/Example Apps/Frens Devtools.app/Contents/src/frens-devtools.appify.bun.ts
@@ -0,0 +1,60 @@
+#!/usr/bin/env bun --watch
+
+import { createSecurity } from "./lib/createSecurity"
+import { firstOpenPortBetween } from "./lib/firstOpenPortBetween"
+import { openBrowser } from "./lib/openBrowser"
+
+///
+export {}
+console.log(__filename, "is running")
+process.chdir(__dirname)
+
+const html = String.raw
+
+import routes from "./routes"
+
+async function main() {
+ const Security = createSecurity()
+
+ const server = Bun.serve({
+ port: await firstOpenPortBetween(3333, 4444),
+ async fetch(request) {
+ try {
+ Security.verifyAuth(request)
+ } catch (error) {
+ console.error(error)
+ return new Response("Unauthorized", { status: 401 })
+ }
+
+ const url = new URL(request.url)
+
+ if (url.pathname in routes) return routes[url.pathname](request)
+
+ return new Response(html`Route not found "${url.pathname}"
`, {
+ status: 404,
+ headers: { "content-type": "text/html" },
+ })
+ },
+ })
+
+ console.log("Server running at", server.url.href)
+ const url = Security.protectURL(new URL(server.url))
+ console.log("Opening browser to", url.href)
+
+ openBrowser(url.href).exited.finally(() => {
+ server.stop(true)
+ process.exit(0)
+ })
+}
+
+process.once("beforeExit", (...args) => console.debug("beforeExit", { args }))
+process.once("exit", (...args) => console.debug("exit", { args }))
+process.once("SIGHUP", (...args) => console.debug("SIGHUP", { args }))
+process.once("SIGINT", (...args) => console.debug("SIGINT", { args }))
+process.once("SIGQUIT", (...args) => console.debug("SIGQUIT", { args }))
+process.once("SIGTERM", (...args) => console.debug("SIGTERM", { args }))
+process.once("SIGKILL", (...args) => console.debug("SIGKILL", { args }))
+process.once("SIGABRT", (...args) => console.debug("SIGABRT", { args }))
+
+// @ts-ignore -- top level await is fine here
+await main()
diff --git a/Example Apps/Frens Devtools.app/Contents/src/lib/createSecurity.ts b/Example Apps/Frens Devtools.app/Contents/src/lib/createSecurity.ts
new file mode 100644
index 0000000..10a1336
--- /dev/null
+++ b/Example Apps/Frens Devtools.app/Contents/src/lib/createSecurity.ts
@@ -0,0 +1,17 @@
+export const createSecurity = () => {
+ const SECRET = `${__filename}#${process.pid}#${Math.random().toString(36).slice(2)}`
+ const verifyAuth = (request: Request) => {
+ const isAuthorizationLegit = request.headers.get("Authorization")?.includes(SECRET)
+ if (isAuthorizationLegit) return
+ const isSearchParamsLegit = JSON.parse(new URL(request.url).searchParams.get("SECRET")!) === SECRET
+ if (isSearchParamsLegit) return
+ throw new Error("Unauthorized")
+ }
+ const safeURL = (unsafeURL: URL) => {
+ const safeURL = new URL(unsafeURL.toString())
+ safeURL.searchParams.set("SECRET", JSON.stringify(SECRET))
+ return safeURL
+ }
+
+ return { SECRET, verifyAuth, protectURL: safeURL }
+}
diff --git a/Example Apps/Frens Devtools.app/Contents/src/lib/firstOpenPortBetween.ts b/Example Apps/Frens Devtools.app/Contents/src/lib/firstOpenPortBetween.ts
new file mode 100644
index 0000000..c620708
--- /dev/null
+++ b/Example Apps/Frens Devtools.app/Contents/src/lib/firstOpenPortBetween.ts
@@ -0,0 +1,12 @@
+export async function firstOpenPortBetween(start: number, end: number) {
+ for (let port = start; port <= end; port++) {
+ try {
+ const server = Bun.serve({ port, fetch: () => new Response("Hi!") })
+ server.stop(true)
+ return port
+ } catch (error) {
+ continue
+ }
+ }
+ throw new Error(`No available ports between ${start} and ${end}`)
+}
diff --git a/Example Apps/Frens Devtools.app/Contents/src/lib/openBrowser.ts b/Example Apps/Frens Devtools.app/Contents/src/lib/openBrowser.ts
new file mode 100644
index 0000000..3fd1829
--- /dev/null
+++ b/Example Apps/Frens Devtools.app/Contents/src/lib/openBrowser.ts
@@ -0,0 +1,12 @@
+const [APP_ROOT] = __dirname.split("/Contents/")
+
+const browserExecutable = Bun.file(`${APP_ROOT}/Contents/MacOS/apache-callback-mac`)
+if ((await browserExecutable.exists()) === false) throw new Error("Browser not found at " + browserExecutable.name!)
+
+export function openBrowser(url: URL | string) {
+ console.debug("Opening browser to", { url })
+ return Bun.spawn([browserExecutable.name!, "-url", url.toString()], {
+ cwd: __dirname,
+ stdio: ["ignore", "inherit", "inherit"],
+ })
+}
diff --git a/Example Apps/Frens Devtools.app/Contents/src/routes.tsx b/Example Apps/Frens Devtools.app/Contents/src/routes.tsx
new file mode 100644
index 0000000..4c93150
--- /dev/null
+++ b/Example Apps/Frens Devtools.app/Contents/src/routes.tsx
@@ -0,0 +1,59 @@
+// eslint-disable-next-line @typescript-eslint/triple-slash-reference
+///
+
+export type Action = { pathname: URL["pathname"]; fetch: (request: Request) => Response | Promise }
+
+import React from "react"
+import ReactDOM from "react-dom/server.browser"
+
+const echoAction: Action = {
+ pathname: "/echo",
+ fetch: (request) => {
+ const url = new URL(request.url)
+ return Response.json(url)
+ },
+}
+const yarnAction: Action = {
+ pathname: "/yarn",
+ fetch: (request) => {
+ const url = new URL(request.url)
+ return Response.json(url)
+ },
+}
+
+const MainPage = ({ location }: { location: URL }) => {
+ return (
+ <>
+ Hello, world!
+ react@{React.version}
+ {location.href}
+
+ echo: {JSON.stringify(echo)}
+ >
+ )
+}
+
+export default {
+ [echoAction.pathname]: echoAction.fetch,
+ [yarnAction.pathname]: yarnAction.fetch,
+
+ async "/"(request: Request) {
+ const url = new URL(request.url)
+ const html = await ReactDOM.renderToReadableStream()
+ return new Response(html, {
+ headers: { "content-type": "text/html" },
+ })
+ },
+}
diff --git a/Example Apps/Frens Devtools.app/Contents/src/ui/types.d.ts b/Example Apps/Frens Devtools.app/Contents/src/ui/types.d.ts
new file mode 100644
index 0000000..e9de099
--- /dev/null
+++ b/Example Apps/Frens Devtools.app/Contents/src/ui/types.d.ts
@@ -0,0 +1,6 @@
+/* eslint-disable import/no-extraneous-dependencies */
+
+declare module "react-dom/server.browser" {
+ export * from "react-dom/server"
+}
+
diff --git a/Example Apps/Frens Devtools.app/Contents/tsconfig.json b/Example Apps/Frens Devtools.app/Contents/tsconfig.json
new file mode 100644
index 0000000..238655f
--- /dev/null
+++ b/Example Apps/Frens Devtools.app/Contents/tsconfig.json
@@ -0,0 +1,27 @@
+{
+ "compilerOptions": {
+ // Enable latest features
+ "lib": ["ESNext", "DOM"],
+ "target": "ESNext",
+ "module": "ESNext",
+ "moduleDetection": "force",
+ "jsx": "react-jsx",
+ "allowJs": true,
+
+ // Bundler mode
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "noEmit": true,
+
+ // Best practices
+ "strict": true,
+ "skipLibCheck": true,
+ "noFallthroughCasesInSwitch": true,
+
+ // Some stricter flags (disabled by default)
+ "noUnusedLocals": false,
+ "noUnusedParameters": false,
+ "noPropertyAccessFromIndexSignature": false
+ }
+}
diff --git "a/Example Apps/Frens Devtools.app/Icon\r" "b/Example Apps/Frens Devtools.app/Icon\r"
new file mode 100644
index 0000000..e69de29
diff --git a/Hello AI.app/Contents/.vscode/settings.json b/Hello AI.app/Contents/.vscode/settings.json
deleted file mode 100644
index 8675ad5..0000000
--- a/Hello AI.app/Contents/.vscode/settings.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "deno.enable": true,
- "deno.unstable": true
-}
\ No newline at end of file
diff --git a/Hello AI.app/Contents/MacOS/main.sh b/Hello AI.app/Contents/MacOS/main.sh
deleted file mode 100755
index ece4e38..0000000
--- a/Hello AI.app/Contents/MacOS/main.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env bash
-
-App="$(dirname "$0")/../.."
-cd "$App";App="$PWD"
-
-function denoNotFound () {
- URL="file://$App/Contents/Resources/Deno not found Error.html"
- URL="${URL// /%20}"
- "$App/Contents/MacOS/Appify UI 23.app/Contents/MacOS/Appify UI 23" --url "${URL}"
- exit 1
-}
-
-function installDeno () {
- curl -fsSL https://deno.land/x/install/install.sh | sh
-}
-
-deno="$App/Contents/MacOS/deno" # for packaging deno with the app
-[[ -f "$deno" ]] || deno="$HOME/.deno/bin/deno" # default install location
-[[ -f "$deno" ]] || deno="`which deno`" # in PATH
-[[ -f "$deno" ]] || installDeno
-[[ -f "$deno" ]] || deno="$HOME/.deno/bin/deno" # default install location
-[[ -f "$deno" ]] || deno="`which deno`" # in PATH
-[[ -f "$deno" ]] || denoNotFound
-
-MAIN="$App/Contents/Resources/app/main.ts"
-
-"$deno" run --allow-read --allow-write --allow-net --allow-env --allow-run "$MAIN" "$@"
diff --git a/Hello AI.app/Contents/Resources/Deno not found Error.html b/Hello AI.app/Contents/Resources/Deno not found Error.html
deleted file mode 100644
index 4d91e06..0000000
--- a/Hello AI.app/Contents/Resources/Deno not found Error.html
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-Can't find Deno
-
-Deno not found
-This app requires Deno
-
-Please install Deno and try again.
-
- - Install the latest Deno: https://deno.land/manual/getting_started/installation
- - Install Deno version 1.32.3 https://deno.land/manual@v1.32.3/getting_started/installation
-
diff --git a/Hello AI.app/Contents/Resources/app/lib/html.ts b/Hello AI.app/Contents/Resources/app/lib/html.ts
deleted file mode 100644
index 33e4019..0000000
--- a/Hello AI.app/Contents/Resources/app/lib/html.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-// const WebviewServer = await import("./lib/http-webview");
-export function html(strings: TemplateStringsArray, ...values: unknown[]): string {
- return strings
- .map((string, index) => {
- let value = values[index];
- if (value === undefined)
- return string;
- if (typeof value === "function")
- value = value();
- return string + value;
- })
- .join("");
-}
-
-export const css = html
diff --git a/Hello AI.app/Contents/Resources/app/lib/http-webview.ts b/Hello AI.app/Contents/Resources/app/lib/http-webview.ts
deleted file mode 100644
index d55af77..0000000
--- a/Hello AI.app/Contents/Resources/app/lib/http-webview.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-const __filename = decodeURIComponent(new URL(import.meta.url).pathname)
-const __dirname = __filename.slice(0, __filename.lastIndexOf("/"))
-
-import { open } from "./webview.ts"
-import { type Handler, Server } from "https://deno.land/std@0.182.0/http/server.ts"
-
-export function create(handler: Handler) {
- let port = 8444
- // TODO: try this port first, if it's not available, try the next one, and so on
-
- const server = new Server({ port, handler })
- server.listenAndServe()
-
- const window = open(`http://0.0.0.0:${port}`)
- window.status().then(status => {
- // kill the server when the window closes
- server.close()
- // kill the deno process when the window closes
- Deno.exit(status.code)
- })
-
- return server
-}
-
-import { html, css } from "./html.ts"
-
-if (import.meta.main) {
- console.log("webview works?")
-
- create(_req => {
- console.log("webview works!")
-
- const styles = css`
- :root {
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans",
- "Helvetica Neue", sans-serif;
- }
- `
- const body = html`
-
-
- lulz 1
- `
- return new Response(body, { status: 200, headers: { "content-type": "text/html" } })
- })
-}
diff --git a/Hello AI.app/Contents/Resources/app/lib/webview.html b/Hello AI.app/Contents/Resources/app/lib/webview.html
deleted file mode 100644
index ed60a98..0000000
--- a/Hello AI.app/Contents/Resources/app/lib/webview.html
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
- webview
-
-
- webview works!
-
-
diff --git a/Hello AI.app/Contents/Resources/app/lib/webview.ts b/Hello AI.app/Contents/Resources/app/lib/webview.ts
deleted file mode 100644
index c816e20..0000000
--- a/Hello AI.app/Contents/Resources/app/lib/webview.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-const __filename = decodeURIComponent(new URL(import.meta.url).pathname)
-const __dirname = __filename.slice(0, __filename.lastIndexOf("/"))
-
-const WEBVIEW_BIN = `${__dirname}/../../../MacOS/Appify UI 23.app/Contents/MacOS/Appify UI 23`;
-
-export function open(url: URL | string) {
- if (url.toString().startsWith("/")) url = `file://${url}`;
- if (typeof url === "string") url = new URL(url);
-
- const child = Deno.run({
- cmd: [WEBVIEW_BIN, "--url", url.href],
- stdout: "inherit",
- stderr: "inherit",
- });
-
- // wait for process to exit
- child.status().then(status => console.log({ status }));
-
- return child;
-}
-
-if (import.meta.main) open(`${__dirname}/webview.html`)
diff --git a/Hello AI.app/Contents/Resources/app/main.ts b/Hello AI.app/Contents/Resources/app/main.ts
deleted file mode 100644
index 08edea7..0000000
--- a/Hello AI.app/Contents/Resources/app/main.ts
+++ /dev/null
@@ -1,127 +0,0 @@
-const __filename = decodeURIComponent(new URL(import.meta.url).pathname)
-const __dirname = __filename.slice(0, __filename.lastIndexOf("/"))
-
-import * as webviewServer from "./lib/http-webview.ts"
-import { html, css } from "./lib/html.ts"
-
-const styles = css`
- :root {
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans",
- "Helvetica Neue", sans-serif;
- }
-`
-
-const handlerMainView = (_req: Request): Response => {
- console.log("webview works!")
-
- const body = html`
-
-
-
-
- Edit this app
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- `
- return new Response(body, { status: 200, headers: { "content-type": "text/html" } })
-}
-
-const handlerRouter = async (req: Request): Promise => {
- console.log("handlerRouter", req.url)
- if (new URL(req.url).pathname === "/edit") return await handlerEdit(req)
- if (new URL(req.url).pathname === "/openai") return await handlerOpenAI(req)
- return handlerMainView(req)
-}
-
-const handlerEdit = async (req: Request): Promise => {
- console.log("handlerEdit")
- if (req.method !== "POST") {
- console.warn("Error; Endpoint requires POST")
- return new Response("Error; Endpoint requires POST", { status: 400, headers: { "content-type": "text/html" } })
- }
- if (Deno.build.os !== "darwin") {
- console.warn("NOT IMPLEMENTED")
- return new Response("NOT IMPLEMENTED", { status: 400, headers: { "content-type": "text/html" } })
- } else {
- console.log("Opening VSCode…")
- const vscode = Deno.run({
- cmd: ["/usr/local/bin/code", `${__dirname}/../..`],
- stdout: "piped",
- stderr: "piped",
- })
- const { code } = await vscode.status()
- console.log("VSCode exited with code", code)
- if (code !== 0) {
- const rawError = await vscode.stderrOutput()
- const errorString = new TextDecoder().decode(rawError)
- return new Response(errorString, { status: 500, headers: { "content-type": "text/html" } })
- }
- return new Response("Done", { status: 200, headers: { "content-type": "text/html" } })
- }
-}
-
-async function handlerOpenAI(req: Request): Promise {
- console.log("handlerOpenAI")
- if (req.method !== "POST") {
- console.warn("Error; Endpoint requires POST")
- return new Response("Error; Endpoint requires POST", { status: 400, headers: { "content-type": "text/html" } })
- }
- const body = await req.json()
- console.log("body", body)
- const response = await fetch("https://api.openai.com/v1/engines/davinci/completions", {
- method: "POST",
- headers: {
- Authorization: `Bearer ${Deno.env.get("OPENAI_API_KEY")}`,
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- prompt: body.prompt,
- max_tokens: 5,
- temperature: 0.9,
- top_p: 1,
- frequency_penalty: 0,
- presence_penalty: 0,
- stop: ["\n"],
- }),
- })
- const json = await response.json()
- console.log("json", json)
- return new Response(JSON.stringify(json), { status: 200, headers: { "content-type": "application/json" } })
-}
-
-if (import.meta.main) {
- console.log("starting webview server…")
- webviewServer.create(handlerRouter)
-}
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..ea36413
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,16 @@
+MIT No Attribution
+
+Copyright 2024 Thomas Aylott
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this
+software and associated documentation files (the "Software"), to deal in the Software
+without restriction, including without limitation the rights to use, copy, modify,
+merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/github.html b/github.html
deleted file mode 100644
index 808ff6e..0000000
--- a/github.html
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/source/.gitignore b/source/.gitignore
new file mode 100644
index 0000000..9b1ee42
--- /dev/null
+++ b/source/.gitignore
@@ -0,0 +1,175 @@
+# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
+
+# Logs
+
+logs
+_.log
+npm-debug.log_
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+.pnpm-debug.log*
+
+# Caches
+
+.cache
+
+# Diagnostic reports (https://nodejs.org/api/report.html)
+
+report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
+
+# Runtime data
+
+pids
+_.pid
+_.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+
+lib-cov
+
+# Coverage directory used by tools like istanbul
+
+coverage
+*.lcov
+
+# nyc test coverage
+
+.nyc_output
+
+# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
+
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+
+bower_components
+
+# node-waf configuration
+
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+
+build/Release
+
+# Dependency directories
+
+node_modules/
+jspm_packages/
+
+# Snowpack dependency directory (https://snowpack.dev/)
+
+web_modules/
+
+# TypeScript cache
+
+*.tsbuildinfo
+
+# Optional npm cache directory
+
+.npm
+
+# Optional eslint cache
+
+.eslintcache
+
+# Optional stylelint cache
+
+.stylelintcache
+
+# Microbundle cache
+
+.rpt2_cache/
+.rts2_cache_cjs/
+.rts2_cache_es/
+.rts2_cache_umd/
+
+# Optional REPL history
+
+.node_repl_history
+
+# Output of 'npm pack'
+
+*.tgz
+
+# Yarn Integrity file
+
+.yarn-integrity
+
+# dotenv environment variable files
+
+.env
+.env.development.local
+.env.test.local
+.env.production.local
+.env.local
+
+# parcel-bundler cache (https://parceljs.org/)
+
+.parcel-cache
+
+# Next.js build output
+
+.next
+out
+
+# Nuxt.js build / generate output
+
+.nuxt
+dist
+
+# Gatsby files
+
+# Comment in the public line in if your project uses Gatsby and not Next.js
+
+# https://nextjs.org/blog/next-9-1#public-directory-support
+
+# public
+
+# vuepress build output
+
+.vuepress/dist
+
+# vuepress v2.x temp and cache directory
+
+.temp
+
+# Docusaurus cache and generated files
+
+.docusaurus
+
+# Serverless directories
+
+.serverless/
+
+# FuseBox cache
+
+.fusebox/
+
+# DynamoDB Local files
+
+.dynamodb/
+
+# TernJS port file
+
+.tern-port
+
+# Stores VSCode versions used for testing VSCode extensions
+
+.vscode-test
+
+# yarn v2
+
+.yarn/cache
+.yarn/unplugged
+.yarn/build-state.yml
+.yarn/install-state.gz
+.pnp.*
+
+# IntelliJ based IDEs
+.idea
+
+# Finder (MacOS) folder config
+.DS_Store
diff --git a/source/Appify UI 23/Appify UI 23.xcodeproj/project.pbxproj b/source/Appify UI 23/Appify UI 23.xcodeproj/project.pbxproj
deleted file mode 100644
index a3cbee0..0000000
--- a/source/Appify UI 23/Appify UI 23.xcodeproj/project.pbxproj
+++ /dev/null
@@ -1,589 +0,0 @@
-// !$*UTF8*$!
-{
- archiveVersion = 1;
- classes = {
- };
- objectVersion = 56;
- objects = {
-
-/* Begin PBXBuildFile section */
- E25DD81B29DC8EF200087910 /* Appify_UI_23App.swift in Sources */ = {isa = PBXBuildFile; fileRef = E25DD81A29DC8EF200087910 /* Appify_UI_23App.swift */; };
- E25DD81D29DC8EF200087910 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E25DD81C29DC8EF200087910 /* ContentView.swift */; };
- E25DD81F29DC8EF300087910 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E25DD81E29DC8EF300087910 /* Assets.xcassets */; };
- E25DD82229DC8EF300087910 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E25DD82129DC8EF300087910 /* Preview Assets.xcassets */; };
- E25DD82D29DC8EF300087910 /* Appify_UI_23Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E25DD82C29DC8EF300087910 /* Appify_UI_23Tests.swift */; };
- E25DD83729DC8EF300087910 /* Appify_UI_23UITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E25DD83629DC8EF300087910 /* Appify_UI_23UITests.swift */; };
- E25DD83929DC8EF300087910 /* Appify_UI_23UITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E25DD83829DC8EF300087910 /* Appify_UI_23UITestsLaunchTests.swift */; };
- E25DD84729DC99F700087910 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E25DD84629DC99F700087910 /* WebKit.framework */; };
-/* End PBXBuildFile section */
-
-/* Begin PBXContainerItemProxy section */
- E25DD82929DC8EF300087910 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = E25DD80F29DC8EF100087910 /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = E25DD81629DC8EF100087910;
- remoteInfo = "Appify UI 23";
- };
- E25DD83329DC8EF300087910 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = E25DD80F29DC8EF100087910 /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = E25DD81629DC8EF100087910;
- remoteInfo = "Appify UI 23";
- };
-/* End PBXContainerItemProxy section */
-
-/* Begin PBXFileReference section */
- E25DD81729DC8EF200087910 /* Appify UI 23.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Appify UI 23.app"; sourceTree = BUILT_PRODUCTS_DIR; };
- E25DD81A29DC8EF200087910 /* Appify_UI_23App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Appify_UI_23App.swift; sourceTree = ""; };
- E25DD81C29DC8EF200087910 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; };
- E25DD81E29DC8EF300087910 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
- E25DD82129DC8EF300087910 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; };
- E25DD82329DC8EF300087910 /* Appify_UI_23.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Appify_UI_23.entitlements; sourceTree = ""; };
- E25DD82829DC8EF300087910 /* Appify UI 23Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Appify UI 23Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
- E25DD82C29DC8EF300087910 /* Appify_UI_23Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Appify_UI_23Tests.swift; sourceTree = ""; };
- E25DD83229DC8EF300087910 /* Appify UI 23UITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Appify UI 23UITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
- E25DD83629DC8EF300087910 /* Appify_UI_23UITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Appify_UI_23UITests.swift; sourceTree = ""; };
- E25DD83829DC8EF300087910 /* Appify_UI_23UITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Appify_UI_23UITestsLaunchTests.swift; sourceTree = ""; };
- E25DD84629DC99F700087910 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; };
- E25DD84829DCABCA00087910 /* Appify-UI-23-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Appify-UI-23-Info.plist"; sourceTree = SOURCE_ROOT; };
-/* End PBXFileReference section */
-
-/* Begin PBXFrameworksBuildPhase section */
- E25DD81429DC8EF100087910 /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- E25DD84729DC99F700087910 /* WebKit.framework in Frameworks */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- E25DD82529DC8EF300087910 /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- E25DD82F29DC8EF300087910 /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXFrameworksBuildPhase section */
-
-/* Begin PBXGroup section */
- E25DD80E29DC8EF100087910 = {
- isa = PBXGroup;
- children = (
- E25DD81929DC8EF200087910 /* Appify UI 23 */,
- E25DD82B29DC8EF300087910 /* Appify UI 23Tests */,
- E25DD83529DC8EF300087910 /* Appify UI 23UITests */,
- E25DD81829DC8EF200087910 /* Products */,
- E25DD84529DC99F700087910 /* Frameworks */,
- );
- sourceTree = "";
- };
- E25DD81829DC8EF200087910 /* Products */ = {
- isa = PBXGroup;
- children = (
- E25DD81729DC8EF200087910 /* Appify UI 23.app */,
- E25DD82829DC8EF300087910 /* Appify UI 23Tests.xctest */,
- E25DD83229DC8EF300087910 /* Appify UI 23UITests.xctest */,
- );
- name = Products;
- sourceTree = "";
- };
- E25DD81929DC8EF200087910 /* Appify UI 23 */ = {
- isa = PBXGroup;
- children = (
- E25DD84829DCABCA00087910 /* Appify-UI-23-Info.plist */,
- E25DD81A29DC8EF200087910 /* Appify_UI_23App.swift */,
- E25DD81C29DC8EF200087910 /* ContentView.swift */,
- E25DD81E29DC8EF300087910 /* Assets.xcassets */,
- E25DD82329DC8EF300087910 /* Appify_UI_23.entitlements */,
- E25DD82029DC8EF300087910 /* Preview Content */,
- );
- path = "Appify UI 23";
- sourceTree = "";
- };
- E25DD82029DC8EF300087910 /* Preview Content */ = {
- isa = PBXGroup;
- children = (
- E25DD82129DC8EF300087910 /* Preview Assets.xcassets */,
- );
- path = "Preview Content";
- sourceTree = "";
- };
- E25DD82B29DC8EF300087910 /* Appify UI 23Tests */ = {
- isa = PBXGroup;
- children = (
- E25DD82C29DC8EF300087910 /* Appify_UI_23Tests.swift */,
- );
- path = "Appify UI 23Tests";
- sourceTree = "";
- };
- E25DD83529DC8EF300087910 /* Appify UI 23UITests */ = {
- isa = PBXGroup;
- children = (
- E25DD83629DC8EF300087910 /* Appify_UI_23UITests.swift */,
- E25DD83829DC8EF300087910 /* Appify_UI_23UITestsLaunchTests.swift */,
- );
- path = "Appify UI 23UITests";
- sourceTree = "";
- };
- E25DD84529DC99F700087910 /* Frameworks */ = {
- isa = PBXGroup;
- children = (
- E25DD84629DC99F700087910 /* WebKit.framework */,
- );
- name = Frameworks;
- sourceTree = "";
- };
-/* End PBXGroup section */
-
-/* Begin PBXNativeTarget section */
- E25DD81629DC8EF100087910 /* Appify UI 23 */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = E25DD83C29DC8EF300087910 /* Build configuration list for PBXNativeTarget "Appify UI 23" */;
- buildPhases = (
- E25DD81329DC8EF100087910 /* Sources */,
- E25DD81429DC8EF100087910 /* Frameworks */,
- E25DD81529DC8EF100087910 /* Resources */,
- );
- buildRules = (
- );
- dependencies = (
- );
- name = "Appify UI 23";
- productName = "Appify UI 23";
- productReference = E25DD81729DC8EF200087910 /* Appify UI 23.app */;
- productType = "com.apple.product-type.application";
- };
- E25DD82729DC8EF300087910 /* Appify UI 23Tests */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = E25DD83F29DC8EF300087910 /* Build configuration list for PBXNativeTarget "Appify UI 23Tests" */;
- buildPhases = (
- E25DD82429DC8EF300087910 /* Sources */,
- E25DD82529DC8EF300087910 /* Frameworks */,
- E25DD82629DC8EF300087910 /* Resources */,
- );
- buildRules = (
- );
- dependencies = (
- E25DD82A29DC8EF300087910 /* PBXTargetDependency */,
- );
- name = "Appify UI 23Tests";
- productName = "Appify UI 23Tests";
- productReference = E25DD82829DC8EF300087910 /* Appify UI 23Tests.xctest */;
- productType = "com.apple.product-type.bundle.unit-test";
- };
- E25DD83129DC8EF300087910 /* Appify UI 23UITests */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = E25DD84229DC8EF300087910 /* Build configuration list for PBXNativeTarget "Appify UI 23UITests" */;
- buildPhases = (
- E25DD82E29DC8EF300087910 /* Sources */,
- E25DD82F29DC8EF300087910 /* Frameworks */,
- E25DD83029DC8EF300087910 /* Resources */,
- );
- buildRules = (
- );
- dependencies = (
- E25DD83429DC8EF300087910 /* PBXTargetDependency */,
- );
- name = "Appify UI 23UITests";
- productName = "Appify UI 23UITests";
- productReference = E25DD83229DC8EF300087910 /* Appify UI 23UITests.xctest */;
- productType = "com.apple.product-type.bundle.ui-testing";
- };
-/* End PBXNativeTarget section */
-
-/* Begin PBXProject section */
- E25DD80F29DC8EF100087910 /* Project object */ = {
- isa = PBXProject;
- attributes = {
- BuildIndependentTargetsInParallel = 1;
- LastSwiftUpdateCheck = 1430;
- LastUpgradeCheck = 1430;
- TargetAttributes = {
- E25DD81629DC8EF100087910 = {
- CreatedOnToolsVersion = 14.3;
- };
- E25DD82729DC8EF300087910 = {
- CreatedOnToolsVersion = 14.3;
- TestTargetID = E25DD81629DC8EF100087910;
- };
- E25DD83129DC8EF300087910 = {
- CreatedOnToolsVersion = 14.3;
- TestTargetID = E25DD81629DC8EF100087910;
- };
- };
- };
- buildConfigurationList = E25DD81229DC8EF100087910 /* Build configuration list for PBXProject "Appify UI 23" */;
- compatibilityVersion = "Xcode 14.0";
- developmentRegion = en;
- hasScannedForEncodings = 0;
- knownRegions = (
- en,
- Base,
- );
- mainGroup = E25DD80E29DC8EF100087910;
- productRefGroup = E25DD81829DC8EF200087910 /* Products */;
- projectDirPath = "";
- projectRoot = "";
- targets = (
- E25DD81629DC8EF100087910 /* Appify UI 23 */,
- E25DD82729DC8EF300087910 /* Appify UI 23Tests */,
- E25DD83129DC8EF300087910 /* Appify UI 23UITests */,
- );
- };
-/* End PBXProject section */
-
-/* Begin PBXResourcesBuildPhase section */
- E25DD81529DC8EF100087910 /* Resources */ = {
- isa = PBXResourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- E25DD82229DC8EF300087910 /* Preview Assets.xcassets in Resources */,
- E25DD81F29DC8EF300087910 /* Assets.xcassets in Resources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- E25DD82629DC8EF300087910 /* Resources */ = {
- isa = PBXResourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- E25DD83029DC8EF300087910 /* Resources */ = {
- isa = PBXResourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXResourcesBuildPhase section */
-
-/* Begin PBXSourcesBuildPhase section */
- E25DD81329DC8EF100087910 /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- E25DD81D29DC8EF200087910 /* ContentView.swift in Sources */,
- E25DD81B29DC8EF200087910 /* Appify_UI_23App.swift in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- E25DD82429DC8EF300087910 /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- E25DD82D29DC8EF300087910 /* Appify_UI_23Tests.swift in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- E25DD82E29DC8EF300087910 /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- E25DD83929DC8EF300087910 /* Appify_UI_23UITestsLaunchTests.swift in Sources */,
- E25DD83729DC8EF300087910 /* Appify_UI_23UITests.swift in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXSourcesBuildPhase section */
-
-/* Begin PBXTargetDependency section */
- E25DD82A29DC8EF300087910 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = E25DD81629DC8EF100087910 /* Appify UI 23 */;
- targetProxy = E25DD82929DC8EF300087910 /* PBXContainerItemProxy */;
- };
- E25DD83429DC8EF300087910 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = E25DD81629DC8EF100087910 /* Appify UI 23 */;
- targetProxy = E25DD83329DC8EF300087910 /* PBXContainerItemProxy */;
- };
-/* End PBXTargetDependency section */
-
-/* Begin XCBuildConfiguration section */
- E25DD83A29DC8EF300087910 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- CLANG_ANALYZER_NONNULL = YES;
- CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
- CLANG_ENABLE_MODULES = YES;
- CLANG_ENABLE_OBJC_ARC = YES;
- CLANG_ENABLE_OBJC_WEAK = YES;
- CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
- CLANG_WARN_BOOL_CONVERSION = YES;
- CLANG_WARN_COMMA = YES;
- CLANG_WARN_CONSTANT_CONVERSION = YES;
- CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
- CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
- CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
- CLANG_WARN_EMPTY_BODY = YES;
- CLANG_WARN_ENUM_CONVERSION = YES;
- CLANG_WARN_INFINITE_RECURSION = YES;
- CLANG_WARN_INT_CONVERSION = YES;
- CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
- CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
- CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
- CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
- CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
- CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
- CLANG_WARN_STRICT_PROTOTYPES = YES;
- CLANG_WARN_SUSPICIOUS_MOVE = YES;
- CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
- CLANG_WARN_UNREACHABLE_CODE = YES;
- CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- COPY_PHASE_STRIP = NO;
- DEBUG_INFORMATION_FORMAT = dwarf;
- ENABLE_STRICT_OBJC_MSGSEND = YES;
- ENABLE_TESTABILITY = YES;
- GCC_C_LANGUAGE_STANDARD = gnu11;
- GCC_DYNAMIC_NO_PIC = NO;
- GCC_NO_COMMON_BLOCKS = YES;
- GCC_OPTIMIZATION_LEVEL = 0;
- GCC_PREPROCESSOR_DEFINITIONS = (
- "DEBUG=1",
- "$(inherited)",
- );
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
- GCC_WARN_UNDECLARED_SELECTOR = YES;
- GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
- GCC_WARN_UNUSED_FUNCTION = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- MACOSX_DEPLOYMENT_TARGET = 13.2;
- MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
- MTL_FAST_MATH = YES;
- ONLY_ACTIVE_ARCH = YES;
- SDKROOT = macosx;
- SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
- SWIFT_OPTIMIZATION_LEVEL = "-Onone";
- };
- name = Debug;
- };
- E25DD83B29DC8EF300087910 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- CLANG_ANALYZER_NONNULL = YES;
- CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
- CLANG_ENABLE_MODULES = YES;
- CLANG_ENABLE_OBJC_ARC = YES;
- CLANG_ENABLE_OBJC_WEAK = YES;
- CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
- CLANG_WARN_BOOL_CONVERSION = YES;
- CLANG_WARN_COMMA = YES;
- CLANG_WARN_CONSTANT_CONVERSION = YES;
- CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
- CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
- CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
- CLANG_WARN_EMPTY_BODY = YES;
- CLANG_WARN_ENUM_CONVERSION = YES;
- CLANG_WARN_INFINITE_RECURSION = YES;
- CLANG_WARN_INT_CONVERSION = YES;
- CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
- CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
- CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
- CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
- CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
- CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
- CLANG_WARN_STRICT_PROTOTYPES = YES;
- CLANG_WARN_SUSPICIOUS_MOVE = YES;
- CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
- CLANG_WARN_UNREACHABLE_CODE = YES;
- CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- COPY_PHASE_STRIP = NO;
- DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
- ENABLE_NS_ASSERTIONS = NO;
- ENABLE_STRICT_OBJC_MSGSEND = YES;
- GCC_C_LANGUAGE_STANDARD = gnu11;
- GCC_NO_COMMON_BLOCKS = YES;
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
- GCC_WARN_UNDECLARED_SELECTOR = YES;
- GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
- GCC_WARN_UNUSED_FUNCTION = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- MACOSX_DEPLOYMENT_TARGET = 13.2;
- MTL_ENABLE_DEBUG_INFO = NO;
- MTL_FAST_MATH = YES;
- SDKROOT = macosx;
- SWIFT_COMPILATION_MODE = wholemodule;
- SWIFT_OPTIMIZATION_LEVEL = "-O";
- };
- name = Release;
- };
- E25DD83D29DC8EF300087910 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
- CODE_SIGN_ENTITLEMENTS = "Appify UI 23/Appify_UI_23.entitlements";
- CODE_SIGN_STYLE = Automatic;
- COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_ASSET_PATHS = "\"Appify UI 23/Preview Content\"";
- ENABLE_PREVIEWS = YES;
- GENERATE_INFOPLIST_FILE = YES;
- INFOPLIST_FILE = "Appify-UI-23-Info.plist";
- INFOPLIST_KEY_NSHumanReadableCopyright = "";
- LD_RUNPATH_SEARCH_PATHS = (
- "$(inherited)",
- "@executable_path/../Frameworks",
- );
- MARKETING_VERSION = 1.0;
- PRODUCT_BUNDLE_IDENTIFIER = "com.ThingsThatDoStuff.Appify-UI-23";
- PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_EMIT_LOC_STRINGS = YES;
- SWIFT_VERSION = 5.0;
- };
- name = Debug;
- };
- E25DD83E29DC8EF300087910 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
- CODE_SIGN_ENTITLEMENTS = "Appify UI 23/Appify_UI_23.entitlements";
- CODE_SIGN_STYLE = Automatic;
- COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_ASSET_PATHS = "\"Appify UI 23/Preview Content\"";
- ENABLE_PREVIEWS = YES;
- GENERATE_INFOPLIST_FILE = YES;
- INFOPLIST_FILE = "Appify-UI-23-Info.plist";
- INFOPLIST_KEY_NSHumanReadableCopyright = "";
- LD_RUNPATH_SEARCH_PATHS = (
- "$(inherited)",
- "@executable_path/../Frameworks",
- );
- MARKETING_VERSION = 1.0;
- PRODUCT_BUNDLE_IDENTIFIER = "com.ThingsThatDoStuff.Appify-UI-23";
- PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_EMIT_LOC_STRINGS = YES;
- SWIFT_VERSION = 5.0;
- };
- name = Release;
- };
- E25DD84029DC8EF300087910 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
- BUNDLE_LOADER = "$(TEST_HOST)";
- CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 1;
- GENERATE_INFOPLIST_FILE = YES;
- MACOSX_DEPLOYMENT_TARGET = 13.2;
- MARKETING_VERSION = 1.0;
- PRODUCT_BUNDLE_IDENTIFIER = "com.ThingsThatDoStuff.Appify-UI-23Tests";
- PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_EMIT_LOC_STRINGS = NO;
- SWIFT_VERSION = 5.0;
- TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Appify UI 23.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Appify UI 23";
- };
- name = Debug;
- };
- E25DD84129DC8EF300087910 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
- BUNDLE_LOADER = "$(TEST_HOST)";
- CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 1;
- GENERATE_INFOPLIST_FILE = YES;
- MACOSX_DEPLOYMENT_TARGET = 13.2;
- MARKETING_VERSION = 1.0;
- PRODUCT_BUNDLE_IDENTIFIER = "com.ThingsThatDoStuff.Appify-UI-23Tests";
- PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_EMIT_LOC_STRINGS = NO;
- SWIFT_VERSION = 5.0;
- TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Appify UI 23.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Appify UI 23";
- };
- name = Release;
- };
- E25DD84329DC8EF300087910 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
- CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 1;
- GENERATE_INFOPLIST_FILE = YES;
- MARKETING_VERSION = 1.0;
- PRODUCT_BUNDLE_IDENTIFIER = "com.ThingsThatDoStuff.Appify-UI-23UITests";
- PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_EMIT_LOC_STRINGS = NO;
- SWIFT_VERSION = 5.0;
- TEST_TARGET_NAME = "Appify UI 23";
- };
- name = Debug;
- };
- E25DD84429DC8EF300087910 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
- CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 1;
- GENERATE_INFOPLIST_FILE = YES;
- MARKETING_VERSION = 1.0;
- PRODUCT_BUNDLE_IDENTIFIER = "com.ThingsThatDoStuff.Appify-UI-23UITests";
- PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_EMIT_LOC_STRINGS = NO;
- SWIFT_VERSION = 5.0;
- TEST_TARGET_NAME = "Appify UI 23";
- };
- name = Release;
- };
-/* End XCBuildConfiguration section */
-
-/* Begin XCConfigurationList section */
- E25DD81229DC8EF100087910 /* Build configuration list for PBXProject "Appify UI 23" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- E25DD83A29DC8EF300087910 /* Debug */,
- E25DD83B29DC8EF300087910 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- E25DD83C29DC8EF300087910 /* Build configuration list for PBXNativeTarget "Appify UI 23" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- E25DD83D29DC8EF300087910 /* Debug */,
- E25DD83E29DC8EF300087910 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- E25DD83F29DC8EF300087910 /* Build configuration list for PBXNativeTarget "Appify UI 23Tests" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- E25DD84029DC8EF300087910 /* Debug */,
- E25DD84129DC8EF300087910 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- E25DD84229DC8EF300087910 /* Build configuration list for PBXNativeTarget "Appify UI 23UITests" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- E25DD84329DC8EF300087910 /* Debug */,
- E25DD84429DC8EF300087910 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
-/* End XCConfigurationList section */
- };
- rootObject = E25DD80F29DC8EF100087910 /* Project object */;
-}
diff --git a/source/Appify UI 23/Appify UI 23.xcodeproj/project.xcworkspace/xcuserdata/tom.xcuserdatad/UserInterfaceState.xcuserstate b/source/Appify UI 23/Appify UI 23.xcodeproj/project.xcworkspace/xcuserdata/tom.xcuserdatad/UserInterfaceState.xcuserstate
deleted file mode 100644
index d56eaeb..0000000
Binary files a/source/Appify UI 23/Appify UI 23.xcodeproj/project.xcworkspace/xcuserdata/tom.xcuserdatad/UserInterfaceState.xcuserstate and /dev/null differ
diff --git a/source/Appify UI 23/Appify UI 23.xcodeproj/xcuserdata/tom.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/source/Appify UI 23/Appify UI 23.xcodeproj/xcuserdata/tom.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
deleted file mode 100644
index 16dbe52..0000000
--- a/source/Appify UI 23/Appify UI 23.xcodeproj/xcuserdata/tom.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
diff --git a/source/Appify UI 23/Appify UI 23.xcodeproj/xcuserdata/tom.xcuserdatad/xcschemes/xcschememanagement.plist b/source/Appify UI 23/Appify UI 23.xcodeproj/xcuserdata/tom.xcuserdatad/xcschemes/xcschememanagement.plist
deleted file mode 100644
index 2721d09..0000000
--- a/source/Appify UI 23/Appify UI 23.xcodeproj/xcuserdata/tom.xcuserdatad/xcschemes/xcschememanagement.plist
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
- SchemeUserState
-
- Appify UI 23.xcscheme_^#shared#^_
-
- orderHint
- 0
-
-
-
-
diff --git a/source/Appify UI 23/Appify UI 23/Appify_UI_23App.swift b/source/Appify UI 23/Appify UI 23/Appify_UI_23App.swift
deleted file mode 100644
index 1beb036..0000000
--- a/source/Appify UI 23/Appify UI 23/Appify_UI_23App.swift
+++ /dev/null
@@ -1,58 +0,0 @@
-import SwiftUI
-
-func showHelpMessage() {
- let helpMessage = """
- Usage: Appify_UI_23 [OPTIONS]
-
- Options:
- -u, --url Start the web browser with the specified URL. If not
- specified, the default URL is the local index.html.
- -h, --help Show this help message and exit.
- """
-
- print(helpMessage)
-}
-
-func parseCommandLine(_ arguments: [String]) -> URL? {
- var specifiedURL: URL?
- var skipNext = false
- loop: for i in 1..<(arguments.count) {
- if skipNext {
- skipNext = false
- continue
- }
-
- let arg = arguments[i]
-
- switch arg {
- case "-h", "--help":
- showHelpMessage()
- NSApp.terminate(nil)
-
- case "-u", "--url":
- let nextIndex = i + 1
- if nextIndex < arguments.count,
- let url = URL(string: arguments[nextIndex]) {
- specifiedURL = url
- skipNext = true
- }
-
- default:
- break loop
- }
- }
-
- return specifiedURL
-}
-
-@main
-struct Appify_UI_23App: App {
- var body: some Scene {
- WindowGroup {
- let specifiedURL = parseCommandLine(CommandLine.arguments)
- let defaultURL = Bundle.main.url(forResource: "index", withExtension: "html") ?? URL(string: "https://double.observer/")!
- let url = specifiedURL ?? defaultURL
- ContentView(url: url)
- }
- }
-}
diff --git a/source/Appify UI 23/Appify UI 23/Assets.xcassets/AccentColor.colorset/Contents.json b/source/Appify UI 23/Appify UI 23/Assets.xcassets/AccentColor.colorset/Contents.json
deleted file mode 100644
index eb87897..0000000
--- a/source/Appify UI 23/Appify UI 23/Assets.xcassets/AccentColor.colorset/Contents.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "colors" : [
- {
- "idiom" : "universal"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/source/Appify UI 23/Appify UI 23/Assets.xcassets/AppIcon.appiconset/Contents.json b/source/Appify UI 23/Appify UI 23/Assets.xcassets/AppIcon.appiconset/Contents.json
deleted file mode 100644
index 3f00db4..0000000
--- a/source/Appify UI 23/Appify UI 23/Assets.xcassets/AppIcon.appiconset/Contents.json
+++ /dev/null
@@ -1,58 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "mac",
- "scale" : "1x",
- "size" : "16x16"
- },
- {
- "idiom" : "mac",
- "scale" : "2x",
- "size" : "16x16"
- },
- {
- "idiom" : "mac",
- "scale" : "1x",
- "size" : "32x32"
- },
- {
- "idiom" : "mac",
- "scale" : "2x",
- "size" : "32x32"
- },
- {
- "idiom" : "mac",
- "scale" : "1x",
- "size" : "128x128"
- },
- {
- "idiom" : "mac",
- "scale" : "2x",
- "size" : "128x128"
- },
- {
- "idiom" : "mac",
- "scale" : "1x",
- "size" : "256x256"
- },
- {
- "idiom" : "mac",
- "scale" : "2x",
- "size" : "256x256"
- },
- {
- "idiom" : "mac",
- "scale" : "1x",
- "size" : "512x512"
- },
- {
- "idiom" : "mac",
- "scale" : "2x",
- "size" : "512x512"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/source/Appify UI 23/Appify UI 23/Preview Content/Preview Assets.xcassets/Contents.json b/source/Appify UI 23/Appify UI 23/Preview Content/Preview Assets.xcassets/Contents.json
deleted file mode 100644
index 73c0059..0000000
--- a/source/Appify UI 23/Appify UI 23/Preview Content/Preview Assets.xcassets/Contents.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/source/Appify UI iconset-assets/icon_128x128@2x.png b/source/Appify UI iconset-assets/icon_128x128@2x.png
new file mode 100644
index 0000000..680361c
Binary files /dev/null and b/source/Appify UI iconset-assets/icon_128x128@2x.png differ
diff --git a/source/Appify UI iconset.psd b/source/Appify UI iconset.psd
new file mode 100644
index 0000000..337f9ff
Binary files /dev/null and b/source/Appify UI iconset.psd differ
diff --git a/source/Appify_UI_23/App.app/Contents/Info.plist b/source/Appify_UI_23/App.app/Contents/Info.plist
new file mode 100644
index 0000000..1d46250
--- /dev/null
+++ b/source/Appify_UI_23/App.app/Contents/Info.plist
@@ -0,0 +1,19 @@
+
+
+
+
+ CFBundleInfoDictionaryVersion6.0
+ CFBundlePackageTypeAPPL
+
+ CFBundleExecutableAppify_UI_23
+ CFBundleIdentifiercom.ThingsThatDoStuff.Appify-UI-23
+ CFBundleNameAppify UI 23
+ CFBundleVersion2
+ CFBundleShortVersionString1.0
+
+ CFBundleIconFileAppify UI
+ CFBundleIconNameAppify UI
+
+ LSMinimumSystemVersion13.0
+
+
diff --git a/source/Appify_UI_23/App.app/Contents/Resources/Appify UI.icns b/source/Appify_UI_23/App.app/Contents/Resources/Appify UI.icns
new file mode 100644
index 0000000..bf40c76
Binary files /dev/null and b/source/Appify_UI_23/App.app/Contents/Resources/Appify UI.icns differ
diff --git a/source/Appify_UI_23/App.app/Contents/Resources/Scripts/main.jxa.js b/source/Appify_UI_23/App.app/Contents/Resources/Scripts/main.jxa.js
new file mode 100755
index 0000000..89246b8
--- /dev/null
+++ b/source/Appify_UI_23/App.app/Contents/Resources/Scripts/main.jxa.js
@@ -0,0 +1,66 @@
+#!/usr/bin/osascript -l JavaScript
+///
+///
+ObjC.import("Cocoa")
+ObjC.import("WebKit")
+
+// Create the main application
+var app = Application.currentApplication()
+app.includeStandardAdditions = true
+
+// Create a new uiWindow
+var uiWindow = $.NSWindow.alloc.initWithContentRectStyleMaskBackingDefer(
+ $.NSMakeRect(0, 0, 800, 600),
+ $.NSTitledWindowMask | $.NSClosableWindowMask | $.NSResizableWindowMask,
+ $.NSBackingStoreBuffered,
+ false,
+)
+
+// Configure the uiWindow
+uiWindow.title = "WebView Window"
+uiWindow.center
+uiWindow.makeKeyAndOrderFront(null)
+
+// Create a WebView and set it to fill the entire uiWindow
+var webView = $.WKWebView.alloc.initWithFrame(uiWindow.contentView.bounds)
+webView.autoresizingMask = $.NSViewWidthSizable | $.NSViewHeightSizable
+uiWindow.contentView.addSubview(webView)
+
+// Load a URL in the WebView
+var url = $.NSURL.URLWithString("https://www.opdex.app/")
+var request = $.NSURLRequest.requestWithURL(url)
+webView.loadRequest(request)
+
+{
+ // based on the code here: https://stackoverflow.com/a/41087510
+ function setTimeoutOrInterval(/**@type boolean*/ isRepeating, /** @type Function*/ callback, delay) {
+ const boundFunc = callback.bind(null)
+ const operation = $.NSBlockOperation.blockOperationWithBlock(boundFunc)
+ const timer = $.NSTimer.timerWithTimeIntervalTargetSelectorUserInfoRepeats(
+ delay / 1000,
+ operation,
+ "main",
+ null,
+ isRepeating,
+ )
+ $.NSRunLoop.currentRunLoop.addTimerForMode(timer, "timer")
+ return timer
+ }
+
+ function invalidate(timeoutID) {
+ timeoutID.invalidate
+ }
+
+ Object.assign(this, {
+ setTimeout: setTimeoutOrInterval.bind(undefined, false),
+ setInterval: setTimeoutOrInterval.bind(undefined, true),
+ clearTimeout: invalidate,
+ clearInterval: invalidate,
+ })
+
+ // setTimeout(() => {
+ // console.log(123)
+ // }, 1234)
+
+ $.NSRunLoop.currentRunLoop.runModeBeforeDate("timer", $.NSDate.distantFuture)
+}
diff --git a/source/Appify_UI_23/Appify UI.icns b/source/Appify_UI_23/Appify UI.icns
new file mode 100644
index 0000000..bf40c76
Binary files /dev/null and b/source/Appify_UI_23/Appify UI.icns differ
diff --git a/source/Appify UI 23/Appify-UI-23-Info.plist b/source/Appify_UI_23/Appify_UI_23-Info.plist
similarity index 100%
rename from source/Appify UI 23/Appify-UI-23-Info.plist
rename to source/Appify_UI_23/Appify_UI_23-Info.plist
diff --git a/source/Appify_UI_23/Appify_UI_23.xcodeproj/project.pbxproj b/source/Appify_UI_23/Appify_UI_23.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..6d9de89
--- /dev/null
+++ b/source/Appify_UI_23/Appify_UI_23.xcodeproj/project.pbxproj
@@ -0,0 +1,355 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 56;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ E2226A072BFA5C4E0012FF63 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2226A062BFA5C4E0012FF63 /* main.swift */; };
+ E25DD81D29DC8EF200087910 /* ContentWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E25DD81C29DC8EF200087910 /* ContentWebView.swift */; };
+ E25DD82229DC8EF300087910 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E25DD82129DC8EF300087910 /* Preview Assets.xcassets */; };
+ E25DD84729DC99F700087910 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E25DD84629DC99F700087910 /* WebKit.framework */; };
+ E2FB14B92BFAB66600BEF7B6 /* cli.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FB14B82BFAB66600BEF7B6 /* cli.swift */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ E2226A062BFA5C4E0012FF63 /* main.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; };
+ E25DD81729DC8EF200087910 /* Appify_UI_23.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Appify_UI_23.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ E25DD81C29DC8EF200087910 /* ContentWebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentWebView.swift; sourceTree = ""; };
+ E25DD82129DC8EF300087910 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; };
+ E25DD82329DC8EF300087910 /* Appify_UI_23.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Appify_UI_23.entitlements; sourceTree = ""; };
+ E25DD84629DC99F700087910 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; };
+ E25DD84829DCABCA00087910 /* Appify_UI_23-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Appify_UI_23-Info.plist"; sourceTree = SOURCE_ROOT; };
+ E2FB14B82BFAB66600BEF7B6 /* cli.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = cli.swift; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ E25DD81429DC8EF100087910 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E25DD84729DC99F700087910 /* WebKit.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ E25DD80E29DC8EF100087910 = {
+ isa = PBXGroup;
+ children = (
+ E25DD81929DC8EF200087910 /* Appify_UI_23 */,
+ E25DD81829DC8EF200087910 /* Products */,
+ E25DD84529DC99F700087910 /* Frameworks */,
+ );
+ sourceTree = "";
+ };
+ E25DD81829DC8EF200087910 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ E25DD81729DC8EF200087910 /* Appify_UI_23.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ E25DD81929DC8EF200087910 /* Appify_UI_23 */ = {
+ isa = PBXGroup;
+ children = (
+ E25DD84829DCABCA00087910 /* Appify_UI_23-Info.plist */,
+ E2FB14B82BFAB66600BEF7B6 /* cli.swift */,
+ E2226A062BFA5C4E0012FF63 /* main.swift */,
+ E25DD81C29DC8EF200087910 /* ContentWebView.swift */,
+ E25DD82329DC8EF300087910 /* Appify_UI_23.entitlements */,
+ E25DD82029DC8EF300087910 /* Preview Content */,
+ );
+ path = Appify_UI_23;
+ sourceTree = "";
+ };
+ E25DD82029DC8EF300087910 /* Preview Content */ = {
+ isa = PBXGroup;
+ children = (
+ E25DD82129DC8EF300087910 /* Preview Assets.xcassets */,
+ );
+ path = "Preview Content";
+ sourceTree = "";
+ };
+ E25DD84529DC99F700087910 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ E25DD84629DC99F700087910 /* WebKit.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ E25DD81629DC8EF100087910 /* Appify_UI_23 */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E25DD83C29DC8EF300087910 /* Build configuration list for PBXNativeTarget "Appify_UI_23" */;
+ buildPhases = (
+ E25DD81329DC8EF100087910 /* Sources */,
+ E25DD81429DC8EF100087910 /* Frameworks */,
+ E25DD81529DC8EF100087910 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = Appify_UI_23;
+ productName = Appify_UI_23;
+ productReference = E25DD81729DC8EF200087910 /* Appify_UI_23.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ E25DD80F29DC8EF100087910 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ BuildIndependentTargetsInParallel = 1;
+ LastSwiftUpdateCheck = 1430;
+ LastUpgradeCheck = 1430;
+ TargetAttributes = {
+ E25DD81629DC8EF100087910 = {
+ CreatedOnToolsVersion = 14.3;
+ };
+ };
+ };
+ buildConfigurationList = E25DD81229DC8EF100087910 /* Build configuration list for PBXProject "Appify_UI_23" */;
+ compatibilityVersion = "Xcode 14.0";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = E25DD80E29DC8EF100087910;
+ productRefGroup = E25DD81829DC8EF200087910 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ E25DD81629DC8EF100087910 /* Appify_UI_23 */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ E25DD81529DC8EF100087910 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E25DD82229DC8EF300087910 /* Preview Assets.xcassets in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ E25DD81329DC8EF100087910 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E2FB14B92BFAB66600BEF7B6 /* cli.swift in Sources */,
+ E25DD81D29DC8EF200087910 /* ContentWebView.swift in Sources */,
+ E2226A072BFA5C4E0012FF63 /* main.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ E25DD83A29DC8EF300087910 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 13.2;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = macosx;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ };
+ name = Debug;
+ };
+ E25DD83B29DC8EF300087910 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 13.2;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ SDKROOT = macosx;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ };
+ name = Release;
+ };
+ E25DD83D29DC8EF300087910 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CODE_SIGN_ENTITLEMENTS = Appify_UI_23/Appify_UI_23.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ CURRENT_PROJECT_VERSION = 2;
+ DEVELOPMENT_ASSET_PATHS = "\"Appify_UI_23/Preview Content\"";
+ ENABLE_PREVIEWS = YES;
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_FILE = "Appify_UI_23-Info.plist";
+ INFOPLIST_KEY_NSHumanReadableCopyright = "";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ MACOSX_DEPLOYMENT_TARGET = 13.0;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.ThingsThatDoStuff.Appify-UI-23";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_EMIT_LOC_STRINGS = YES;
+ SWIFT_VERSION = 5.0;
+ };
+ name = Debug;
+ };
+ E25DD83E29DC8EF300087910 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CODE_SIGN_ENTITLEMENTS = Appify_UI_23/Appify_UI_23.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ CURRENT_PROJECT_VERSION = 2;
+ DEVELOPMENT_ASSET_PATHS = "\"Appify_UI_23/Preview Content\"";
+ ENABLE_PREVIEWS = YES;
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_FILE = "Appify_UI_23-Info.plist";
+ INFOPLIST_KEY_NSHumanReadableCopyright = "";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ MACOSX_DEPLOYMENT_TARGET = 13.0;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.ThingsThatDoStuff.Appify-UI-23";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_EMIT_LOC_STRINGS = YES;
+ SWIFT_VERSION = 5.0;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ E25DD81229DC8EF100087910 /* Build configuration list for PBXProject "Appify_UI_23" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E25DD83A29DC8EF300087910 /* Debug */,
+ E25DD83B29DC8EF300087910 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E25DD83C29DC8EF300087910 /* Build configuration list for PBXNativeTarget "Appify_UI_23" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E25DD83D29DC8EF300087910 /* Debug */,
+ E25DD83E29DC8EF300087910 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = E25DD80F29DC8EF100087910 /* Project object */;
+}
diff --git a/source/Appify UI 23/Appify UI 23.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/source/Appify_UI_23/Appify_UI_23.xcodeproj/project.xcworkspace/contents.xcworkspacedata
similarity index 100%
rename from source/Appify UI 23/Appify UI 23.xcodeproj/project.xcworkspace/contents.xcworkspacedata
rename to source/Appify_UI_23/Appify_UI_23.xcodeproj/project.xcworkspace/contents.xcworkspacedata
diff --git a/source/Appify UI 23/Appify UI 23.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/source/Appify_UI_23/Appify_UI_23.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
similarity index 100%
rename from source/Appify UI 23/Appify UI 23.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
rename to source/Appify_UI_23/Appify_UI_23.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
diff --git a/source/Appify_UI_23/Appify_UI_23.xcodeproj/xcshareddata/xcschemes/Appify_UI_23.xcscheme b/source/Appify_UI_23/Appify_UI_23.xcodeproj/xcshareddata/xcschemes/Appify_UI_23.xcscheme
new file mode 100644
index 0000000..33a3d8f
--- /dev/null
+++ b/source/Appify_UI_23/Appify_UI_23.xcodeproj/xcshareddata/xcschemes/Appify_UI_23.xcscheme
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/Appify UI 23/Appify UI 23/Appify_UI_23.entitlements b/source/Appify_UI_23/Appify_UI_23/Appify_UI_23.entitlements
similarity index 100%
rename from source/Appify UI 23/Appify UI 23/Appify_UI_23.entitlements
rename to source/Appify_UI_23/Appify_UI_23/Appify_UI_23.entitlements
diff --git a/source/Appify UI 23/Appify UI 23/ContentView.swift b/source/Appify_UI_23/Appify_UI_23/ContentWebView.swift
similarity index 87%
rename from source/Appify UI 23/Appify UI 23/ContentView.swift
rename to source/Appify_UI_23/Appify_UI_23/ContentWebView.swift
index 37394ba..3c4b64d 100644
--- a/source/Appify UI 23/Appify UI 23/ContentView.swift
+++ b/source/Appify_UI_23/Appify_UI_23/ContentWebView.swift
@@ -1,9 +1,6 @@
import SwiftUI
import WebKit
-import SwiftUI
-import WebKit
-
struct WebView: NSViewRepresentable {
let url: URL
@@ -31,7 +28,7 @@ struct WebView: NSViewRepresentable {
}
}
-struct ContentView: View {
+struct ContentWebView: View {
let url: URL
var body: some View {
@@ -43,6 +40,6 @@ struct ContentView: View {
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
- ContentView(url: URL(string: "https://double.observer/")!)
+ ContentWebView(url: URL(string: "https://double.observer/")!)
}
}
diff --git a/source/Appify UI 23/Appify UI 23/Assets.xcassets/Contents.json b/source/Appify_UI_23/Appify_UI_23/Preview Content/Preview Assets.xcassets/Contents.json
similarity index 100%
rename from source/Appify UI 23/Appify UI 23/Assets.xcassets/Contents.json
rename to source/Appify_UI_23/Appify_UI_23/Preview Content/Preview Assets.xcassets/Contents.json
diff --git a/source/Appify_UI_23/Appify_UI_23/cli.swift b/source/Appify_UI_23/Appify_UI_23/cli.swift
new file mode 100644
index 0000000..19922fc
--- /dev/null
+++ b/source/Appify_UI_23/Appify_UI_23/cli.swift
@@ -0,0 +1,49 @@
+import AppKit
+import Cocoa
+import Foundation
+
+func showHelpMessage() {
+ let helpMessage = """
+ Usage: Appify_UI_23 [OPTIONS]
+
+ Options:
+ -u, --url Start the web browser with the specified URL. If not
+ specified, the default URL is the local index.html.
+ -h, --help Show this help message and exit.
+ """
+
+ print(helpMessage)
+}
+
+func parseCommandLine(_ arguments: [String]) -> URL? {
+ var specifiedURL: URL?
+ var skipNext = false
+ loop: for i in 1..<(arguments.count) {
+ if skipNext {
+ skipNext = false
+ continue
+ }
+
+ let arg = arguments[i]
+
+ switch arg {
+ case "-h", "--help":
+ showHelpMessage()
+ NSApp.terminate(nil)
+
+ case "-u", "--url":
+ let nextIndex = i + 1
+ if nextIndex < arguments.count,
+ let url = URL(string: arguments[nextIndex])
+ {
+ specifiedURL = url
+ skipNext = true
+ }
+
+ default:
+ break loop
+ }
+ }
+
+ return specifiedURL
+}
diff --git a/source/Appify_UI_23/Appify_UI_23/jxa.swift b/source/Appify_UI_23/Appify_UI_23/jxa.swift
new file mode 100644
index 0000000..bf8b72a
--- /dev/null
+++ b/source/Appify_UI_23/Appify_UI_23/jxa.swift
@@ -0,0 +1,78 @@
+import Cocoa
+
+func compileAndExecuteJXA(named scriptName: String) {
+ let jxaPathBase = "\(scriptName).jxa"
+ let scptPathBase = "\(scriptName)"
+
+ DispatchQueue.global(qos: .background).async {
+ // Paths for the source and compiled scripts
+ guard
+ let scriptPath = Bundle.main.path(
+ forResource: jxaPathBase, ofType: "js", inDirectory: "Scripts")
+ else {
+ print("Script not found: \(jxaPathBase).js")
+ return
+ }
+
+ var compiledScriptPath = scriptPath.replacingOccurrences(of: ".jxa.js", with: ".scpt")
+
+ let shouldRecompile: Bool
+ if let scptModificationDate = try? FileManager.default.attributesOfItem(
+ atPath: compiledScriptPath)[.modificationDate] as? Date,
+ let jsModificationDate = try? FileManager.default.attributesOfItem(atPath: scriptPath)[
+ .modificationDate] as? Date
+ {
+ shouldRecompile = jsModificationDate > scptModificationDate
+ } else {
+ shouldRecompile = true
+ }
+
+ if shouldRecompile {
+ print("Compiled script not found or outdated: \(scptPathBase).scpt. Compiling...")
+ print("Compiling and executing JXA script: \(scriptPath) -> \(compiledScriptPath)")
+
+ // Compile the .jxa.js to .scpt using osacompile
+ let compileProcess = Process()
+ compileProcess.executableURL = URL(fileURLWithPath: "/usr/bin/osacompile")
+ compileProcess.arguments = ["-l", "JavaScript", "-o", compiledScriptPath, scriptPath]
+
+ do {
+ try compileProcess.run()
+ compileProcess.waitUntilExit()
+
+ if compileProcess.terminationStatus != 0 {
+ print("Compilation failed with status: \(compileProcess.terminationStatus)")
+ return
+ }
+ } catch {
+ print("Failed to compile script: \(error.localizedDescription)")
+ return
+ }
+ }
+
+ print("Compiled script found or up-to-date: \(scptPathBase).scpt")
+ compiledScriptPath =
+ Bundle.main.path(forResource: scptPathBase, ofType: "scpt", inDirectory: "Scripts")
+ ?? compiledScriptPath
+
+ // Execute the compiled script on the main thread
+ DispatchQueue.main.async {
+ print("Executing compiled script: \(compiledScriptPath)")
+ executeAppleScript(at: compiledScriptPath)
+ }
+ }
+}
+
+func executeAppleScript(at path: String) {
+ var error: NSDictionary?
+ if let appleScript = NSAppleScript(contentsOf: URL(fileURLWithPath: path), error: &error) {
+ let executionOutput = appleScript.executeAndReturnError(&error)
+ if let output = executionOutput.stringValue {
+ print("Output: \(output)")
+ } else if let error = error {
+ print("Execution error: \(error)")
+ }
+ } else if let error = error {
+ print("Error initializing AppleScript: \(error)")
+ }
+}
diff --git a/source/Appify_UI_23/Appify_UI_23/main.swift b/source/Appify_UI_23/Appify_UI_23/main.swift
new file mode 100644
index 0000000..eee76f3
--- /dev/null
+++ b/source/Appify_UI_23/Appify_UI_23/main.swift
@@ -0,0 +1,20 @@
+import SwiftUI
+
+@main
+struct Appify_UI_23App: App {
+ var body: some Scene {
+ WindowGroup {
+ ContentWebView(
+ url: parseCommandLine(CommandLine.arguments) ?? Bundle.main.url(
+ forResource: "index", withExtension: "html") ?? URL(
+ string: "https://opdex.app/")!
+ )
+ .onAppear {
+ compileAndExecuteJXA(named: "main")
+ }
+ .onDisappear {
+ compileAndExecuteJXA(named: "cleanup")
+ }
+ }
+ }
+}
diff --git a/source/Appify_UI_23/Bundling/Install HelloWorldApp.dmg.bundle/.hidden/cleanup-terminal.jxa.js b/source/Appify_UI_23/Bundling/Install HelloWorldApp.dmg.bundle/.hidden/cleanup-terminal.jxa.js
new file mode 100644
index 0000000..43c4df1
--- /dev/null
+++ b/source/Appify_UI_23/Bundling/Install HelloWorldApp.dmg.bundle/.hidden/cleanup-terminal.jxa.js
@@ -0,0 +1,11 @@
+#!/usr/bin/osascript -l JavaScript
+
+const Terminal = Application("Terminal")
+
+if (Terminal.windows.length === 1) {
+ const thisWindow = Terminal.windows[0]
+ if (thisWindow?.tabs().length === 1) {
+ thisWindow?.close() // this is fine because we know there is only one tab
+ Terminal.quit() // this is fine because we know there is only one window
+ }
+}
diff --git a/source/Appify_UI_23/Bundling/Install HelloWorldApp.dmg.bundle/Install HelloWorldApp.app (Right-click, Open).command b/source/Appify_UI_23/Bundling/Install HelloWorldApp.dmg.bundle/Install HelloWorldApp.app (Right-click, Open).command
new file mode 100644
index 0000000..ec3f17f
--- /dev/null
+++ b/source/Appify_UI_23/Bundling/Install HelloWorldApp.dmg.bundle/Install HelloWorldApp.app (Right-click, Open).command
@@ -0,0 +1,166 @@
+#!/bin/bash # This is a bash script
+#
+# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
+# ┃ ┃
+# ┃ ┃
+# ┃ ┃
+# ┃ ┃
+# ┃ Install the app ┃
+# ┃ ┃
+# ┃ HOW? ┃
+# ┃ ┃
+# ┃ 1. Right-click on this script ┃
+# ┃ 2. Select "Open" ┃
+# ┃ 3. See Confirmation dialog ┃
+# ┃ 4. Click "Open" ┃
+# ┃ ┃
+# ┃ ┃
+# ┃ ┃
+# ┃ ┃
+# ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
+# │ Why do I need to right-click and select "Open"? │
+# │ Security. It SHOULD be hard to accidentally run │
+# │ scripts you find on the internet. │
+# └──────────────────────────────────────────────────┘
+#
+#
+# 🫡 We always read (and understand) scripts before running them.
+#
+#
+# Here's how it works:
+# --------------------
+#
+# 1. Check if the app is already installed...
+#
+# 2. If it IS already installed...
+#
+# - 👀 Compare the installed version with this new version.
+# - ✅ If the installed version is the same as this one, we're done.
+# - 🗑️ Uninstall the old version, if it's different.
+#
+# 3. If it's NOT already installed...
+#
+# - 🔧 Install the new app.
+# - 🦺 Tell macOS that it's safe. (So it won't stop you from opening it)
+# - 📍 Show the user where to find it.
+#
+# 4. Cleanup
+#
+# NOTE: This script is designed to be run from a disk image.
+#
+# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+AppName="HelloWorldApp" # The name of the app
+App_before_install=".quarantined/$AppName.app" # The new app is hidden in a folder called .quarantined in the disk image.
+App_after_install="$HOME/Applications/$AppName.app" # The app will be installed in the user's personal Applications folder.
+
+RUNTIME_WARNINGS=0
+
+# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+# Next, let's define some functions that we'll use later.
+
+This_stuff_is_safe_I_trust_it() { # Tell macOS: I trust the app maker and I want to open this app.
+ local theApp="$1" #
+ if [ ! -d "$theApp" ]; then # Check if the app exists
+ RUNTIME_WARNINGS=1 #
+ echo "ERROR: $theApp does not exist." # If it doesn't, show an error message
+ return # Abort the function
+ fi
+ # check if the quarantine flag is set
+ xattr -p com.apple.quarantine $theApp &>/dev/null || return # If the quarantine flag is not set, we're already done
+ xattr -d com.apple.quarantine $theApp # Remove the quarantine flag from the app
+}
+
+try_to_Install_the_app() {
+ if [ -d "$App_after_install" ]; then
+ RUNTIME_WARNINGS=1
+ echo -en " ${ANSI_RESET}${ANSI_FG_BLUE}"
+ echo " Already installed."
+ echo " Comparing versions..."
+ # Read the version and build number from Info.plist
+ NewVersion=$(defaults read "$App_before_install/Contents/Info.plist" CFBundleShortVersionString 2>/dev/null)
+ NewBuild=$(defaults read "$App_before_install/Contents/Info.plist" CFBundleVersion 2>/dev/null)
+ OldVersion=$(defaults read "$App_after_install/Contents/Info.plist" CFBundleShortVersionString 2>/dev/null)
+ OldBuild=$(defaults read "$App_after_install/Contents/Info.plist" CFBundleVersion 2>/dev/null)
+
+ # if versions are identical, do nothing
+ if [ "${NewVersion-1}" -eq "${OldVersion-1}" ] && [ "${NewBuild-1}" -eq "${OldBuild-1}" ]; then
+ echo " Already up-to-date."
+ return
+ else
+ RUNTIME_WARNINGS=1
+ echo " Uninstalling old version..."
+ # Remove the old version by moving it to the trash
+ mv "$App_after_install" ~/.Trash
+ fi
+ fi
+
+ cp -r "$App_before_install" "$App_after_install" # Copy the new app to the Applications folder
+ This_stuff_is_safe_I_trust_it "$App_after_install" # Tell macOS that we trust the newly installed app
+ psychologically_weighty_progress # Pretend to do something important
+}
+
+main() {
+ cd "$(dirname "$0")" # Focus on the directory of this script
+
+ clear # Clear the terminal window
+ echo -en "${ANSI_BG_BLUE_FG_WHITE} " # Set the background color to blue and the text color to white
+ echo -n "Installing app" # Print the message "Installing app"
+
+ try_to_Install_the_app
+
+ echo -en " ${ANSI_RESET}${ANSI_FG_BLUE}" # (Reset the styles and set the text color to blue)
+ if [ -d "$App_after_install" ]; then # If the app was installed successfully...
+ echo " INSTALLED"
+ open --reveal "$App_after_install" # Open the Applications folder and reveal the app
+ else
+ RUNTIME_WARNINGS=1
+ echo " INSTALL FAILED"
+ fi
+
+ echo -en "${ANSI_RESET}${ANSI_FG_BLACK}"
+ Cleanup_terminal
+}
+
+Cleanup_terminal() {
+ # skip cleanup unless RUNTIME_WARNINGS=0
+ [ $RUNTIME_WARNINGS -eq 0 ] || return
+ # once the script is done, we don't need the terminal window anymore, so let's close it
+ osascript -l JavaScript ".hidden/cleanup-terminal.jxa.js" &
+}
+
+# Show a progress bar
+Show_progress() {
+ local seconds_total=${1-1}
+ local seconds_between_dots=${2-0.1}
+ local progress_dot="${3-.}"
+ end_time=$((SECONDS + $seconds_total)) # Calculate the end time
+ while [ $SECONDS -lt $end_time ]; do # Loop until the time is up
+ sleep $seconds_between_dots # Wait a bit
+ echo -n "$progress_dot" # Print a dot
+ done
+}
+
+# Installing the app is pretty much instant
+# But psychologically, stuff feels broken if you don't see any progress
+# So we'll pretend to do something important for a few seconds
+# This gives this process a more natural feel
+psychologically_weighty_progress() {
+ Show_progress 1 0.025 '.' # Show some dots fast
+ Show_progress 1 0.050 '.' # Show some dots a bit slower
+ Show_progress 1 0.200 '.' # Show the final dots much slower
+}
+
+# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+# prepare some styles to make stuff look nice
+ANSI_RESET="\033[0m" # Reset styles
+ANSI_BG_BLUE_FG_WHITE="\033[44;37m" # Background Blue, Foreground White
+ANSI_FG_BLUE="\033[34m" # Foreground Blue
+ANSI_FG_BLACK="\033[30m" # Foreground Black
+
+# Finally, run the main function (with all arguments)
+main "$@"
+
+# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+# Congratulations on making it to the end of this script
diff --git a/source/Appify_UI_23/Bundling/build.sh.command b/source/Appify_UI_23/Bundling/build.sh.command
new file mode 100755
index 0000000..3a101ad
--- /dev/null
+++ b/source/Appify_UI_23/Bundling/build.sh.command
@@ -0,0 +1,41 @@
+#!bash
+set -e # exit on error
+set -u # exit on undefined variable
+set -o pipefail # exit on pipe error
+set -o posix # more strict failures
+# set -x # print commands
+
+cd "$(dirname "$0")"
+source ./helpers.lib.sh
+
+main() {
+ clear
+ echo -en "${ANSI_BG_BLUE_FG_WHITE}"
+ echo -n "Building $AppName"
+
+ Prepare_disk
+ Build
+ BuildIcon
+ Bundle
+ # Create_dmg
+ open --reveal "$App"
+ # open --reveal "$TargetInstallScript"
+
+ echo -en "${ANSI_RESET}${ANSI_FG_BLUE}"
+ echo -n " DONE"
+ echo -e "${ANSI_RESET}${ANSI_FG_BLACK}"
+}
+
+TIMESTAMP=$(printf '%X\n' $(date +%s))
+
+ANSI_BG_BLUE_FG_WHITE="\033[44;37m"
+ANSI_FG_BLUE="\033[34m"
+ANSI_RESET="\033[0m"
+ANSI_FG_BLACK="\033[30m"
+
+# if no args, run main
+if [ $# -eq 0 ]; then
+ main
+else # otherwise, run the function named by the first arg
+ "$@"
+fi
diff --git a/source/Appify_UI_23/Bundling/bundle.sh.command b/source/Appify_UI_23/Bundling/bundle.sh.command
new file mode 100755
index 0000000..5e21da2
--- /dev/null
+++ b/source/Appify_UI_23/Bundling/bundle.sh.command
@@ -0,0 +1,34 @@
+#!bash
+set -e # exit on error
+set -u # exit on undefined variable
+set -o pipefail # exit on pipe error
+set -o posix # more strict failures
+# set -x # print commands
+
+cd "$(dirname "$0")"
+source ./helpers.lib.sh
+
+main() {
+ clear
+ echo -en "${ANSI_BG_BLUE_FG_WHITE}"
+ echo -n "Building $AppName"
+
+ Prepare_disk
+ Build
+ Bundle
+ Create_dmg
+ open --reveal "$DiskImage"
+
+ echo -en "${ANSI_RESET}${ANSI_FG_BLUE}"
+ echo -n " DONE"
+ echo -e "${ANSI_RESET}${ANSI_FG_BLACK}"
+}
+
+TIMESTAMP=$(printf '%X\n' $(date +%s))
+
+ANSI_BG_BLUE_FG_WHITE="\033[44;37m"
+ANSI_FG_BLUE="\033[34m"
+ANSI_RESET="\033[0m"
+ANSI_FG_BLACK="\033[30m"
+
+main
diff --git a/source/Appify_UI_23/Bundling/helpers.lib.sh b/source/Appify_UI_23/Bundling/helpers.lib.sh
new file mode 100644
index 0000000..b6ac6e7
--- /dev/null
+++ b/source/Appify_UI_23/Bundling/helpers.lib.sh
@@ -0,0 +1,78 @@
+AppName="Appify_UI_23"
+echo "AppName: $AppName"
+
+BundleRoot="."
+SourceAppRoot=".."
+SourceAppBuildRoot="$SourceAppRoot/.build/release"
+BundleBuildRoot="$BundleRoot/.build"
+
+DiskTemplate="$BundleRoot/Install HelloWorldApp.dmg.bundle"
+Disk="$BundleBuildRoot/FakeInstallDisk"
+DiskImage="$Disk.dmg"
+DiskImageTitle="Install $AppName"
+SourceInstallScript="$DiskTemplate/Install HelloWorldApp.app (Right-click, Open).command"
+TargetInstallScript="$Disk/Install HelloWorldApp.app (Right-click, Open).command"
+AppRoot="$Disk/.quarantined"
+App="$AppRoot/$AppName.app"
+SourceAppBuild="$SourceAppBuildRoot/$AppName"
+SourceIconSet="../../Appify UI iconset-assets"
+
+AppTemplate="$SourceAppRoot/Template.app"
+SourceInfoPlist="$AppTemplate/Contents/Info.plist"
+SourceIcon="$AppTemplate/Contents/Resources/Appify UI.icns"
+
+Build() {
+ # [[ -f "$SourceAppBuild" ]] ||
+ swift build -c release -Xswiftc -parse-as-library
+}
+BuildIcon() {
+ rm -rf "$BundleBuildRoot/AppIcon.iconset"
+ cp -r "$SourceIconSet" "$BundleBuildRoot/AppIcon.iconset"
+ iconutil --convert icns --output "$SourceIcon" "$BundleBuildRoot/AppIcon.iconset"
+}
+Bundle() {
+ rm -rf "$App"
+ mkdir -p "$AppRoot"
+ cp -r "$AppTemplate" "$App"
+ # mkdir -p "$App"/Contents/MacOS
+ # mkdir -p "$App"/Contents/Resources
+
+ cp "$SourceAppBuild" "$App/Contents/MacOS"
+ # [[ -f "$SourceInfoPlist" ]] || cp "$SourceAppBuild/Info.plist" "$SourceInfoPlist"
+ # cp "$SourceInfoPlist" "$App/Contents"
+ # cp "$SourceIcon" "$App/Contents/Resources"
+}
+Prepare_disk() {
+ echo "Preparing disk"
+ rm -rf "$Disk"
+ # copy everything from the template, including hidden files and .DS_Store
+ mkdir -p "$Disk"
+ cp -r "$DiskTemplate"/* "$Disk"
+ # WIP
+ # cp "$DiskTemplate/.DS_Store" "$Disk"
+ ls -lar "$Disk"
+
+ cat "$SourceInstallScript" | sed "s/HelloWorldApp/$AppName/g" >"$TargetInstallScript"
+ chmod +x "$TargetInstallScript"
+
+ local TargetInstallScript_next="$Disk/Install $AppName.app (Right-click, Open).command"
+ mv "$TargetInstallScript" "$TargetInstallScript_next"
+ TargetInstallScript="$TargetInstallScript_next"
+}
+Create_dmg() {
+ echo "Probably use https://github.com/create-dmg/create-dmg to create the disk image instead of this script"
+ # TODO: use https://github.com/create-dmg/create-dmg instead
+ # wait for the user to press enter
+ # echo "You can now customize the disk image template before creating the readonly disk image"
+ # read -p "Press enter to open disk image template"
+ # open "$Disk"
+ # read -p "Press enter to create disk image"
+
+ echo "Creating disk image"
+ # xattr -w com.apple.quarantine "0082;$TIMESTAMP;Thomas Aylott;" "$App"
+
+ rm -f "$DiskImage"
+ # hdiutil create -srcfolder "$Disk" -volname "$DiskImageTitle" -fs HFS+ -fsargs "-c c=64,a=16,e=16" -format SPARSE -size 5g "$DiskImage"
+ hdiutil create -volname "$DiskImageTitle" -srcfolder "$Disk" -ov -format UDZO "$DiskImage"
+ xattr -w com.apple.quarantine "0082;$TIMESTAMP;Thomas Aylott;" "$DiskImage"
+}
diff --git a/source/Appify_UI_23/Info.plist b/source/Appify_UI_23/Info.plist
new file mode 100644
index 0000000..1d46250
--- /dev/null
+++ b/source/Appify_UI_23/Info.plist
@@ -0,0 +1,19 @@
+
+
+
+
+ CFBundleInfoDictionaryVersion6.0
+ CFBundlePackageTypeAPPL
+
+ CFBundleExecutableAppify_UI_23
+ CFBundleIdentifiercom.ThingsThatDoStuff.Appify-UI-23
+ CFBundleNameAppify UI 23
+ CFBundleVersion2
+ CFBundleShortVersionString1.0
+
+ CFBundleIconFileAppify UI
+ CFBundleIconNameAppify UI
+
+ LSMinimumSystemVersion13.0
+
+
diff --git a/source/Appify_UI_23/Package.swift b/source/Appify_UI_23/Package.swift
new file mode 100644
index 0000000..c2b2a2c
--- /dev/null
+++ b/source/Appify_UI_23/Package.swift
@@ -0,0 +1,23 @@
+// swift-tools-version:5.3
+import PackageDescription
+
+let package = Package(
+ name: "Appify_UI_23",
+ platforms: [
+ .macOS(.v11)
+ ],
+ products: [
+ .executable(
+ name: "Appify_UI_23",
+ targets: ["Appify_UI_23"])
+ ],
+ dependencies: [],
+ targets: [
+ .target(
+ name: "Appify_UI_23",
+ dependencies: [],
+ path: "Appify_UI_23",
+ exclude: ["Appify_UI_23.entitlements"] // Exclude non-source files
+ )
+ ]
+)
diff --git a/source/Appify_UI_23/pbcopy-for-ai.sh.command b/source/Appify_UI_23/pbcopy-for-ai.sh.command
new file mode 100755
index 0000000..b3d6b85
--- /dev/null
+++ b/source/Appify_UI_23/pbcopy-for-ai.sh.command
@@ -0,0 +1,4 @@
+#!/bin/bash
+cd "$(dirname "$0")"
+combine_files_to_markdown.ts *.swift **/*.swift *.plist | pbcopy
+echo "Copied to clipboard"
diff --git a/source/README.md b/source/README.md
new file mode 100644
index 0000000..4a6e5d9
--- /dev/null
+++ b/source/README.md
@@ -0,0 +1,15 @@
+# source
+
+To install dependencies:
+
+```bash
+bun install
+```
+
+To run:
+
+```bash
+bun run index.ts
+```
+
+This project was created using `bun init` in bun v1.1.8. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
diff --git a/source/bun.lockb b/source/bun.lockb
new file mode 100755
index 0000000..bdcb34e
Binary files /dev/null and b/source/bun.lockb differ
diff --git a/source/index.ts b/source/index.ts
new file mode 100644
index 0000000..f67b2c6
--- /dev/null
+++ b/source/index.ts
@@ -0,0 +1 @@
+console.log("Hello via Bun!");
\ No newline at end of file
diff --git a/source/package.json b/source/package.json
new file mode 100644
index 0000000..c5ad66d
--- /dev/null
+++ b/source/package.json
@@ -0,0 +1,12 @@
+{
+ "name": "appify-ui-23",
+ "private": true,
+ "type": "module",
+ "devDependencies": {
+ "@jxa/global-type": "^1.3.6",
+ "@types/bun": "latest"
+ },
+ "peerDependencies": {
+ "typescript": "^5"
+ }
+}
diff --git a/source/tsconfig.json b/source/tsconfig.json
new file mode 100644
index 0000000..238655f
--- /dev/null
+++ b/source/tsconfig.json
@@ -0,0 +1,27 @@
+{
+ "compilerOptions": {
+ // Enable latest features
+ "lib": ["ESNext", "DOM"],
+ "target": "ESNext",
+ "module": "ESNext",
+ "moduleDetection": "force",
+ "jsx": "react-jsx",
+ "allowJs": true,
+
+ // Bundler mode
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "noEmit": true,
+
+ // Best practices
+ "strict": true,
+ "skipLibCheck": true,
+ "noFallthroughCasesInSwitch": true,
+
+ // Some stricter flags (disabled by default)
+ "noUnusedLocals": false,
+ "noUnusedParameters": false,
+ "noPropertyAccessFromIndexSignature": false
+ }
+}
diff --git a/upgrade.sh b/upgrade.sh
deleted file mode 100755
index bbb2a1c..0000000
--- a/upgrade.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env bash
-# lol, hard-coded paths
-
-cd "$(dirname "$0")"
-
-for bin_path in *.app/Contents/MacOS/apache-callback-mac; do
- mv "$bin_path" "$bin_path.old"
- cp "$(ls $HOME/Library/Developer/Xcode/DerivedData/callback-mac-*/Build/Products/Debug/Callback.app/Contents/MacOS/Callback)" "$bin_path"
-done
-
-for bin_path in *.app/Contents/MacOS/apache-callback-mac.old; do
- if [[ -f "${bin_path/\.old/}" ]]; then
- rm "$bin_path"
- else
- mv "$bin_path" "${bin_path/\.old/}"
- fi
-done
-
-for nib_path in *.app/Contents/Resources/English.lproj/MainMenu.nib; do
- mv "$nib_path" "$nib_path.old"
- cp "$(ls $HOME/Library/Developer/Xcode/DerivedData/callback-mac-*/Build/Products/Debug/Callback.app/Contents/Resources/English.lproj/MainMenu.nib)" "$nib_path"
-done
-
-for nib_path in *.app/Contents/Resources/English.lproj/MainMenu.nib.old; do
- if [[ -f "${nib_path/\.old/}" ]]; then
- rm "$nib_path"
- else
- mv "$nib_path" "${nib_path/\.old/}"
- fi
-done