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 + + + + + + + +
+ + + +

+ +

+ +

+ +

+ +

+ +

Marketing version number for users to see.

+ +

Launch Services expects the following format: nnnnn[.nn[.nn]][X] where n is a digit 0-9, square brackets indicate optional components, and X is any string not starting with a digit. X is ignored when present.

+ + +
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