Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a0f1a4ce80 | |||
| 80fbbcddf3 | |||
| 0ab87e25a4 | |||
| 495255206e | |||
| 46254730bd | |||
| d1e60babf4 | |||
| ab84f685c0 | |||
| 1a8c4bfebc | |||
| b15b48f702 | |||
| 29c732faa0 | |||
| dcebccf947 | |||
| 67138c7035 | |||
| 6f848be1ee | |||
| b6d02dbe78 | |||
| ffecf780ee | |||
| fad9d2d26f |
@@ -2,7 +2,13 @@ name: "CI"
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
- "development"
|
||||||
|
- "public"
|
||||||
pull_request:
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- "development"
|
||||||
|
- "public"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
run-checks:
|
run-checks:
|
||||||
@@ -55,14 +61,29 @@ jobs:
|
|||||||
push: false
|
push: false
|
||||||
load: true
|
load: true
|
||||||
tags: "docker-hosted.nexus.bthlabs.pl/hotpocket/packages:ci-local"
|
tags: "docker-hosted.nexus.bthlabs.pl/hotpocket/packages:ci-local"
|
||||||
|
- name: "Build `extension-ci` image"
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
file: "services/extension/Dockerfile"
|
||||||
|
context: "services/"
|
||||||
|
target: "ci"
|
||||||
|
push: false
|
||||||
|
load: true
|
||||||
|
tags: "docker-hosted.nexus.bthlabs.pl/hotpocket/extension:ci-local"
|
||||||
- name: "Run `backend` checks"
|
- name: "Run `backend` checks"
|
||||||
run: |
|
run: |
|
||||||
set -x
|
set -x
|
||||||
docker compose -f docker-compose.yaml -f docker-compose-ci.yaml run --rm backend-ci inv ci
|
docker compose -f docker-compose.yaml -f docker-compose-ci.yaml run --rm backend-ci inv ci
|
||||||
- name: "Run `packages` checks"
|
- name: "Run `packages` checks"
|
||||||
|
if: always()
|
||||||
run: |
|
run: |
|
||||||
set -x
|
set -x
|
||||||
docker compose -f docker-compose.yaml -f docker-compose-ci.yaml run --rm packages-ci inv ci
|
docker compose -f docker-compose.yaml -f docker-compose-ci.yaml run --rm packages-ci inv ci
|
||||||
|
- name: "Run `extension` checks"
|
||||||
|
if: always()
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
docker compose -f docker-compose.yaml -f docker-compose-ci.yaml run --rm extension-ci inv ci
|
||||||
- name: "Clean up"
|
- name: "Clean up"
|
||||||
if: always()
|
if: always()
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ $ docker run --rm -it \
|
|||||||
-e HOTPOCKET_BACKEND_INITIAL_ACCOUNT_USERNAME=hotpocket \
|
-e HOTPOCKET_BACKEND_INITIAL_ACCOUNT_USERNAME=hotpocket \
|
||||||
-e HOTPOCKET_BACKEND_INITIAL_ACCOUNT_PASSWORD=hotpocketm4st3r \
|
-e HOTPOCKET_BACKEND_INITIAL_ACCOUNT_PASSWORD=hotpocketm4st3r \
|
||||||
-p 8000:8000 \
|
-p 8000:8000 \
|
||||||
docker-hosted.nexus.bthlabs.pl/hotpocket/backend:aio-v1.0.2-01
|
docker-hosted.nexus.bthlabs.pl/hotpocket/backend:aio-v25.9.12-01
|
||||||
```
|
```
|
||||||
|
|
||||||
The command above will set up and start the application. The SQLite file will
|
The command above will set up and start the application. The SQLite file will
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
services:
|
services:
|
||||||
backend:
|
backend:
|
||||||
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:aio-v1.0.2-01"
|
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:aio-v25.9.12-01"
|
||||||
environment:
|
environment:
|
||||||
HOTPOCKET_BACKEND_SECRET_KEY: "thisisntright"
|
HOTPOCKET_BACKEND_SECRET_KEY: "thisisntright"
|
||||||
HOTPOCKET_BACKEND_INITIAL_ACCOUNT_USERNAME: "hotpocket"
|
HOTPOCKET_BACKEND_INITIAL_ACCOUNT_USERNAME: "hotpocket"
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ x-backend-environment: &x-backend-environment
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
webapp:
|
webapp:
|
||||||
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:deployment-v1.0.2-01"
|
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:deployment-v25.9.12-01"
|
||||||
environment:
|
environment:
|
||||||
<<: *x-backend-environment
|
<<: *x-backend-environment
|
||||||
HOTPOCKET_BACKEND_ALLOWED_HOSTS: "app.staging.hotpocket.bthlab.bthlabs.net"
|
HOTPOCKET_BACKEND_ALLOWED_HOSTS: "app.staging.hotpocket.bthlab.bthlabs.net"
|
||||||
@@ -21,7 +21,7 @@ services:
|
|||||||
restart: "unless-stopped"
|
restart: "unless-stopped"
|
||||||
|
|
||||||
admin:
|
admin:
|
||||||
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:deployment-v1.0.2-01"
|
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:deployment-v25.9.12-01"
|
||||||
environment:
|
environment:
|
||||||
<<: *x-backend-environment
|
<<: *x-backend-environment
|
||||||
HOTPOCKET_BACKEND_APP: "admin"
|
HOTPOCKET_BACKEND_APP: "admin"
|
||||||
@@ -35,7 +35,7 @@ services:
|
|||||||
restart: "unless-stopped"
|
restart: "unless-stopped"
|
||||||
|
|
||||||
celery-worker:
|
celery-worker:
|
||||||
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:deployment-v1.0.2-01"
|
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:deployment-v25.9.12-01"
|
||||||
command:
|
command:
|
||||||
- "/srv/venv/bin/celery"
|
- "/srv/venv/bin/celery"
|
||||||
- "-A"
|
- "-A"
|
||||||
@@ -57,7 +57,7 @@ services:
|
|||||||
restart: "unless-stopped"
|
restart: "unless-stopped"
|
||||||
|
|
||||||
celery-beat:
|
celery-beat:
|
||||||
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:deployment-v1.0.2-01"
|
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:deployment-v25.9.12-01"
|
||||||
command:
|
command:
|
||||||
- "/srv/venv/bin/celery"
|
- "/srv/venv/bin/celery"
|
||||||
- "-A"
|
- "-A"
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"targets": [
|
"targets": [
|
||||||
"backend-management",
|
"backend-management",
|
||||||
"caddy",
|
"caddy",
|
||||||
|
"extension-management",
|
||||||
"keycloak",
|
"keycloak",
|
||||||
"packages-management",
|
"packages-management",
|
||||||
"postgres",
|
"postgres",
|
||||||
@@ -67,6 +68,28 @@
|
|||||||
"type=docker,load=true,push=false"
|
"type=docker,load=true,push=false"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"extension-management": {
|
||||||
|
"context": "services/",
|
||||||
|
"dockerfile": "extension/Dockerfile",
|
||||||
|
"tags": [
|
||||||
|
"docker-hosted.nexus.bthlabs.pl/hotpocket/extension:local"
|
||||||
|
],
|
||||||
|
"target": "development",
|
||||||
|
"output": [
|
||||||
|
"type=docker,load=true,push=false"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"extension-ci": {
|
||||||
|
"context": "services/",
|
||||||
|
"dockerfile": "extension/Dockerfile",
|
||||||
|
"tags": [
|
||||||
|
"docker-hosted.nexus.bthlabs.pl/hotpocket/extension:ci-local"
|
||||||
|
],
|
||||||
|
"target": "ci",
|
||||||
|
"output": [
|
||||||
|
"type=docker,load=true,push=false"
|
||||||
|
]
|
||||||
|
},
|
||||||
"caddy": {
|
"caddy": {
|
||||||
"context": "services/",
|
"context": "services/",
|
||||||
"dockerfile": "caddy/Dockerfile",
|
"dockerfile": "caddy/Dockerfile",
|
||||||
|
|||||||
@@ -13,3 +13,4 @@ services:
|
|||||||
include:
|
include:
|
||||||
- path: "./services/backend/docker-compose-ci.yaml"
|
- path: "./services/backend/docker-compose-ci.yaml"
|
||||||
- path: "./services/packages/docker-compose-ci.yaml"
|
- path: "./services/packages/docker-compose-ci.yaml"
|
||||||
|
- path: "./services/extension/docker-compose-ci.yaml"
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ include:
|
|||||||
- path: "./docker-compose-cloud.yaml"
|
- path: "./docker-compose-cloud.yaml"
|
||||||
- path: "./services/backend/docker-compose.yaml"
|
- path: "./services/backend/docker-compose.yaml"
|
||||||
- path: "./services/packages/docker-compose.yaml"
|
- path: "./services/packages/docker-compose.yaml"
|
||||||
|
- path: "./services/extension/docker-compose.yaml"
|
||||||
|
|
||||||
volumes: {}
|
volumes: {}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"run": {
|
|
||||||
"echo": true,
|
|
||||||
"pty": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
7
invoke.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
run:
|
||||||
|
echo: true
|
||||||
|
pty: true
|
||||||
|
files_to_version:
|
||||||
|
- "deployment/aio/docker-compose.yaml"
|
||||||
|
- "deployment/fullstack/docker-compose.yaml"
|
||||||
|
- "README.md"
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
_tmp/
|
_tmp/
|
||||||
|
apple/
|
||||||
backend/node_modules/
|
backend/node_modules/
|
||||||
backend/ops/metal/
|
backend/ops/metal/
|
||||||
backend/hotpocket_backend/playground.py
|
backend/hotpocket_backend/playground.py
|
||||||
@@ -7,4 +8,6 @@ backend/hotpocket_backend/settings/docker/
|
|||||||
backend/hotpocket_backend/secrets/metal/
|
backend/hotpocket_backend/secrets/metal/
|
||||||
backend/hotpocket_backend/settings/metal/
|
backend/hotpocket_backend/settings/metal/
|
||||||
backend/hotpocket_backend/static/
|
backend/hotpocket_backend/static/
|
||||||
|
extension/node_modules/
|
||||||
|
extension/dist/
|
||||||
.envrc*
|
.envrc*
|
||||||
|
|||||||
94
services/apple/.gitignore
vendored
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
# Xcode
|
||||||
|
|
||||||
|
## Build generated
|
||||||
|
build/
|
||||||
|
DerivedData/
|
||||||
|
|
||||||
|
## Various settings
|
||||||
|
ExportOptions.plist
|
||||||
|
*.pbxuser
|
||||||
|
!default.pbxuser
|
||||||
|
*.mode1v3
|
||||||
|
!default.mode1v3
|
||||||
|
*.mode2v3
|
||||||
|
!default.mode2v3
|
||||||
|
*.perspectivev3
|
||||||
|
!default.perspectivev3
|
||||||
|
xcuserdata/
|
||||||
|
|
||||||
|
## Other
|
||||||
|
*.moved-aside
|
||||||
|
*.xccheckout
|
||||||
|
*.xcscmblueprint
|
||||||
|
|
||||||
|
## We don't want any memgrap's to leak ;)
|
||||||
|
**.memgraph
|
||||||
|
|
||||||
|
## Obj-C/Swift specific
|
||||||
|
*.hmap
|
||||||
|
*.ipa
|
||||||
|
*.dSYM.zip
|
||||||
|
*.dSYM
|
||||||
|
|
||||||
|
## Playgrounds
|
||||||
|
timeline.xctimeline
|
||||||
|
playground.xcworkspace
|
||||||
|
|
||||||
|
# Swift Package Manager
|
||||||
|
#
|
||||||
|
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
|
||||||
|
# Packages/
|
||||||
|
# Package.pins
|
||||||
|
# Package.resolved
|
||||||
|
.build/
|
||||||
|
|
||||||
|
# CocoaPods
|
||||||
|
#
|
||||||
|
# We recommend against adding the Pods directory to your .gitignore. However
|
||||||
|
# you should judge for yourself, the pros and cons are mentioned at:
|
||||||
|
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
||||||
|
#
|
||||||
|
# Pods/
|
||||||
|
#
|
||||||
|
# Add this line if you want to avoid checking in source code from the Xcode workspace
|
||||||
|
# *.xcworkspace
|
||||||
|
|
||||||
|
# Carthage
|
||||||
|
#
|
||||||
|
# Add this line if you want to avoid checking in source code from Carthage dependencies.
|
||||||
|
# Carthage/Checkouts
|
||||||
|
|
||||||
|
Carthage/Build
|
||||||
|
|
||||||
|
# Accio dependency management
|
||||||
|
Dependencies/
|
||||||
|
.accio/
|
||||||
|
|
||||||
|
# fastlane
|
||||||
|
#
|
||||||
|
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
|
||||||
|
# screenshots whenever they are needed.
|
||||||
|
# For more information about the recommended setup visit:
|
||||||
|
# https://docs.fastlane.tools/best-practices/source-control/#source-control
|
||||||
|
|
||||||
|
fastlane/report.xml
|
||||||
|
fastlane/Preview.html
|
||||||
|
fastlane/screenshots/**/*.png
|
||||||
|
fastlane/test_output
|
||||||
|
fastlane/*.env
|
||||||
|
|
||||||
|
# Code Injection
|
||||||
|
#
|
||||||
|
# After new code Injection tools there's a generated folder /iOSInjectionProject
|
||||||
|
# https://github.com/johnno1962/injectionforxcode
|
||||||
|
|
||||||
|
iOSInjectionProject/
|
||||||
|
|
||||||
|
# Extension stuff
|
||||||
|
Shared (Extension)/Resources/_locales/
|
||||||
|
Shared (Extension)/Resources/images/
|
||||||
|
Shared (Extension)/Resources/background-bundle.js
|
||||||
|
Shared (Extension)/Resources/content-bundle.js
|
||||||
|
Shared (Extension)/Resources/manifest.json
|
||||||
|
Shared (Extension)/Resources/preauth.html
|
||||||
|
Shared (Extension)/Resources/preauth.js
|
||||||
913
services/apple/HotPocket.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,913 @@
|
|||||||
|
// !$*UTF8*$!
|
||||||
|
{
|
||||||
|
archiveVersion = 1;
|
||||||
|
classes = {
|
||||||
|
};
|
||||||
|
objectVersion = 77;
|
||||||
|
objects = {
|
||||||
|
|
||||||
|
/* Begin PBXBuildFile section */
|
||||||
|
4CABCAD62E56F0C900D8A354 /* HotPocket Extension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 4CABCAD52E56F0C900D8A354 /* HotPocket Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
|
4CABCAE02E56F0C900D8A354 /* HotPocket Extension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 4CABCADF2E56F0C900D8A354 /* HotPocket Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
4CABCAD72E56F0C900D8A354 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 4CABCA922E56F0C800D8A354 /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = 4CABCAD42E56F0C900D8A354;
|
||||||
|
remoteInfo = "HotPocket Extension (iOS)";
|
||||||
|
};
|
||||||
|
4CABCAE12E56F0C900D8A354 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 4CABCA922E56F0C800D8A354 /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = 4CABCADE2E56F0C900D8A354;
|
||||||
|
remoteInfo = "HotPocket Extension (macOS)";
|
||||||
|
};
|
||||||
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
|
4CABCB092E56F0C900D8A354 /* Embed Foundation Extensions */ = {
|
||||||
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
dstPath = "";
|
||||||
|
dstSubfolderSpec = 13;
|
||||||
|
files = (
|
||||||
|
4CABCAD62E56F0C900D8A354 /* HotPocket Extension.appex in Embed Foundation Extensions */,
|
||||||
|
);
|
||||||
|
name = "Embed Foundation Extensions";
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
4CABCB132E56F0C900D8A354 /* Embed Foundation Extensions */ = {
|
||||||
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
dstPath = "";
|
||||||
|
dstSubfolderSpec = 13;
|
||||||
|
files = (
|
||||||
|
4CABCAE02E56F0C900D8A354 /* HotPocket Extension.appex in Embed Foundation Extensions */,
|
||||||
|
);
|
||||||
|
name = "Embed Foundation Extensions";
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXFileReference section */
|
||||||
|
4CABCAB02E56F0C900D8A354 /* HotPocket.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HotPocket.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
4CABCAC62E56F0C900D8A354 /* HotPocket.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HotPocket.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
4CABCAD52E56F0C900D8A354 /* HotPocket Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "HotPocket Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
4CABCADF2E56F0C900D8A354 /* HotPocket Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "HotPocket Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||||
|
4CABCB042E56F0C900D8A354 /* Exceptions for "Shared (App)" folder in "HotPocket (iOS)" target */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
|
membershipExceptions = (
|
||||||
|
"/Localized: Resources/Main.html",
|
||||||
|
Assets.xcassets,
|
||||||
|
"Resources/icon-mac-384.png",
|
||||||
|
Resources/Script.js,
|
||||||
|
Resources/Style.css,
|
||||||
|
ViewController.m,
|
||||||
|
);
|
||||||
|
target = 4CABCAAF2E56F0C900D8A354 /* HotPocket (iOS) */;
|
||||||
|
};
|
||||||
|
4CABCB082E56F0C900D8A354 /* Exceptions for "iOS (Extension)" folder in "HotPocket Extension (iOS)" target */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
|
membershipExceptions = (
|
||||||
|
Info.plist,
|
||||||
|
);
|
||||||
|
target = 4CABCAD42E56F0C900D8A354 /* HotPocket Extension (iOS) */;
|
||||||
|
};
|
||||||
|
4CABCB0D2E56F0C900D8A354 /* Exceptions for "iOS (App)" folder in "HotPocket (iOS)" target */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
|
membershipExceptions = (
|
||||||
|
Info.plist,
|
||||||
|
);
|
||||||
|
target = 4CABCAAF2E56F0C900D8A354 /* HotPocket (iOS) */;
|
||||||
|
};
|
||||||
|
4CABCB0E2E56F0C900D8A354 /* Exceptions for "Shared (App)" folder in "HotPocket (macOS)" target */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
|
membershipExceptions = (
|
||||||
|
"/Localized: Resources/Main.html",
|
||||||
|
Assets.xcassets,
|
||||||
|
"Resources/icon-mac-384.png",
|
||||||
|
Resources/Script.js,
|
||||||
|
Resources/Style.css,
|
||||||
|
ViewController.m,
|
||||||
|
);
|
||||||
|
target = 4CABCAC52E56F0C900D8A354 /* HotPocket (macOS) */;
|
||||||
|
};
|
||||||
|
4CABCB122E56F0C900D8A354 /* Exceptions for "macOS (Extension)" folder in "HotPocket Extension (macOS)" target */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
|
membershipExceptions = (
|
||||||
|
Info.plist,
|
||||||
|
);
|
||||||
|
target = 4CABCADE2E56F0C900D8A354 /* HotPocket Extension (macOS) */;
|
||||||
|
};
|
||||||
|
4CABCB172E56F0C900D8A354 /* Exceptions for "Shared (Extension)" folder in "HotPocket Extension (iOS)" target */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
|
membershipExceptions = (
|
||||||
|
Resources/_locales,
|
||||||
|
"Resources/background-bundle.js",
|
||||||
|
"Resources/content-bundle.js",
|
||||||
|
Resources/images,
|
||||||
|
Resources/manifest.json,
|
||||||
|
Resources/preauth.html,
|
||||||
|
Resources/preauth.js,
|
||||||
|
SafariWebExtensionHandler.m,
|
||||||
|
);
|
||||||
|
target = 4CABCAD42E56F0C900D8A354 /* HotPocket Extension (iOS) */;
|
||||||
|
};
|
||||||
|
4CABCB182E56F0C900D8A354 /* Exceptions for "Shared (Extension)" folder in "HotPocket Extension (macOS)" target */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
|
membershipExceptions = (
|
||||||
|
Resources/_locales,
|
||||||
|
"Resources/background-bundle.js",
|
||||||
|
"Resources/content-bundle.js",
|
||||||
|
Resources/images,
|
||||||
|
Resources/manifest.json,
|
||||||
|
Resources/preauth.html,
|
||||||
|
Resources/preauth.js,
|
||||||
|
SafariWebExtensionHandler.m,
|
||||||
|
);
|
||||||
|
target = 4CABCADE2E56F0C900D8A354 /* HotPocket Extension (macOS) */;
|
||||||
|
};
|
||||||
|
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||||
|
|
||||||
|
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||||
|
4CABCA962E56F0C800D8A354 /* Shared (App) */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
|
exceptions = (
|
||||||
|
4CABCB042E56F0C900D8A354 /* Exceptions for "Shared (App)" folder in "HotPocket (iOS)" target */,
|
||||||
|
4CABCB0E2E56F0C900D8A354 /* Exceptions for "Shared (App)" folder in "HotPocket (macOS)" target */,
|
||||||
|
);
|
||||||
|
path = "Shared (App)";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
4CABCAA02E56F0C900D8A354 /* Shared (Extension) */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
|
exceptions = (
|
||||||
|
4CABCB172E56F0C900D8A354 /* Exceptions for "Shared (Extension)" folder in "HotPocket Extension (iOS)" target */,
|
||||||
|
4CABCB182E56F0C900D8A354 /* Exceptions for "Shared (Extension)" folder in "HotPocket Extension (macOS)" target */,
|
||||||
|
);
|
||||||
|
explicitFolders = (
|
||||||
|
Resources/_locales,
|
||||||
|
Resources/images,
|
||||||
|
);
|
||||||
|
path = "Shared (Extension)";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
4CABCAB22E56F0C900D8A354 /* iOS (App) */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
|
exceptions = (
|
||||||
|
4CABCB0D2E56F0C900D8A354 /* Exceptions for "iOS (App)" folder in "HotPocket (iOS)" target */,
|
||||||
|
);
|
||||||
|
path = "iOS (App)";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
4CABCAC72E56F0C900D8A354 /* macOS (App) */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
|
path = "macOS (App)";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
4CABCAD92E56F0C900D8A354 /* iOS (Extension) */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
|
exceptions = (
|
||||||
|
4CABCB082E56F0C900D8A354 /* Exceptions for "iOS (Extension)" folder in "HotPocket Extension (iOS)" target */,
|
||||||
|
);
|
||||||
|
path = "iOS (Extension)";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
4CABCAE32E56F0C900D8A354 /* macOS (Extension) */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
|
exceptions = (
|
||||||
|
4CABCB122E56F0C900D8A354 /* Exceptions for "macOS (Extension)" folder in "HotPocket Extension (macOS)" target */,
|
||||||
|
);
|
||||||
|
path = "macOS (Extension)";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXFileSystemSynchronizedRootGroup section */
|
||||||
|
|
||||||
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
4CABCAAD2E56F0C900D8A354 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
4CABCAC32E56F0C900D8A354 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
4CABCAD22E56F0C900D8A354 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
4CABCADC2E56F0C900D8A354 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXGroup section */
|
||||||
|
4CABCA912E56F0C800D8A354 = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
4CABCA962E56F0C800D8A354 /* Shared (App) */,
|
||||||
|
4CABCAA02E56F0C900D8A354 /* Shared (Extension) */,
|
||||||
|
4CABCAB22E56F0C900D8A354 /* iOS (App) */,
|
||||||
|
4CABCAC72E56F0C900D8A354 /* macOS (App) */,
|
||||||
|
4CABCAD92E56F0C900D8A354 /* iOS (Extension) */,
|
||||||
|
4CABCAE32E56F0C900D8A354 /* macOS (Extension) */,
|
||||||
|
4CABCAB12E56F0C900D8A354 /* Products */,
|
||||||
|
);
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
4CABCAB12E56F0C900D8A354 /* Products */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
4CABCAB02E56F0C900D8A354 /* HotPocket.app */,
|
||||||
|
4CABCAC62E56F0C900D8A354 /* HotPocket.app */,
|
||||||
|
4CABCAD52E56F0C900D8A354 /* HotPocket Extension.appex */,
|
||||||
|
4CABCADF2E56F0C900D8A354 /* HotPocket Extension.appex */,
|
||||||
|
);
|
||||||
|
name = Products;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXGroup section */
|
||||||
|
|
||||||
|
/* Begin PBXNativeTarget section */
|
||||||
|
4CABCAAF2E56F0C900D8A354 /* HotPocket (iOS) */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 4CABCB0A2E56F0C900D8A354 /* Build configuration list for PBXNativeTarget "HotPocket (iOS)" */;
|
||||||
|
buildPhases = (
|
||||||
|
4CABCAAC2E56F0C900D8A354 /* Sources */,
|
||||||
|
4CABCAAD2E56F0C900D8A354 /* Frameworks */,
|
||||||
|
4CABCAAE2E56F0C900D8A354 /* Resources */,
|
||||||
|
4CABCB092E56F0C900D8A354 /* Embed Foundation Extensions */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
4CABCAD82E56F0C900D8A354 /* PBXTargetDependency */,
|
||||||
|
);
|
||||||
|
fileSystemSynchronizedGroups = (
|
||||||
|
4CABCAB22E56F0C900D8A354 /* iOS (App) */,
|
||||||
|
);
|
||||||
|
name = "HotPocket (iOS)";
|
||||||
|
packageProductDependencies = (
|
||||||
|
);
|
||||||
|
productName = "HotPocket (iOS)";
|
||||||
|
productReference = 4CABCAB02E56F0C900D8A354 /* HotPocket.app */;
|
||||||
|
productType = "com.apple.product-type.application";
|
||||||
|
};
|
||||||
|
4CABCAC52E56F0C900D8A354 /* HotPocket (macOS) */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 4CABCB142E56F0C900D8A354 /* Build configuration list for PBXNativeTarget "HotPocket (macOS)" */;
|
||||||
|
buildPhases = (
|
||||||
|
4CABCAC22E56F0C900D8A354 /* Sources */,
|
||||||
|
4CABCAC32E56F0C900D8A354 /* Frameworks */,
|
||||||
|
4CABCAC42E56F0C900D8A354 /* Resources */,
|
||||||
|
4CABCB132E56F0C900D8A354 /* Embed Foundation Extensions */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
4CABCAE22E56F0C900D8A354 /* PBXTargetDependency */,
|
||||||
|
);
|
||||||
|
fileSystemSynchronizedGroups = (
|
||||||
|
4CABCAC72E56F0C900D8A354 /* macOS (App) */,
|
||||||
|
);
|
||||||
|
name = "HotPocket (macOS)";
|
||||||
|
packageProductDependencies = (
|
||||||
|
);
|
||||||
|
productName = "HotPocket (macOS)";
|
||||||
|
productReference = 4CABCAC62E56F0C900D8A354 /* HotPocket.app */;
|
||||||
|
productType = "com.apple.product-type.application";
|
||||||
|
};
|
||||||
|
4CABCAD42E56F0C900D8A354 /* HotPocket Extension (iOS) */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 4CABCB052E56F0C900D8A354 /* Build configuration list for PBXNativeTarget "HotPocket Extension (iOS)" */;
|
||||||
|
buildPhases = (
|
||||||
|
4CABCAD12E56F0C900D8A354 /* Sources */,
|
||||||
|
4CABCAD22E56F0C900D8A354 /* Frameworks */,
|
||||||
|
4CABCAD32E56F0C900D8A354 /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
fileSystemSynchronizedGroups = (
|
||||||
|
4CABCAD92E56F0C900D8A354 /* iOS (Extension) */,
|
||||||
|
);
|
||||||
|
name = "HotPocket Extension (iOS)";
|
||||||
|
packageProductDependencies = (
|
||||||
|
);
|
||||||
|
productName = "HotPocket Extension (iOS)";
|
||||||
|
productReference = 4CABCAD52E56F0C900D8A354 /* HotPocket Extension.appex */;
|
||||||
|
productType = "com.apple.product-type.app-extension";
|
||||||
|
};
|
||||||
|
4CABCADE2E56F0C900D8A354 /* HotPocket Extension (macOS) */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 4CABCB0F2E56F0C900D8A354 /* Build configuration list for PBXNativeTarget "HotPocket Extension (macOS)" */;
|
||||||
|
buildPhases = (
|
||||||
|
4CABCADB2E56F0C900D8A354 /* Sources */,
|
||||||
|
4CABCADC2E56F0C900D8A354 /* Frameworks */,
|
||||||
|
4CABCADD2E56F0C900D8A354 /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
fileSystemSynchronizedGroups = (
|
||||||
|
4CABCAE32E56F0C900D8A354 /* macOS (Extension) */,
|
||||||
|
);
|
||||||
|
name = "HotPocket Extension (macOS)";
|
||||||
|
packageProductDependencies = (
|
||||||
|
);
|
||||||
|
productName = "HotPocket Extension (macOS)";
|
||||||
|
productReference = 4CABCADF2E56F0C900D8A354 /* HotPocket Extension.appex */;
|
||||||
|
productType = "com.apple.product-type.app-extension";
|
||||||
|
};
|
||||||
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
|
/* Begin PBXProject section */
|
||||||
|
4CABCA922E56F0C800D8A354 /* Project object */ = {
|
||||||
|
isa = PBXProject;
|
||||||
|
attributes = {
|
||||||
|
BuildIndependentTargetsInParallel = 1;
|
||||||
|
LastUpgradeCheck = 1640;
|
||||||
|
TargetAttributes = {
|
||||||
|
4CABCAAF2E56F0C900D8A354 = {
|
||||||
|
CreatedOnToolsVersion = 16.4;
|
||||||
|
};
|
||||||
|
4CABCAC52E56F0C900D8A354 = {
|
||||||
|
CreatedOnToolsVersion = 16.4;
|
||||||
|
};
|
||||||
|
4CABCAD42E56F0C900D8A354 = {
|
||||||
|
CreatedOnToolsVersion = 16.4;
|
||||||
|
};
|
||||||
|
4CABCADE2E56F0C900D8A354 = {
|
||||||
|
CreatedOnToolsVersion = 16.4;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
buildConfigurationList = 4CABCA952E56F0C800D8A354 /* Build configuration list for PBXProject "HotPocket" */;
|
||||||
|
developmentRegion = en;
|
||||||
|
hasScannedForEncodings = 0;
|
||||||
|
knownRegions = (
|
||||||
|
en,
|
||||||
|
Base,
|
||||||
|
);
|
||||||
|
mainGroup = 4CABCA912E56F0C800D8A354;
|
||||||
|
minimizedProjectReferenceProxies = 1;
|
||||||
|
preferredProjectObjectVersion = 77;
|
||||||
|
productRefGroup = 4CABCAB12E56F0C900D8A354 /* Products */;
|
||||||
|
projectDirPath = "";
|
||||||
|
projectRoot = "";
|
||||||
|
targets = (
|
||||||
|
4CABCAAF2E56F0C900D8A354 /* HotPocket (iOS) */,
|
||||||
|
4CABCAC52E56F0C900D8A354 /* HotPocket (macOS) */,
|
||||||
|
4CABCAD42E56F0C900D8A354 /* HotPocket Extension (iOS) */,
|
||||||
|
4CABCADE2E56F0C900D8A354 /* HotPocket Extension (macOS) */,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
/* End PBXProject section */
|
||||||
|
|
||||||
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
4CABCAAE2E56F0C900D8A354 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
4CABCAC42E56F0C900D8A354 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
4CABCAD32E56F0C900D8A354 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
4CABCADD2E56F0C900D8A354 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
4CABCAAC2E56F0C900D8A354 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
4CABCAC22E56F0C900D8A354 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
4CABCAD12E56F0C900D8A354 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
4CABCADB2E56F0C900D8A354 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXTargetDependency section */
|
||||||
|
4CABCAD82E56F0C900D8A354 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = 4CABCAD42E56F0C900D8A354 /* HotPocket Extension (iOS) */;
|
||||||
|
targetProxy = 4CABCAD72E56F0C900D8A354 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
|
4CABCAE22E56F0C900D8A354 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = 4CABCADE2E56F0C900D8A354 /* HotPocket Extension (macOS) */;
|
||||||
|
targetProxy = 4CABCAE12E56F0C900D8A354 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
|
/* Begin XCBuildConfiguration section */
|
||||||
|
4CABCB062E56F0C900D8A354 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 2025091701;
|
||||||
|
DEVELOPMENT_TEAM = 648728X64K;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = "iOS (Extension)/Info.plist";
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = HotPocket;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 25.9.17;
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"-framework",
|
||||||
|
SafariServices,
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = pl.bthlabs.HotPocket.Extension;
|
||||||
|
PRODUCT_NAME = "HotPocket Extension";
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
4CABCB072E56F0C900D8A354 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 2025091701;
|
||||||
|
DEVELOPMENT_TEAM = 648728X64K;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = "iOS (Extension)/Info.plist";
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = HotPocket;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 25.9.17;
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"-framework",
|
||||||
|
SafariServices,
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = pl.bthlabs.HotPocket.Extension;
|
||||||
|
PRODUCT_NAME = "HotPocket Extension";
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
VALIDATE_PRODUCT = YES;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
4CABCB0B2E56F0C900D8A354 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 2025091701;
|
||||||
|
DEVELOPMENT_TEAM = 648728X64K;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = "iOS (App)/Info.plist";
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = HotPocket;
|
||||||
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2025-present BTHLabs";
|
||||||
|
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||||
|
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
|
||||||
|
INFOPLIST_KEY_UIMainStoryboardFile = Main;
|
||||||
|
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 25.9.17;
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"-framework",
|
||||||
|
SafariServices,
|
||||||
|
"-framework",
|
||||||
|
WebKit,
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = pl.bthlabs.HotPocket;
|
||||||
|
PRODUCT_NAME = HotPocket;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
|
SUPPORTS_MACCATALYST = NO;
|
||||||
|
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||||
|
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
4CABCB0C2E56F0C900D8A354 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 2025091701;
|
||||||
|
DEVELOPMENT_TEAM = 648728X64K;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = "iOS (App)/Info.plist";
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = HotPocket;
|
||||||
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2025-present BTHLabs";
|
||||||
|
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||||
|
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
|
||||||
|
INFOPLIST_KEY_UIMainStoryboardFile = Main;
|
||||||
|
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 25.9.17;
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"-framework",
|
||||||
|
SafariServices,
|
||||||
|
"-framework",
|
||||||
|
WebKit,
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = pl.bthlabs.HotPocket;
|
||||||
|
PRODUCT_NAME = HotPocket;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
|
SUPPORTS_MACCATALYST = NO;
|
||||||
|
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||||
|
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
VALIDATE_PRODUCT = YES;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
4CABCB102E56F0C900D8A354 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CODE_SIGN_ENTITLEMENTS = "macOS (Extension)/HotPocket.entitlements";
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 2025091701;
|
||||||
|
DEVELOPMENT_TEAM = 648728X64K;
|
||||||
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = "macOS (Extension)/Info.plist";
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = HotPocket;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/../Frameworks",
|
||||||
|
"@executable_path/../../../../Frameworks",
|
||||||
|
);
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||||
|
MARKETING_VERSION = 25.9.17;
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"-framework",
|
||||||
|
SafariServices,
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = pl.bthlabs.HotPocket.Extension;
|
||||||
|
PRODUCT_NAME = "HotPocket Extension";
|
||||||
|
SDKROOT = macosx;
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
4CABCB112E56F0C900D8A354 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CODE_SIGN_ENTITLEMENTS = "macOS (Extension)/HotPocket.entitlements";
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 2025091701;
|
||||||
|
DEVELOPMENT_TEAM = 648728X64K;
|
||||||
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = "macOS (Extension)/Info.plist";
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = HotPocket;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/../Frameworks",
|
||||||
|
"@executable_path/../../../../Frameworks",
|
||||||
|
);
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||||
|
MARKETING_VERSION = 25.9.17;
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"-framework",
|
||||||
|
SafariServices,
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = pl.bthlabs.HotPocket.Extension;
|
||||||
|
PRODUCT_NAME = "HotPocket Extension";
|
||||||
|
SDKROOT = macosx;
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
4CABCB152E56F0C900D8A354 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = "macOS (App)/HotPocket.entitlements";
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 2025091701;
|
||||||
|
DEVELOPMENT_TEAM = 648728X64K;
|
||||||
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = HotPocket;
|
||||||
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2025-present BTHLabs";
|
||||||
|
INFOPLIST_KEY_NSMainStoryboardFile = Main;
|
||||||
|
INFOPLIST_KEY_NSPrincipalClass = NSApplication;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/../Frameworks",
|
||||||
|
);
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 15.0;
|
||||||
|
MARKETING_VERSION = 25.9.17;
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"-framework",
|
||||||
|
SafariServices,
|
||||||
|
"-framework",
|
||||||
|
WebKit,
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = pl.bthlabs.HotPocket;
|
||||||
|
PRODUCT_NAME = HotPocket;
|
||||||
|
REGISTER_APP_GROUPS = YES;
|
||||||
|
SDKROOT = macosx;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
4CABCB162E56F0C900D8A354 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = "macOS (App)/HotPocket.entitlements";
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 2025091701;
|
||||||
|
DEVELOPMENT_TEAM = 648728X64K;
|
||||||
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = HotPocket;
|
||||||
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2025-present BTHLabs";
|
||||||
|
INFOPLIST_KEY_NSMainStoryboardFile = Main;
|
||||||
|
INFOPLIST_KEY_NSPrincipalClass = NSApplication;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/../Frameworks",
|
||||||
|
);
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 15.0;
|
||||||
|
MARKETING_VERSION = 25.9.17;
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"-framework",
|
||||||
|
SafariServices,
|
||||||
|
"-framework",
|
||||||
|
WebKit,
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = pl.bthlabs.HotPocket;
|
||||||
|
PRODUCT_NAME = HotPocket;
|
||||||
|
REGISTER_APP_GROUPS = YES;
|
||||||
|
SDKROOT = macosx;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
4CABCB192E56F0C900D8A354 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
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;
|
||||||
|
DEVELOPMENT_TEAM = 648728X64K;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
ENABLE_TESTABILITY = YES;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
|
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;
|
||||||
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
4CABCB1A2E56F0C900D8A354 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
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";
|
||||||
|
DEVELOPMENT_TEAM = 648728X64K;
|
||||||
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
|
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;
|
||||||
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
|
/* Begin XCConfigurationList section */
|
||||||
|
4CABCA952E56F0C800D8A354 /* Build configuration list for PBXProject "HotPocket" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
4CABCB192E56F0C900D8A354 /* Debug */,
|
||||||
|
4CABCB1A2E56F0C900D8A354 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
4CABCB052E56F0C900D8A354 /* Build configuration list for PBXNativeTarget "HotPocket Extension (iOS)" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
4CABCB062E56F0C900D8A354 /* Debug */,
|
||||||
|
4CABCB072E56F0C900D8A354 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
4CABCB0A2E56F0C900D8A354 /* Build configuration list for PBXNativeTarget "HotPocket (iOS)" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
4CABCB0B2E56F0C900D8A354 /* Debug */,
|
||||||
|
4CABCB0C2E56F0C900D8A354 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
4CABCB0F2E56F0C900D8A354 /* Build configuration list for PBXNativeTarget "HotPocket Extension (macOS)" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
4CABCB102E56F0C900D8A354 /* Debug */,
|
||||||
|
4CABCB112E56F0C900D8A354 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
4CABCB142E56F0C900D8A354 /* Build configuration list for PBXNativeTarget "HotPocket (macOS)" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
4CABCB152E56F0C900D8A354 /* Debug */,
|
||||||
|
4CABCB162E56F0C900D8A354 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
/* End XCConfigurationList section */
|
||||||
|
};
|
||||||
|
rootObject = 4CABCA922E56F0C800D8A354 /* Project object */;
|
||||||
|
}
|
||||||
7
services/apple/HotPocket.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "self:">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
||||||
3
services/apple/README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# HotPocket by BTHLabs
|
||||||
|
|
||||||
|
This repository contains the _HotPocket Apple Integrations_ project.
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0xED",
|
||||||
|
"green" : "0xBA",
|
||||||
|
"red" : "0x1C"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "icon-1024.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"size" : "1024x1024"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename" : "icon-1024 1.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"size" : "1024x1024"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "tinted"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename" : "icon-1024 2.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"size" : "1024x1024"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "icon-16.png",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "16x16"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "icon-32.png",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "16x16"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "icon-32 1.png",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "32x32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "icon-64.png",
|
||||||
|
"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"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "icon-mac-1024.png",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "512x512"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 115 KiB |
|
After Width: | Height: | Size: 115 KiB |
|
After Width: | Height: | Size: 115 KiB |
|
After Width: | Height: | Size: 874 B |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 117 KiB |
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0x29",
|
||||||
|
"green" : "0x25",
|
||||||
|
"red" : "0x21"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
23
services/apple/Shared (App)/Assets.xcassets/LargeIcon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "icon-large-128.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "icon-large-128@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "icon-large-128@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
services/apple/Shared (App)/Assets.xcassets/LargeIcon.imageset/icon-large-128.png
vendored
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
services/apple/Shared (App)/Assets.xcassets/LargeIcon.imageset/icon-large-128@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
services/apple/Shared (App)/Assets.xcassets/LargeIcon.imageset/icon-large-128@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 63 KiB |
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0xDD",
|
||||||
|
"green" : "0x82",
|
||||||
|
"red" : "0x00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
20
services/apple/Shared (App)/Resources/Base.lproj/Main.html
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
|
<meta http-equiv="Content-Security-Policy" content="default-src 'self'">
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="../Style.css">
|
||||||
|
<script src="../Script.js" defer></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<img src="../icon-mac-384.png" width="128" height="128" alt="HotPocket Icon">
|
||||||
|
<p class="platform-ios">You can turn on Save to Hotpocket Safari extension in Settings.</p>
|
||||||
|
<p class="platform-mac state-unknown">You can turn on Save to Hotpocket extension in Safari Extensions preferences.</p>
|
||||||
|
<p class="platform-mac state-on">Save to Hotpocket extension is currently on. You can turn it off in Safari Extensions preferences.</p>
|
||||||
|
<p class="platform-mac state-off">Save to Hotpocket extension is currently off. You can turn it on in Safari Extensions preferences.</p>
|
||||||
|
<button class="platform-mac open-preferences">Quit and Open Safari Extensions Preferences…</button>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
24
services/apple/Shared (App)/Resources/Script.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
function show(platform, enabled, useSettingsInsteadOfPreferences) {
|
||||||
|
document.body.classList.add(`platform-${platform}`);
|
||||||
|
|
||||||
|
if (useSettingsInsteadOfPreferences) {
|
||||||
|
document.getElementsByClassName('platform-mac state-on')[0].innerText = "Save to Hotpocket extension is currently on. You can turn it off in the Extensions section of Safari Settings.";
|
||||||
|
document.getElementsByClassName('platform-mac state-off')[0].innerText = "Save to Hotpocket extension is currently off. You can turn it on in the Extensions section of Safari Settings.";
|
||||||
|
document.getElementsByClassName('platform-mac state-unknown')[0].innerText = "You can turn on Save to Hotpocket extension in the Extensions section of Safari Settings.";
|
||||||
|
document.getElementsByClassName('platform-mac open-preferences')[0].innerText = "Quit and Open Safari Settings…";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof enabled === "boolean") {
|
||||||
|
document.body.classList.toggle(`state-on`, enabled);
|
||||||
|
document.body.classList.toggle(`state-off`, !enabled);
|
||||||
|
} else {
|
||||||
|
document.body.classList.remove(`state-on`);
|
||||||
|
document.body.classList.remove(`state-off`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function openPreferences() {
|
||||||
|
webkit.messageHandlers.controller.postMessage("open-preferences");
|
||||||
|
}
|
||||||
|
|
||||||
|
document.querySelector("button.open-preferences").addEventListener("click", openPreferences);
|
||||||
63
services/apple/Shared (App)/Resources/Style.css
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
* {
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-webkit-user-drag: none;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
color-scheme: light dark;
|
||||||
|
|
||||||
|
--spacing: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: #212529;
|
||||||
|
color: white;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
gap: var(--spacing);
|
||||||
|
margin: 0 calc(var(--spacing) * 2);
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
font: -apple-system-short-body;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
body:not(.platform-mac, .platform-ios) :is(.platform-mac, .platform-ios) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.platform-ios .platform-mac {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.platform-mac .platform-ios {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.platform-ios .platform-mac {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body:not(.state-on, .state-off) :is(.state-on, .state-off) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.state-on :is(.state-off, .state-unknown) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.state-off :is(.state-on, .state-unknown) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
BIN
services/apple/Shared (App)/Resources/icon-mac-384.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
26
services/apple/Shared (App)/ViewController.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// ViewController.h
|
||||||
|
// Shared (App)
|
||||||
|
//
|
||||||
|
// Created by Tomek Wójcik on 21/08/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <TargetConditionals.h>
|
||||||
|
|
||||||
|
#if TARGET_OS_IOS
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
typedef UIViewController PlatformViewController;
|
||||||
|
|
||||||
|
#elif TARGET_OS_OSX
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
typedef NSViewController PlatformViewController;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@interface ViewController : PlatformViewController
|
||||||
|
|
||||||
|
@end
|
||||||
76
services/apple/Shared (App)/ViewController.m
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
//
|
||||||
|
// ViewController.m
|
||||||
|
// Shared (App)
|
||||||
|
//
|
||||||
|
// Created by Tomek Wójcik on 21/08/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "ViewController.h"
|
||||||
|
|
||||||
|
#import <WebKit/WebKit.h>
|
||||||
|
|
||||||
|
#if TARGET_OS_OSX
|
||||||
|
#import <SafariServices/SafariServices.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static NSString * const extensionBundleIdentifier = @"pl.bthlabs.HotPocket.HotPocket.Extension";
|
||||||
|
|
||||||
|
@interface ViewController () <WKNavigationDelegate, WKScriptMessageHandler>
|
||||||
|
|
||||||
|
@property (nonatomic) IBOutlet WKWebView *webView;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation ViewController
|
||||||
|
|
||||||
|
- (void)viewDidLoad {
|
||||||
|
[super viewDidLoad];
|
||||||
|
|
||||||
|
_webView.navigationDelegate = self;
|
||||||
|
|
||||||
|
#if TARGET_OS_IOS
|
||||||
|
_webView.scrollView.scrollEnabled = NO;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
[_webView.configuration.userContentController addScriptMessageHandler:self name:@"controller"];
|
||||||
|
|
||||||
|
[_webView loadFileURL:[NSBundle.mainBundle URLForResource:@"Main" withExtension:@"html"] allowingReadAccessToURL:NSBundle.mainBundle.resourceURL];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
|
||||||
|
#if TARGET_OS_IOS
|
||||||
|
[webView evaluateJavaScript:@"show('ios')" completionHandler:nil];
|
||||||
|
#elif TARGET_OS_OSX
|
||||||
|
[webView evaluateJavaScript:@"show('mac')" completionHandler:nil];
|
||||||
|
|
||||||
|
[SFSafariExtensionManager getStateOfSafariExtensionWithIdentifier:extensionBundleIdentifier completionHandler:^(SFSafariExtensionState *state, NSError *error) {
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
if (!state) {
|
||||||
|
// Insert code to inform the user something went wrong.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *isExtensionEnabledAsString = state.isEnabled ? @"true" : @"false";
|
||||||
|
if (@available(macOS 13, *))
|
||||||
|
[webView evaluateJavaScript:[NSString stringWithFormat:@"show('mac', %@, true)", isExtensionEnabledAsString] completionHandler:nil];
|
||||||
|
else
|
||||||
|
[webView evaluateJavaScript:[NSString stringWithFormat:@"show('mac', %@, false)", isExtensionEnabledAsString] completionHandler:nil];
|
||||||
|
});
|
||||||
|
}];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
|
||||||
|
#if TARGET_OS_OSX
|
||||||
|
if (![message.body isEqualToString:@"open-preferences"])
|
||||||
|
return;
|
||||||
|
|
||||||
|
[SFSafariApplication showPreferencesForExtensionWithIdentifier:extensionBundleIdentifier completionHandler:^(NSError *error) {
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
[NSApp terminate:self];
|
||||||
|
});
|
||||||
|
}];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
//
|
||||||
|
// SafariWebExtensionHandler.h
|
||||||
|
// Shared (Extension)
|
||||||
|
//
|
||||||
|
// Created by Tomek Wójcik on 21/08/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@interface SafariWebExtensionHandler : NSObject <NSExtensionRequestHandling>
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
//
|
||||||
|
// SafariWebExtensionHandler.m
|
||||||
|
// Shared (Extension)
|
||||||
|
//
|
||||||
|
// Created by Tomek Wójcik on 21/08/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "SafariWebExtensionHandler.h"
|
||||||
|
|
||||||
|
#import <SafariServices/SafariServices.h>
|
||||||
|
|
||||||
|
@implementation SafariWebExtensionHandler
|
||||||
|
|
||||||
|
- (void)beginRequestWithExtensionContext:(NSExtensionContext *)context {
|
||||||
|
NSExtensionItem *request = context.inputItems.firstObject;
|
||||||
|
|
||||||
|
NSUUID *profile;
|
||||||
|
if (@available(iOS 17.0, macOS 14.0, *)) {
|
||||||
|
profile = request.userInfo[SFExtensionProfileKey];
|
||||||
|
} else {
|
||||||
|
profile = request.userInfo[@"profile"];
|
||||||
|
}
|
||||||
|
|
||||||
|
id message;
|
||||||
|
if (@available(iOS 15.0, macOS 11.0, *)) {
|
||||||
|
message = request.userInfo[SFExtensionMessageKey];
|
||||||
|
} else {
|
||||||
|
message = request.userInfo[@"message"];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSLog(@"Received message from browser.runtime.sendNativeMessage: %@ (profile: %@)", message, profile.UUIDString ?: @"none");
|
||||||
|
|
||||||
|
NSExtensionItem *response = [[NSExtensionItem alloc] init];
|
||||||
|
if (@available(iOS 15.0, macOS 11.0, *)) {
|
||||||
|
response.userInfo = @{ SFExtensionMessageKey: @{ @"echo": message } };
|
||||||
|
} else {
|
||||||
|
response.userInfo = @{ @"message": @{ @"echo": message } };
|
||||||
|
}
|
||||||
|
|
||||||
|
[context completeRequestReturningItems:@[ response ] completionHandler:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
12
services/apple/iOS (App)/AppDelegate.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
//
|
||||||
|
// AppDelegate.h
|
||||||
|
// iOS (App)
|
||||||
|
//
|
||||||
|
// Created by Tomek Wójcik on 21/08/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||||
|
|
||||||
|
@end
|
||||||
21
services/apple/iOS (App)/AppDelegate.m
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// AppDelegate.m
|
||||||
|
// iOS (App)
|
||||||
|
//
|
||||||
|
// Created by Tomek Wójcik on 21/08/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "AppDelegate.h"
|
||||||
|
|
||||||
|
@implementation AppDelegate
|
||||||
|
|
||||||
|
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||||
|
// Override point for customization after application launch.
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
|
||||||
|
return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
41
services/apple/iOS (App)/Base.lproj/LaunchScreen.storyboard
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23727" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||||
|
<device id="retina6_12" orientation="portrait" appearance="light"/>
|
||||||
|
<dependencies>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23721"/>
|
||||||
|
<capability name="Image references" minToolsVersion="12.0"/>
|
||||||
|
<capability name="Named colors" minToolsVersion="9.0"/>
|
||||||
|
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--View Controller-->
|
||||||
|
<scene sceneID="EHf-IW-A2E">
|
||||||
|
<objects>
|
||||||
|
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||||
|
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6HG-Um-bch">
|
||||||
|
<rect key="frame" x="131" y="363" width="128" height="128"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
|
<imageReference key="image" image="LargeIcon"/>
|
||||||
|
</imageView>
|
||||||
|
</subviews>
|
||||||
|
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||||
|
<color key="backgroundColor" name="BackgroundColor"/>
|
||||||
|
</view>
|
||||||
|
</viewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="53" y="375"/>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
<resources>
|
||||||
|
<image name="LargeIcon" width="128" height="128"/>
|
||||||
|
<namedColor name="BackgroundColor">
|
||||||
|
<color red="0.12941176470588237" green="0.14509803921568629" blue="0.16078431372549021" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
</namedColor>
|
||||||
|
</resources>
|
||||||
|
</document>
|
||||||
46
services/apple/iOS (App)/Base.lproj/Main.storyboard
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23727" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||||
|
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||||
|
<dependencies>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23721"/>
|
||||||
|
<capability name="Named colors" minToolsVersion="9.0"/>
|
||||||
|
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--View Controller-->
|
||||||
|
<scene sceneID="tne-QT-ifu">
|
||||||
|
<objects>
|
||||||
|
<viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
|
||||||
|
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<wkWebView contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="RDB-ib-igF">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<color key="backgroundColor" name="BackgroundColor"/>
|
||||||
|
<wkWebViewConfiguration key="configuration">
|
||||||
|
<audiovisualMediaTypes key="mediaTypesRequiringUserActionForPlayback" none="YES"/>
|
||||||
|
<wkPreferences key="preferences"/>
|
||||||
|
</wkWebViewConfiguration>
|
||||||
|
</wkWebView>
|
||||||
|
</subviews>
|
||||||
|
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||||
|
<color key="backgroundColor" name="BackgroundColor"/>
|
||||||
|
</view>
|
||||||
|
<connections>
|
||||||
|
<outlet property="webView" destination="RDB-ib-igF" id="avx-RC-qRB"/>
|
||||||
|
</connections>
|
||||||
|
</viewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="53" y="375"/>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
<resources>
|
||||||
|
<namedColor name="BackgroundColor">
|
||||||
|
<color red="0.12941176470588237" green="0.14509803921568629" blue="0.16078431372549021" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
</namedColor>
|
||||||
|
</resources>
|
||||||
|
</document>
|
||||||
25
services/apple/iOS (App)/Info.plist
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>UIApplicationSceneManifest</key>
|
||||||
|
<dict>
|
||||||
|
<key>UIApplicationSupportsMultipleScenes</key>
|
||||||
|
<false/>
|
||||||
|
<key>UISceneConfigurations</key>
|
||||||
|
<dict>
|
||||||
|
<key>UIWindowSceneSessionRoleApplication</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>UISceneConfigurationName</key>
|
||||||
|
<string>Default Configuration</string>
|
||||||
|
<key>UISceneDelegateClassName</key>
|
||||||
|
<string>SceneDelegate</string>
|
||||||
|
<key>UISceneStoryboardFile</key>
|
||||||
|
<string>Main</string>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
14
services/apple/iOS (App)/SceneDelegate.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
//
|
||||||
|
// SceneDelegate.h
|
||||||
|
// iOS (App)
|
||||||
|
//
|
||||||
|
// Created by Tomek Wójcik on 21/08/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@interface SceneDelegate : UIResponder <UIWindowSceneDelegate>
|
||||||
|
|
||||||
|
@property (strong, nonatomic) UIWindow * window;
|
||||||
|
|
||||||
|
@end
|
||||||
12
services/apple/iOS (App)/SceneDelegate.m
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
//
|
||||||
|
// SceneDelegate.m
|
||||||
|
// iOS (App)
|
||||||
|
//
|
||||||
|
// Created by Tomek Wójcik on 21/08/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "SceneDelegate.h"
|
||||||
|
|
||||||
|
@implementation SceneDelegate
|
||||||
|
|
||||||
|
@end
|
||||||
18
services/apple/iOS (App)/main.m
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
//
|
||||||
|
// main.m
|
||||||
|
// iOS (App)
|
||||||
|
//
|
||||||
|
// Created by Tomek Wójcik on 21/08/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
#import "AppDelegate.h"
|
||||||
|
|
||||||
|
int main(int argc, char * argv[]) {
|
||||||
|
NSString *appDelegateClassName;
|
||||||
|
@autoreleasepool {
|
||||||
|
// Setup code that might create autoreleased objects goes here.
|
||||||
|
appDelegateClassName = NSStringFromClass([AppDelegate class]);
|
||||||
|
}
|
||||||
|
return UIApplicationMain(argc, argv, nil, appDelegateClassName);
|
||||||
|
}
|
||||||
13
services/apple/iOS (Extension)/Info.plist
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>NSExtension</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSExtensionPointIdentifier</key>
|
||||||
|
<string>com.apple.Safari.web-extension</string>
|
||||||
|
<key>NSExtensionPrincipalClass</key>
|
||||||
|
<string>SafariWebExtensionHandler</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
5
services/apple/invoke.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
run:
|
||||||
|
echo: true
|
||||||
|
pty: true
|
||||||
|
files_to_version:
|
||||||
|
- "HotPocket.xcodeproj/project.pbxproj"
|
||||||
12
services/apple/macOS (App)/AppDelegate.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
//
|
||||||
|
// AppDelegate.h
|
||||||
|
// macOS (App)
|
||||||
|
//
|
||||||
|
// Created by Tomek Wójcik on 21/08/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||||
|
|
||||||
|
@end
|
||||||
20
services/apple/macOS (App)/AppDelegate.m
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
//
|
||||||
|
// AppDelegate.m
|
||||||
|
// macOS (App)
|
||||||
|
//
|
||||||
|
// Created by Tomek Wójcik on 21/08/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "AppDelegate.h"
|
||||||
|
|
||||||
|
@implementation AppDelegate
|
||||||
|
|
||||||
|
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
|
||||||
|
// Override point for customization after application launch.
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
124
services/apple/macOS (App)/Base.lproj/Main.storyboard
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="23727" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
|
||||||
|
<dependencies>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="23727"/>
|
||||||
|
<plugIn identifier="com.apple.WebKit2IBPlugin" version="23727"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--Application-->
|
||||||
|
<scene sceneID="JPo-4y-FX3">
|
||||||
|
<objects>
|
||||||
|
<application id="hnw-xV-0zn" sceneMemberID="viewController">
|
||||||
|
<menu key="mainMenu" title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
|
||||||
|
<items>
|
||||||
|
<menuItem title="HotPocket" id="1Xt-HY-uBw">
|
||||||
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
|
<menu key="submenu" title="HotPocket" systemMenu="apple" id="uQy-DD-JDr">
|
||||||
|
<items>
|
||||||
|
<menuItem title="About HotPocket" id="5kV-Vb-QxS">
|
||||||
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="orderFrontStandardAboutPanel:" target="Ady-hI-5gd" id="Exp-CZ-Vem"/>
|
||||||
|
</connections>
|
||||||
|
</menuItem>
|
||||||
|
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
|
||||||
|
<menuItem title="Hide HotPocket" keyEquivalent="h" id="Olw-nP-bQN">
|
||||||
|
<connections>
|
||||||
|
<action selector="hide:" target="Ady-hI-5gd" id="PnN-Uc-m68"/>
|
||||||
|
</connections>
|
||||||
|
</menuItem>
|
||||||
|
<menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
|
||||||
|
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="hideOtherApplications:" target="Ady-hI-5gd" id="VT4-aY-XCT"/>
|
||||||
|
</connections>
|
||||||
|
</menuItem>
|
||||||
|
<menuItem title="Show All" id="Kd2-mp-pUS">
|
||||||
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="unhideAllApplications:" target="Ady-hI-5gd" id="Dhg-Le-xox"/>
|
||||||
|
</connections>
|
||||||
|
</menuItem>
|
||||||
|
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
|
||||||
|
<menuItem title="Quit HotPocket" keyEquivalent="q" id="4sb-4s-VLi">
|
||||||
|
<connections>
|
||||||
|
<action selector="terminate:" target="Ady-hI-5gd" id="Te7-pn-YzF"/>
|
||||||
|
</connections>
|
||||||
|
</menuItem>
|
||||||
|
</items>
|
||||||
|
</menu>
|
||||||
|
</menuItem>
|
||||||
|
<menuItem title="Help" id="wpr-3q-Mcd">
|
||||||
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
|
<menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
|
||||||
|
<items>
|
||||||
|
<menuItem title="HotPocket Help" keyEquivalent="?" id="FKE-Sm-Kum">
|
||||||
|
<connections>
|
||||||
|
<action selector="showHelp:" target="Ady-hI-5gd" id="y7X-2Q-9no"/>
|
||||||
|
</connections>
|
||||||
|
</menuItem>
|
||||||
|
</items>
|
||||||
|
</menu>
|
||||||
|
</menuItem>
|
||||||
|
</items>
|
||||||
|
</menu>
|
||||||
|
<connections>
|
||||||
|
<outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/>
|
||||||
|
</connections>
|
||||||
|
</application>
|
||||||
|
<customObject id="Voe-Tx-rLC" customClass="AppDelegate"/>
|
||||||
|
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
|
||||||
|
<customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="76" y="-134"/>
|
||||||
|
</scene>
|
||||||
|
<!--Window Controller-->
|
||||||
|
<scene sceneID="R2V-B0-nI4">
|
||||||
|
<objects>
|
||||||
|
<windowController showSeguePresentationStyle="single" id="B8D-0N-5wS" sceneMemberID="viewController">
|
||||||
|
<window key="window" title="HotPocket" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" releasedWhenClosed="NO" animationBehavior="default" id="IQv-IB-iLA">
|
||||||
|
<windowStyleMask key="styleMask" titled="YES" closable="YES"/>
|
||||||
|
<windowCollectionBehavior key="collectionBehavior" fullScreenNone="YES"/>
|
||||||
|
<rect key="contentRect" x="196" y="240" width="425" height="325"/>
|
||||||
|
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
|
||||||
|
<connections>
|
||||||
|
<outlet property="delegate" destination="B8D-0N-5wS" id="98r-iN-zZc"/>
|
||||||
|
</connections>
|
||||||
|
</window>
|
||||||
|
<connections>
|
||||||
|
<segue destination="XfG-lQ-9wD" kind="relationship" relationship="window.shadowedContentViewController" id="cq2-FE-JQM"/>
|
||||||
|
</connections>
|
||||||
|
</windowController>
|
||||||
|
<customObject id="Oky-zY-oP4" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="75" y="250"/>
|
||||||
|
</scene>
|
||||||
|
<!--View Controller-->
|
||||||
|
<scene sceneID="hIz-AP-VOD">
|
||||||
|
<objects>
|
||||||
|
<viewController id="XfG-lQ-9wD" customClass="ViewController" sceneMemberID="viewController">
|
||||||
|
<view key="view" appearanceType="darkAqua" id="m2S-Jp-Qdl">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="425" height="325"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<subviews>
|
||||||
|
<wkWebView wantsLayer="YES" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eOr-cG-IQY">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="425" height="325"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<wkWebViewConfiguration key="configuration">
|
||||||
|
<audiovisualMediaTypes key="mediaTypesRequiringUserActionForPlayback" none="YES"/>
|
||||||
|
<wkPreferences key="preferences"/>
|
||||||
|
</wkWebViewConfiguration>
|
||||||
|
</wkWebView>
|
||||||
|
</subviews>
|
||||||
|
</view>
|
||||||
|
<connections>
|
||||||
|
<outlet property="webView" destination="eOr-cG-IQY" id="GFe-mU-dBY"/>
|
||||||
|
</connections>
|
||||||
|
</viewController>
|
||||||
|
<customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="75" y="655"/>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
</document>
|
||||||
12
services/apple/macOS (App)/HotPocket.entitlements
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.app-sandbox</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.files.user-selected.read-only</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.network.client</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
15
services/apple/macOS (App)/main.m
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// main.m
|
||||||
|
// macOS (App)
|
||||||
|
//
|
||||||
|
// Created by Tomek Wójcik on 21/08/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
int main(int argc, const char * argv[]) {
|
||||||
|
@autoreleasepool {
|
||||||
|
// Setup code that might create autoreleased objects goes here.
|
||||||
|
}
|
||||||
|
return NSApplicationMain(argc, argv);
|
||||||
|
}
|
||||||
10
services/apple/macOS (Extension)/HotPocket.entitlements
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.app-sandbox</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.files.user-selected.read-only</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
13
services/apple/macOS (Extension)/Info.plist
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>NSExtension</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSExtensionPointIdentifier</key>
|
||||||
|
<string>com.apple.Safari.web-extension</string>
|
||||||
|
<key>NSExtensionPrincipalClass</key>
|
||||||
|
<string>SafariWebExtensionHandler</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
511
services/apple/poetry.lock
generated
Normal file
@@ -0,0 +1,511 @@
|
|||||||
|
# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "asttokens"
|
||||||
|
version = "3.0.0"
|
||||||
|
description = "Annotate AST trees with source code positions"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2"},
|
||||||
|
{file = "asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
astroid = ["astroid (>=2,<4)"]
|
||||||
|
test = ["astroid (>=2,<4)", "pytest", "pytest-cov", "pytest-xdist"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorama"
|
||||||
|
version = "0.4.6"
|
||||||
|
description = "Cross-platform colored terminal text."
|
||||||
|
optional = false
|
||||||
|
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
||||||
|
files = [
|
||||||
|
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
||||||
|
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "decorator"
|
||||||
|
version = "5.2.1"
|
||||||
|
description = "Decorators for Humans"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a"},
|
||||||
|
{file = "decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "executing"
|
||||||
|
version = "2.2.1"
|
||||||
|
description = "Get the currently executing AST node of a frame, and other information"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017"},
|
||||||
|
{file = "executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "factory-boy"
|
||||||
|
version = "3.3.3"
|
||||||
|
description = "A versatile test fixtures replacement based on thoughtbot's factory_bot for Ruby."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "factory_boy-3.3.3-py2.py3-none-any.whl", hash = "sha256:1c39e3289f7e667c4285433f305f8d506efc2fe9c73aaea4151ebd5cdea394fc"},
|
||||||
|
{file = "factory_boy-3.3.3.tar.gz", hash = "sha256:866862d226128dfac7f2b4160287e899daf54f2612778327dd03d0e2cb1e3d03"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
Faker = ">=0.7.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
dev = ["Django", "Pillow", "SQLAlchemy", "coverage", "flake8", "isort", "mongoengine", "mongomock", "mypy", "tox", "wheel (>=0.32.0)", "zest.releaser[recommended]"]
|
||||||
|
doc = ["Sphinx", "sphinx-rtd-theme", "sphinxcontrib-spelling"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "faker"
|
||||||
|
version = "37.6.0"
|
||||||
|
description = "Faker is a Python package that generates fake data for you."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
files = [
|
||||||
|
{file = "faker-37.6.0-py3-none-any.whl", hash = "sha256:3c5209b23d7049d596a51db5d76403a0ccfea6fc294ffa2ecfef6a8843b1e6a7"},
|
||||||
|
{file = "faker-37.6.0.tar.gz", hash = "sha256:0f8cc34f30095184adf87c3c24c45b38b33ad81c35ef6eb0a3118f301143012c"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
tzdata = "*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "flake8"
|
||||||
|
version = "7.3.0"
|
||||||
|
description = "the modular source code checker: pep8 pyflakes and co"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
files = [
|
||||||
|
{file = "flake8-7.3.0-py2.py3-none-any.whl", hash = "sha256:b9696257b9ce8beb888cdbe31cf885c90d31928fe202be0889a7cdafad32f01e"},
|
||||||
|
{file = "flake8-7.3.0.tar.gz", hash = "sha256:fe044858146b9fc69b551a4b490d69cf960fcb78ad1edcb84e7fbb1b4a8e3872"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
mccabe = ">=0.7.0,<0.8.0"
|
||||||
|
pycodestyle = ">=2.14.0,<2.15.0"
|
||||||
|
pyflakes = ">=3.4.0,<3.5.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "flake8-commas"
|
||||||
|
version = "4.0.0"
|
||||||
|
description = "Flake8 lint for trailing commas."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "flake8_commas-4.0.0-py3-none-any.whl", hash = "sha256:cad476d71ba72e8b941a8508d5b9ffb6b03e50f7102982474f085ad0d674b685"},
|
||||||
|
{file = "flake8_commas-4.0.0.tar.gz", hash = "sha256:a68834b42a9a31c94ca790efe557a932c0eae21a3479c6b9a23c4dc077e3ea96"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
flake8 = ">=5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hotpocket-workspace-tools"
|
||||||
|
version = "1.0.0.dev0"
|
||||||
|
description = "HotPocket Workspace Tools"
|
||||||
|
optional = false
|
||||||
|
python-versions = "^3.12"
|
||||||
|
files = []
|
||||||
|
develop = true
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
invoke = "2.2.0"
|
||||||
|
|
||||||
|
[package.source]
|
||||||
|
type = "directory"
|
||||||
|
url = "../packages/workspace_tools"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "invoke"
|
||||||
|
version = "2.2.0"
|
||||||
|
description = "Pythonic task execution"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
files = [
|
||||||
|
{file = "invoke-2.2.0-py3-none-any.whl", hash = "sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820"},
|
||||||
|
{file = "invoke-2.2.0.tar.gz", hash = "sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ipdb"
|
||||||
|
version = "0.13.13"
|
||||||
|
description = "IPython-enabled pdb"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||||
|
files = [
|
||||||
|
{file = "ipdb-0.13.13-py3-none-any.whl", hash = "sha256:45529994741c4ab6d2388bfa5d7b725c2cf7fe9deffabdb8a6113aa5ed449ed4"},
|
||||||
|
{file = "ipdb-0.13.13.tar.gz", hash = "sha256:e3ac6018ef05126d442af680aad863006ec19d02290561ac88b8b1c0b0cfc726"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
decorator = {version = "*", markers = "python_version >= \"3.11\""}
|
||||||
|
ipython = {version = ">=7.31.1", markers = "python_version >= \"3.11\""}
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ipython"
|
||||||
|
version = "9.3.0"
|
||||||
|
description = "IPython: Productive Interactive Computing"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.11"
|
||||||
|
files = [
|
||||||
|
{file = "ipython-9.3.0-py3-none-any.whl", hash = "sha256:1a0b6dd9221a1f5dddf725b57ac0cb6fddc7b5f470576231ae9162b9b3455a04"},
|
||||||
|
{file = "ipython-9.3.0.tar.gz", hash = "sha256:79eb896f9f23f50ad16c3bc205f686f6e030ad246cc309c6279a242b14afe9d8"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
||||||
|
decorator = "*"
|
||||||
|
ipython-pygments-lexers = "*"
|
||||||
|
jedi = ">=0.16"
|
||||||
|
matplotlib-inline = "*"
|
||||||
|
pexpect = {version = ">4.3", markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\""}
|
||||||
|
prompt_toolkit = ">=3.0.41,<3.1.0"
|
||||||
|
pygments = ">=2.4.0"
|
||||||
|
stack_data = "*"
|
||||||
|
traitlets = ">=5.13.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
all = ["ipython[doc,matplotlib,test,test-extra]"]
|
||||||
|
black = ["black"]
|
||||||
|
doc = ["docrepr", "exceptiongroup", "intersphinx_registry", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinx_toml (==0.0.4)", "typing_extensions"]
|
||||||
|
matplotlib = ["matplotlib"]
|
||||||
|
test = ["packaging", "pytest", "pytest-asyncio (<0.22)", "testpath"]
|
||||||
|
test-extra = ["curio", "ipykernel", "ipython[test]", "jupyter_ai", "matplotlib (!=3.2.0)", "nbclient", "nbformat", "numpy (>=1.23)", "pandas", "trio"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ipython-pygments-lexers"
|
||||||
|
version = "1.1.1"
|
||||||
|
description = "Defines a variety of Pygments lexers for highlighting IPython code."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c"},
|
||||||
|
{file = "ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
pygments = "*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "isort"
|
||||||
|
version = "6.0.1"
|
||||||
|
description = "A Python utility / library to sort Python imports."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9.0"
|
||||||
|
files = [
|
||||||
|
{file = "isort-6.0.1-py3-none-any.whl", hash = "sha256:2dc5d7f65c9678d94c88dfc29161a320eec67328bc97aad576874cb4be1e9615"},
|
||||||
|
{file = "isort-6.0.1.tar.gz", hash = "sha256:1cb5df28dfbc742e490c5e41bad6da41b805b0a8be7bc93cd0fb2a8a890ac450"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
colors = ["colorama"]
|
||||||
|
plugins = ["setuptools"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jedi"
|
||||||
|
version = "0.19.2"
|
||||||
|
description = "An autocompletion tool for Python that can be used for text editors."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
files = [
|
||||||
|
{file = "jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9"},
|
||||||
|
{file = "jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
parso = ">=0.8.4,<0.9.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"]
|
||||||
|
qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"]
|
||||||
|
testing = ["Django", "attrs", "colorama", "docopt", "pytest (<9.0.0)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matplotlib-inline"
|
||||||
|
version = "0.1.7"
|
||||||
|
description = "Inline Matplotlib backend for Jupyter"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca"},
|
||||||
|
{file = "matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
traitlets = "*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mccabe"
|
||||||
|
version = "0.7.0"
|
||||||
|
description = "McCabe checker, plugin for flake8"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
files = [
|
||||||
|
{file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"},
|
||||||
|
{file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mypy"
|
||||||
|
version = "1.16.1"
|
||||||
|
description = "Optional static typing for Python"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
files = [
|
||||||
|
{file = "mypy-1.16.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b4f0fed1022a63c6fec38f28b7fc77fca47fd490445c69d0a66266c59dd0b88a"},
|
||||||
|
{file = "mypy-1.16.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:86042bbf9f5a05ea000d3203cf87aa9d0ccf9a01f73f71c58979eb9249f46d72"},
|
||||||
|
{file = "mypy-1.16.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ea7469ee5902c95542bea7ee545f7006508c65c8c54b06dc2c92676ce526f3ea"},
|
||||||
|
{file = "mypy-1.16.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:352025753ef6a83cb9e7f2427319bb7875d1fdda8439d1e23de12ab164179574"},
|
||||||
|
{file = "mypy-1.16.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ff9fa5b16e4c1364eb89a4d16bcda9987f05d39604e1e6c35378a2987c1aac2d"},
|
||||||
|
{file = "mypy-1.16.1-cp310-cp310-win_amd64.whl", hash = "sha256:1256688e284632382f8f3b9e2123df7d279f603c561f099758e66dd6ed4e8bd6"},
|
||||||
|
{file = "mypy-1.16.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:472e4e4c100062488ec643f6162dd0d5208e33e2f34544e1fc931372e806c0cc"},
|
||||||
|
{file = "mypy-1.16.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea16e2a7d2714277e349e24d19a782a663a34ed60864006e8585db08f8ad1782"},
|
||||||
|
{file = "mypy-1.16.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08e850ea22adc4d8a4014651575567b0318ede51e8e9fe7a68f25391af699507"},
|
||||||
|
{file = "mypy-1.16.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22d76a63a42619bfb90122889b903519149879ddbf2ba4251834727944c8baca"},
|
||||||
|
{file = "mypy-1.16.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2c7ce0662b6b9dc8f4ed86eb7a5d505ee3298c04b40ec13b30e572c0e5ae17c4"},
|
||||||
|
{file = "mypy-1.16.1-cp311-cp311-win_amd64.whl", hash = "sha256:211287e98e05352a2e1d4e8759c5490925a7c784ddc84207f4714822f8cf99b6"},
|
||||||
|
{file = "mypy-1.16.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:af4792433f09575d9eeca5c63d7d90ca4aeceda9d8355e136f80f8967639183d"},
|
||||||
|
{file = "mypy-1.16.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:66df38405fd8466ce3517eda1f6640611a0b8e70895e2a9462d1d4323c5eb4b9"},
|
||||||
|
{file = "mypy-1.16.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44e7acddb3c48bd2713994d098729494117803616e116032af192871aed80b79"},
|
||||||
|
{file = "mypy-1.16.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ab5eca37b50188163fa7c1b73c685ac66c4e9bdee4a85c9adac0e91d8895e15"},
|
||||||
|
{file = "mypy-1.16.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb6229b2c9086247e21a83c309754b9058b438704ad2f6807f0d8227f6ebdd"},
|
||||||
|
{file = "mypy-1.16.1-cp312-cp312-win_amd64.whl", hash = "sha256:1f0435cf920e287ff68af3d10a118a73f212deb2ce087619eb4e648116d1fe9b"},
|
||||||
|
{file = "mypy-1.16.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ddc91eb318c8751c69ddb200a5937f1232ee8efb4e64e9f4bc475a33719de438"},
|
||||||
|
{file = "mypy-1.16.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:87ff2c13d58bdc4bbe7dc0dedfe622c0f04e2cb2a492269f3b418df2de05c536"},
|
||||||
|
{file = "mypy-1.16.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a7cfb0fe29fe5a9841b7c8ee6dffb52382c45acdf68f032145b75620acfbd6f"},
|
||||||
|
{file = "mypy-1.16.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:051e1677689c9d9578b9c7f4d206d763f9bbd95723cd1416fad50db49d52f359"},
|
||||||
|
{file = "mypy-1.16.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d5d2309511cc56c021b4b4e462907c2b12f669b2dbeb68300110ec27723971be"},
|
||||||
|
{file = "mypy-1.16.1-cp313-cp313-win_amd64.whl", hash = "sha256:4f58ac32771341e38a853c5d0ec0dfe27e18e27da9cdb8bbc882d2249c71a3ee"},
|
||||||
|
{file = "mypy-1.16.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7fc688329af6a287567f45cc1cefb9db662defeb14625213a5b7da6e692e2069"},
|
||||||
|
{file = "mypy-1.16.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e198ab3f55924c03ead626ff424cad1732d0d391478dfbf7bb97b34602395da"},
|
||||||
|
{file = "mypy-1.16.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09aa4f91ada245f0a45dbc47e548fd94e0dd5a8433e0114917dc3b526912a30c"},
|
||||||
|
{file = "mypy-1.16.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13c7cd5b1cb2909aa318a90fd1b7e31f17c50b242953e7dd58345b2a814f6383"},
|
||||||
|
{file = "mypy-1.16.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:58e07fb958bc5d752a280da0e890c538f1515b79a65757bbdc54252ba82e0b40"},
|
||||||
|
{file = "mypy-1.16.1-cp39-cp39-win_amd64.whl", hash = "sha256:f895078594d918f93337a505f8add9bd654d1a24962b4c6ed9390e12531eb31b"},
|
||||||
|
{file = "mypy-1.16.1-py3-none-any.whl", hash = "sha256:5fc2ac4027d0ef28d6ba69a0343737a23c4d1b83672bf38d1fe237bdc0643b37"},
|
||||||
|
{file = "mypy-1.16.1.tar.gz", hash = "sha256:6bd00a0a2094841c5e47e7374bb42b83d64c527a502e3334e1173a0c24437bab"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
mypy_extensions = ">=1.0.0"
|
||||||
|
pathspec = ">=0.9.0"
|
||||||
|
typing_extensions = ">=4.6.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
dmypy = ["psutil (>=4.0)"]
|
||||||
|
faster-cache = ["orjson"]
|
||||||
|
install-types = ["pip"]
|
||||||
|
mypyc = ["setuptools (>=50)"]
|
||||||
|
reports = ["lxml"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mypy-extensions"
|
||||||
|
version = "1.1.0"
|
||||||
|
description = "Type system extensions for programs checked with the mypy type checker."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"},
|
||||||
|
{file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parso"
|
||||||
|
version = "0.8.5"
|
||||||
|
description = "A Python Parser"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
files = [
|
||||||
|
{file = "parso-0.8.5-py2.py3-none-any.whl", hash = "sha256:646204b5ee239c396d040b90f9e272e9a8017c630092bf59980beb62fd033887"},
|
||||||
|
{file = "parso-0.8.5.tar.gz", hash = "sha256:034d7354a9a018bdce352f48b2a8a450f05e9d6ee85db84764e9b6bd96dafe5a"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"]
|
||||||
|
testing = ["docopt", "pytest"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pathspec"
|
||||||
|
version = "0.12.1"
|
||||||
|
description = "Utility library for gitignore style pattern matching of file paths."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"},
|
||||||
|
{file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pexpect"
|
||||||
|
version = "4.9.0"
|
||||||
|
description = "Pexpect allows easy control of interactive console applications."
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"},
|
||||||
|
{file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
ptyprocess = ">=0.5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prompt-toolkit"
|
||||||
|
version = "3.0.52"
|
||||||
|
description = "Library for building powerful interactive command lines in Python"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955"},
|
||||||
|
{file = "prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
wcwidth = "*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ptyprocess"
|
||||||
|
version = "0.7.0"
|
||||||
|
description = "Run a subprocess in a pseudo terminal"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"},
|
||||||
|
{file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pure-eval"
|
||||||
|
version = "0.2.3"
|
||||||
|
description = "Safely evaluate AST nodes without side effects"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0"},
|
||||||
|
{file = "pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
tests = ["pytest"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pycodestyle"
|
||||||
|
version = "2.14.0"
|
||||||
|
description = "Python style guide checker"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
files = [
|
||||||
|
{file = "pycodestyle-2.14.0-py2.py3-none-any.whl", hash = "sha256:dd6bf7cb4ee77f8e016f9c8e74a35ddd9f67e1d5fd4184d86c3b98e07099f42d"},
|
||||||
|
{file = "pycodestyle-2.14.0.tar.gz", hash = "sha256:c4b5b517d278089ff9d0abdec919cd97262a3367449ea1c8b49b91529167b783"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyflakes"
|
||||||
|
version = "3.4.0"
|
||||||
|
description = "passive checker of Python programs"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
files = [
|
||||||
|
{file = "pyflakes-3.4.0-py2.py3-none-any.whl", hash = "sha256:f742a7dbd0d9cb9ea41e9a24a918996e8170c799fa528688d40dd582c8265f4f"},
|
||||||
|
{file = "pyflakes-3.4.0.tar.gz", hash = "sha256:b24f96fafb7d2ab0ec5075b7350b3d2d2218eab42003821c06344973d3ea2f58"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pygments"
|
||||||
|
version = "2.19.2"
|
||||||
|
description = "Pygments is a syntax highlighting package written in Python."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"},
|
||||||
|
{file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
windows-terminal = ["colorama (>=0.4.6)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "stack-data"
|
||||||
|
version = "0.6.3"
|
||||||
|
description = "Extract data from python stack frames and tracebacks for informative displays"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"},
|
||||||
|
{file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
asttokens = ">=2.1.0"
|
||||||
|
executing = ">=1.2.0"
|
||||||
|
pure-eval = "*"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "traitlets"
|
||||||
|
version = "5.14.3"
|
||||||
|
description = "Traitlets Python configuration system"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f"},
|
||||||
|
{file = "traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"]
|
||||||
|
test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<8.2)", "pytest-mock", "pytest-mypy-testing"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typing-extensions"
|
||||||
|
version = "4.15.0"
|
||||||
|
description = "Backported and Experimental Type Hints for Python 3.9+"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
files = [
|
||||||
|
{file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"},
|
||||||
|
{file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tzdata"
|
||||||
|
version = "2025.2"
|
||||||
|
description = "Provider of IANA time zone data"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=2"
|
||||||
|
files = [
|
||||||
|
{file = "tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8"},
|
||||||
|
{file = "tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wcwidth"
|
||||||
|
version = "0.2.13"
|
||||||
|
description = "Measures the displayed width of unicode strings in a terminal"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"},
|
||||||
|
{file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
lock-version = "2.0"
|
||||||
|
python-versions = "^3.12"
|
||||||
|
content-hash = "1c74b6d5928a0b1bde41962f4233af2eba2242324c3155b21093b2f46baf5cd0"
|
||||||
26
services/apple/pyproject.toml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
[tool.poetry]
|
||||||
|
name = "hotpocket-apple"
|
||||||
|
version = "25.9.12"
|
||||||
|
description = "HotPocket Apple Integrations"
|
||||||
|
authors = ["Tomek Wójcik <contact@bthlabs.pl>"]
|
||||||
|
license = "Apache-2.0"
|
||||||
|
readme = "README.md"
|
||||||
|
package-mode = false
|
||||||
|
|
||||||
|
[tool.poetry.dependencies]
|
||||||
|
python = "^3.12"
|
||||||
|
|
||||||
|
[tool.poetry.group.dev.dependencies]
|
||||||
|
factory-boy = "3.3.3"
|
||||||
|
flake8 = "7.3.0"
|
||||||
|
flake8-commas = "4.0.0"
|
||||||
|
hotpocket-workspace-tools = {path = "../packages/workspace_tools", develop = true}
|
||||||
|
invoke = "2.2.0"
|
||||||
|
ipdb = "0.13.13"
|
||||||
|
ipython = "9.3.0"
|
||||||
|
isort = "6.0.1"
|
||||||
|
mypy = "1.16.1"
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["poetry-core"]
|
||||||
|
build-backend = "poetry.core.masonry.api"
|
||||||
16
services/apple/setup.cfg
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
[flake8]
|
||||||
|
extend-exclude =
|
||||||
|
node_modules/**/*.py
|
||||||
|
ignore = E131,W503,W504
|
||||||
|
max-line-length = 119
|
||||||
|
hang-closing = False
|
||||||
|
|
||||||
|
[isort]
|
||||||
|
known_first_party=hotpocket_backend,hotpocket_backend_testing,hotpocket_common,hotpocket_soa,hotpocket_testing,hotpocket_workspace_tools
|
||||||
|
multi_line_output=3
|
||||||
|
include_trailing_comma=true
|
||||||
|
force_sort_within_sections=true
|
||||||
|
line_length=80
|
||||||
|
use_parentheses=true
|
||||||
|
combine_as_imports=true
|
||||||
|
star_first=true
|
||||||
124
services/apple/tasks.py
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# type: ignore
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
from invoke import Context, task
|
||||||
|
from invoke.exceptions import UnexpectedExit
|
||||||
|
|
||||||
|
from hotpocket_workspace_tools import get_workspace_mode
|
||||||
|
import hotpocket_workspace_tools.tasks
|
||||||
|
|
||||||
|
WORKSPACE_MODE = get_workspace_mode()
|
||||||
|
|
||||||
|
|
||||||
|
@task
|
||||||
|
def clean(ctx: Context):
|
||||||
|
ctx.run('rm -rf DerivedData/')
|
||||||
|
|
||||||
|
|
||||||
|
@task
|
||||||
|
def test(ctx: Context):
|
||||||
|
print('NOOP')
|
||||||
|
|
||||||
|
|
||||||
|
@task
|
||||||
|
def flake8(ctx: Context):
|
||||||
|
ctx.run('flake8')
|
||||||
|
|
||||||
|
|
||||||
|
@task
|
||||||
|
def isort(ctx, check=False, diff=False):
|
||||||
|
command_parts = [
|
||||||
|
'isort',
|
||||||
|
]
|
||||||
|
|
||||||
|
if check is True:
|
||||||
|
command_parts.append('--check')
|
||||||
|
|
||||||
|
if diff is True:
|
||||||
|
command_parts.append('--diff')
|
||||||
|
|
||||||
|
command_parts.append('.')
|
||||||
|
|
||||||
|
ctx.run(' '.join(command_parts))
|
||||||
|
|
||||||
|
|
||||||
|
@task
|
||||||
|
def eslint(ctx: Context):
|
||||||
|
print('NOOP')
|
||||||
|
|
||||||
|
|
||||||
|
@task
|
||||||
|
def lint(ctx: Context):
|
||||||
|
ihazsuccess = True
|
||||||
|
|
||||||
|
try:
|
||||||
|
flake8(ctx)
|
||||||
|
except UnexpectedExit:
|
||||||
|
ihazsuccess = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
isort(ctx, check=True)
|
||||||
|
except UnexpectedExit:
|
||||||
|
ihazsuccess = False
|
||||||
|
|
||||||
|
if ihazsuccess is False:
|
||||||
|
raise RuntimeError('FIAL')
|
||||||
|
|
||||||
|
|
||||||
|
@task
|
||||||
|
def typecheck(ctx: Context):
|
||||||
|
ctx.run('mypy .')
|
||||||
|
|
||||||
|
|
||||||
|
@task
|
||||||
|
def django_shell(ctx: Context):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
|
@task
|
||||||
|
def ci(ctx: Context):
|
||||||
|
ihazsuccess = True
|
||||||
|
|
||||||
|
ci_tasks = [test, lint, typecheck]
|
||||||
|
for ci_task in ci_tasks:
|
||||||
|
try:
|
||||||
|
ci_task(ctx)
|
||||||
|
except UnexpectedExit:
|
||||||
|
ihazsuccess = False
|
||||||
|
|
||||||
|
if ihazsuccess is False:
|
||||||
|
raise RuntimeError('FIAL')
|
||||||
|
|
||||||
|
|
||||||
|
@task
|
||||||
|
def setup(ctx: Context):
|
||||||
|
print('NOOP')
|
||||||
|
|
||||||
|
|
||||||
|
@task
|
||||||
|
def start_web(ctx: Context):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
|
@task
|
||||||
|
def bump_version(ctx: Context, next_version: str, build: str | None = None):
|
||||||
|
hotpocket_workspace_tools.tasks.utils.bump_version(
|
||||||
|
ctx, next_version, build=build,
|
||||||
|
)
|
||||||
|
|
||||||
|
pbxproj_content = None
|
||||||
|
with open('HotPocket.xcodeproj/project.pbxproj', 'r', encoding='utf-8') as pbxproj_content_f:
|
||||||
|
pbxproj_content = pbxproj_content_f.read()
|
||||||
|
|
||||||
|
pbxproj_content = re.sub(
|
||||||
|
r'CURRENT_PROJECT_VERSION = [0-9]{10};',
|
||||||
|
f'CURRENT_PROJECT_VERSION = {build};',
|
||||||
|
pbxproj_content,
|
||||||
|
flags=re.MULTILINE,
|
||||||
|
)
|
||||||
|
|
||||||
|
with open('HotPocket.xcodeproj/project.pbxproj', 'w', encoding='utf-8') as pbxproj_content_f:
|
||||||
|
pbxproj_content_f.write(pbxproj_content)
|
||||||
@@ -7,7 +7,7 @@ export default defineConfig([
|
|||||||
{
|
{
|
||||||
files: [
|
files: [
|
||||||
'eslint.config.js',
|
'eslint.config.js',
|
||||||
'hotpocket_backend/apps/ui/static/ui/js/hotpocket.*.js',
|
'hotpocket_backend/apps/ui/static/ui/js/hotpocket-backend.*.js',
|
||||||
],
|
],
|
||||||
plugins: {
|
plugins: {
|
||||||
js,
|
js,
|
||||||
@@ -64,4 +64,9 @@ export default defineConfig([
|
|||||||
'no-invalid-this': 'off',
|
'no-invalid-this': 'off',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
ignores: [
|
||||||
|
'hotpocket_backend/static/**/*.js',
|
||||||
|
],
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
version = '1.0.2'
|
version = '25.9.17'
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
|
from .access_token import AccessToken # noqa: F401
|
||||||
from .account import AccountAdmin # noqa: F401
|
from .account import AccountAdmin # noqa: F401
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
from hotpocket_backend.apps.accounts.models import AccessToken
|
||||||
|
|
||||||
|
|
||||||
|
class AccessTokenAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ('pk', 'account_uuid', 'origin', 'created_at', 'is_active')
|
||||||
|
search_fields = ('pk', 'account_uuid', 'key', 'origin')
|
||||||
|
|
||||||
|
def has_delete_permission(self, request, obj=None):
|
||||||
|
return request.user.is_superuser
|
||||||
|
|
||||||
|
|
||||||
|
admin.site.register(AccessToken, AccessTokenAdmin)
|
||||||
36
services/backend/hotpocket_backend/apps/accounts/backends.py
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import typing
|
||||||
|
|
||||||
|
from django.contrib.auth.backends import ModelBackend, UserModel
|
||||||
|
from django.http import HttpRequest
|
||||||
|
|
||||||
|
from hotpocket_backend.apps.accounts.models import AccessToken, Account
|
||||||
|
|
||||||
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class AccessTokenBackend(ModelBackend):
|
||||||
|
def authenticate(self,
|
||||||
|
request: HttpRequest,
|
||||||
|
access_token: AccessToken | None,
|
||||||
|
) -> Account | None:
|
||||||
|
if not access_token:
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
user = UserModel.objects.get(pk=access_token.account_uuid)
|
||||||
|
except UserModel.DoesNotExist as exception:
|
||||||
|
LOGGER.error(
|
||||||
|
'Unhandled exception in AccessToken auth: %s',
|
||||||
|
exception,
|
||||||
|
exc_info=exception,
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.user_can_authenticate(user) is False:
|
||||||
|
return None
|
||||||
|
|
||||||
|
request.access_token = access_token
|
||||||
|
return typing.cast(Account, user)
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from django.contrib import auth
|
||||||
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
from django.http import HttpRequest
|
||||||
|
from django.utils.deprecation import MiddlewareMixin
|
||||||
|
|
||||||
|
from hotpocket_backend.apps.accounts.models import AccessToken, Account
|
||||||
|
|
||||||
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class AccessTokenMiddleware(MiddlewareMixin):
|
||||||
|
def process_request(self, request: HttpRequest):
|
||||||
|
if not hasattr(request, 'user'):
|
||||||
|
raise ImproperlyConfigured('No `AuthenticationMiddleware`?')
|
||||||
|
|
||||||
|
authorization_header = request.headers.get('Authorization', None)
|
||||||
|
if authorization_header is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
scheme, authorization = authorization_header.split(' ', maxsplit=1)
|
||||||
|
assert scheme == 'Bearer', (
|
||||||
|
f'Unsupported authorization scheme: `{scheme}`'
|
||||||
|
)
|
||||||
|
|
||||||
|
access_token = AccessToken.active_objects.get(key=authorization)
|
||||||
|
except (ValueError, AssertionError, AccessToken.DoesNotExist, Account.DoesNotExist) as exception:
|
||||||
|
LOGGER.error(
|
||||||
|
'Unhandled exception in AccessToken middleware: %s',
|
||||||
|
exception,
|
||||||
|
exc_info=exception,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
account = auth.authenticate(request, access_token=access_token)
|
||||||
|
if account:
|
||||||
|
request.user = account
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# Generated by Django 5.2.3 on 2025-09-04 18:50
|
||||||
|
|
||||||
|
import uuid6
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('accounts', '0004_alter_account_settings_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='AccessToken',
|
||||||
|
fields=[
|
||||||
|
('id', models.UUIDField(default=uuid6.uuid7, editable=False, primary_key=True, serialize=False)),
|
||||||
|
('account_uuid', models.UUIDField(db_index=True, default=None)),
|
||||||
|
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('updated_at', models.DateTimeField(auto_now=True)),
|
||||||
|
('deleted_at', models.DateTimeField(blank=True, db_index=True, default=None, editable=False, null=True)),
|
||||||
|
('key', models.CharField(db_index=True, default=None, editable=False, max_length=128, unique=True)),
|
||||||
|
('origin', models.CharField(db_index=True, default=None)),
|
||||||
|
('meta', models.JSONField(blank=True, default=dict, null=True)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Access Token',
|
||||||
|
'verbose_name_plural': 'Access Tokens',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -1 +1,2 @@
|
|||||||
|
from .access_token import AccessToken # noqa: F401
|
||||||
from .account import Account # noqa: F401
|
from .account import Account # noqa: F401
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
from hotpocket_backend.apps.core.models import Model
|
||||||
|
|
||||||
|
|
||||||
|
class ActiveAccessTokensManager(models.Manager):
|
||||||
|
def get_queryset(self) -> models.QuerySet[AccessToken]:
|
||||||
|
return super().get_queryset().filter(
|
||||||
|
deleted_at__isnull=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class AccessToken(Model):
|
||||||
|
key = models.CharField(
|
||||||
|
blank=False,
|
||||||
|
default=None,
|
||||||
|
null=False,
|
||||||
|
max_length=128,
|
||||||
|
db_index=True,
|
||||||
|
unique=True,
|
||||||
|
editable=False,
|
||||||
|
)
|
||||||
|
origin = models.CharField(
|
||||||
|
blank=False, default=None, null=False, db_index=True,
|
||||||
|
)
|
||||||
|
meta = models.JSONField(blank=True, default=dict, null=True)
|
||||||
|
|
||||||
|
objects = models.Manager()
|
||||||
|
active_objects = ActiveAccessTokensManager()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _('Access Token')
|
||||||
|
verbose_name_plural = _('Access Tokens')
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return f'<AccessToken pk={self.pk} account_uuid={self.account_uuid}>'
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
from .access_tokens import AccessTokensService # noqa: F401
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
import hmac
|
||||||
|
import logging
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
import uuid6
|
||||||
|
|
||||||
|
from hotpocket_backend.apps.accounts.models import AccessToken
|
||||||
|
from hotpocket_backend.apps.core.conf import settings
|
||||||
|
from hotpocket_soa.dto.accounts import (
|
||||||
|
AccessTokenMetaUpdateIn,
|
||||||
|
AccessTokensQuery,
|
||||||
|
)
|
||||||
|
|
||||||
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class AccessTokensService:
|
||||||
|
class AccessTokensServiceError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class AccessTokenNotFound(AccessTokensServiceError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def create(self,
|
||||||
|
*,
|
||||||
|
account_uuid: uuid.UUID,
|
||||||
|
origin: str,
|
||||||
|
meta: dict,
|
||||||
|
) -> AccessToken:
|
||||||
|
pk = uuid6.uuid7()
|
||||||
|
key = hmac.new(
|
||||||
|
settings.SECRET_KEY.encode('ascii'),
|
||||||
|
msg=pk.bytes,
|
||||||
|
digestmod=hashlib.sha256,
|
||||||
|
)
|
||||||
|
|
||||||
|
return AccessToken.objects.create(
|
||||||
|
pk=pk,
|
||||||
|
account_uuid=account_uuid,
|
||||||
|
key=key.hexdigest(),
|
||||||
|
origin=origin,
|
||||||
|
meta=meta,
|
||||||
|
)
|
||||||
|
|
||||||
|
def get(self, *, pk: uuid.UUID) -> AccessToken:
|
||||||
|
try:
|
||||||
|
query_set = AccessToken.active_objects
|
||||||
|
|
||||||
|
return query_set.get(pk=pk)
|
||||||
|
except AccessToken.DoesNotExist as exception:
|
||||||
|
raise self.AccessTokenNotFound(
|
||||||
|
f'Access Token not found: pk=`{pk}`',
|
||||||
|
) from exception
|
||||||
|
|
||||||
|
def get_by_key(self, *, key: str) -> AccessToken:
|
||||||
|
try:
|
||||||
|
query_set = AccessToken.active_objects
|
||||||
|
|
||||||
|
return query_set.get(key=key)
|
||||||
|
except AccessToken.DoesNotExist as exception:
|
||||||
|
raise self.AccessTokenNotFound(
|
||||||
|
f'Access Token not found: key=`{key}`',
|
||||||
|
) from exception
|
||||||
|
|
||||||
|
def search(self,
|
||||||
|
*,
|
||||||
|
query: AccessTokensQuery,
|
||||||
|
offset: int = 0,
|
||||||
|
limit: int = 10,
|
||||||
|
order_by: str = '-pk',
|
||||||
|
) -> models.QuerySet[AccessToken]:
|
||||||
|
filters = [
|
||||||
|
models.Q(account_uuid=query.account_uuid),
|
||||||
|
]
|
||||||
|
|
||||||
|
if query.before is not None:
|
||||||
|
filters.append(models.Q(pk__lt=query.before))
|
||||||
|
|
||||||
|
result = AccessToken.active_objects.\
|
||||||
|
filter(*filters).\
|
||||||
|
order_by(order_by)
|
||||||
|
|
||||||
|
return result[offset:offset + limit]
|
||||||
|
|
||||||
|
def delete(self, *, pk: uuid.UUID) -> bool:
|
||||||
|
access_token = self.get(pk=pk)
|
||||||
|
access_token.soft_delete()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def update_meta(self,
|
||||||
|
*,
|
||||||
|
pk: uuid.UUID,
|
||||||
|
update: AccessTokenMetaUpdateIn,
|
||||||
|
) -> AccessToken:
|
||||||
|
access_token = AccessToken.active_objects.get(pk=pk)
|
||||||
|
|
||||||
|
next_meta = {
|
||||||
|
**(access_token.meta or {}),
|
||||||
|
}
|
||||||
|
|
||||||
|
if update.version is not None:
|
||||||
|
next_meta['version'] = update.version
|
||||||
|
|
||||||
|
if update.platform is not None:
|
||||||
|
next_meta['platform'] = update.platform
|
||||||
|
|
||||||
|
access_token.meta = next_meta
|
||||||
|
access_token.save()
|
||||||
|
|
||||||
|
access_token.refresh_from_db()
|
||||||
|
|
||||||
|
return access_token
|
||||||
51
services/backend/hotpocket_backend/apps/core/rpc.py
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import typing
|
||||||
|
|
||||||
|
from bthlabs_jsonrpc_django import (
|
||||||
|
DjangoExecutor,
|
||||||
|
DjangoJSONRPCSerializer,
|
||||||
|
JSONRPCView as BaseJSONRPCView,
|
||||||
|
)
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
|
import uuid6
|
||||||
|
|
||||||
|
|
||||||
|
class JSONRPCSerializer(DjangoJSONRPCSerializer):
|
||||||
|
STRING_COERCIBLE_TYPES: typing.Any = (
|
||||||
|
*DjangoJSONRPCSerializer.STRING_COERCIBLE_TYPES,
|
||||||
|
uuid6.UUID,
|
||||||
|
)
|
||||||
|
|
||||||
|
def serialize_value(self, value: typing.Any) -> typing.Any:
|
||||||
|
if isinstance(value, ValidationError):
|
||||||
|
result: typing.Any = None
|
||||||
|
|
||||||
|
if hasattr(value, 'error_dict') is True:
|
||||||
|
result = {}
|
||||||
|
for field, errors in value.error_dict.items():
|
||||||
|
result[field] = [
|
||||||
|
error.code
|
||||||
|
for error
|
||||||
|
in errors
|
||||||
|
]
|
||||||
|
elif hasattr(value, 'error_list') is True:
|
||||||
|
result = [
|
||||||
|
error.code
|
||||||
|
for error in value.error_list
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
result = value.code
|
||||||
|
|
||||||
|
return self.serialize_value(result)
|
||||||
|
|
||||||
|
return super().serialize_value(value)
|
||||||
|
|
||||||
|
|
||||||
|
class Executor(DjangoExecutor):
|
||||||
|
serializer = JSONRPCSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class JSONRPCView(BaseJSONRPCView):
|
||||||
|
executor = Executor
|
||||||
@@ -3,6 +3,8 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import enum
|
import enum
|
||||||
|
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
class MessageLevelAlertClass(enum.Enum):
|
class MessageLevelAlertClass(enum.Enum):
|
||||||
debug = 'alert-secondary'
|
debug = 'alert-secondary'
|
||||||
@@ -15,3 +17,9 @@ class MessageLevelAlertClass(enum.Enum):
|
|||||||
class StarUnstarAssociationViewMode(enum.Enum):
|
class StarUnstarAssociationViewMode(enum.Enum):
|
||||||
STAR = 'STAR'
|
STAR = 'STAR'
|
||||||
UNSTAR = 'UNSTAR'
|
UNSTAR = 'UNSTAR'
|
||||||
|
|
||||||
|
|
||||||
|
class UIAccessTokenOriginApp(enum.Enum):
|
||||||
|
SAFARI_WEB_EXTENSION = _('Safari Web Extension')
|
||||||
|
CHROME_EXTENSION = _('Chrome Extension')
|
||||||
|
FIREFOX_EXTENSION = _('Firefox Extension')
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from .base import BrowseParams as BaseBrowseParams
|
||||||
|
|
||||||
|
|
||||||
|
class AppsBrowseParams(BaseBrowseParams):
|
||||||
|
pass
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from crispy_forms.layout import Submit
|
||||||
|
from django import forms
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
from hotpocket_backend.apps.ui.forms.base import ConfirmationMixin, Form
|
||||||
|
|
||||||
|
|
||||||
|
class AppForm(Form):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ConfirmationForm(ConfirmationMixin, AppForm):
|
||||||
|
origin_app = forms.CharField(
|
||||||
|
label=_('App'),
|
||||||
|
required=False,
|
||||||
|
disabled=True,
|
||||||
|
show_hidden_initial=True,
|
||||||
|
)
|
||||||
|
platform = forms.CharField(
|
||||||
|
label=_('Platform'),
|
||||||
|
required=False,
|
||||||
|
disabled=True,
|
||||||
|
show_hidden_initial=True,
|
||||||
|
)
|
||||||
|
version = forms.CharField(
|
||||||
|
label=_('Version'),
|
||||||
|
required=False,
|
||||||
|
disabled=True,
|
||||||
|
show_hidden_initial=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_layout_fields(self) -> list[str]:
|
||||||
|
return [
|
||||||
|
'canhazconfirm',
|
||||||
|
'origin_app',
|
||||||
|
'platform',
|
||||||
|
'version',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteForm(ConfirmationForm):
|
||||||
|
def get_submit_button(self) -> Submit:
|
||||||
|
return Submit('submit', _('Delete'), css_class='btn btn-danger')
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from crispy_forms.bootstrap import FormActions
|
||||||
|
from crispy_forms.helper import FormHelper
|
||||||
|
from crispy_forms.layout import Layout, Submit
|
||||||
|
from django.contrib.auth.forms import (
|
||||||
|
AuthenticationForm as BaseAuthenticationForm,
|
||||||
|
)
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
|
class LoginForm(BaseAuthenticationForm):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
self.helper = FormHelper(self)
|
||||||
|
self.helper.attrs = {
|
||||||
|
'id': self.__class__.__name__,
|
||||||
|
'novalidate': '',
|
||||||
|
}
|
||||||
|
self.helper.layout = Layout(
|
||||||
|
'username',
|
||||||
|
'password',
|
||||||
|
FormActions(
|
||||||
|
Submit('submit', _('Log in'), css_class='btn btn-primary'),
|
||||||
|
template='ui/ui/forms/formactions.html',
|
||||||
|
css_class='mb-0',
|
||||||
|
),
|
||||||
|
)
|
||||||
@@ -6,32 +6,11 @@ from crispy_forms.helper import FormHelper
|
|||||||
from crispy_forms.layout import Layout, Submit
|
from crispy_forms.layout import Layout, Submit
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib.auth.forms import (
|
from django.contrib.auth.forms import (
|
||||||
AuthenticationForm as BaseAuthenticationForm,
|
|
||||||
PasswordChangeForm as BasePasswordChangeForm,
|
PasswordChangeForm as BasePasswordChangeForm,
|
||||||
)
|
)
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from .base import Form
|
from hotpocket_backend.apps.ui.forms.base import Form
|
||||||
|
|
||||||
|
|
||||||
class LoginForm(BaseAuthenticationForm):
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
self.helper = FormHelper(self)
|
|
||||||
self.helper.attrs = {
|
|
||||||
'id': self.__class__.__name__,
|
|
||||||
'novalidate': '',
|
|
||||||
}
|
|
||||||
self.helper.layout = Layout(
|
|
||||||
'username',
|
|
||||||
'password',
|
|
||||||
FormActions(
|
|
||||||
Submit('submit', _('Log in'), css_class='btn btn-primary'),
|
|
||||||
template='ui/ui/forms/formactions.html',
|
|
||||||
css_class='mb-0',
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class ProfileForm(Form):
|
class ProfileForm(Form):
|
||||||
@@ -131,17 +110,17 @@ class PasswordForm(BasePasswordChangeForm):
|
|||||||
|
|
||||||
|
|
||||||
class FederatedPasswordForm(PasswordForm):
|
class FederatedPasswordForm(PasswordForm):
|
||||||
current_password = forms.CharField(
|
old_password = forms.CharField(
|
||||||
label=_('Old password'),
|
label=_('Old password'),
|
||||||
disabled=True,
|
disabled=True,
|
||||||
required=False,
|
required=False,
|
||||||
)
|
)
|
||||||
new_password = forms.CharField(
|
new_password1 = forms.CharField(
|
||||||
label=_('New password'),
|
label=_('New password'),
|
||||||
disabled=True,
|
disabled=True,
|
||||||
required=False,
|
required=False,
|
||||||
)
|
)
|
||||||
new_password_again = forms.CharField(
|
new_password2 = forms.CharField(
|
||||||
label=_('New password confirmation'),
|
label=_('New password confirmation'),
|
||||||
disabled=True,
|
disabled=True,
|
||||||
required=False,
|
required=False,
|
||||||
@@ -5,19 +5,14 @@ from crispy_forms.layout import Submit
|
|||||||
from django import forms
|
from django import forms
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from .base import Form
|
from .base import ConfirmationMixin, Form
|
||||||
|
|
||||||
|
|
||||||
class AssociationForm(Form):
|
class AssociationForm(Form):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ConfirmationForm(AssociationForm):
|
class ConfirmationForm(ConfirmationMixin, AssociationForm):
|
||||||
canhazconfirm = forms.CharField(
|
|
||||||
label='',
|
|
||||||
required=True,
|
|
||||||
widget=forms.HiddenInput,
|
|
||||||
)
|
|
||||||
title = forms.CharField(
|
title = forms.CharField(
|
||||||
label=_('Title'),
|
label=_('Title'),
|
||||||
required=False,
|
required=False,
|
||||||
|
|||||||
@@ -61,3 +61,11 @@ class Form(forms.Form):
|
|||||||
template=self.get_form_actions_template(),
|
template=self.get_form_actions_template(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ConfirmationMixin(forms.Form):
|
||||||
|
canhazconfirm = forms.CharField(
|
||||||
|
label='',
|
||||||
|
required=True,
|
||||||
|
widget=forms.HiddenInput,
|
||||||
|
)
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
from . import accounts # noqa: F401
|
||||||
|
from . import saves # noqa: F401
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
from . import access_tokens # noqa: F401
|
||||||
|
from . import auth # noqa: F401
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from bthlabs_jsonrpc_core import register_method
|
||||||
|
from django import db
|
||||||
|
from django.http import HttpRequest
|
||||||
|
|
||||||
|
from hotpocket_soa.services import AccessTokensService
|
||||||
|
|
||||||
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@register_method('accounts.access_tokens.create')
|
||||||
|
def create(request: HttpRequest,
|
||||||
|
auth_key: str,
|
||||||
|
meta: dict,
|
||||||
|
) -> str:
|
||||||
|
with db.transaction.atomic():
|
||||||
|
try:
|
||||||
|
assert 'extension_auth_key' in request.session, 'Auth key missing'
|
||||||
|
assert request.session['extension_auth_key'] == auth_key, (
|
||||||
|
'Auth key mismatch'
|
||||||
|
)
|
||||||
|
except AssertionError as exception:
|
||||||
|
LOGGER.error(
|
||||||
|
'Unable to issue access token: %s',
|
||||||
|
exception,
|
||||||
|
exc_info=exception,
|
||||||
|
)
|
||||||
|
raise
|
||||||
|
|
||||||
|
access_token = AccessTokensService().create(
|
||||||
|
account_uuid=request.user.pk,
|
||||||
|
origin=request.META['HTTP_ORIGIN'],
|
||||||
|
meta=meta,
|
||||||
|
)
|
||||||
|
|
||||||
|
request.session.pop('extension_auth_key')
|
||||||
|
request.session.save()
|
||||||
|
|
||||||
|
return access_token.key
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from bthlabs_jsonrpc_core import register_method
|
||||||
|
from django import db
|
||||||
|
from django.http import HttpRequest
|
||||||
|
|
||||||
|
from hotpocket_soa.dto.accounts import AccessTokenMetaUpdateIn
|
||||||
|
from hotpocket_soa.services import AccessTokensService
|
||||||
|
|
||||||
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@register_method('accounts.auth.check')
|
||||||
|
def check(request: HttpRequest) -> bool:
|
||||||
|
return request.user.is_anonymous is False
|
||||||
|
|
||||||
|
|
||||||
|
@register_method('accounts.auth.check_access_token')
|
||||||
|
def check_access_token(request: HttpRequest,
|
||||||
|
access_token: str,
|
||||||
|
meta: dict | None = None,
|
||||||
|
) -> bool:
|
||||||
|
result = True
|
||||||
|
|
||||||
|
try:
|
||||||
|
access_tokens_service = AccessTokensService()
|
||||||
|
|
||||||
|
with db.transaction.atomic():
|
||||||
|
access_token_object = access_tokens_service.get_by_key(
|
||||||
|
account_uuid=request.user.pk,
|
||||||
|
key=access_token,
|
||||||
|
)
|
||||||
|
|
||||||
|
meta_update = AccessTokenMetaUpdateIn.model_validate(
|
||||||
|
(meta or {}),
|
||||||
|
)
|
||||||
|
|
||||||
|
_ = access_tokens_service.update_meta(
|
||||||
|
access_token=access_token_object,
|
||||||
|
update=meta_update,
|
||||||
|
)
|
||||||
|
except AccessTokensService.AccessTokenNotFound as exception:
|
||||||
|
LOGGER.error(
|
||||||
|
'Access Token not found: account_uuid=`%s` key=`%s`',
|
||||||
|
request.user.pk,
|
||||||
|
access_token,
|
||||||
|
exc_info=exception,
|
||||||
|
)
|
||||||
|
result = False
|
||||||
|
except AccessTokensService.AccessTokenAccessDenied as exception:
|
||||||
|
LOGGER.error(
|
||||||
|
'Access Token access denied: account_uuid=`%s` key=`%s`',
|
||||||
|
request.user.pk,
|
||||||
|
access_token,
|
||||||
|
exc_info=exception,
|
||||||
|
)
|
||||||
|
result = False
|
||||||
|
|
||||||
|
return result
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from bthlabs_jsonrpc_core import register_method
|
||||||
|
from django import db
|
||||||
|
from django.http import HttpRequest
|
||||||
|
|
||||||
|
from hotpocket_backend.apps.ui.services.workflows import CreateSaveWorkflow
|
||||||
|
from hotpocket_soa.dto.associations import AssociationOut
|
||||||
|
|
||||||
|
|
||||||
|
@register_method(method='saves.create')
|
||||||
|
def create(request: HttpRequest, url: str) -> AssociationOut:
|
||||||
|
with db.transaction.atomic():
|
||||||
|
association = CreateSaveWorkflow().run_rpc(
|
||||||
|
request=request,
|
||||||
|
account=request.user,
|
||||||
|
url=url,
|
||||||
|
)
|
||||||
|
|
||||||
|
return association
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from .access_tokens import UIAccessTokensService # noqa: F401
|
||||||
from .associations import UIAssociationsService # noqa: F401
|
from .associations import UIAssociationsService # noqa: F401
|
||||||
from .imports import UIImportsService # noqa: F401
|
from .imports import UIImportsService # noqa: F401
|
||||||
from .saves import UISavesService # noqa: F401
|
from .saves import UISavesService # noqa: F401
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from django.core.exceptions import PermissionDenied
|
||||||
|
from django.http import Http404
|
||||||
|
|
||||||
|
from hotpocket_soa.dto.accounts import AccessTokenOut
|
||||||
|
from hotpocket_soa.services import AccessTokensService
|
||||||
|
|
||||||
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class UIAccessTokensService:
|
||||||
|
def __init__(self):
|
||||||
|
self.access_tokens_service = AccessTokensService()
|
||||||
|
|
||||||
|
def get_or_404(self,
|
||||||
|
*,
|
||||||
|
account_uuid: uuid.UUID,
|
||||||
|
pk: uuid.UUID,
|
||||||
|
) -> AccessTokenOut:
|
||||||
|
try:
|
||||||
|
return AccessTokensService().get(
|
||||||
|
account_uuid=account_uuid,
|
||||||
|
pk=pk,
|
||||||
|
)
|
||||||
|
except AccessTokensService.AccessTokenNotFound as exception:
|
||||||
|
LOGGER.error(
|
||||||
|
'Access Token not found: account_uuid=`%s` pk=`%s`',
|
||||||
|
account_uuid,
|
||||||
|
pk,
|
||||||
|
exc_info=exception,
|
||||||
|
)
|
||||||
|
raise Http404()
|
||||||
|
except AccessTokensService.AccessTokenAccessDenied as exception:
|
||||||
|
LOGGER.error(
|
||||||
|
'Access Token access denied: account_uuid=`%s` pk=`%s`',
|
||||||
|
account_uuid,
|
||||||
|
pk,
|
||||||
|
exc_info=exception,
|
||||||
|
)
|
||||||
|
raise PermissionDenied()
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from bthlabs_jsonrpc_core import JSONRPCInternalError
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
import django.db
|
import django.db
|
||||||
from django.http import HttpRequest, HttpResponse
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
@@ -9,19 +11,19 @@ from django.urls import reverse
|
|||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from hotpocket_backend.apps.accounts.types import PAccount
|
from hotpocket_backend.apps.accounts.types import PAccount
|
||||||
from hotpocket_soa.dto.saves import SaveIn
|
from hotpocket_soa.dto.associations import AssociationOut
|
||||||
|
from hotpocket_soa.dto.celery import AsyncResultOut
|
||||||
|
from hotpocket_soa.dto.saves import SaveIn, SaveOut
|
||||||
|
from hotpocket_soa.services import SavesService
|
||||||
|
|
||||||
from .base import SaveWorkflow
|
from .base import SaveWorkflow
|
||||||
|
|
||||||
|
|
||||||
class CreateSaveWorkflow(SaveWorkflow):
|
class CreateSaveWorkflow(SaveWorkflow):
|
||||||
def run(self,
|
def create_associate_and_process(self,
|
||||||
*,
|
|
||||||
request: HttpRequest,
|
|
||||||
account: PAccount,
|
account: PAccount,
|
||||||
url: str,
|
url: str,
|
||||||
force_post_save: bool = False,
|
) -> tuple[SaveOut, AssociationOut, AsyncResultOut | None]:
|
||||||
) -> HttpResponse:
|
|
||||||
with django.db.transaction.atomic():
|
with django.db.transaction.atomic():
|
||||||
save = self.create(
|
save = self.create(
|
||||||
account.pk,
|
account.pk,
|
||||||
@@ -30,6 +32,23 @@ class CreateSaveWorkflow(SaveWorkflow):
|
|||||||
|
|
||||||
association = self.associate(account.pk, save)
|
association = self.associate(account.pk, save)
|
||||||
|
|
||||||
|
processing_result: AsyncResultOut | None = None
|
||||||
|
if save.last_processed_at is None:
|
||||||
|
processing_result = self.schedule_processing(save)
|
||||||
|
|
||||||
|
return (save, association, processing_result)
|
||||||
|
|
||||||
|
def run(self,
|
||||||
|
*,
|
||||||
|
request: HttpRequest,
|
||||||
|
account: PAccount,
|
||||||
|
url: str,
|
||||||
|
force_post_save: bool = False,
|
||||||
|
) -> HttpResponse:
|
||||||
|
save, association, processing_result = self.create_associate_and_process(
|
||||||
|
account, url,
|
||||||
|
)
|
||||||
|
|
||||||
response = redirect(reverse('ui.associations.browse'))
|
response = redirect(reverse('ui.associations.browse'))
|
||||||
if force_post_save is True or save.is_netloc_banned is True:
|
if force_post_save is True or save.is_netloc_banned is True:
|
||||||
response = redirect(reverse(
|
response = redirect(reverse(
|
||||||
@@ -46,7 +65,22 @@ class CreateSaveWorkflow(SaveWorkflow):
|
|||||||
response.headers['X-HotPocket-Testing-Save-PK'] = save.pk
|
response.headers['X-HotPocket-Testing-Save-PK'] = save.pk
|
||||||
response.headers['X-HotPocket-Testing-Association-PK'] = association.pk
|
response.headers['X-HotPocket-Testing-Association-PK'] = association.pk
|
||||||
|
|
||||||
if save.last_processed_at is None:
|
|
||||||
processing_result = self.schedule_processing(save) # noqa: F841
|
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
def run_rpc(self,
|
||||||
|
*,
|
||||||
|
request: HttpRequest,
|
||||||
|
account: PAccount,
|
||||||
|
url: str,
|
||||||
|
) -> AssociationOut:
|
||||||
|
try:
|
||||||
|
save, association, processing_result = self.create_associate_and_process(
|
||||||
|
account, url,
|
||||||
|
)
|
||||||
|
|
||||||
|
return association
|
||||||
|
except SavesService.SavesServiceError as exception:
|
||||||
|
if isinstance(exception.__cause__, ValidationError) is True:
|
||||||
|
raise JSONRPCInternalError(data=exception.__cause__)
|
||||||
|
|
||||||
|
raise
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ body, html {
|
|||||||
}
|
}
|
||||||
|
|
||||||
body > .ui-viewport {
|
body > .ui-viewport {
|
||||||
padding-bottom: 3.5rem;
|
|
||||||
padding-top: 3.5rem;
|
padding-top: 3.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,7 +35,7 @@ body:not(.ui-js-enabled) .ui-noscript-hide {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#navbar .ui-navbar-brand > img {
|
#navbar .ui-navbar-brand > img {
|
||||||
border-radius: 0.25rem;
|
border-radius: 20%;
|
||||||
height: 1.5rem;
|
height: 1.5rem;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
@@ -45,11 +44,11 @@ body:not(.ui-js-enabled) .ui-noscript-hide {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-save-card .card-footer .spinner-border {
|
.spinner-border.ui-htmx-indicator {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-save-card .card-footer .spinner-border.htmx-request {
|
.spinner-border.ui-htmx-indicator.htmx-request {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,3 +102,23 @@ body.ui-mode-standalone #offcanvas-controls .offcanvas-body {
|
|||||||
#BrowseSavesView-Search .form-select {
|
#BrowseSavesView-Search .form-select {
|
||||||
min-width: 10rem;
|
min-width: 10rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#navbar .ui-inline-create-save-form {
|
||||||
|
bottom: 0px;
|
||||||
|
right: 0px;
|
||||||
|
top: 0px;
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 767px) {
|
||||||
|
#navbar .ui-inline-create-save-form {
|
||||||
|
right: 0.5rem;
|
||||||
|
width: calc(100vw - 0.5rem - 0.5rem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 768px) {
|
||||||
|
#InlineCreateSaveForm {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 874 B |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 51 KiB |
@@ -0,0 +1,63 @@
|
|||||||
|
/*!
|
||||||
|
* HotPocket by BTHLabs (https://hotpocket.app/)
|
||||||
|
* Copyright 2025-present BTHLabs <contact@bthlabs.pl> (https://bthlabs.pl/)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
((HotPocket, htmx) => {
|
||||||
|
class BrowseAccountAppsView {
|
||||||
|
constructor (app) {
|
||||||
|
this.app = app;
|
||||||
|
}
|
||||||
|
onLoad = (event) => {
|
||||||
|
document.addEventListener(
|
||||||
|
'HotPocket:BrowseAccountAppsView:updateLoadMoreButton',
|
||||||
|
this.onUpdateLoadMoreButton,
|
||||||
|
);
|
||||||
|
|
||||||
|
document.addEventListener(
|
||||||
|
'HotPocket:BrowseAccountAppsView:delete',
|
||||||
|
this.onDelete,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
onUpdateLoadMoreButton = (event) => {
|
||||||
|
const button = document.querySelector('#BrowseAccountAppsView .ui-load-more-button');
|
||||||
|
if (button) {
|
||||||
|
if (event.detail.next_url) {
|
||||||
|
button.setAttribute('hx-get', event.detail.next_url);
|
||||||
|
button.classList.remove('disable');
|
||||||
|
button.removeAttribute('disabled', true);
|
||||||
|
} else {
|
||||||
|
button.classList.add('disable');
|
||||||
|
button.setAttribute('disabled', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
htmx.process('#BrowseAccountAppsView .ui-load-more-button');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
onDelete = (event) => {
|
||||||
|
if (event.detail && event.detail.pk) {
|
||||||
|
const elementsToRemove = document.querySelectorAll(
|
||||||
|
`[data-access-token="${event.detail.pk}"]`,
|
||||||
|
);
|
||||||
|
for (let elementToRemove of elementsToRemove) {
|
||||||
|
elementToRemove.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
HotPocket.addPlugin('UI.BrowseAccountAppsView', (app) => {
|
||||||
|
return new BrowseAccountAppsView(app);
|
||||||
|
});
|
||||||
|
})(window.HotPocket, window.htmx);
|
||||||
@@ -20,7 +20,12 @@
|
|||||||
this.app = app;
|
this.app = app;
|
||||||
}
|
}
|
||||||
onLoad = (event) => {
|
onLoad = (event) => {
|
||||||
document.addEventListener('HotPocket:BrowseSavesView:updateLoadMoreButton', (event) => {
|
document.addEventListener(
|
||||||
|
'HotPocket:BrowseSavesView:updateLoadMoreButton',
|
||||||
|
this.onUpdateLoadMoreButton,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
onUpdateLoadMoreButton = (event) => {
|
||||||
const button = document.querySelector('#BrowseSavesView .ui-load-more-button');
|
const button = document.querySelector('#BrowseSavesView .ui-load-more-button');
|
||||||
if (button) {
|
if (button) {
|
||||||
if (event.detail.next_url) {
|
if (event.detail.next_url) {
|
||||||
@@ -34,7 +39,6 @@
|
|||||||
|
|
||||||
htmx.process('#BrowseSavesView .ui-load-more-button');
|
htmx.process('#BrowseSavesView .ui-load-more-button');
|
||||||
}
|
}
|
||||||
});
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/*!
|
||||||
|
* HotPocket by BTHLabs (https://hotpocket.app/)
|
||||||
|
* Copyright 2025-present BTHLabs <contact@bthlabs.pl> (https://bthlabs.pl/)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
((HotPocket, htmx) => {
|
||||||
|
class InlineCreateSaveForm {
|
||||||
|
constructor (app) {
|
||||||
|
this.app = app;
|
||||||
|
this.element = null;
|
||||||
|
this.buttonTrigger = null;
|
||||||
|
this.form = null;
|
||||||
|
}
|
||||||
|
onLoad = (event) => {
|
||||||
|
this.element = document.getElementById('InlineCreateSaveForm');
|
||||||
|
this.buttonTrigger = this.element.querySelector('.ui-inline-create-save-form-trigger');
|
||||||
|
this.buttonClose = this.element.querySelector('.ui-inline-create-save-form-close');
|
||||||
|
this.form = this.element.querySelector('.ui-inline-create-save-form');
|
||||||
|
|
||||||
|
this.buttonTrigger.addEventListener('click', this.onTriggerClick);
|
||||||
|
this.buttonClose.addEventListener('click', this.onCloseClick);
|
||||||
|
};
|
||||||
|
onTriggerClick = (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
this.form.classList.remove('d-none');
|
||||||
|
this.form.classList.add('d-flex');
|
||||||
|
};
|
||||||
|
onCloseClick = (event) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
this.form.classList.add('d-none');
|
||||||
|
this.form.classList.remove('d-flex');
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
HotPocket.addPlugin('UI.InlineCreateSaveForm', (app) => {
|
||||||
|
return new InlineCreateSaveForm(app);
|
||||||
|
});
|
||||||
|
})(window.HotPocket, window.htmx);
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/*!
|
||||||
|
* HotPocket by BTHLabs (https://hotpocket.app/)
|
||||||
|
* Copyright 2025-present BTHLabs <contact@bthlabs.pl> (https://bthlabs.pl/)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
((HotPocket) => {
|
||||||
|
class HotPocketUIPasteboardLinkPlugin {
|
||||||
|
constructor (app) {
|
||||||
|
}
|
||||||
|
onLoad (event) {
|
||||||
|
let canCopy = false;
|
||||||
|
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||||
|
canCopy = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let pasteboardLink of document.querySelectorAll('.ui-pasteboard-link')) {
|
||||||
|
if (canCopy === false) {
|
||||||
|
pasteboardLink.classList.add('d-none');
|
||||||
|
} else {
|
||||||
|
pasteboardLink.addEventListener('click', this.onClick);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onClick = (event) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const icon = event.target.querySelector('i.bi');
|
||||||
|
icon.classList.replace('bi-clipboard-fill', 'bi-clipboard');
|
||||||
|
|
||||||
|
navigator.clipboard.writeText(event.target.href).
|
||||||
|
then(() => {
|
||||||
|
icon.classList.replace('bi-clipboard', 'bi-clipboard-fill');
|
||||||
|
}).
|
||||||
|
catch((reason) => {
|
||||||
|
console.error('HotPocket.UI.PasteboardLink.onClick()', reason);
|
||||||
|
window.alert('Could not copy the link :(');
|
||||||
|
});
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
HotPocket.addPlugin('UI.PasteboardLink', (app) => {
|
||||||
|
return new HotPocketUIPasteboardLinkPlugin(app);
|
||||||
|
});
|
||||||
|
})(window.HotPocket);
|
||||||