Compare commits
2 commits
main
...
onboarding
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30886771c5 | ||
|
|
534e615919 |
|
|
@ -1,3 +1,6 @@
|
|||
[target.'cfg(unix)']
|
||||
runner = "sudo -E"
|
||||
|
||||
[alias] # command aliases
|
||||
rr = "run --release"
|
||||
bb = "build --release"
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
# Xcode
|
||||
Apple/
|
||||
|
||||
# Rust
|
||||
target/
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
name: Build Rust
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- "**"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
rust:
|
||||
name: Cargo Test
|
||||
runs-on: [self-hosted, linux, x86_64, burrow-forge]
|
||||
steps:
|
||||
- name: Checkout
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
repo_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git"
|
||||
if [ ! -d .git ]; then
|
||||
git init .
|
||||
fi
|
||||
if git remote get-url origin >/dev/null 2>&1; then
|
||||
git remote set-url origin "${repo_url}"
|
||||
else
|
||||
git remote add origin "${repo_url}"
|
||||
fi
|
||||
git fetch --force --tags origin "${GITHUB_SHA}"
|
||||
git checkout --force --detach FETCH_HEAD
|
||||
git clean -ffdqx
|
||||
|
||||
- name: Test
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
nix develop .#ci -c cargo test --workspace --all-features
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
name: Build Site
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- "**"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
site:
|
||||
name: Next.js Build
|
||||
runs-on: [self-hosted, linux, x86_64, burrow-forge]
|
||||
steps:
|
||||
- name: Checkout
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
repo_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git"
|
||||
if [ ! -d .git ]; then
|
||||
git init .
|
||||
fi
|
||||
if git remote get-url origin >/dev/null 2>&1; then
|
||||
git remote set-url origin "${repo_url}"
|
||||
else
|
||||
git remote add origin "${repo_url}"
|
||||
fi
|
||||
git fetch --force --tags origin "${GITHUB_SHA}"
|
||||
git checkout --force --detach FETCH_HEAD
|
||||
git clean -ffdqx
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
nix develop .#ci -c bash -lc 'cd site && npm ci --no-audit --no-fund && npm run build'
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
name: Lint Governance
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- "**"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
governance:
|
||||
name: BEP Metadata
|
||||
runs-on: [self-hosted, linux, x86_64, burrow-forge]
|
||||
steps:
|
||||
- name: Checkout
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
repo_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git"
|
||||
if [ ! -d .git ]; then
|
||||
git init .
|
||||
fi
|
||||
if git remote get-url origin >/dev/null 2>&1; then
|
||||
git remote set-url origin "${repo_url}"
|
||||
else
|
||||
git remote add origin "${repo_url}"
|
||||
fi
|
||||
git fetch --force --tags origin "${GITHUB_SHA}"
|
||||
git checkout --force --detach FETCH_HEAD
|
||||
git clean -ffdqx
|
||||
|
||||
- name: Validate BEP metadata
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
python3 Scripts/check-bep-metadata.py
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Release Build
|
||||
runs-on: namespace-profile-linux-medium
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: https://code.forgejo.org/actions/checkout@v4
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Bootstrap Nix
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
chmod +x Scripts/ci/ensure-nix.sh
|
||||
Scripts/ci/ensure-nix.sh
|
||||
|
||||
- name: Build release artifacts
|
||||
shell: bash
|
||||
env:
|
||||
RELEASE_REF: ${{ github.ref_name }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
ref="${RELEASE_REF:-manual-${GITHUB_SHA::7}}"
|
||||
export RELEASE_REF="${ref}"
|
||||
chmod +x Scripts/ci/build-release-artifacts.sh
|
||||
nix develop .#ci -c Scripts/ci/build-release-artifacts.sh
|
||||
|
||||
- name: Upload release artifacts
|
||||
uses: https://code.forgejo.org/actions/upload-artifact@v4
|
||||
with:
|
||||
name: burrow-release-${{ github.ref_name }}
|
||||
path: dist/*
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Publish Forgejo release
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
shell: bash
|
||||
env:
|
||||
RELEASE_TAG: ${{ github.ref_name }}
|
||||
API_URL: ${{ github.api_url }}
|
||||
REPOSITORY: ${{ github.repository }}
|
||||
TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
chmod +x Scripts/ci/publish-forgejo-release.sh
|
||||
nix develop .#ci -c Scripts/ci/publish-forgejo-release.sh
|
||||
5
.github/CODEOWNERS
vendored
|
|
@ -1,4 +1 @@
|
|||
* @conradev @malted @JettChenT @jdogcoder
|
||||
burrow/ @conradev @malted @JettChenT @jdogcoder @Muirrum
|
||||
tun/ @conradev @malted @JettChenT @jdogcoder @Muirrum
|
||||
burrow-gtk/ @conradev @malted @JettChenT @jdogcoder @davnotdev
|
||||
* @conradev @ma1ted @Muirrum
|
||||
8
.github/actions/archive/action.yml
vendored
|
|
@ -26,18 +26,18 @@ runs:
|
|||
run: |
|
||||
echo "${{ inputs.app-store-key }}" > AuthKey_${{ inputs.app-store-key-id }}.p8
|
||||
|
||||
xcodebuild clean archive \
|
||||
xcodebuild archive \
|
||||
-allowProvisioningUpdates \
|
||||
-allowProvisioningDeviceRegistration \
|
||||
-skipPackagePluginValidation \
|
||||
-skipMacroValidation \
|
||||
-onlyUsePackageVersionsFromResolvedFile \
|
||||
-authenticationKeyID ${{ inputs.app-store-key-id }} \
|
||||
-authenticationKeyIssuerID ${{ inputs.app-store-key-issuer-id }} \
|
||||
-authenticationKeyPath "${PWD}/AuthKey_${{ inputs.app-store-key-id }}.p8" \
|
||||
-onlyUsePackageVersionsFromResolvedFile \
|
||||
-scheme '${{ inputs.scheme }}' \
|
||||
-destination '${{ inputs.destination }}' \
|
||||
-archivePath '${{ inputs.archive-path }}' \
|
||||
-resultBundlePath BuildResults.xcresult
|
||||
|
||||
./Tools/xcresulttool-github BuildResults.xcresult
|
||||
|
||||
rm -rf AuthKey_${{ inputs.app-store-key-id }}.p8
|
||||
|
|
|
|||
13
.github/actions/build-for-testing/action.yml
vendored
|
|
@ -18,36 +18,31 @@ inputs:
|
|||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Xcode Cache
|
||||
- name: Cache Swift Packages
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
Apple/PackageCache
|
||||
Apple/SourcePackages
|
||||
Apple/DerivedData
|
||||
key: ${{ runner.os }}-${{ inputs.scheme }}-${{ hashFiles('**/Package.resolved') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ inputs.scheme }}-${{ hashFiles('**/Package.resolved') }}
|
||||
${{ runner.os }}-${{ inputs.scheme }}-
|
||||
${{ runner.os }}-
|
||||
- name: Build
|
||||
shell: bash
|
||||
working-directory: Apple
|
||||
run: |
|
||||
echo "${{ inputs.app-store-key }}" > AuthKey_${{ inputs.app-store-key-id }}.p8
|
||||
|
||||
xcodebuild build-for-testing \
|
||||
xcodebuild clean build-for-testing \
|
||||
-allowProvisioningUpdates \
|
||||
-allowProvisioningDeviceRegistration \
|
||||
-skipPackagePluginValidation \
|
||||
-skipMacroValidation \
|
||||
-onlyUsePackageVersionsFromResolvedFile \
|
||||
-authenticationKeyID ${{ inputs.app-store-key-id }} \
|
||||
-authenticationKeyIssuerID ${{ inputs.app-store-key-issuer-id }} \
|
||||
-authenticationKeyPath "${PWD}/AuthKey_${{ inputs.app-store-key-id }}.p8" \
|
||||
-onlyUsePackageVersionsFromResolvedFile \
|
||||
-clonedSourcePackagesDirPath SourcePackages \
|
||||
-packageCachePath $PWD/PackageCache \
|
||||
-derivedDataPath $PWD/DerivedData \
|
||||
-skipPackagePluginValidation \
|
||||
-scheme '${{ inputs.scheme }}' \
|
||||
-destination '${{ inputs.destination }}' \
|
||||
-resultBundlePath BuildResults.xcresult
|
||||
|
|
|
|||
30
.github/actions/download-profiles/action.yml
vendored
|
|
@ -1,30 +0,0 @@
|
|||
name: Download Provisioning Profiles
|
||||
inputs:
|
||||
app-store-key:
|
||||
description: App Store key in PEM PKCS#8 format
|
||||
required: true
|
||||
app-store-key-id:
|
||||
description: App Store key ID
|
||||
required: true
|
||||
app-store-key-issuer-id:
|
||||
description: App Store key issuer ID
|
||||
required: true
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- shell: bash
|
||||
env:
|
||||
FASTLANE_OPT_OUT_USAGE: 'YES'
|
||||
run: |
|
||||
APP_STORE_KEY=$(echo "${{ inputs.app-store-key }}" | jq -sR .)
|
||||
cat << EOF > api-key.json
|
||||
{
|
||||
"key_id": "${{ inputs.app-store-key-id }}",
|
||||
"issuer_id": "${{ inputs.app-store-key-issuer-id }}",
|
||||
"key": $APP_STORE_KEY
|
||||
}
|
||||
EOF
|
||||
|
||||
fastlane sigh download_all --api_key_path api-key.json
|
||||
|
||||
rm -rf api-key.json
|
||||
18
.github/actions/export/action.yml
vendored
|
|
@ -1,4 +1,4 @@
|
|||
name: Export
|
||||
name: Notarize
|
||||
inputs:
|
||||
app-store-key:
|
||||
description: App Store key in PEM PKCS#8 format
|
||||
|
|
@ -12,8 +12,11 @@ inputs:
|
|||
archive-path:
|
||||
description: Xcode archive path
|
||||
required: true
|
||||
export-options:
|
||||
description: The export options in JSON format
|
||||
destination:
|
||||
description: The Xcode export destination. This can either be "export" or "upload"
|
||||
required: true
|
||||
method:
|
||||
description: The Xcode export method. This can be one of app-store, validation, ad-hoc, package, enterprise, development, developer-id, or mac-application.
|
||||
required: true
|
||||
export-path:
|
||||
description: The path to export the archive to
|
||||
|
|
@ -21,20 +24,19 @@ inputs:
|
|||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- shell: bash
|
||||
- id: notarize
|
||||
shell: bash
|
||||
working-directory: Apple
|
||||
run: |
|
||||
echo "${{ inputs.app-store-key }}" > AuthKey_${{ inputs.app-store-key-id }}.p8
|
||||
|
||||
echo '${{ inputs.export-options }}' | plutil -convert xml1 -o ExportOptions.plist -
|
||||
echo '{"destination":"${{ inputs.destination }}","method":"${{ inputs.method }}"}' \
|
||||
| plutil -convert xml1 -o ExportOptions.plist -
|
||||
|
||||
xcodebuild \
|
||||
-exportArchive \
|
||||
-allowProvisioningUpdates \
|
||||
-allowProvisioningDeviceRegistration \
|
||||
-skipPackagePluginValidation \
|
||||
-skipMacroValidation \
|
||||
-onlyUsePackageVersionsFromResolvedFile \
|
||||
-authenticationKeyID ${{ inputs.app-store-key-id }} \
|
||||
-authenticationKeyIssuerID ${{ inputs.app-store-key-issuer-id }} \
|
||||
-authenticationKeyPath "${PWD}/AuthKey_${{ inputs.app-store-key-id }}.p8" \
|
||||
|
|
|
|||
25
.github/actions/notarize/action.yml
vendored
|
|
@ -1,25 +0,0 @@
|
|||
name: Notarize
|
||||
inputs:
|
||||
app-store-key:
|
||||
description: App Store key in PEM PKCS#8 format
|
||||
required: true
|
||||
app-store-key-id:
|
||||
description: App Store key ID
|
||||
required: true
|
||||
app-store-key-issuer-id:
|
||||
description: App Store key issuer ID
|
||||
required: true
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- id: notarize
|
||||
shell: bash
|
||||
working-directory: Apple
|
||||
run: |
|
||||
echo "${{ inputs.app-store-key }}" > AuthKey_${{ inputs.app-store-key-id }}.p8
|
||||
|
||||
ditto -c -k --keepParent Release/Burrow.app Upload.zip
|
||||
xcrun notarytool submit --wait --issuer ${{ inputs.app-store-key-issuer-id }} --key-id ${{ inputs.app-store-key-id }} --key "${PWD}/AuthKey_${{ inputs.app-store-key-id }}.p8" Upload.zip
|
||||
xcrun stapler staple Release/Burrow.app
|
||||
|
||||
rm -rf AuthKey_${{ inputs.app-store-key-id }}.p8 Release
|
||||
|
|
@ -18,6 +18,9 @@ inputs:
|
|||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- shell: bash
|
||||
id: vars
|
||||
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
- shell: bash
|
||||
working-directory: Apple
|
||||
run: |
|
||||
|
|
@ -25,10 +28,10 @@ runs:
|
|||
-scheme '${{ inputs.scheme }}' \
|
||||
-destination '${{ inputs.destination }}' \
|
||||
${{ inputs.test-plan && '-testPlan ' }}${{ inputs.test-plan }} \
|
||||
-resultBundlePath "${{ inputs.artifact-prefix }}.xcresult"
|
||||
-resultBundlePath "${{ inputs.artifact-prefix }}-${{ steps.vars.outputs.sha_short }}.xcresult"
|
||||
- uses: kishikawakatsumi/xcresulttool@v1
|
||||
if: always()
|
||||
with:
|
||||
path: Apple/${{ inputs.artifact-prefix }}.xcresult
|
||||
path: Apple/${{ inputs.artifact-prefix }}-${{ steps.vars.outputs.sha_short }}.xcresult
|
||||
title: ${{ inputs.check-name }}
|
||||
show-passed-tests: false
|
||||
|
|
|
|||
29
.github/workflows/build-appimage.yml
vendored
|
|
@ -1,29 +0,0 @@
|
|||
name: Build AppImage
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- "*"
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
appimage:
|
||||
name: Build AppImage
|
||||
runs-on: ubuntu-latest
|
||||
container: docker
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build AppImage
|
||||
run: |
|
||||
docker build -t appimage-builder . -f burrow-gtk/build-aux/Dockerfile
|
||||
docker create --name temp appimage-builder
|
||||
docker cp temp:/app/burrow-gtk/build-appimage/Burrow-x86_64.AppImage .
|
||||
docker rm temp
|
||||
- uses: actions/upload-artifact@v4
|
||||
name: Upload to GitHub
|
||||
with:
|
||||
name: AppImage
|
||||
path: Burrow-x86_64.AppImage
|
||||
21
.github/workflows/build-apple.yml
vendored
|
|
@ -1,4 +1,4 @@
|
|||
name: Build Apple Apps
|
||||
name: Apple Build
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
|
|
@ -6,13 +6,10 @@ on:
|
|||
pull_request:
|
||||
branches:
|
||||
- "*"
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
build:
|
||||
name: Build App (${{ matrix.platform }})
|
||||
runs-on: macos-14
|
||||
runs-on: macos-12
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
|
@ -24,7 +21,7 @@ jobs:
|
|||
rust-targets:
|
||||
- aarch64-apple-ios
|
||||
- scheme: App
|
||||
destination: platform=iOS Simulator,OS=18.0,name=iPhone 15 Pro
|
||||
destination: platform=iOS Simulator,OS=16.2,name=iPhone 14 Pro
|
||||
platform: iOS Simulator
|
||||
sdk-name: iphonesimulator
|
||||
rust-targets:
|
||||
|
|
@ -38,8 +35,7 @@ jobs:
|
|||
- x86_64-apple-darwin
|
||||
- aarch64-apple-darwin
|
||||
env:
|
||||
DEVELOPER_DIR: /Applications/Xcode_16.0.app/Contents/Developer
|
||||
PROTOC_PATH: /opt/homebrew/bin/protoc
|
||||
DEVELOPER_DIR: /Applications/Xcode_14.2.app/Contents/Developer
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
|
@ -54,11 +50,8 @@ jobs:
|
|||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: 1.85.0
|
||||
toolchain: stable
|
||||
targets: ${{ join(matrix.rust-targets, ', ') }}
|
||||
- name: Install Protobuf
|
||||
shell: bash
|
||||
run: brew install protobuf
|
||||
- name: Build
|
||||
id: build
|
||||
uses: ./.github/actions/build-for-testing
|
||||
|
|
@ -68,7 +61,7 @@ jobs:
|
|||
app-store-key: ${{ secrets.APPSTORE_KEY }}
|
||||
app-store-key-id: ${{ secrets.APPSTORE_KEY_ID }}
|
||||
app-store-key-issuer-id: ${{ secrets.APPSTORE_KEY_ISSUER_ID }}
|
||||
- name: Run Unit Tests
|
||||
- name: Xcode Unit Test
|
||||
if: ${{ matrix.xcode-unit-test != '' }}
|
||||
continue-on-error: true
|
||||
uses: ./.github/actions/test-without-building
|
||||
|
|
@ -78,7 +71,7 @@ jobs:
|
|||
test-plan: ${{ matrix.xcode-unit-test }}
|
||||
artifact-prefix: unit-tests-${{ matrix.sdk-name }}
|
||||
check-name: Xcode Unit Tests (${{ matrix.platform }})
|
||||
- name: Run UI Tests
|
||||
- name: Xcode UI Test
|
||||
if: ${{ matrix.xcode-ui-test != '' }}
|
||||
continue-on-error: true
|
||||
uses: ./.github/actions/test-without-building
|
||||
|
|
|
|||
49
.github/workflows/build-docker.yml
vendored
|
|
@ -1,49 +0,0 @@
|
|||
name: Build Docker
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- "*"
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
build:
|
||||
name: Build Docker Image
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: Setup QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
with:
|
||||
platforms: arm64
|
||||
- name: Setup BuildKit
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Authenticate
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Extract Metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: ghcr.io/${{ github.repository }}
|
||||
tags: |
|
||||
type=sha
|
||||
type=match,pattern=builds/(.*),group=1
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
- name: Build and Push
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
platforms: ${{ github.event_name != 'pull_request' && 'linux/amd64,linux/arm64' || 'linux/amd64' }}
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
16
.github/workflows/build-flatpak.yml
vendored
|
|
@ -1,16 +0,0 @@
|
|||
on: workflow_dispatch
|
||||
name: Build Flatpak
|
||||
jobs:
|
||||
flatpak:
|
||||
name: Build Flatpak
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: bilelmoussaoui/flatpak-github-actions:gnome-45
|
||||
options: --privileged
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: flatpak/flatpak-github-actions/flatpak-builder@v6
|
||||
with:
|
||||
bundle: Burrow.flatpak
|
||||
manifest-path: burrow-gtk/build-aux/com.hackclub.burrow.devel.json
|
||||
cache-key: flatpak-builder-${{ github.sha }}
|
||||
17
.github/workflows/build-rpm.yml
vendored
|
|
@ -1,17 +0,0 @@
|
|||
on: workflow_dispatch
|
||||
name: Build RPM
|
||||
jobs:
|
||||
build:
|
||||
name: Build RPM
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- name: Install RPM
|
||||
run: cargo install cargo-generate-rpm
|
||||
- name: Build RPM
|
||||
run: |
|
||||
cargo build --release
|
||||
strip -s target/release/burrow
|
||||
- name: Build RPM
|
||||
run: cargo generate-rpm -p burrow
|
||||
46
.github/workflows/build-rust.yml
vendored
|
|
@ -1,4 +1,4 @@
|
|||
name: Build Rust Crate
|
||||
name: Rust Build
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
|
|
@ -6,9 +6,6 @@ on:
|
|||
pull_request:
|
||||
branches:
|
||||
- "*"
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
build:
|
||||
name: Build Crate (${{ matrix.platform }})
|
||||
|
|
@ -20,38 +17,28 @@ jobs:
|
|||
platform: Linux
|
||||
packages:
|
||||
- gcc-aarch64-linux-gnu
|
||||
test-targets:
|
||||
targets:
|
||||
- x86_64-unknown-linux-gnu
|
||||
targets:
|
||||
- aarch64-unknown-linux-gnu
|
||||
- os: macos-13
|
||||
platform: macOS (Intel)
|
||||
xcode: /Applications/Xcode_15.2.app
|
||||
test-targets:
|
||||
- x86_64-apple-darwin
|
||||
targets:
|
||||
- x86_64-apple-ios
|
||||
- os: macos-14
|
||||
- os: macos-12
|
||||
platform: macOS
|
||||
xcode: /Applications/Xcode_16.0.app
|
||||
test-targets:
|
||||
- aarch64-apple-darwin
|
||||
targets:
|
||||
- x86_64-apple-darwin
|
||||
- aarch64-apple-darwin
|
||||
- aarch64-apple-ios
|
||||
- aarch64-apple-ios-sim
|
||||
- x86_64-apple-ios
|
||||
- os: windows-2022
|
||||
platform: Windows
|
||||
test-targets:
|
||||
- x86_64-pc-windows-msvc
|
||||
targets:
|
||||
- x86_64-pc-windows-msvc
|
||||
- aarch64-pc-windows-msvc
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
DEVELOPER_DIR: ${{ matrix.xcode }}/Contents/Developer
|
||||
DEVELOPER_DIR: /Applications/Xcode_14.2.app/Contents/Developer
|
||||
CARGO_INCREMENTAL: 0
|
||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
|
||||
RUST_BACKTRACE: short
|
||||
PROTOC_VERSION: 3.25.1
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
|
@ -64,25 +51,12 @@ jobs:
|
|||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ${{ join(matrix.packages, ' ') }}
|
||||
- name: Configure LLVM
|
||||
if: matrix.os == 'windows-2022'
|
||||
shell: bash
|
||||
run: echo "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\Llvm\x64\bin" >> $GITHUB_PATH
|
||||
- name: Install protoc
|
||||
uses: taiki-e/install-action@v2
|
||||
with:
|
||||
tool: protoc@${{ env.PROTOC_VERSION }}
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: 1.85.0
|
||||
toolchain: stable
|
||||
components: rustfmt
|
||||
targets: ${{ join(matrix.targets, ', ') }}
|
||||
- name: Setup Rust Cache
|
||||
uses: Swatinem/rust-cache@v2
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: cargo build --locked --verbose --workspace --all-features --target ${{ join(matrix.targets, ' --target ') }} --target ${{ join(matrix.test-targets, ' --target ') }}
|
||||
- name: Test
|
||||
shell: bash
|
||||
run: cargo test --locked --verbose --workspace --all-features --target ${{ join(matrix.test-targets, ' --target ') }}
|
||||
run: cargo build --verbose --workspace --all-features --target ${{ join(matrix.targets, ' --target ') }}
|
||||
|
|
|
|||
7
.github/workflows/lint-git.yml
vendored
|
|
@ -8,14 +8,13 @@ jobs:
|
|||
name: Git Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
- name: Install
|
||||
- name: Install Gitlint
|
||||
shell: bash
|
||||
run: python -m pip install gitlint
|
||||
- name: Lint
|
||||
- name: Run Gitlint
|
||||
shell: bash
|
||||
run: gitlint --commits "${{ github.event.pull_request.base.sha }}..HEAD"
|
||||
|
|
|
|||
23
.github/workflows/lint-governance.yml
vendored
|
|
@ -1,23 +0,0 @@
|
|||
name: Governance Lint
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- "*"
|
||||
|
||||
jobs:
|
||||
governance:
|
||||
name: BEP Metadata
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Validate BEP metadata
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
python3 Scripts/check-bep-metadata.py
|
||||
9
.github/workflows/lint-swift.yml
vendored
|
|
@ -1,5 +1,8 @@
|
|||
name: Swift Lint
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- "*"
|
||||
|
|
@ -11,6 +14,8 @@ jobs:
|
|||
image: ghcr.io/realm/swiftlint:latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ssh-key: ${{ secrets.DEPLOY_KEY }}
|
||||
- name: Lint
|
||||
run: swiftlint lint --strict --reporter github-actions-logging
|
||||
run: swiftlint lint --reporter github-actions-logging
|
||||
|
|
|
|||
113
.github/workflows/release-apple.yml
vendored
|
|
@ -1,120 +1,65 @@
|
|||
name: Release (Apple)
|
||||
name: Build Apple Release
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- created
|
||||
jobs:
|
||||
build:
|
||||
name: Build ${{ matrix.platform }} Release
|
||||
runs-on: macos-14
|
||||
permissions:
|
||||
contents: write
|
||||
name: Build ${{ matrix.configuration['platform'] }} Release
|
||||
runs-on: macos-12
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: iOS
|
||||
rust-targets:
|
||||
- aarch64-apple-ios
|
||||
- platform: macOS
|
||||
rust-targets:
|
||||
- x86_64-apple-darwin
|
||||
- aarch64-apple-darwin
|
||||
configuration:
|
||||
- scheme: App (iOS)
|
||||
destination: generic/platform=iOS
|
||||
platform: iOS
|
||||
method: ad-hoc
|
||||
artifact-file: Apple/Release/Burrow.ipa
|
||||
- scheme: App (macOS)
|
||||
destination: generic/platform=macOS
|
||||
platform: macOS
|
||||
method: mac-application
|
||||
artifact-file: Burrow.app.txz
|
||||
env:
|
||||
DEVELOPER_DIR: /Applications/Xcode_16.0.app/Contents/Developer
|
||||
PROTOC_PATH: /opt/homebrew/bin/protoc
|
||||
DEVELOPER_DIR: /Applications/Xcode_14.2.app/Contents/Developer
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ssh-key: ${{ secrets.DEPLOY_KEY }}
|
||||
submodules: recursive
|
||||
- name: Import Certificate
|
||||
uses: ./.github/actions/import-cert
|
||||
with:
|
||||
certificate: ${{ secrets.DEVELOPER_CERT }}
|
||||
password: ${{ secrets.DEVELOPER_CERT_PASSWORD }}
|
||||
- name: Download Provisioning Profiles
|
||||
uses: ./.github/actions/download-profiles
|
||||
with:
|
||||
app-store-key: ${{ secrets.APPSTORE_KEY }}
|
||||
app-store-key-id: ${{ secrets.APPSTORE_KEY_ID }}
|
||||
app-store-key-issuer-id: ${{ secrets.APPSTORE_KEY_ISSUER_ID }}
|
||||
- name: Install Provisioning Profiles
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles/
|
||||
cp -f Apple/Profiles/* ~/Library/MobileDevice/Provisioning\ Profiles/
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: 1.85.0
|
||||
targets: ${{ join(matrix.rust-targets, ', ') }}
|
||||
- name: Install Protobuf
|
||||
shell: bash
|
||||
run: brew install protobuf
|
||||
- name: Configure Version
|
||||
id: version
|
||||
shell: bash
|
||||
run: echo "BUILD_NUMBER=$(Tools/version.sh)" >> $GITHUB_OUTPUT
|
||||
- name: Archive
|
||||
uses: ./.github/actions/archive
|
||||
with:
|
||||
scheme: App
|
||||
destination: generic/platform=${{ matrix.platform }}
|
||||
scheme: ${{ matrix.configuration['scheme'] }}
|
||||
destination: ${{ matrix.configuration['destination'] }}
|
||||
app-store-key: ${{ secrets.APPSTORE_KEY }}
|
||||
app-store-key-id: ${{ secrets.APPSTORE_KEY_ID }}
|
||||
app-store-key-issuer-id: ${{ secrets.APPSTORE_KEY_ISSUER_ID }}
|
||||
archive-path: Burrow.xcarchive
|
||||
- name: Export
|
||||
- name: Export Locally
|
||||
uses: ./.github/actions/export
|
||||
with:
|
||||
method: ${{ matrix.platform == 'macOS' && 'developer-id' || 'ad-hoc' }}
|
||||
method: ${{ matrix.configuration['method'] }}
|
||||
destination: export
|
||||
app-store-key: ${{ secrets.APPSTORE_KEY }}
|
||||
app-store-key-id: ${{ secrets.APPSTORE_KEY_ID }}
|
||||
app-store-key-issuer-id: ${{ secrets.APPSTORE_KEY_ISSUER_ID }}
|
||||
archive-path: Burrow.xcarchive
|
||||
export-options: |
|
||||
{"teamID":"P6PV2R9443","destination":"export","method":"developer-id","provisioningProfiles":{"com.hackclub.burrow":"Burrow Developer ID","com.hackclub.burrow.network":"Burrow Network Developer ID"},"signingCertificate":"Developer ID Application","signingStyle":"manual"}
|
||||
export-path: Release
|
||||
- name: Notarize
|
||||
if: ${{ matrix.platform == 'macOS' }}
|
||||
uses: ./.github/actions/notarize
|
||||
with:
|
||||
app-store-key: ${{ secrets.APPSTORE_KEY }}
|
||||
app-store-key-id: ${{ secrets.APPSTORE_KEY_ID }}
|
||||
app-store-key-issuer-id: ${{ secrets.APPSTORE_KEY_ISSUER_ID }}
|
||||
- name: Compress (iOS)
|
||||
if: ${{ matrix.platform == 'iOS' }}
|
||||
- name: Compress
|
||||
if: ${{ matrix.configuration['platform'] == 'macOS' }}
|
||||
shell: bash
|
||||
run: |
|
||||
cp Apple/Release/Burrow.ipa Burrow.ipa
|
||||
aa archive -a lzma -b 8m -d Apple -subdir Burrow.xcarchive -o Burrow-${{ matrix.platform }}.xcarchive.aar
|
||||
rm -rf Apple/Release
|
||||
- name: Compress (macOS)
|
||||
if: ${{ matrix.platform == 'macOS' }}
|
||||
shell: bash
|
||||
run: |
|
||||
aa archive -a lzma -b 8m -d Apple/Release -subdir Burrow.app -o Burrow.app.aar
|
||||
aa archive -a lzma -b 8m -d Apple -subdir Burrow.xcarchive -o Burrow-${{ matrix.platform }}.xcarchive.aar
|
||||
rm -rf Apple/Release
|
||||
- name: Upload to GitHub
|
||||
uses: SierraSoftworks/gh-releases@v1.0.7
|
||||
run: tar --options xz:compression-level=9 -C Apple/Release -cJf Burrow.app.txz ./
|
||||
- name: Attach Artifact
|
||||
uses: SierraSoftworks/gh-releases@v1.0.6
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
release_tag: ${{ github.ref_name }}
|
||||
overwrite: 'true'
|
||||
files: |
|
||||
${{ matrix.platform == 'macOS' && 'Burrow.aap.aar' || 'Burrow.ipa' }}
|
||||
Burrow-${{ matrix.platform }}.xcarchive.aar
|
||||
- name: Upload to App Store Connect
|
||||
if: ${{ matrix.platform == 'iOS' }}
|
||||
uses: ./.github/actions/export
|
||||
with:
|
||||
app-store-key: ${{ secrets.APPSTORE_KEY }}
|
||||
app-store-key-id: ${{ secrets.APPSTORE_KEY_ID }}
|
||||
app-store-key-issuer-id: ${{ secrets.APPSTORE_KEY_ISSUER_ID }}
|
||||
archive-path: Burrow.xcarchive
|
||||
export-options: |
|
||||
{"method": "app-store", "destination": "upload"}
|
||||
export-path: Release
|
||||
overwrite: 'false'
|
||||
files: ${{ matrix.configuration['artifact-file'] }}
|
||||
|
|
|
|||
23
.github/workflows/release-if-needed.yaml
vendored
|
|
@ -1,23 +0,0 @@
|
|||
name: Create Release If Needed
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 10 * * *'
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}
|
||||
jobs:
|
||||
create:
|
||||
name: Create Release If Needed
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- shell: bash
|
||||
run: |
|
||||
if [[ $(Tools/version.sh status) == "dirty" ]]; then
|
||||
gh workflow run release-now.yml
|
||||
fi
|
||||
29
.github/workflows/release-linux.yml
vendored
|
|
@ -1,29 +0,0 @@
|
|||
name: Release (Linux)
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- created
|
||||
jobs:
|
||||
appimage:
|
||||
name: Build AppImage
|
||||
runs-on: ubuntu-latest
|
||||
container: docker
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Build AppImage
|
||||
run: |
|
||||
docker build -t appimage-builder . -f burrow-gtk/build-aux/Dockerfile
|
||||
docker create --name temp appimage-builder
|
||||
docker cp temp:/app/burrow-gtk/build-appimage/Burrow-x86_64.AppImage .
|
||||
docker rm temp
|
||||
- name: Attach Artifacts
|
||||
uses: SierraSoftworks/gh-releases@v1.0.7
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
release_tag: ${{ github.ref_name }}
|
||||
overwrite: "true"
|
||||
files: |
|
||||
Burrow-x86_64.AppImage
|
||||
17
.github/workflows/release-now.yml
vendored
|
|
@ -1,17 +0,0 @@
|
|||
name: Create Release
|
||||
on: workflow_dispatch
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}
|
||||
jobs:
|
||||
create:
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_RELEASE_TOKEN }}
|
||||
name: Create Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- shell: bash
|
||||
run: Tools/version.sh increment
|
||||
16
.gitignore
vendored
|
|
@ -1,20 +1,8 @@
|
|||
# Xcode
|
||||
xcuserdata
|
||||
Apple/build/
|
||||
|
||||
# Swift
|
||||
Apple/Package/.swiftpm/
|
||||
|
||||
# Rust
|
||||
target/
|
||||
.env
|
||||
|
||||
.DS_STORE
|
||||
.idea/
|
||||
|
||||
tmp/
|
||||
intake/
|
||||
|
||||
*.db
|
||||
*.sqlite3
|
||||
*.sock
|
||||
# DS Store
|
||||
**/.DS_Store
|
||||
|
|
|
|||
2
.gitlint
|
|
@ -1,5 +1,5 @@
|
|||
[general]
|
||||
ignore=body-changed-file-mention,body-is-missing
|
||||
ignore=body-changed-file-mention
|
||||
ignore-merge-commits=false
|
||||
ignore-fixup-commits=false
|
||||
ignore-squash-commits=false
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
condense_wildcard_suffixes = true
|
||||
format_macro_matchers = true
|
||||
imports_layout = "HorizontalVertical"
|
||||
imports_granularity = "Crate"
|
||||
newline_style = "Unix"
|
||||
overflow_delimited_expr = true
|
||||
reorder_impl_items = true
|
||||
group_imports = "StdExternalCrate"
|
||||
trailing_semicolon = false
|
||||
use_field_init_shorthand = true
|
||||
use_try_shorthand = true
|
||||
struct_lit_width = 30
|
||||
|
|
@ -30,6 +30,7 @@ opt_in_rules:
|
|||
- function_default_parameter_at_end
|
||||
- ibinspectable_in_extension
|
||||
- identical_operands
|
||||
- implicitly_unwrapped_optional
|
||||
- indentation_width
|
||||
- joined_default_parameter
|
||||
- last_where
|
||||
|
|
@ -45,6 +46,7 @@ opt_in_rules:
|
|||
- multiline_parameters
|
||||
- multiline_parameters_brackets
|
||||
- no_extension_access_modifier
|
||||
- no_grouping_extension
|
||||
- nslocalizedstring_key
|
||||
- nslocalizedstring_require_bundle
|
||||
- number_separator
|
||||
|
|
@ -74,7 +76,9 @@ opt_in_rules:
|
|||
- sorted_first_last
|
||||
- sorted_imports
|
||||
- static_operator
|
||||
- strict_fileprivate
|
||||
- strong_iboutlet
|
||||
- switch_case_on_newline
|
||||
- test_case_accessibility
|
||||
- toggle_bool
|
||||
- trailing_closure
|
||||
|
|
@ -93,5 +97,3 @@ disabled_rules:
|
|||
- force_try
|
||||
- nesting
|
||||
- todo
|
||||
- trailing_comma
|
||||
- switch_case_on_newline
|
||||
|
|
|
|||
25
.vscode/settings.json
vendored
|
|
@ -8,19 +8,16 @@
|
|||
"editor.acceptSuggestionOnEnter": "on",
|
||||
"rust-analyzer.restartServerOnConfigChange": true,
|
||||
"rust-analyzer.cargo.features": "all",
|
||||
"rust-analyzer.rustfmt.extraArgs": ["+nightly"],
|
||||
"[rust]": {
|
||||
"editor.defaultFormatter": "rust-lang.rust-analyzer"
|
||||
},
|
||||
"rust-analyzer.inlayHints.typeHints.enable": false,
|
||||
"rust-analyzer.linkedProjects": [
|
||||
"./burrow/Cargo.toml"
|
||||
"rust-analyzer.check.overrideCommand": [
|
||||
"cargo",
|
||||
"clippy",
|
||||
"--fix",
|
||||
"--workspace",
|
||||
"--message-format=json",
|
||||
"--all-targets",
|
||||
"--allow-dirty"
|
||||
],
|
||||
"[yaml]": {
|
||||
"editor.insertSpaces": true,
|
||||
"editor.tabSize": 2,
|
||||
"editor.autoIndent": "advanced",
|
||||
"diffEditor.ignoreTrimWhitespace": false,
|
||||
"editor.formatOnSave": false
|
||||
}
|
||||
"[rust]": {
|
||||
"editor.defaultFormatter": "rust-lang.rust-analyzer",
|
||||
},
|
||||
}
|
||||
14
AGENTS.md
|
|
@ -1,14 +0,0 @@
|
|||
# instructions for agents
|
||||
|
||||
1. Spell the project name as `Burrow` in user-facing copy and `burrow` in code, package, and protocol identifiers unless an existing integration requires a different literal.
|
||||
2. Read [CONSTITUTION.md](CONSTITUTION.md) before changing Apple clients, the daemon, the control plane, forge infrastructure, identity, or security-sensitive code.
|
||||
3. Anchor non-trivial changes in a Burrow Evolution Proposal (BEP) under [evolution/](evolution/README.md) so future contributors can inherit the rationale, safeguards, and rollout shape.
|
||||
4. Before touching the Apple app, daemon IPC, or Tailnet flows, review:
|
||||
- [evolution/proposals/BEP-0002-control-plane-bootstrap-and-local-auth.md](evolution/proposals/BEP-0002-control-plane-bootstrap-and-local-auth.md)
|
||||
- [evolution/proposals/BEP-0003-connect-ip-and-negotiation-roadmap.md](evolution/proposals/BEP-0003-connect-ip-and-negotiation-roadmap.md)
|
||||
- [evolution/proposals/BEP-0005-daemon-ipc-and-apple-boundary.md](evolution/proposals/BEP-0005-daemon-ipc-and-apple-boundary.md)
|
||||
- [evolution/proposals/BEP-0006-tailnet-authority-first-control-plane.md](evolution/proposals/BEP-0006-tailnet-authority-first-control-plane.md)
|
||||
5. Apple clients must talk only to the daemon over gRPC. Do not add direct HTTP, control-plane, or helper-process calls from Swift UI code.
|
||||
6. Treat Tailnet as one protocol family. Tailscale-managed and self-hosted Headscale-style deployments differ by authority, policy, and auth details, not by a separate user-facing protocol surface.
|
||||
7. Maintain canonical identity and operator metadata in [contributors.nix](contributors.nix). If Burrow forge, Authentik, Headscale, or admin/group mappings need to change, edit that registry first and derive runtime configuration from it.
|
||||
8. When process or architecture is unclear, stop and draft or update a BEP instead of improvising durable behavior in code.
|
||||
|
|
@ -2,11 +2,6 @@
|
|||
<!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.developer.associated-domains</key>
|
||||
<array>
|
||||
<string>applinks:burrow.rs?mode=developer</string>
|
||||
<string>webcredentials:burrow.rs?mode=developer</string>
|
||||
</array>
|
||||
<key>com.apple.developer.networking.networkextension</key>
|
||||
<array>
|
||||
<string>packet-tunnel-provider</string>
|
||||
|
|
|
|||
|
|
@ -2,18 +2,13 @@
|
|||
<!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.developer.associated-domains</key>
|
||||
<array>
|
||||
<string>applinks:burrow.rs?mode=developer</string>
|
||||
<string>webcredentials:burrow.rs?mode=developer</string>
|
||||
</array>
|
||||
<key>com.apple.developer.networking.networkextension</key>
|
||||
<array>
|
||||
<string>packet-tunnel-provider</string>
|
||||
</array>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>$(APP_GROUP_IDENTIFIER)</string>
|
||||
<string>group.com.hackclub.burrow</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
|
|
@ -11,12 +11,7 @@ INFOPLIST_KEY_UIStatusBarStyle[sdk=iphone*] = UIStatusBarStyleDefault
|
|||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad[sdk=iphone*] = UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone[sdk=iphone*] = UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight
|
||||
TARGETED_DEVICE_FAMILY[sdk=iphone*] = 1,2
|
||||
EXCLUDED_SOURCE_FILE_NAMES = MainMenu.xib
|
||||
|
||||
EXCLUDED_SOURCE_FILE_NAMES[sdk=macosx*] =
|
||||
INFOPLIST_KEY_LSUIElement[sdk=macosx*] = YES
|
||||
INFOPLIST_KEY_NSMainNibFile[sdk=macosx*] = MainMenu
|
||||
INFOPLIST_KEY_NSPrincipalClass[sdk=macosx*] = NSApplication
|
||||
INFOPLIST_KEY_LSApplicationCategoryType[sdk=macosx*] = public.app-category.utilities
|
||||
|
||||
CODE_SIGN_ENTITLEMENTS = App/App-iOS.entitlements
|
||||
|
|
|
|||
|
|
@ -1,90 +0,0 @@
|
|||
#if os(macOS)
|
||||
import AppKit
|
||||
import BurrowUI
|
||||
import SwiftUI
|
||||
|
||||
@main
|
||||
@MainActor
|
||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
private var windowController: NSWindowController?
|
||||
|
||||
private let quitItem: NSMenuItem = {
|
||||
let quitItem = NSMenuItem(
|
||||
title: "Quit Burrow",
|
||||
action: #selector(NSApplication.terminate(_:)),
|
||||
keyEquivalent: "q"
|
||||
)
|
||||
quitItem.target = NSApplication.shared
|
||||
quitItem.keyEquivalentModifierMask = .command
|
||||
return quitItem
|
||||
}()
|
||||
|
||||
private lazy var openItem: NSMenuItem = {
|
||||
let item = NSMenuItem(
|
||||
title: "Open Burrow",
|
||||
action: #selector(openWindow),
|
||||
keyEquivalent: "o"
|
||||
)
|
||||
item.target = self
|
||||
item.keyEquivalentModifierMask = .command
|
||||
return item
|
||||
}()
|
||||
|
||||
private let toggleItem: NSMenuItem = {
|
||||
let toggleView = NSHostingView(rootView: MenuItemToggleView())
|
||||
toggleView.frame.size = CGSize(width: 300, height: 32)
|
||||
toggleView.autoresizingMask = [.width]
|
||||
|
||||
let toggleItem = NSMenuItem()
|
||||
toggleItem.view = toggleView
|
||||
return toggleItem
|
||||
}()
|
||||
|
||||
private lazy var menu: NSMenu = {
|
||||
let menu = NSMenu()
|
||||
menu.items = [
|
||||
toggleItem,
|
||||
openItem,
|
||||
.separator(),
|
||||
quitItem
|
||||
]
|
||||
return menu
|
||||
}()
|
||||
|
||||
private lazy var statusItem: NSStatusItem = {
|
||||
let statusBar = NSStatusBar.system
|
||||
let statusItem = statusBar.statusItem(withLength: NSStatusItem.squareLength)
|
||||
if let button = statusItem.button {
|
||||
button.image = NSImage(systemSymbolName: "pipe.and.drop.fill", accessibilityDescription: nil)
|
||||
}
|
||||
return statusItem
|
||||
}()
|
||||
|
||||
func applicationDidFinishLaunching(_ notification: Notification) {
|
||||
statusItem.menu = menu
|
||||
}
|
||||
|
||||
@objc
|
||||
private func openWindow() {
|
||||
if let window = windowController?.window {
|
||||
window.makeKeyAndOrderFront(nil)
|
||||
NSApplication.shared.activate(ignoringOtherApps: true)
|
||||
return
|
||||
}
|
||||
|
||||
let contentView = BurrowView()
|
||||
let hostingController = NSHostingController(rootView: contentView)
|
||||
let window = NSWindow(contentViewController: hostingController)
|
||||
window.title = "Burrow"
|
||||
window.setContentSize(NSSize(width: 820, height: 720))
|
||||
window.styleMask.insert([.titled, .closable, .miniaturizable, .resizable])
|
||||
window.center()
|
||||
|
||||
let controller = NSWindowController(window: window)
|
||||
controller.shouldCascadeWindows = true
|
||||
controller.showWindow(nil)
|
||||
windowController = controller
|
||||
NSApplication.shared.activate(ignoringOtherApps: true)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
63
Apple/App/Assets.xcassets/AppIcon.appiconset/Contents.json
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "512x512"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "512x512"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "WireGuardTitle.svg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "background.jpeg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
BIN
Apple/App/Assets.xcassets/OnboardingBackground.imageset/background.jpeg
vendored
Normal file
|
After Width: | Height: | Size: 134 KiB |
|
|
@ -1,14 +1,62 @@
|
|||
#if !os(macOS)
|
||||
import BurrowUI
|
||||
import NetworkExtension
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
@available(macOS 13.0, *)
|
||||
@main
|
||||
@MainActor
|
||||
struct BurrowApp: App {
|
||||
// To connect to the App Delegate
|
||||
@NSApplicationDelegateAdaptor(AppDelegate.self)
|
||||
var delegate
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
BurrowView()
|
||||
WindowGroup(id: "onboarding", content: {
|
||||
OnboardingView().frame(width: 1000, height: 600.0).scaledToFill().fixedSize()
|
||||
}).windowStyle(.hiddenTitleBar).windowResizability(.contentSize)
|
||||
}
|
||||
}
|
||||
|
||||
@available(macOS 13.0, *)
|
||||
@MainActor
|
||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
static let tunnel = Tunnel { manager, proto in
|
||||
proto.serverAddress = "hackclub.com"
|
||||
manager.localizedDescription = "Burrow"
|
||||
}
|
||||
|
||||
// Verifies app status
|
||||
func checkFirstTime() {
|
||||
let launchedBefore = UserDefaults.standard.bool(forKey: "launchedBefore")
|
||||
if launchedBefore {
|
||||
print("Not first launch.")
|
||||
closeApp()
|
||||
} else {
|
||||
print("First launch, setting UserDefault.")
|
||||
setVisited()
|
||||
}
|
||||
}
|
||||
|
||||
var statusItem: NSStatusItem?
|
||||
var popOver = NSPopover()
|
||||
func applicationDidFinishLaunching(_ notification: Notification) {
|
||||
checkFirstTime()
|
||||
let menuView = MenuView(tunnel: AppDelegate.tunnel)
|
||||
// Creating apopOver
|
||||
popOver.behavior = .transient
|
||||
popOver.animates = true
|
||||
popOver.contentViewController = NSViewController()
|
||||
popOver.contentViewController?.view = NSHostingView(rootView: menuView)
|
||||
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
|
||||
// Safe Check if status Button is Available or not...
|
||||
if let menuButton = statusItem?.button {
|
||||
let icon = "network.badge.shield.half.filled"
|
||||
menuButton.image = NSImage(systemSymbolName: icon, accessibilityDescription: nil)
|
||||
menuButton.action = #selector(menuButtonToggle)
|
||||
}
|
||||
}
|
||||
@objc func
|
||||
menuButtonToggle() {
|
||||
if let menuButton = statusItem?.button {
|
||||
self.popOver.show(relativeTo: menuButton.bounds, of: menuButton, preferredEdge: NSRectEdge.minY)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,679 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="23091" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="23091"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||
<connections>
|
||||
<outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="BurrowApp" customModuleProvider="target"/>
|
||||
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
|
||||
<menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
|
||||
<items>
|
||||
<menuItem title="Burrow" id="1Xt-HY-uBw">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Burrow" systemMenu="apple" id="uQy-DD-JDr">
|
||||
<items>
|
||||
<menuItem title="About Burrow" id="5kV-Vb-QxS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
|
||||
<menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
|
||||
<menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
|
||||
<menuItem title="Services" id="NMo-om-nkz">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
|
||||
<menuItem title="Hide Burrow" keyEquivalent="h" id="Olw-nP-bQN">
|
||||
<connections>
|
||||
<action selector="hide:" target="-1" 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="-1" id="VT4-aY-XCT"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Show All" id="Kd2-mp-pUS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
|
||||
<menuItem title="Quit Burrow" keyEquivalent="q" id="4sb-4s-VLi">
|
||||
<connections>
|
||||
<action selector="terminate:" target="-1" id="Te7-pn-YzF"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="File" id="dMs-cI-mzQ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="File" id="bib-Uj-vzu">
|
||||
<items>
|
||||
<menuItem title="New" keyEquivalent="n" id="Was-JA-tGl">
|
||||
<connections>
|
||||
<action selector="newDocument:" target="-1" id="4Si-XN-c54"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open…" keyEquivalent="o" id="IAo-SY-fd9">
|
||||
<connections>
|
||||
<action selector="openDocument:" target="-1" id="bVn-NM-KNZ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open Recent" id="tXI-mr-wws">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="oas-Oc-fiZ">
|
||||
<items>
|
||||
<menuItem title="Clear Menu" id="vNY-rz-j42">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="clearRecentDocuments:" target="-1" id="Daa-9d-B3U"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="m54-Is-iLE"/>
|
||||
<menuItem title="Close" keyEquivalent="w" id="DVo-aG-piG">
|
||||
<connections>
|
||||
<action selector="performClose:" target="-1" id="HmO-Ls-i7Q"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Save…" keyEquivalent="s" id="pxx-59-PXV">
|
||||
<connections>
|
||||
<action selector="saveDocument:" target="-1" id="teZ-XB-qJY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Save As…" keyEquivalent="S" id="Bw7-FT-i3A">
|
||||
<connections>
|
||||
<action selector="saveDocumentAs:" target="-1" id="mDf-zr-I0C"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Revert to Saved" keyEquivalent="r" id="KaW-ft-85H">
|
||||
<connections>
|
||||
<action selector="revertDocumentToSaved:" target="-1" id="iJ3-Pv-kwq"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="aJh-i4-bef"/>
|
||||
<menuItem title="Page Setup…" keyEquivalent="P" id="qIS-W8-SiK">
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="runPageLayout:" target="-1" id="Din-rz-gC5"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Print…" keyEquivalent="p" id="aTl-1u-JFS">
|
||||
<connections>
|
||||
<action selector="print:" target="-1" id="qaZ-4w-aoO"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Edit" id="5QF-Oa-p0T">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Edit" id="W48-6f-4Dl">
|
||||
<items>
|
||||
<menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
|
||||
<connections>
|
||||
<action selector="undo:" target="-1" id="M6e-cu-g7V"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
|
||||
<connections>
|
||||
<action selector="redo:" target="-1" id="oIA-Rs-6OD"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
|
||||
<menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
|
||||
<connections>
|
||||
<action selector="cut:" target="-1" id="YJe-68-I9s"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
|
||||
<connections>
|
||||
<action selector="copy:" target="-1" id="G1f-GL-Joy"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
|
||||
<connections>
|
||||
<action selector="paste:" target="-1" id="UvS-8e-Qdg"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteAsPlainText:" target="-1" id="cEh-KX-wJQ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Delete" id="pa3-QI-u2k">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="delete:" target="-1" id="0Mk-Ml-PaM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
|
||||
<connections>
|
||||
<action selector="selectAll:" target="-1" id="VNm-Mi-diN"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/>
|
||||
<menuItem title="Find" id="4EN-yA-p0u">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Find" id="1b7-l0-nxx">
|
||||
<items>
|
||||
<menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="cD7-Qs-BN4"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="WD3-Gg-5AJ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="NDo-RZ-v9R"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="HOh-sY-3ay"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="U76-nv-p5D"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd">
|
||||
<connections>
|
||||
<action selector="centerSelectionInVisibleArea:" target="-1" id="IOG-6D-g5B"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Spelling and Grammar" id="Dv1-io-Yv7">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Spelling" id="3IN-sU-3Bg">
|
||||
<items>
|
||||
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI">
|
||||
<connections>
|
||||
<action selector="showGuessPanel:" target="-1" id="vFj-Ks-hy3"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7">
|
||||
<connections>
|
||||
<action selector="checkSpelling:" target="-1" id="fz7-VC-reM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="bNw-od-mp5"/>
|
||||
<menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleContinuousSpellChecking:" target="-1" id="7w6-Qz-0kB"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleGrammarChecking:" target="-1" id="muD-Qn-j4w"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Correct Spelling Automatically" id="78Y-hA-62v">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticSpellingCorrection:" target="-1" id="2lM-Qi-WAP"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Substitutions" id="9ic-FL-obx">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Substitutions" id="FeM-D8-WVr">
|
||||
<items>
|
||||
<menuItem title="Show Substitutions" id="z6F-FW-3nz">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontSubstitutionsPanel:" target="-1" id="oku-mr-iSq"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/>
|
||||
<menuItem title="Smart Copy/Paste" id="9yt-4B-nSM">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleSmartInsertDelete:" target="-1" id="3IJ-Se-DZD"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Quotes" id="hQb-2v-fYv">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="ptq-xd-QOA"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Dashes" id="rgM-f4-ycn">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticDashSubstitution:" target="-1" id="oCt-pO-9gS"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Links" id="cwL-P1-jid">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticLinkDetection:" target="-1" id="Gip-E3-Fov"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Data Detectors" id="tRr-pd-1PS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticDataDetection:" target="-1" id="R1I-Nq-Kbl"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Text Replacement" id="HFQ-gK-NFA">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticTextReplacement:" target="-1" id="DvP-Fe-Py6"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Transformations" id="2oI-Rn-ZJC">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Transformations" id="c8a-y6-VQd">
|
||||
<items>
|
||||
<menuItem title="Make Upper Case" id="vmV-6d-7jI">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="uppercaseWord:" target="-1" id="sPh-Tk-edu"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Make Lower Case" id="d9M-CD-aMd">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="lowercaseWord:" target="-1" id="iUZ-b5-hil"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Capitalize" id="UEZ-Bs-lqG">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="capitalizeWord:" target="-1" id="26H-TL-nsh"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Speech" id="xrE-MZ-jX0">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Speech" id="3rS-ZA-NoH">
|
||||
<items>
|
||||
<menuItem title="Start Speaking" id="Ynk-f8-cLZ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="startSpeaking:" target="-1" id="654-Ng-kyl"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Stop Speaking" id="Oyz-dy-DGm">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="stopSpeaking:" target="-1" id="dX8-6p-jy9"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Format" id="jxT-CU-nIS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Format" id="GEO-Iw-cKr">
|
||||
<items>
|
||||
<menuItem title="Font" id="Gi5-1S-RQB">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Font" systemMenu="font" id="aXa-aM-Jaq">
|
||||
<items>
|
||||
<menuItem title="Show Fonts" keyEquivalent="t" id="Q5e-8K-NDq">
|
||||
<connections>
|
||||
<action selector="orderFrontFontPanel:" target="YLy-65-1bz" id="WHr-nq-2xA"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Bold" tag="2" keyEquivalent="b" id="GB9-OM-e27">
|
||||
<connections>
|
||||
<action selector="addFontTrait:" target="YLy-65-1bz" id="hqk-hr-sYV"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Italic" tag="1" keyEquivalent="i" id="Vjx-xi-njq">
|
||||
<connections>
|
||||
<action selector="addFontTrait:" target="YLy-65-1bz" id="IHV-OB-c03"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Underline" keyEquivalent="u" id="WRG-CD-K1S">
|
||||
<connections>
|
||||
<action selector="underline:" target="-1" id="FYS-2b-JAY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="5gT-KC-WSO"/>
|
||||
<menuItem title="Bigger" tag="3" keyEquivalent="+" id="Ptp-SP-VEL">
|
||||
<connections>
|
||||
<action selector="modifyFont:" target="YLy-65-1bz" id="Uc7-di-UnL"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="i1d-Er-qST">
|
||||
<connections>
|
||||
<action selector="modifyFont:" target="YLy-65-1bz" id="HcX-Lf-eNd"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="kx3-Dk-x3B"/>
|
||||
<menuItem title="Kern" id="jBQ-r6-VK2">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Kern" id="tlD-Oa-oAM">
|
||||
<items>
|
||||
<menuItem title="Use Default" id="GUa-eO-cwY">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useStandardKerning:" target="-1" id="6dk-9l-Ckg"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use None" id="cDB-IK-hbR">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="turnOffKerning:" target="-1" id="U8a-gz-Maa"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Tighten" id="46P-cB-AYj">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="tightenKerning:" target="-1" id="hr7-Nz-8ro"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Loosen" id="ogc-rX-tC1">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="loosenKerning:" target="-1" id="8i4-f9-FKE"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Ligatures" id="o6e-r0-MWq">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Ligatures" id="w0m-vy-SC9">
|
||||
<items>
|
||||
<menuItem title="Use Default" id="agt-UL-0e3">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useStandardLigatures:" target="-1" id="7uR-wd-Dx6"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use None" id="J7y-lM-qPV">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="turnOffLigatures:" target="-1" id="iX2-gA-Ilz"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use All" id="xQD-1f-W4t">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useAllLigatures:" target="-1" id="KcB-kA-TuK"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Baseline" id="OaQ-X3-Vso">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Baseline" id="ijk-EB-dga">
|
||||
<items>
|
||||
<menuItem title="Use Default" id="3Om-Ey-2VK">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="unscript:" target="-1" id="0vZ-95-Ywn"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Superscript" id="Rqc-34-cIF">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="superscript:" target="-1" id="3qV-fo-wpU"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Subscript" id="I0S-gh-46l">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="subscript:" target="-1" id="Q6W-4W-IGz"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Raise" id="2h7-ER-AoG">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="raiseBaseline:" target="-1" id="4sk-31-7Q9"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Lower" id="1tx-W0-xDw">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="lowerBaseline:" target="-1" id="OF1-bc-KW4"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="Ndw-q3-faq"/>
|
||||
<menuItem title="Show Colors" keyEquivalent="C" id="bgn-CT-cEk">
|
||||
<connections>
|
||||
<action selector="orderFrontColorPanel:" target="-1" id="mSX-Xz-DV3"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="iMs-zA-UFJ"/>
|
||||
<menuItem title="Copy Style" keyEquivalent="c" id="5Vv-lz-BsD">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="copyFont:" target="-1" id="GJO-xA-L4q"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste Style" keyEquivalent="v" id="vKC-jM-MkH">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteFont:" target="-1" id="JfD-CL-leO"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Text" id="Fal-I4-PZk">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Text" id="d9c-me-L2H">
|
||||
<items>
|
||||
<menuItem title="Align Left" keyEquivalent="{" id="ZM1-6Q-yy1">
|
||||
<connections>
|
||||
<action selector="alignLeft:" target="-1" id="zUv-R1-uAa"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Center" keyEquivalent="|" id="VIY-Ag-zcb">
|
||||
<connections>
|
||||
<action selector="alignCenter:" target="-1" id="spX-mk-kcS"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Justify" id="J5U-5w-g23">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="alignJustified:" target="-1" id="ljL-7U-jND"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Align Right" keyEquivalent="}" id="wb2-vD-lq4">
|
||||
<connections>
|
||||
<action selector="alignRight:" target="-1" id="r48-bG-YeY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="4s2-GY-VfK"/>
|
||||
<menuItem title="Writing Direction" id="H1b-Si-o9J">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Writing Direction" id="8mr-sm-Yjd">
|
||||
<items>
|
||||
<menuItem title="Paragraph" enabled="NO" id="ZvO-Gk-QUH">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem id="YGs-j5-SAR">
|
||||
<string key="title"> Default</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeBaseWritingDirectionNatural:" target="-1" id="qtV-5e-UBP"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="Lbh-J2-qVU">
|
||||
<string key="title"> Left to Right</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeBaseWritingDirectionLeftToRight:" target="-1" id="S0X-9S-QSf"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="jFq-tB-4Kx">
|
||||
<string key="title"> Right to Left</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeBaseWritingDirectionRightToLeft:" target="-1" id="5fk-qB-AqJ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="swp-gr-a21"/>
|
||||
<menuItem title="Selection" enabled="NO" id="cqv-fj-IhA">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem id="Nop-cj-93Q">
|
||||
<string key="title"> Default</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeTextWritingDirectionNatural:" target="-1" id="lPI-Se-ZHp"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="BgM-ve-c93">
|
||||
<string key="title"> Left to Right</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeTextWritingDirectionLeftToRight:" target="-1" id="caW-Bv-w94"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="RB4-Sm-HuC">
|
||||
<string key="title"> Right to Left</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeTextWritingDirectionRightToLeft:" target="-1" id="EXD-6r-ZUu"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="fKy-g9-1gm"/>
|
||||
<menuItem title="Show Ruler" id="vLm-3I-IUL">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleRuler:" target="-1" id="FOx-HJ-KwY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Copy Ruler" keyEquivalent="c" id="MkV-Pr-PK5">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="copyRuler:" target="-1" id="71i-fW-3W2"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste Ruler" keyEquivalent="v" id="LVM-kO-fVI">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteRuler:" target="-1" id="cSh-wd-qM2"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="View" id="H8h-7b-M4v">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="View" id="HyV-fh-RgO">
|
||||
<items>
|
||||
<menuItem title="Show Toolbar" keyEquivalent="t" id="snW-S8-Cw5">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleToolbarShown:" target="-1" id="BXY-wc-z0C"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Customize Toolbar…" id="1UK-8n-QPP">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="runToolbarCustomizationPalette:" target="-1" id="pQI-g3-MTW"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="hB3-LF-h0Y"/>
|
||||
<menuItem title="Show Sidebar" keyEquivalent="s" id="kIP-vf-haE">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleSidebar:" target="-1" id="iwa-gc-5KM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleFullScreen:" target="-1" id="dU3-MA-1Rq"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Window" id="aUF-d1-5bR">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
|
||||
<items>
|
||||
<menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
|
||||
<connections>
|
||||
<action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Zoom" id="R4o-n2-Eq4">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="performZoom:" target="-1" id="DIl-cC-cCs"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
|
||||
<menuItem title="Bring All to Front" id="LE2-aR-0XJ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/>
|
||||
</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="Burrow Help" keyEquivalent="?" id="FKE-Sm-Kum">
|
||||
<connections>
|
||||
<action selector="showHelp:" target="-1" id="y7X-2Q-9no"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
<point key="canvasLocation" x="200" y="121"/>
|
||||
</menu>
|
||||
</objects>
|
||||
</document>
|
||||
68
Apple/App/Menu/MenuView.swift
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
//
|
||||
// MenuView.swift
|
||||
// App
|
||||
//
|
||||
// Created by Thomas Stubblefield on 5/13/23.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct MenuView: View {
|
||||
@State private var isToggled = false
|
||||
@ObservedObject var tunnel: Tunnel
|
||||
|
||||
private func start() {
|
||||
do {
|
||||
try tunnel.start()
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
|
||||
private func stop() {
|
||||
tunnel.stop()
|
||||
}
|
||||
|
||||
private func configure() {
|
||||
Task { try await tunnel.configure() }
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
HStack {
|
||||
Text("Burrow")
|
||||
.fontWeight(.bold)
|
||||
|
||||
Spacer()
|
||||
Toggle("", isOn: $isToggled)
|
||||
.toggleStyle(SwitchToggleStyle(tint: .blue))
|
||||
.onChange(of: isToggled) { value in
|
||||
if value {
|
||||
start()
|
||||
} else {
|
||||
stop()
|
||||
}
|
||||
print("Toggle value: \(value)")
|
||||
}
|
||||
}
|
||||
Divider()
|
||||
switch tunnel.status {
|
||||
case .permissionRequired:
|
||||
VStack(alignment: .leading) {
|
||||
Text("Burrow requires additional permissions to function optimally on your machine. Please grant the necessary permissions to ensure smooth operation.")
|
||||
.font(.caption)
|
||||
.truncationMode(.tail)
|
||||
|
||||
Button("Grant Permissions", action: configure)
|
||||
}
|
||||
default:
|
||||
|
||||
Text("Burrow is equipped with the necessary permissions to operate seamlessly on your device.")
|
||||
.font(.caption)
|
||||
}
|
||||
}
|
||||
.frame(width: 250)
|
||||
.padding(16)
|
||||
.task { await tunnel.update() }
|
||||
}
|
||||
}
|
||||
54
Apple/App/Menu/OnboardingView.swift
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
//
|
||||
// OnboardingView.swift
|
||||
// App
|
||||
//
|
||||
// Created by Juan Pablo Gutierrez on 25/05/23.
|
||||
//
|
||||
// Represents the onboarding screen
|
||||
|
||||
import SwiftUI
|
||||
|
||||
//Sets burrow visited status
|
||||
func setVisited() {
|
||||
UserDefaults.standard.set(true, forKey: "launchedBefore")
|
||||
}
|
||||
|
||||
func closeApp() {
|
||||
setVisited()
|
||||
NSApp.windows.first?.close()
|
||||
}
|
||||
|
||||
@available(macOS 13.0, *)
|
||||
struct OnboardingView: View {
|
||||
var body: some View {
|
||||
ZStack(alignment: .center) {
|
||||
Image("OnboardingBackground")
|
||||
.resizable(resizingMode: .stretch)
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.scaledToFill()
|
||||
Color.black
|
||||
.opacity(0.6)
|
||||
.cornerRadius(15)
|
||||
.blur(radius: 0.2)
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
.frame(width: 450, height: 300)
|
||||
VStack(alignment: .center) {
|
||||
Text("Welcome to burrow").font(.system(size: 24, weight: .bold, design: .rounded))
|
||||
Spacer().frame(height: /*@START_MENU_TOKEN@*/20.0/*@END_MENU_TOKEN@*/)
|
||||
Text("It is a best-in-class tool for burrowing through firewalls.").font(.system(size: 14))
|
||||
Spacer().frame(height: 10.0)
|
||||
Text("Built by teenagers at HackClub").font(.system(size: 14))
|
||||
Button(action: closeApp, label: {
|
||||
Text("Start burrowing")
|
||||
.font(
|
||||
.system(
|
||||
size : 14,
|
||||
weight: .regular,
|
||||
design: .rounded))
|
||||
.padding(.all, 30.0)
|
||||
.foregroundColor(.white)
|
||||
}).buttonBorderShape(.roundedRectangle).buttonStyle(.borderless)
|
||||
}.padding(20.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +1,30 @@
|
|||
import NetworkExtension
|
||||
|
||||
extension NEVPNManager: @unchecked @retroactive Sendable {
|
||||
extension NEVPNManager {
|
||||
func remove() async throws {
|
||||
_ = try await withUnsafeThrowingContinuation { continuation in
|
||||
let _: Void = try await withUnsafeThrowingContinuation { continuation in
|
||||
removeFromPreferences(completionHandler: completion(continuation))
|
||||
}
|
||||
}
|
||||
|
||||
func save() async throws {
|
||||
_ = try await withUnsafeThrowingContinuation { continuation in
|
||||
let _: Void = try await withUnsafeThrowingContinuation { continuation in
|
||||
saveToPreferences(completionHandler: completion(continuation))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension NETunnelProviderManager: @unchecked @retroactive Sendable {
|
||||
extension NETunnelProviderManager {
|
||||
class var managers: [NETunnelProviderManager] {
|
||||
get async throws {
|
||||
try await withUnsafeThrowingContinuation { continuation in
|
||||
loadAllFromPreferences(completionHandler: completion(continuation))
|
||||
loadAllFromPreferences { managers, error in
|
||||
if let error = error {
|
||||
continuation.resume(throwing: error)
|
||||
} else {
|
||||
continuation.resume(returning: managers ?? [])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -26,20 +32,10 @@ extension NETunnelProviderManager: @unchecked @retroactive Sendable {
|
|||
|
||||
private func completion(_ continuation: UnsafeContinuation<Void, Error>) -> (Error?) -> Void {
|
||||
return { error in
|
||||
if let error {
|
||||
if let error = error {
|
||||
continuation.resume(throwing: error)
|
||||
} else {
|
||||
continuation.resume(returning: ())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func completion<T: Sendable>(_ continuation: UnsafeContinuation<T, Error>) -> (T?, Error?) -> Void {
|
||||
return { value, error in
|
||||
if let error {
|
||||
continuation.resume(throwing: error)
|
||||
} else if let value {
|
||||
continuation.resume(returning: value)
|
||||
}
|
||||
}
|
||||
}
|
||||
42
Apple/App/Status.swift
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import Foundation
|
||||
import NetworkExtension
|
||||
|
||||
extension Tunnel {
|
||||
enum Status: CustomStringConvertible, Equatable, Hashable {
|
||||
case unknown
|
||||
case permissionRequired
|
||||
case disabled
|
||||
case connecting
|
||||
case connected(Date)
|
||||
case disconnecting
|
||||
case disconnected
|
||||
case reasserting
|
||||
case invalid
|
||||
case configurationReadWriteFailed
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .unknown:
|
||||
return "Unknown"
|
||||
case .permissionRequired:
|
||||
return "Permission Required"
|
||||
case .disconnected:
|
||||
return "Disconnected"
|
||||
case .disabled:
|
||||
return "Disabled"
|
||||
case .connecting:
|
||||
return "Connecting"
|
||||
case .connected:
|
||||
return "Connected"
|
||||
case .disconnecting:
|
||||
return "Disconnecting"
|
||||
case .reasserting:
|
||||
return "Reasserting"
|
||||
case .invalid:
|
||||
return "Invalid"
|
||||
case .configurationReadWriteFailed:
|
||||
return "System Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
135
Apple/App/Tunnel.swift
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
import Combine
|
||||
import NetworkExtension
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
class Tunnel: ObservableObject {
|
||||
@Published private(set) var status: Status = .unknown
|
||||
@Published private var error: NEVPNError?
|
||||
|
||||
private let bundleIdentifier: String
|
||||
private let configure: (NETunnelProviderManager, NETunnelProviderProtocol) -> Void
|
||||
private var tasks: [Task<Void, Error>] = []
|
||||
|
||||
private var managers: [NEVPNManager]? {
|
||||
didSet { status = currentStatus }
|
||||
}
|
||||
|
||||
private var currentStatus: Status {
|
||||
guard let managers = managers else {
|
||||
guard let error = error else {
|
||||
return .unknown
|
||||
}
|
||||
|
||||
switch error.code {
|
||||
case .configurationReadWriteFailed:
|
||||
return .configurationReadWriteFailed
|
||||
default:
|
||||
return .unknown
|
||||
}
|
||||
}
|
||||
|
||||
guard let manager = managers.first else {
|
||||
return .permissionRequired
|
||||
}
|
||||
|
||||
guard manager.isEnabled else {
|
||||
return .disabled
|
||||
}
|
||||
|
||||
return manager.connection.tunnelStatus
|
||||
}
|
||||
|
||||
convenience init(configure: @escaping (NETunnelProviderManager, NETunnelProviderProtocol) -> Void) {
|
||||
self.init("com.hackclub.burrow.network", configure: configure)
|
||||
}
|
||||
|
||||
init(_ bundleIdentifier: String, configure: @escaping (NETunnelProviderManager, NETunnelProviderProtocol) -> Void) {
|
||||
self.bundleIdentifier = bundleIdentifier
|
||||
self.configure = configure
|
||||
|
||||
let statusTask = Task {
|
||||
for try await _ in NotificationCenter.default.notifications(named: .NEVPNStatusDidChange) {
|
||||
status = currentStatus
|
||||
}
|
||||
}
|
||||
let configurationTask = Task {
|
||||
for try await _ in NotificationCenter.default.notifications(named: .NEVPNConfigurationChange) {
|
||||
await update()
|
||||
}
|
||||
}
|
||||
tasks = [statusTask, configurationTask]
|
||||
}
|
||||
|
||||
func update() async {
|
||||
do {
|
||||
managers = try await NETunnelProviderManager.managers
|
||||
} catch let error as NEVPNError {
|
||||
self.error = error
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
|
||||
func configure() async throws {
|
||||
if managers == nil {
|
||||
await update()
|
||||
}
|
||||
|
||||
guard let managers = managers else { return }
|
||||
|
||||
if managers.count > 1 {
|
||||
try await withThrowingTaskGroup(of: Void.self, returning: Void.self) { group in
|
||||
for manager in managers.suffix(from: 1) {
|
||||
group.addTask { try await manager.remove() }
|
||||
}
|
||||
try await group.waitForAll()
|
||||
}
|
||||
}
|
||||
|
||||
if managers.isEmpty {
|
||||
let manager = NETunnelProviderManager()
|
||||
let proto = NETunnelProviderProtocol()
|
||||
proto.providerBundleIdentifier = bundleIdentifier
|
||||
configure(manager, proto)
|
||||
|
||||
manager.protocolConfiguration = proto
|
||||
try await manager.save()
|
||||
}
|
||||
}
|
||||
|
||||
func start() throws {
|
||||
guard let manager = managers?.first else { return }
|
||||
try manager.connection.startVPNTunnel()
|
||||
}
|
||||
|
||||
func stop() {
|
||||
guard let manager = managers?.first else { return }
|
||||
manager.connection.stopVPNTunnel()
|
||||
}
|
||||
|
||||
deinit {
|
||||
tasks.forEach { $0.cancel() }
|
||||
}
|
||||
}
|
||||
|
||||
extension NEVPNConnection {
|
||||
var tunnelStatus: Tunnel.Status {
|
||||
switch status {
|
||||
case .connected:
|
||||
return .connected(connectedDate!)
|
||||
case .connecting:
|
||||
return .connecting
|
||||
case .disconnecting:
|
||||
return .disconnecting
|
||||
case .disconnected:
|
||||
return .disconnected
|
||||
case .reasserting:
|
||||
return .reasserting
|
||||
case .invalid:
|
||||
return .invalid
|
||||
@unknown default:
|
||||
return .unknown
|
||||
}
|
||||
}
|
||||
}
|
||||
36
Apple/App/TunnelView.swift
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import SwiftUI
|
||||
|
||||
struct TunnelView: View {
|
||||
// @ObservedObject var tunnel: Tunnel
|
||||
|
||||
var body: some View {
|
||||
EmptyView()
|
||||
// VStack {
|
||||
// Text(verbatim: tunnel.status.description)
|
||||
// switch tunnel.status {
|
||||
// case .connected:
|
||||
// Button("Disconnect", action: stop)
|
||||
// case .permissionRequired:
|
||||
// Button("Allow", action: configure)
|
||||
// case .disconnected:
|
||||
// Button("Start", action: start)
|
||||
// default:
|
||||
// EmptyView()
|
||||
// }
|
||||
// }
|
||||
// .task { await tunnel.update() }
|
||||
// .padding()
|
||||
}
|
||||
|
||||
// private func start() {
|
||||
// try? tunnel.start()
|
||||
// }
|
||||
//
|
||||
// private func stop() {
|
||||
// tunnel.stop()
|
||||
// }
|
||||
//
|
||||
// private func configure() {
|
||||
// Task { try await tunnel.configure() }
|
||||
// }
|
||||
}
|
||||
|
|
@ -1,439 +0,0 @@
|
|||
import XCTest
|
||||
import UIKit
|
||||
|
||||
@MainActor
|
||||
final class BurrowTailnetLoginUITests: XCTestCase {
|
||||
private enum TailnetLoginMode: String, Decodable {
|
||||
case tailscale
|
||||
case discovered
|
||||
}
|
||||
|
||||
private struct TestConfig: Decodable {
|
||||
let email: String
|
||||
let username: String
|
||||
let password: String
|
||||
let mode: TailnetLoginMode?
|
||||
}
|
||||
|
||||
override func setUpWithError() throws {
|
||||
continueAfterFailure = false
|
||||
}
|
||||
|
||||
func testTailnetLoginThroughAuthentikWebSession() throws {
|
||||
let config = try loadTestConfig()
|
||||
let email = config.email
|
||||
let username = config.username
|
||||
let password = config.password
|
||||
let mode = config.mode ?? .tailscale
|
||||
let browserIdentity = mode == .tailscale ? email : username
|
||||
|
||||
let app = XCUIApplication()
|
||||
app.launch()
|
||||
|
||||
let tailnetButton = app.buttons["quick-add-tailnet"]
|
||||
XCTAssertTrue(tailnetButton.waitForExistence(timeout: 15), "Tailnet add button did not appear")
|
||||
tailnetButton.tap()
|
||||
|
||||
configureTailnetIfNeeded(in: app, mode: mode)
|
||||
|
||||
let discoveryField = app.textFields["tailnet-discovery-email"]
|
||||
XCTAssertTrue(discoveryField.waitForExistence(timeout: 10), "Tailnet discovery email field did not appear")
|
||||
replaceText(in: discoveryField, with: email)
|
||||
|
||||
let serverCard = app.descendants(matching: .any)
|
||||
.matching(identifier: "tailnet-server-card")
|
||||
.firstMatch
|
||||
XCTAssertTrue(serverCard.waitForExistence(timeout: 5), "Tailnet server card did not appear")
|
||||
|
||||
let signInButton = app.buttons["tailnet-start-sign-in"]
|
||||
XCTAssertTrue(signInButton.waitForExistence(timeout: 10), "Tailnet sign-in button did not appear")
|
||||
signInButton.tap()
|
||||
|
||||
acceptAuthenticationPromptIfNeeded(in: app, timeout: 20)
|
||||
|
||||
let webSession = webAuthenticationSession()
|
||||
XCTAssertTrue(webSession.waitForExistence(timeout: 20), "Safari authentication session did not appear")
|
||||
|
||||
signIntoAuthentik(in: webSession, username: browserIdentity, password: password)
|
||||
|
||||
app.activate()
|
||||
XCTAssertTrue(
|
||||
waitForTailnetSignedIn(in: app, timeout: 60),
|
||||
"Tailnet sign-in never reached the running state"
|
||||
)
|
||||
}
|
||||
|
||||
private func configureTailnetIfNeeded(in app: XCUIApplication, mode: TailnetLoginMode) {
|
||||
guard mode == .discovered else { return }
|
||||
|
||||
openTailnetMenu(in: app)
|
||||
tapMenuButton(named: "Edit Custom Server", in: app)
|
||||
|
||||
openTailnetMenu(in: app)
|
||||
tapMenuButton(named: "Show Advanced Settings", in: app)
|
||||
|
||||
let authorityField = app.textFields["tailnet-authority"]
|
||||
XCTAssertTrue(authorityField.waitForExistence(timeout: 10), "Tailnet authority field did not appear")
|
||||
replaceText(in: authorityField, with: "")
|
||||
}
|
||||
|
||||
private func openTailnetMenu(in app: XCUIApplication) {
|
||||
let moreButton = app.buttons["More"]
|
||||
XCTAssertTrue(moreButton.waitForExistence(timeout: 5), "Tailnet menu button did not appear")
|
||||
moreButton.tap()
|
||||
}
|
||||
|
||||
private func tapMenuButton(named title: String, in app: XCUIApplication) {
|
||||
let menuButton = firstExistingElement(
|
||||
from: [
|
||||
app.buttons[title],
|
||||
app.descendants(matching: .button)[title],
|
||||
],
|
||||
timeout: 5
|
||||
)
|
||||
XCTAssertTrue(menuButton.exists, "Menu action \(title) did not appear")
|
||||
menuButton.tap()
|
||||
}
|
||||
|
||||
private func acceptAuthenticationPromptIfNeeded(
|
||||
in app: XCUIApplication,
|
||||
timeout: TimeInterval
|
||||
) {
|
||||
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
|
||||
let deadline = Date().addingTimeInterval(timeout)
|
||||
|
||||
repeat {
|
||||
let promptCandidates = [
|
||||
springboard.buttons["Continue"],
|
||||
springboard.buttons["Allow"],
|
||||
app.buttons["Continue"],
|
||||
app.buttons["Allow"],
|
||||
]
|
||||
|
||||
for button in promptCandidates where button.exists && button.isHittable {
|
||||
button.tap()
|
||||
return
|
||||
}
|
||||
|
||||
RunLoop.current.run(until: Date().addingTimeInterval(0.25))
|
||||
} while Date() < deadline
|
||||
|
||||
let promptCandidates = [
|
||||
springboard.buttons["Continue"],
|
||||
springboard.buttons["Allow"],
|
||||
app.buttons["Continue"],
|
||||
app.buttons["Allow"],
|
||||
]
|
||||
|
||||
for button in promptCandidates where button.exists {
|
||||
button.tap()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
private func webAuthenticationSession() -> XCUIApplication {
|
||||
let safariViewService = XCUIApplication(bundleIdentifier: "com.apple.SafariViewService")
|
||||
if safariViewService.waitForExistence(timeout: 5) {
|
||||
return safariViewService
|
||||
}
|
||||
|
||||
let safari = XCUIApplication(bundleIdentifier: "com.apple.mobilesafari")
|
||||
_ = safari.waitForExistence(timeout: 5)
|
||||
return safari
|
||||
}
|
||||
|
||||
private func signIntoAuthentik(in webSession: XCUIApplication, username: String, password: String) {
|
||||
followTailnetRedirectIfNeeded(in: webSession)
|
||||
|
||||
if !webSession.exists {
|
||||
return
|
||||
}
|
||||
|
||||
let immediatePasswordField = firstExistingSecureField(in: webSession, timeout: 2)
|
||||
if immediatePasswordField.exists {
|
||||
replaceSecureText(in: immediatePasswordField, within: webSession, with: password)
|
||||
submitAuthenticationForm(in: webSession, focusedField: immediatePasswordField)
|
||||
return
|
||||
}
|
||||
|
||||
let usernameField = firstExistingElement(
|
||||
in: webSession,
|
||||
queries: [
|
||||
{ $0.textFields["Username"] },
|
||||
{ $0.textFields["Email or Username"] },
|
||||
{ $0.textFields["Email address"] },
|
||||
{ $0.textFields["Email"] },
|
||||
{ $0.webViews.textFields["Username"] },
|
||||
{ $0.webViews.textFields["Email or Username"] },
|
||||
{ $0.descendants(matching: .textField).firstMatch },
|
||||
],
|
||||
timeout: 12
|
||||
)
|
||||
if !usernameField.exists {
|
||||
return
|
||||
}
|
||||
replaceText(in: usernameField, with: username)
|
||||
|
||||
tapFirstExistingButton(
|
||||
in: webSession,
|
||||
titles: ["Continue", "Next", "Sign In", "Log in", "Login"],
|
||||
timeout: 5
|
||||
)
|
||||
|
||||
let passwordField = firstExistingSecureField(in: webSession, timeout: 20)
|
||||
XCTAssertTrue(passwordField.exists, "Authentik password field did not appear")
|
||||
replaceSecureText(in: passwordField, within: webSession, with: password)
|
||||
submitAuthenticationForm(in: webSession, focusedField: passwordField)
|
||||
}
|
||||
|
||||
private func followTailnetRedirectIfNeeded(in webSession: XCUIApplication) {
|
||||
let redirectCandidates = [
|
||||
webSession.links["Found"],
|
||||
webSession.webViews.links["Found"],
|
||||
webSession.buttons["Found"],
|
||||
webSession.webViews.buttons["Found"],
|
||||
]
|
||||
|
||||
let redirectLink = firstExistingElement(from: redirectCandidates, timeout: 8)
|
||||
if redirectLink.exists {
|
||||
redirectLink.tap()
|
||||
}
|
||||
}
|
||||
|
||||
private func firstExistingSecureField(in app: XCUIApplication, timeout: TimeInterval) -> XCUIElement {
|
||||
let candidates = [
|
||||
app.descendants(matching: .secureTextField).firstMatch,
|
||||
app.secureTextFields["Password"],
|
||||
app.secureTextFields["Password or Token"],
|
||||
app.webViews.secureTextFields["Password"],
|
||||
app.webViews.secureTextFields["Password or Token"],
|
||||
]
|
||||
|
||||
return firstExistingElement(from: candidates, timeout: timeout)
|
||||
}
|
||||
|
||||
private func tapFirstExistingButton(
|
||||
in app: XCUIApplication,
|
||||
titles: [String],
|
||||
timeout: TimeInterval
|
||||
) {
|
||||
let candidates = titles.flatMap { title in
|
||||
[
|
||||
app.buttons[title],
|
||||
app.webViews.buttons[title],
|
||||
]
|
||||
} + [app.descendants(matching: .button).firstMatch]
|
||||
|
||||
let button = firstExistingElement(from: candidates, timeout: timeout)
|
||||
XCTAssertTrue(button.exists, "Expected one of \(titles.joined(separator: ", ")) to appear")
|
||||
button.tap()
|
||||
}
|
||||
|
||||
private func submitAuthenticationForm(in app: XCUIApplication, focusedField: XCUIElement) {
|
||||
focus(focusedField)
|
||||
focusedField.typeText("\n")
|
||||
if waitForAny(
|
||||
[
|
||||
{ !focusedField.exists },
|
||||
{ !app.staticTexts["Burrow Tailnet Authentication"].exists },
|
||||
],
|
||||
timeout: 1.5
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
let keyboard = app.keyboards.firstMatch
|
||||
if keyboard.waitForExistence(timeout: 2) {
|
||||
let keyboardCandidates = [
|
||||
"Return",
|
||||
"return",
|
||||
"Go",
|
||||
"go",
|
||||
"Continue",
|
||||
"continue",
|
||||
"Done",
|
||||
"done",
|
||||
"Join",
|
||||
"join",
|
||||
"Sign In",
|
||||
"Log In",
|
||||
"Login",
|
||||
]
|
||||
for title in keyboardCandidates {
|
||||
let key = keyboard.buttons[title]
|
||||
if key.exists && key.isHittable {
|
||||
key.tap()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if let lastKey = keyboard.buttons.allElementsBoundByIndex.last,
|
||||
lastKey.exists,
|
||||
lastKey.isHittable
|
||||
{
|
||||
lastKey.tap()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
tapFirstExistingButton(
|
||||
in: app,
|
||||
titles: ["Continue", "Sign In", "Log in", "Login"],
|
||||
timeout: 5
|
||||
)
|
||||
}
|
||||
|
||||
private func loadTestConfig() throws -> TestConfig {
|
||||
let environment = ProcessInfo.processInfo.environment
|
||||
if let email = nonEmptyEnvironment("BURROW_UI_TEST_EMAIL"),
|
||||
let password = nonEmptyEnvironment("BURROW_UI_TEST_PASSWORD")
|
||||
{
|
||||
return TestConfig(
|
||||
email: email,
|
||||
username: nonEmptyEnvironment("BURROW_UI_TEST_USERNAME") ?? email,
|
||||
password: password,
|
||||
mode: nonEmptyEnvironment("BURROW_UI_TEST_TAILNET_MODE")
|
||||
.flatMap(TailnetLoginMode.init(rawValue:))
|
||||
)
|
||||
}
|
||||
|
||||
let configPath = environment["BURROW_UI_TEST_CONFIG_PATH"] ?? "/tmp/burrow-ui-test-config.json"
|
||||
let configURL = URL(fileURLWithPath: configPath)
|
||||
guard FileManager.default.fileExists(atPath: configURL.path) else {
|
||||
throw XCTSkip(
|
||||
"Missing UI test configuration. Expected env vars or config file at \(configURL.path)"
|
||||
)
|
||||
}
|
||||
|
||||
let data = try Data(contentsOf: configURL)
|
||||
return try JSONDecoder().decode(TestConfig.self, from: data)
|
||||
}
|
||||
|
||||
private func nonEmptyEnvironment(_ key: String) -> String? {
|
||||
guard let value = ProcessInfo.processInfo.environment[key]?
|
||||
.trimmingCharacters(in: .whitespacesAndNewlines),
|
||||
!value.isEmpty
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
private func waitForFieldValue(
|
||||
_ field: XCUIElement,
|
||||
containing substring: String,
|
||||
timeout: TimeInterval
|
||||
) -> Bool {
|
||||
let predicate = NSPredicate(format: "value CONTAINS %@", substring)
|
||||
let expectation = XCTNSPredicateExpectation(predicate: predicate, object: field)
|
||||
return XCTWaiter.wait(for: [expectation], timeout: timeout) == .completed
|
||||
}
|
||||
|
||||
private func waitForButtonLabel(
|
||||
_ button: XCUIElement,
|
||||
equals expected: String,
|
||||
timeout: TimeInterval
|
||||
) -> Bool {
|
||||
let predicate = NSPredicate(format: "label == %@", expected)
|
||||
let expectation = XCTNSPredicateExpectation(predicate: predicate, object: button)
|
||||
return XCTWaiter.wait(for: [expectation], timeout: timeout) == .completed
|
||||
}
|
||||
|
||||
private func waitForTailnetSignedIn(in app: XCUIApplication, timeout: TimeInterval) -> Bool {
|
||||
let button = app.buttons["tailnet-start-sign-in"]
|
||||
let deadline = Date().addingTimeInterval(timeout)
|
||||
|
||||
repeat {
|
||||
acceptAuthenticationPromptIfNeeded(in: app, timeout: 1)
|
||||
if button.exists, button.label == "Signed In" {
|
||||
return true
|
||||
}
|
||||
RunLoop.current.run(until: Date().addingTimeInterval(0.3))
|
||||
} while Date() < deadline
|
||||
|
||||
return button.exists && button.label == "Signed In"
|
||||
}
|
||||
|
||||
private func waitForAny(_ conditions: [() -> Bool], timeout: TimeInterval) -> Bool {
|
||||
let deadline = Date().addingTimeInterval(timeout)
|
||||
repeat {
|
||||
if conditions.contains(where: { $0() }) {
|
||||
return true
|
||||
}
|
||||
RunLoop.current.run(until: Date().addingTimeInterval(0.2))
|
||||
} while Date() < deadline
|
||||
return conditions.contains(where: { $0() })
|
||||
}
|
||||
|
||||
private func firstExistingElement(
|
||||
in app: XCUIApplication,
|
||||
queries: [(XCUIApplication) -> XCUIElement],
|
||||
timeout: TimeInterval
|
||||
) -> XCUIElement {
|
||||
firstExistingElement(from: queries.map { $0(app) }, timeout: timeout)
|
||||
}
|
||||
|
||||
private func firstExistingElement(from candidates: [XCUIElement], timeout: TimeInterval) -> XCUIElement {
|
||||
let deadline = Date().addingTimeInterval(timeout)
|
||||
repeat {
|
||||
for candidate in candidates where candidate.exists {
|
||||
return candidate
|
||||
}
|
||||
RunLoop.current.run(until: Date().addingTimeInterval(0.2))
|
||||
} while Date() < deadline
|
||||
|
||||
return candidates[0]
|
||||
}
|
||||
|
||||
private func replaceText(in element: XCUIElement, with value: String) {
|
||||
focus(element)
|
||||
clearText(in: element)
|
||||
element.typeText(value)
|
||||
}
|
||||
|
||||
private func replaceSecureText(in element: XCUIElement, within app: XCUIApplication, with value: String) {
|
||||
UIPasteboard.general.string = value
|
||||
focus(element)
|
||||
for revealMenu in [
|
||||
{ element.doubleTap() },
|
||||
{ element.press(forDuration: 1.2) },
|
||||
] {
|
||||
revealMenu()
|
||||
let pasteButton = firstExistingElement(from: pasteCandidates(in: app), timeout: 3)
|
||||
if pasteButton.exists {
|
||||
pasteButton.tap()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
focus(element)
|
||||
element.typeText(value)
|
||||
}
|
||||
|
||||
private func clearText(in element: XCUIElement) {
|
||||
guard let currentValue = element.value as? String, !currentValue.isEmpty else {
|
||||
return
|
||||
}
|
||||
|
||||
let deleteSequence = String(repeating: XCUIKeyboardKey.delete.rawValue, count: currentValue.count)
|
||||
element.typeText(deleteSequence)
|
||||
}
|
||||
|
||||
private func focus(_ element: XCUIElement) {
|
||||
element.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap()
|
||||
RunLoop.current.run(until: Date().addingTimeInterval(0.3))
|
||||
}
|
||||
|
||||
private func pasteCandidates(in app: XCUIApplication) -> [XCUIElement] {
|
||||
let pasteLabels = ["Paste", "Incolla", "Paste from Clipboard"]
|
||||
return pasteLabels.flatMap { label in
|
||||
[
|
||||
app.menuItems[label],
|
||||
app.buttons[label],
|
||||
app.webViews.buttons[label],
|
||||
app.descendants(matching: .button).matching(NSPredicate(format: "label == %@", label)).firstMatch,
|
||||
app.descendants(matching: .menuItem).matching(NSPredicate(format: "label == %@", label)).firstMatch,
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,56 +7,20 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
D00AA8972A4669BC005C8102 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00AA8962A4669BC005C8102 /* AppDelegate.swift */; };
|
||||
D11000012F70000100112233 /* BurrowUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D11000042F70000100112233 /* BurrowUITests.swift */; };
|
||||
43AA26D82A10004900F14CE6 /* MenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43AA26D72A10004900F14CE6 /* MenuView.swift */; };
|
||||
91D80FC72A20615500952E28 /* OnboardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91D80FC62A20615500952E28 /* OnboardingView.swift */; };
|
||||
D020F65829E4A697002790F6 /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = D020F65729E4A697002790F6 /* PacketTunnelProvider.swift */; };
|
||||
D020F65D29E4A697002790F6 /* BurrowNetworkExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = D020F65329E4A697002790F6 /* BurrowNetworkExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
D03383AD2C8E67E300F7C44E /* SwiftProtobuf in Frameworks */ = {isa = PBXBuildFile; productRef = D078F7E22C8DA375008A8CEC /* SwiftProtobuf */; };
|
||||
D03383AE2C8E67E300F7C44E /* NIO in Frameworks */ = {isa = PBXBuildFile; productRef = D044EE902C8DAB2000778185 /* NIO */; };
|
||||
D03383AF2C8E67E300F7C44E /* NIOConcurrencyHelpers in Frameworks */ = {isa = PBXBuildFile; productRef = D044EE922C8DAB2000778185 /* NIOConcurrencyHelpers */; };
|
||||
D03383B02C8E67E300F7C44E /* NIOTransportServices in Frameworks */ = {isa = PBXBuildFile; productRef = D044EE952C8DAB2800778185 /* NIOTransportServices */; };
|
||||
D05B9F7629E39EEC008CB1F9 /* BurrowApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05B9F7529E39EEC008CB1F9 /* BurrowApp.swift */; };
|
||||
D09150422B9D2AF700BE3CB0 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D09150412B9D2AF700BE3CB0 /* MainMenu.xib */; platformFilters = (macos, ); };
|
||||
D0B1D1102C436152004B7823 /* AsyncAlgorithms in Frameworks */ = {isa = PBXBuildFile; productRef = D0B1D10F2C436152004B7823 /* AsyncAlgorithms */; };
|
||||
D05B9F7A29E39EED008CB1F9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D05B9F7929E39EED008CB1F9 /* Assets.xcassets */; };
|
||||
D0BCC5FD2A086D4700AD070D /* NetworkExtension+Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BCC5FC2A086D4700AD070D /* NetworkExtension+Async.swift */; };
|
||||
D0BCC5FF2A086E1C00AD070D /* Status.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BCC5FE2A086E1C00AD070D /* Status.swift */; };
|
||||
D0BCC6082A0981FE00AD070D /* Tunnel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B98FC629FDC5B5004E7149 /* Tunnel.swift */; };
|
||||
D0BCC6092A09A03E00AD070D /* libburrow.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCC6032A09535900AD070D /* libburrow.a */; };
|
||||
D0BF09522C8E66F6000D8DEC /* BurrowConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D4E5622C8D9BF4007F820A /* BurrowConfiguration.framework */; };
|
||||
D0BF09552C8E66FD000D8DEC /* BurrowConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D4E5622C8D9BF4007F820A /* BurrowConfiguration.framework */; };
|
||||
D0D4E53A2C8D996F007F820A /* BurrowCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D0D4E5312C8D996F007F820A /* BurrowCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
D0D4E56B2C8D9C2F007F820A /* Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E49A2C8D921A007F820A /* Logging.swift */; };
|
||||
D0D4E5702C8D9C62007F820A /* BurrowCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D4E5312C8D996F007F820A /* BurrowCore.framework */; };
|
||||
D0D4E5722C8D9C6F007F820A /* Network.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E49E2C8D921A007F820A /* Network.swift */; };
|
||||
D0D4E5732C8D9C6F007F820A /* WireGuard.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E49F2C8D921A007F820A /* WireGuard.swift */; };
|
||||
D0D4E5742C8D9C6F007F820A /* BurrowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4A22C8D921A007F820A /* BurrowView.swift */; };
|
||||
D0D4E5752C8D9C6F007F820A /* FloatingButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4A32C8D921A007F820A /* FloatingButtonStyle.swift */; };
|
||||
D0D4E5762C8D9C6F007F820A /* MenuItemToggleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4A42C8D921A007F820A /* MenuItemToggleView.swift */; };
|
||||
D0D4E5772C8D9C6F007F820A /* NetworkCarouselView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4A52C8D921A007F820A /* NetworkCarouselView.swift */; };
|
||||
D0D4E5782C8D9C6F007F820A /* NetworkExtension+Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4A62C8D921A007F820A /* NetworkExtension+Async.swift */; };
|
||||
D0D4E5792C8D9C6F007F820A /* NetworkExtensionTunnel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4A72C8D921A007F820A /* NetworkExtensionTunnel.swift */; };
|
||||
D0D4E57A2C8D9C6F007F820A /* NetworkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4A82C8D921A007F820A /* NetworkView.swift */; };
|
||||
D0D4E57C2C8D9C6F007F820A /* Tunnel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4AA2C8D921A007F820A /* Tunnel.swift */; };
|
||||
D0D4E57D2C8D9C6F007F820A /* TunnelButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4AB2C8D921A007F820A /* TunnelButton.swift */; };
|
||||
D0D4E57E2C8D9C6F007F820A /* TunnelStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4AC2C8D921A007F820A /* TunnelStatusView.swift */; };
|
||||
D0D4E5892C8D9C94007F820A /* BurrowUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D4E5582C8D9BF2007F820A /* BurrowUI.framework */; };
|
||||
D0D4E58A2C8D9C9E007F820A /* BurrowUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D0D4E5582C8D9BF2007F820A /* BurrowUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
D0D4E58B2C8D9CA4007F820A /* BurrowConfiguration.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D0D4E5622C8D9BF4007F820A /* BurrowConfiguration.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
D0D4E5922C8D9D15007F820A /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E58F2C8D9D0A007F820A /* Constants.swift */; };
|
||||
D0D4E5A62C8D9E65007F820A /* BurrowCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D4E5312C8D996F007F820A /* BurrowCore.framework */; };
|
||||
D0F4FAD32C8DC79C0068730A /* BurrowCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D4E5312C8D996F007F820A /* BurrowCore.framework */; };
|
||||
D0F7594E2C8DAB6B00126CF3 /* GRPC in Frameworks */ = {isa = PBXBuildFile; productRef = D078F7E02C8DA375008A8CEC /* GRPC */; };
|
||||
D0FA10012D10200100112233 /* burrow.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FA10032D10200100112233 /* burrow.pb.swift */; };
|
||||
D0FA10022D10200100112233 /* burrow.grpc.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FA10042D10200100112233 /* burrow.grpc.swift */; };
|
||||
D0F7597E2C8DB30500126CF3 /* CGRPCZlib in Frameworks */ = {isa = PBXBuildFile; productRef = D0F7597D2C8DB30500126CF3 /* CGRPCZlib */; };
|
||||
D0F7598D2C8DB3DA00126CF3 /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4992C8D921A007F820A /* Client.swift */; };
|
||||
D0BCC60A2A09A0B800AD070D /* build-rust.sh in Resources */ = {isa = PBXBuildFile; fileRef = D0B98FBF29FD8072004E7149 /* build-rust.sh */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
D11000022F70000100112233 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D05B9F7129E39EEC008CB1F9;
|
||||
remoteInfo = App;
|
||||
};
|
||||
D020F65B29E4A697002790F6 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
||||
|
|
@ -64,48 +28,6 @@
|
|||
remoteGlobalIDString = D020F65229E4A697002790F6;
|
||||
remoteInfo = BurrowNetworkExtension;
|
||||
};
|
||||
D0BF09502C8E66F1000D8DEC /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D0D4E55A2C8D9BF4007F820A;
|
||||
remoteInfo = Configuration;
|
||||
};
|
||||
D0BF09532C8E66FA000D8DEC /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D0D4E55A2C8D9BF4007F820A;
|
||||
remoteInfo = Configuration;
|
||||
};
|
||||
D0D4E56E2C8D9C5D007F820A /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D0D4E5302C8D996F007F820A;
|
||||
remoteInfo = Core;
|
||||
};
|
||||
D0D4E57F2C8D9C78007F820A /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D0D4E5302C8D996F007F820A;
|
||||
remoteInfo = Core;
|
||||
};
|
||||
D0D4E5872C8D9C88007F820A /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D0D4E5502C8D9BF2007F820A;
|
||||
remoteInfo = UI;
|
||||
};
|
||||
D0F4FAD12C8DC7960068730A /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D0D4E5302C8D996F007F820A;
|
||||
remoteInfo = Core;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
|
|
@ -120,27 +42,11 @@
|
|||
name = "Embed Foundation Extensions";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D0D4E53F2C8D996F007F820A /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
D0D4E58B2C8D9CA4007F820A /* BurrowConfiguration.framework in Embed Frameworks */,
|
||||
D0D4E58A2C8D9C9E007F820A /* BurrowUI.framework in Embed Frameworks */,
|
||||
D0D4E53A2C8D996F007F820A /* BurrowCore.framework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
D00117422B30348D00D87C25 /* Configuration.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Configuration.xcconfig; sourceTree = "<group>"; };
|
||||
D00AA8962A4669BC005C8102 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
D11000032F70000100112233 /* BurrowUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BurrowUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D11000042F70000100112233 /* BurrowUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BurrowUITests.swift; sourceTree = "<group>"; };
|
||||
D11000052F70000100112233 /* UITests.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = UITests.xcconfig; sourceTree = "<group>"; };
|
||||
43AA26D72A10004900F14CE6 /* MenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuView.swift; sourceTree = "<group>"; };
|
||||
91D80FC62A20615500952E28 /* OnboardingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingView.swift; sourceTree = "<group>"; wrapsLines = 0; };
|
||||
D020F63D29E4A1FF002790F6 /* Identity.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Identity.xcconfig; sourceTree = "<group>"; };
|
||||
D020F64029E4A1FF002790F6 /* Compiler.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Compiler.xcconfig; sourceTree = "<group>"; };
|
||||
D020F64229E4A1FF002790F6 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
|
|
@ -155,59 +61,24 @@
|
|||
D020F66729E4A95D002790F6 /* NetworkExtension-iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "NetworkExtension-iOS.entitlements"; sourceTree = "<group>"; };
|
||||
D020F66829E4AA74002790F6 /* App-iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "App-iOS.entitlements"; sourceTree = "<group>"; };
|
||||
D020F66929E4AA74002790F6 /* App-macOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "App-macOS.entitlements"; sourceTree = "<group>"; };
|
||||
D04A3E1D2BAF465F0043EC85 /* Version.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Version.xcconfig; sourceTree = "<group>"; };
|
||||
D05B9F7229E39EEC008CB1F9 /* Burrow.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Burrow.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D05B9F7529E39EEC008CB1F9 /* BurrowApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BurrowApp.swift; sourceTree = "<group>"; };
|
||||
D09150412B9D2AF700BE3CB0 /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = "<group>"; };
|
||||
D05B9F7929E39EED008CB1F9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
D0B98FBF29FD8072004E7149 /* build-rust.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "build-rust.sh"; sourceTree = "<group>"; };
|
||||
D0B98FC629FDC5B5004E7149 /* Tunnel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tunnel.swift; sourceTree = "<group>"; };
|
||||
D0B98FD829FDDB6F004E7149 /* libburrow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = libburrow.h; sourceTree = "<group>"; };
|
||||
D0B98FDC29FDDDCF004E7149 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
|
||||
D0BCC5FC2A086D4700AD070D /* NetworkExtension+Async.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NetworkExtension+Async.swift"; sourceTree = "<group>"; };
|
||||
D0BCC5FE2A086E1C00AD070D /* Status.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Status.swift; sourceTree = "<group>"; };
|
||||
D0BCC6032A09535900AD070D /* libburrow.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libburrow.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D0BF09582C8E6789000D8DEC /* UI.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = UI.xcconfig; sourceTree = "<group>"; };
|
||||
D0D4E4952C8D921A007F820A /* burrow.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = burrow.proto; sourceTree = "<group>"; };
|
||||
D0D4E4992C8D921A007F820A /* Client.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = "<group>"; };
|
||||
D0D4E49A2C8D921A007F820A /* Logging.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logging.swift; sourceTree = "<group>"; };
|
||||
D0D4E49E2C8D921A007F820A /* Network.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Network.swift; sourceTree = "<group>"; };
|
||||
D0D4E49F2C8D921A007F820A /* WireGuard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WireGuard.swift; sourceTree = "<group>"; };
|
||||
D0D4E4A12C8D921A007F820A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
D0D4E4A22C8D921A007F820A /* BurrowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BurrowView.swift; sourceTree = "<group>"; };
|
||||
D0D4E4A32C8D921A007F820A /* FloatingButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingButtonStyle.swift; sourceTree = "<group>"; };
|
||||
D0D4E4A42C8D921A007F820A /* MenuItemToggleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuItemToggleView.swift; sourceTree = "<group>"; };
|
||||
D0D4E4A52C8D921A007F820A /* NetworkCarouselView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkCarouselView.swift; sourceTree = "<group>"; };
|
||||
D0D4E4A62C8D921A007F820A /* NetworkExtension+Async.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NetworkExtension+Async.swift"; sourceTree = "<group>"; };
|
||||
D0D4E4A72C8D921A007F820A /* NetworkExtensionTunnel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkExtensionTunnel.swift; sourceTree = "<group>"; };
|
||||
D0D4E4A82C8D921A007F820A /* NetworkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkView.swift; sourceTree = "<group>"; };
|
||||
D0D4E4AA2C8D921A007F820A /* Tunnel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tunnel.swift; sourceTree = "<group>"; };
|
||||
D0D4E4AB2C8D921A007F820A /* TunnelButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelButton.swift; sourceTree = "<group>"; };
|
||||
D0D4E4AC2C8D921A007F820A /* TunnelStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelStatusView.swift; sourceTree = "<group>"; };
|
||||
D0D4E4F62C8D932D007F820A /* Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
|
||||
D0D4E4F72C8D941D007F820A /* Framework.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Framework.xcconfig; sourceTree = "<group>"; };
|
||||
D0D4E5312C8D996F007F820A /* BurrowCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BurrowCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D0D4E5582C8D9BF2007F820A /* BurrowUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BurrowUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D0D4E5622C8D9BF4007F820A /* BurrowConfiguration.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BurrowConfiguration.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D0D4E58E2C8D9D0A007F820A /* Constants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Constants.h; sourceTree = "<group>"; };
|
||||
D0D4E58F2C8D9D0A007F820A /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
|
||||
D0D4E5902C8D9D0A007F820A /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
|
||||
D0FA10032D10200100112233 /* burrow.pb.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Generated/burrow.pb.swift; sourceTree = "<group>"; };
|
||||
D0FA10042D10200100112233 /* burrow.grpc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Generated/burrow.grpc.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
D11000062F70000100112233 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D020F65029E4A697002790F6 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D0BF09522C8E66F6000D8DEC /* BurrowConfiguration.framework in Frameworks */,
|
||||
D0D4E5A62C8D9E65007F820A /* BurrowCore.framework in Frameworks */,
|
||||
D0BCC6092A09A03E00AD070D /* libburrow.a in Frameworks */,
|
||||
D0B1D1102C436152004B7823 /* AsyncAlgorithms in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
@ -215,41 +86,19 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D0BF09552C8E66FD000D8DEC /* BurrowConfiguration.framework in Frameworks */,
|
||||
D0F4FAD32C8DC79C0068730A /* BurrowCore.framework in Frameworks */,
|
||||
D0D4E5892C8D9C94007F820A /* BurrowUI.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D078F7CF2C8DA213008A8CEC /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D03383B02C8E67E300F7C44E /* NIOTransportServices in Frameworks */,
|
||||
D03383AF2C8E67E300F7C44E /* NIOConcurrencyHelpers in Frameworks */,
|
||||
D03383AE2C8E67E300F7C44E /* NIO in Frameworks */,
|
||||
D03383AD2C8E67E300F7C44E /* SwiftProtobuf in Frameworks */,
|
||||
D0F7594E2C8DAB6B00126CF3 /* GRPC in Frameworks */,
|
||||
D0F7597E2C8DB30500126CF3 /* CGRPCZlib in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D0D4E5532C8D9BF2007F820A /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D0D4E5702C8D9C62007F820A /* BurrowCore.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
D00117432B30372900D87C25 /* Frameworks */ = {
|
||||
43AA26D62A0FFFD000F14CE6 /* Menu */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
43AA26D72A10004900F14CE6 /* MenuView.swift */,
|
||||
91D80FC62A20615500952E28 /* OnboardingView.swift */,
|
||||
);
|
||||
name = Frameworks;
|
||||
path = Menu;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D020F63C29E4A1FF002790F6 /* Configuration */ = {
|
||||
|
|
@ -258,14 +107,8 @@
|
|||
D020F63D29E4A1FF002790F6 /* Identity.xcconfig */,
|
||||
D020F64A29E4A452002790F6 /* App.xcconfig */,
|
||||
D020F66329E4A703002790F6 /* Extension.xcconfig */,
|
||||
D0D4E4F72C8D941D007F820A /* Framework.xcconfig */,
|
||||
D020F64029E4A1FF002790F6 /* Compiler.xcconfig */,
|
||||
D0D4E4F62C8D932D007F820A /* Debug.xcconfig */,
|
||||
D11000052F70000100112233 /* UITests.xcconfig */,
|
||||
D04A3E1D2BAF465F0043EC85 /* Version.xcconfig */,
|
||||
D020F64229E4A1FF002790F6 /* Info.plist */,
|
||||
D0D4E5912C8D9D0A007F820A /* Constants */,
|
||||
D00117422B30348D00D87C25 /* Configuration.xcconfig */,
|
||||
);
|
||||
path = Configuration;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -287,13 +130,9 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
D05B9F7429E39EEC008CB1F9 /* App */,
|
||||
D11000072F70000100112233 /* AppUITests */,
|
||||
D020F65629E4A697002790F6 /* NetworkExtension */,
|
||||
D0D4E49C2C8D921A007F820A /* Core */,
|
||||
D0D4E4AD2C8D921A007F820A /* UI */,
|
||||
D020F63C29E4A1FF002790F6 /* Configuration */,
|
||||
D05B9F7329E39EEC008CB1F9 /* Products */,
|
||||
D00117432B30372900D87C25 /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
|
|
@ -301,12 +140,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
D05B9F7229E39EEC008CB1F9 /* Burrow.app */,
|
||||
D11000032F70000100112233 /* BurrowUITests.xctest */,
|
||||
D020F65329E4A697002790F6 /* BurrowNetworkExtension.appex */,
|
||||
D0BCC6032A09535900AD070D /* libburrow.a */,
|
||||
D0D4E5312C8D996F007F820A /* BurrowCore.framework */,
|
||||
D0D4E5582C8D9BF2007F820A /* BurrowUI.framework */,
|
||||
D0D4E5622C8D9BF4007F820A /* BurrowConfiguration.framework */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -314,9 +148,12 @@
|
|||
D05B9F7429E39EEC008CB1F9 /* App */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
43AA26D62A0FFFD000F14CE6 /* Menu */,
|
||||
D05B9F7529E39EEC008CB1F9 /* BurrowApp.swift */,
|
||||
D00AA8962A4669BC005C8102 /* AppDelegate.swift */,
|
||||
D09150412B9D2AF700BE3CB0 /* MainMenu.xib */,
|
||||
D0B98FC629FDC5B5004E7149 /* Tunnel.swift */,
|
||||
D0BCC5FE2A086E1C00AD070D /* Status.swift */,
|
||||
D0BCC5FC2A086D4700AD070D /* NetworkExtension+Async.swift */,
|
||||
D05B9F7929E39EED008CB1F9 /* Assets.xcassets */,
|
||||
D020F66829E4AA74002790F6 /* App-iOS.entitlements */,
|
||||
D020F66929E4AA74002790F6 /* App-macOS.entitlements */,
|
||||
D020F64929E4A34B002790F6 /* App.xcconfig */,
|
||||
|
|
@ -324,104 +161,20 @@
|
|||
path = App;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D11000072F70000100112233 /* AppUITests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D11000042F70000100112233 /* BurrowUITests.swift */,
|
||||
);
|
||||
path = AppUITests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D0B98FD729FDDB57004E7149 /* libburrow */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D0B98FBF29FD8072004E7149 /* build-rust.sh */,
|
||||
D0B98FDC29FDDDCF004E7149 /* module.modulemap */,
|
||||
D0B98FD829FDDB6F004E7149 /* libburrow.h */,
|
||||
D0BCC6032A09535900AD070D /* libburrow.a */,
|
||||
);
|
||||
path = libburrow;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D0D4E4982C8D921A007F820A /* Client */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D0D4E4952C8D921A007F820A /* burrow.proto */,
|
||||
D0FA10032D10200100112233 /* burrow.pb.swift */,
|
||||
D0FA10042D10200100112233 /* burrow.grpc.swift */,
|
||||
);
|
||||
path = Client;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D0D4E49C2C8D921A007F820A /* Core */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D0D4E49A2C8D921A007F820A /* Logging.swift */,
|
||||
D0D4E4992C8D921A007F820A /* Client.swift */,
|
||||
D0D4E4982C8D921A007F820A /* Client */,
|
||||
);
|
||||
path = Core;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D0D4E4A02C8D921A007F820A /* Networks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D0D4E49E2C8D921A007F820A /* Network.swift */,
|
||||
D0D4E49F2C8D921A007F820A /* WireGuard.swift */,
|
||||
);
|
||||
path = Networks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D0D4E4AD2C8D921A007F820A /* UI */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D0D4E4A22C8D921A007F820A /* BurrowView.swift */,
|
||||
D0D4E4A02C8D921A007F820A /* Networks */,
|
||||
D0D4E4A32C8D921A007F820A /* FloatingButtonStyle.swift */,
|
||||
D0D4E4A42C8D921A007F820A /* MenuItemToggleView.swift */,
|
||||
D0D4E4A52C8D921A007F820A /* NetworkCarouselView.swift */,
|
||||
D0D4E4A62C8D921A007F820A /* NetworkExtension+Async.swift */,
|
||||
D0D4E4A72C8D921A007F820A /* NetworkExtensionTunnel.swift */,
|
||||
D0D4E4A82C8D921A007F820A /* NetworkView.swift */,
|
||||
D0D4E4AA2C8D921A007F820A /* Tunnel.swift */,
|
||||
D0D4E4AB2C8D921A007F820A /* TunnelButton.swift */,
|
||||
D0D4E4AC2C8D921A007F820A /* TunnelStatusView.swift */,
|
||||
D0D4E4A12C8D921A007F820A /* Assets.xcassets */,
|
||||
D0BF09582C8E6789000D8DEC /* UI.xcconfig */,
|
||||
);
|
||||
path = UI;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D0D4E5912C8D9D0A007F820A /* Constants */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D0D4E58E2C8D9D0A007F820A /* Constants.h */,
|
||||
D0D4E58F2C8D9D0A007F820A /* Constants.swift */,
|
||||
D0D4E5902C8D9D0A007F820A /* module.modulemap */,
|
||||
);
|
||||
path = Constants;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
D11000082F70000100112233 /* BurrowUITests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D110000E2F70000100112233 /* Build configuration list for PBXNativeTarget "BurrowUITests" */;
|
||||
buildPhases = (
|
||||
D110000A2F70000100112233 /* Sources */,
|
||||
D11000062F70000100112233 /* Frameworks */,
|
||||
D11000092F70000100112233 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
D110000B2F70000100112233 /* PBXTargetDependency */,
|
||||
);
|
||||
name = BurrowUITests;
|
||||
productName = BurrowUITests;
|
||||
productReference = D11000032F70000100112233 /* BurrowUITests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.ui-testing";
|
||||
};
|
||||
D020F65229E4A697002790F6 /* NetworkExtension */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D020F65E29E4A697002790F6 /* Build configuration list for PBXNativeTarget "NetworkExtension" */;
|
||||
|
|
@ -429,12 +182,12 @@
|
|||
D0BCC60B2A09A0C100AD070D /* Compile Rust */,
|
||||
D020F64F29E4A697002790F6 /* Sources */,
|
||||
D020F65029E4A697002790F6 /* Frameworks */,
|
||||
D020F65129E4A697002790F6 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
D0BF09512C8E66F1000D8DEC /* PBXTargetDependency */,
|
||||
D0D4E5802C8D9C78007F820A /* PBXTargetDependency */,
|
||||
D0BCC6122A0B328800AD070D /* PBXTargetDependency */,
|
||||
);
|
||||
name = NetworkExtension;
|
||||
productName = BurrowNetworkExtension;
|
||||
|
|
@ -448,15 +201,12 @@
|
|||
D05B9F6E29E39EEC008CB1F9 /* Sources */,
|
||||
D05B9F6F29E39EEC008CB1F9 /* Frameworks */,
|
||||
D05B9F7029E39EEC008CB1F9 /* Resources */,
|
||||
D0D4E53F2C8D996F007F820A /* Embed Frameworks */,
|
||||
D020F66129E4A697002790F6 /* Embed Foundation Extensions */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
D0BF09542C8E66FA000D8DEC /* PBXTargetDependency */,
|
||||
D0F4FAD22C8DC7960068730A /* PBXTargetDependency */,
|
||||
D0D4E5882C8D9C88007F820A /* PBXTargetDependency */,
|
||||
D0BCC6142A0B329200AD070D /* PBXTargetDependency */,
|
||||
D020F65C29E4A697002790F6 /* PBXTargetDependency */,
|
||||
);
|
||||
name = App;
|
||||
|
|
@ -464,69 +214,6 @@
|
|||
productReference = D05B9F7229E39EEC008CB1F9 /* Burrow.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
D0D4E5302C8D996F007F820A /* Core */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D0D4E53C2C8D996F007F820A /* Build configuration list for PBXNativeTarget "Core" */;
|
||||
buildPhases = (
|
||||
D0D4E52D2C8D996F007F820A /* Sources */,
|
||||
D078F7CF2C8DA213008A8CEC /* Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
D0F7598A2C8DB34200126CF3 /* PBXTargetDependency */,
|
||||
);
|
||||
name = Core;
|
||||
packageProductDependencies = (
|
||||
D078F7E02C8DA375008A8CEC /* GRPC */,
|
||||
D078F7E22C8DA375008A8CEC /* SwiftProtobuf */,
|
||||
D044EE902C8DAB2000778185 /* NIO */,
|
||||
D044EE922C8DAB2000778185 /* NIOConcurrencyHelpers */,
|
||||
D044EE952C8DAB2800778185 /* NIOTransportServices */,
|
||||
D0F7597D2C8DB30500126CF3 /* CGRPCZlib */,
|
||||
);
|
||||
productName = Core;
|
||||
productReference = D0D4E5312C8D996F007F820A /* BurrowCore.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
D0D4E5502C8D9BF2007F820A /* UI */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D0D4E5552C8D9BF2007F820A /* Build configuration list for PBXNativeTarget "UI" */;
|
||||
buildPhases = (
|
||||
D0D4E5522C8D9BF2007F820A /* Sources */,
|
||||
D0D4E5532C8D9BF2007F820A /* Frameworks */,
|
||||
D0D4E5542C8D9BF2007F820A /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
D0D4E56F2C8D9C5D007F820A /* PBXTargetDependency */,
|
||||
);
|
||||
name = UI;
|
||||
packageProductDependencies = (
|
||||
);
|
||||
productName = Core;
|
||||
productReference = D0D4E5582C8D9BF2007F820A /* BurrowUI.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
D0D4E55A2C8D9BF4007F820A /* Configuration */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D0D4E55F2C8D9BF4007F820A /* Build configuration list for PBXNativeTarget "Configuration" */;
|
||||
buildPhases = (
|
||||
D0F759912C8DB49E00126CF3 /* Configure Version */,
|
||||
D0D4E55C2C8D9BF4007F820A /* Sources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Configuration;
|
||||
packageProductDependencies = (
|
||||
);
|
||||
productName = Core;
|
||||
productReference = D0D4E5622C8D9BF4007F820A /* BurrowConfiguration.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
|
|
@ -534,22 +221,15 @@
|
|||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = 1;
|
||||
LastSwiftUpdateCheck = 1600;
|
||||
LastUpgradeCheck = 1520;
|
||||
LastSwiftUpdateCheck = 1430;
|
||||
LastUpgradeCheck = 1430;
|
||||
TargetAttributes = {
|
||||
D11000082F70000100112233 = {
|
||||
CreatedOnToolsVersion = 16.0;
|
||||
TestTargetID = D05B9F7129E39EEC008CB1F9;
|
||||
};
|
||||
D020F65229E4A697002790F6 = {
|
||||
CreatedOnToolsVersion = 14.3;
|
||||
};
|
||||
D05B9F7129E39EEC008CB1F9 = {
|
||||
CreatedOnToolsVersion = 14.3;
|
||||
};
|
||||
D0D4E5302C8D996F007F820A = {
|
||||
CreatedOnToolsVersion = 16.0;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = D05B9F6D29E39EEC008CB1F9 /* Build configuration list for PBXProject "Burrow" */;
|
||||
|
|
@ -562,31 +242,24 @@
|
|||
);
|
||||
mainGroup = D05B9F6929E39EEC008CB1F9;
|
||||
packageReferences = (
|
||||
D0B1D10E2C436152004B7823 /* XCRemoteSwiftPackageReference "swift-async-algorithms" */,
|
||||
D0D4E4822C8D8EF6007F820A /* XCRemoteSwiftPackageReference "grpc-swift" */,
|
||||
D0D4E4852C8D8F29007F820A /* XCRemoteSwiftPackageReference "swift-protobuf" */,
|
||||
D044EE8F2C8DAB2000778185 /* XCRemoteSwiftPackageReference "swift-nio" */,
|
||||
D044EE942C8DAB2800778185 /* XCRemoteSwiftPackageReference "swift-nio-transport-services" */,
|
||||
D0BCC6102A0B327700AD070D /* XCRemoteSwiftPackageReference "SwiftLint" */,
|
||||
);
|
||||
productRefGroup = D05B9F7329E39EEC008CB1F9 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
D05B9F7129E39EEC008CB1F9 /* App */,
|
||||
D11000082F70000100112233 /* BurrowUITests */,
|
||||
D020F65229E4A697002790F6 /* NetworkExtension */,
|
||||
D0D4E5502C8D9BF2007F820A /* UI */,
|
||||
D0D4E5302C8D996F007F820A /* Core */,
|
||||
D0D4E55A2C8D9BF4007F820A /* Configuration */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
D11000092F70000100112233 /* Resources */ = {
|
||||
D020F65129E4A697002790F6 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D0BCC60A2A09A0B800AD070D /* build-rust.sh in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
@ -594,14 +267,7 @@
|
|||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D09150422B9D2AF700BE3CB0 /* MainMenu.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D0D4E5542C8D9BF2007F820A /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D05B9F7A29E39EED008CB1F9 /* Assets.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
@ -628,39 +294,9 @@
|
|||
shellScript = "\"${PROJECT_DIR}/NetworkExtension/libburrow/build-rust.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
D0F759912C8DB49E00126CF3 /* Configure Version */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"$(PROJECT_DIR)/../Tools/version.sh",
|
||||
"$(PROJECT_DIR)/../.git",
|
||||
);
|
||||
name = "Configure Version";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(PROJECT_DIR)/Configuration/Version.xcconfig",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"$PROJECT_DIR/../Tools/version.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
D110000A2F70000100112233 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D11000012F70000100112233 /* BurrowUITests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D020F64F29E4A697002790F6 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
|
@ -673,117 +309,42 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D00AA8972A4669BC005C8102 /* AppDelegate.swift in Sources */,
|
||||
D0BCC6082A0981FE00AD070D /* Tunnel.swift in Sources */,
|
||||
43AA26D82A10004900F14CE6 /* MenuView.swift in Sources */,
|
||||
D0BCC5FF2A086E1C00AD070D /* Status.swift in Sources */,
|
||||
D05B9F7629E39EEC008CB1F9 /* BurrowApp.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D0D4E52D2C8D996F007F820A /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D0FA10012D10200100112233 /* burrow.pb.swift in Sources */,
|
||||
D0FA10022D10200100112233 /* burrow.grpc.swift in Sources */,
|
||||
D0F7598D2C8DB3DA00126CF3 /* Client.swift in Sources */,
|
||||
D0D4E56B2C8D9C2F007F820A /* Logging.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D0D4E5522C8D9BF2007F820A /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D0D4E5722C8D9C6F007F820A /* Network.swift in Sources */,
|
||||
D0D4E5732C8D9C6F007F820A /* WireGuard.swift in Sources */,
|
||||
D0D4E5742C8D9C6F007F820A /* BurrowView.swift in Sources */,
|
||||
D0D4E5752C8D9C6F007F820A /* FloatingButtonStyle.swift in Sources */,
|
||||
D0D4E5762C8D9C6F007F820A /* MenuItemToggleView.swift in Sources */,
|
||||
D0D4E5772C8D9C6F007F820A /* NetworkCarouselView.swift in Sources */,
|
||||
D0D4E5782C8D9C6F007F820A /* NetworkExtension+Async.swift in Sources */,
|
||||
D0D4E5792C8D9C6F007F820A /* NetworkExtensionTunnel.swift in Sources */,
|
||||
D0D4E57A2C8D9C6F007F820A /* NetworkView.swift in Sources */,
|
||||
D0D4E57C2C8D9C6F007F820A /* Tunnel.swift in Sources */,
|
||||
D0D4E57D2C8D9C6F007F820A /* TunnelButton.swift in Sources */,
|
||||
D0D4E57E2C8D9C6F007F820A /* TunnelStatusView.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D0D4E55C2C8D9BF4007F820A /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D0D4E5922C8D9D15007F820A /* Constants.swift in Sources */,
|
||||
D0BCC5FD2A086D4700AD070D /* NetworkExtension+Async.swift in Sources */,
|
||||
91D80FC72A20615500952E28 /* OnboardingView.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
D110000B2F70000100112233 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D05B9F7129E39EEC008CB1F9 /* App */;
|
||||
targetProxy = D11000022F70000100112233 /* PBXContainerItemProxy */;
|
||||
};
|
||||
D020F65C29E4A697002790F6 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D020F65229E4A697002790F6 /* NetworkExtension */;
|
||||
targetProxy = D020F65B29E4A697002790F6 /* PBXContainerItemProxy */;
|
||||
};
|
||||
D0BF09512C8E66F1000D8DEC /* PBXTargetDependency */ = {
|
||||
D0BCC6122A0B328800AD070D /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D0D4E55A2C8D9BF4007F820A /* Configuration */;
|
||||
targetProxy = D0BF09502C8E66F1000D8DEC /* PBXContainerItemProxy */;
|
||||
productRef = D0BCC6112A0B328800AD070D /* SwiftLintPlugin */;
|
||||
};
|
||||
D0BF09542C8E66FA000D8DEC /* PBXTargetDependency */ = {
|
||||
D0BCC6142A0B329200AD070D /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D0D4E55A2C8D9BF4007F820A /* Configuration */;
|
||||
targetProxy = D0BF09532C8E66FA000D8DEC /* PBXContainerItemProxy */;
|
||||
};
|
||||
D0D4E56F2C8D9C5D007F820A /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D0D4E5302C8D996F007F820A /* Core */;
|
||||
targetProxy = D0D4E56E2C8D9C5D007F820A /* PBXContainerItemProxy */;
|
||||
};
|
||||
D0D4E5802C8D9C78007F820A /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D0D4E5302C8D996F007F820A /* Core */;
|
||||
targetProxy = D0D4E57F2C8D9C78007F820A /* PBXContainerItemProxy */;
|
||||
};
|
||||
D0D4E5882C8D9C88007F820A /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D0D4E5502C8D9BF2007F820A /* UI */;
|
||||
targetProxy = D0D4E5872C8D9C88007F820A /* PBXContainerItemProxy */;
|
||||
};
|
||||
D0F4FAD22C8DC7960068730A /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D0D4E5302C8D996F007F820A /* Core */;
|
||||
targetProxy = D0F4FAD12C8DC7960068730A /* PBXContainerItemProxy */;
|
||||
};
|
||||
D0F7598A2C8DB34200126CF3 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
productRef = D0F759892C8DB34200126CF3 /* GRPC */;
|
||||
productRef = D0BCC6132A0B329200AD070D /* SwiftLintPlugin */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
D110000C2F70000100112233 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D11000052F70000100112233 /* UITests.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
D110000D2F70000100112233 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D11000052F70000100112233 /* UITests.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
D020F65F29E4A697002790F6 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D020F66229E4A6E5002790F6 /* NetworkExtension.xcconfig */;
|
||||
buildSettings = {
|
||||
DEVELOPMENT_TEAM = P6PV2R9443;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Burrow;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2023 Hack Club";
|
||||
"PRODUCT_BUNDLE_IDENTIFIER[sdk=iphoneos*]" = com.hackclub.burrow.network;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
|
|
@ -791,6 +352,10 @@
|
|||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D020F66229E4A6E5002790F6 /* NetworkExtension.xcconfig */;
|
||||
buildSettings = {
|
||||
DEVELOPMENT_TEAM = P6PV2R9443;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Burrow;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2023 Hack Club";
|
||||
"PRODUCT_BUNDLE_IDENTIFIER[sdk=iphoneos*]" = com.hackclub.burrow.network;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
|
@ -812,6 +377,10 @@
|
|||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D020F64929E4A34B002790F6 /* App.xcconfig */;
|
||||
buildSettings = {
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Burrow;
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||
INFOPLIST_KEY_LSUIElement = YES;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2023 Hack Club";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
|
|
@ -819,63 +388,16 @@
|
|||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D020F64929E4A34B002790F6 /* App.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
D0D4E53D2C8D996F007F820A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D0D4E4F72C8D941D007F820A /* Framework.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
D0D4E53E2C8D996F007F820A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D0D4E4F72C8D941D007F820A /* Framework.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
D0D4E5562C8D9BF2007F820A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D0BF09582C8E6789000D8DEC /* UI.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
D0D4E5572C8D9BF2007F820A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D0BF09582C8E6789000D8DEC /* UI.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
D0D4E5602C8D9BF4007F820A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D00117422B30348D00D87C25 /* Configuration.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
D0D4E5612C8D9BF4007F820A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D00117422B30348D00D87C25 /* Configuration.xcconfig */;
|
||||
buildSettings = {
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Burrow;
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||
INFOPLIST_KEY_LSUIElement = YES;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2023 Hack Club";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
D110000E2F70000100112233 /* Build configuration list for PBXNativeTarget "BurrowUITests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D110000C2F70000100112233 /* Debug */,
|
||||
D110000D2F70000100112233 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
D020F65E29E4A697002790F6 /* Build configuration list for PBXNativeTarget "NetworkExtension" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
|
@ -903,118 +425,29 @@
|
|||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
D0D4E53C2C8D996F007F820A /* Build configuration list for PBXNativeTarget "Core" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D0D4E53D2C8D996F007F820A /* Debug */,
|
||||
D0D4E53E2C8D996F007F820A /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
D0D4E5552C8D9BF2007F820A /* Build configuration list for PBXNativeTarget "UI" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D0D4E5562C8D9BF2007F820A /* Debug */,
|
||||
D0D4E5572C8D9BF2007F820A /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
D0D4E55F2C8D9BF4007F820A /* Build configuration list for PBXNativeTarget "Configuration" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D0D4E5602C8D9BF4007F820A /* Debug */,
|
||||
D0D4E5612C8D9BF4007F820A /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCRemoteSwiftPackageReference section */
|
||||
D044EE8F2C8DAB2000778185 /* XCRemoteSwiftPackageReference "swift-nio" */ = {
|
||||
D0BCC6102A0B327700AD070D /* XCRemoteSwiftPackageReference "SwiftLint" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/apple/swift-nio.git";
|
||||
repositoryURL = "https://github.com/realm/SwiftLint.git";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 2.72.0;
|
||||
};
|
||||
};
|
||||
D044EE942C8DAB2800778185 /* XCRemoteSwiftPackageReference "swift-nio-transport-services" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/apple/swift-nio-transport-services.git";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 1.21.0;
|
||||
};
|
||||
};
|
||||
D0B1D10E2C436152004B7823 /* XCRemoteSwiftPackageReference "swift-async-algorithms" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/apple/swift-async-algorithms.git";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 1.0.1;
|
||||
};
|
||||
};
|
||||
D0D4E4822C8D8EF6007F820A /* XCRemoteSwiftPackageReference "grpc-swift" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/grpc/grpc-swift.git";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 1.23.0;
|
||||
};
|
||||
};
|
||||
D0D4E4852C8D8F29007F820A /* XCRemoteSwiftPackageReference "swift-protobuf" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/apple/swift-protobuf.git";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 1.28.1;
|
||||
minimumVersion = 0.51.0;
|
||||
};
|
||||
};
|
||||
/* End XCRemoteSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
D044EE902C8DAB2000778185 /* NIO */ = {
|
||||
D0BCC6112A0B328800AD070D /* SwiftLintPlugin */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = D044EE8F2C8DAB2000778185 /* XCRemoteSwiftPackageReference "swift-nio" */;
|
||||
productName = NIO;
|
||||
package = D0BCC6102A0B327700AD070D /* XCRemoteSwiftPackageReference "SwiftLint" */;
|
||||
productName = "plugin:SwiftLintPlugin";
|
||||
};
|
||||
D044EE922C8DAB2000778185 /* NIOConcurrencyHelpers */ = {
|
||||
D0BCC6132A0B329200AD070D /* SwiftLintPlugin */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = D044EE8F2C8DAB2000778185 /* XCRemoteSwiftPackageReference "swift-nio" */;
|
||||
productName = NIOConcurrencyHelpers;
|
||||
};
|
||||
D044EE952C8DAB2800778185 /* NIOTransportServices */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = D044EE942C8DAB2800778185 /* XCRemoteSwiftPackageReference "swift-nio-transport-services" */;
|
||||
productName = NIOTransportServices;
|
||||
};
|
||||
D078F7E02C8DA375008A8CEC /* GRPC */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = D0D4E4822C8D8EF6007F820A /* XCRemoteSwiftPackageReference "grpc-swift" */;
|
||||
productName = GRPC;
|
||||
};
|
||||
D078F7E22C8DA375008A8CEC /* SwiftProtobuf */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = D0D4E4852C8D8F29007F820A /* XCRemoteSwiftPackageReference "swift-protobuf" */;
|
||||
productName = SwiftProtobuf;
|
||||
};
|
||||
D0B1D10F2C436152004B7823 /* AsyncAlgorithms */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = D0B1D10E2C436152004B7823 /* XCRemoteSwiftPackageReference "swift-async-algorithms" */;
|
||||
productName = AsyncAlgorithms;
|
||||
};
|
||||
D0F7597D2C8DB30500126CF3 /* CGRPCZlib */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = D0D4E4822C8D8EF6007F820A /* XCRemoteSwiftPackageReference "grpc-swift" */;
|
||||
productName = CGRPCZlib;
|
||||
};
|
||||
D0F759892C8DB34200126CF3 /* GRPC */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = D0D4E4822C8D8EF6007F820A /* XCRemoteSwiftPackageReference "grpc-swift" */;
|
||||
productName = GRPC;
|
||||
package = D0BCC6102A0B327700AD070D /* XCRemoteSwiftPackageReference "SwiftLint" */;
|
||||
productName = "plugin:SwiftLintPlugin";
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,123 +1,77 @@
|
|||
{
|
||||
"originHash" : "fa512b990383b7e309c5854a5279817052294a8191a6d3c55c49cfb38e88c0c3",
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "grpc-swift",
|
||||
"identity" : "collectionconcurrencykit",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/grpc/grpc-swift.git",
|
||||
"location" : "https://github.com/JohnSundell/CollectionConcurrencyKit.git",
|
||||
"state" : {
|
||||
"revision" : "6a90b7e77e29f9bda6c2b3a4165a40d6c02cfda1",
|
||||
"version" : "1.23.0"
|
||||
"revision" : "b4f23e24b5a1bff301efc5e70871083ca029ff95",
|
||||
"version" : "0.2.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-async-algorithms",
|
||||
"identity" : "sourcekitten",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-async-algorithms.git",
|
||||
"location" : "https://github.com/jpsim/SourceKitten.git",
|
||||
"state" : {
|
||||
"revision" : "6ae9a051f76b81cc668305ceed5b0e0a7fd93d20",
|
||||
"version" : "1.0.1"
|
||||
"revision" : "b6dc09ee51dfb0c66e042d2328c017483a1a5d56",
|
||||
"version" : "0.34.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-atomics",
|
||||
"identity" : "swift-argument-parser",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-atomics.git",
|
||||
"location" : "https://github.com/apple/swift-argument-parser.git",
|
||||
"state" : {
|
||||
"revision" : "cd142fd2f64be2100422d658e7411e39489da985",
|
||||
"version" : "1.2.0"
|
||||
"revision" : "fee6933f37fde9a5e12a1e4aeaa93fe60116ff2a",
|
||||
"version" : "1.2.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-collections",
|
||||
"identity" : "swift-syntax",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-collections.git",
|
||||
"location" : "https://github.com/apple/swift-syntax.git",
|
||||
"state" : {
|
||||
"revision" : "9bf03ff58ce34478e66aaee630e491823326fd06",
|
||||
"version" : "1.1.3"
|
||||
"revision" : "013a48e2312e57b7b355db25bd3ea75282ebf274",
|
||||
"version" : "0.50900.0-swift-DEVELOPMENT-SNAPSHOT-2023-02-06-a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-http-types",
|
||||
"identity" : "swiftlint",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-http-types",
|
||||
"location" : "https://github.com/realm/SwiftLint.git",
|
||||
"state" : {
|
||||
"revision" : "ae67c8178eb46944fd85e4dc6dd970e1f3ed6ccd",
|
||||
"version" : "1.3.0"
|
||||
"revision" : "eb85125a5f293de3d3248af259980c98bc2b1faa",
|
||||
"version" : "0.51.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-log",
|
||||
"identity" : "swiftytexttable",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-log.git",
|
||||
"location" : "https://github.com/scottrhoyt/SwiftyTextTable.git",
|
||||
"state" : {
|
||||
"revision" : "9cb486020ebf03bfa5b5df985387a14a98744537",
|
||||
"version" : "1.6.1"
|
||||
"revision" : "c6df6cf533d120716bff38f8ff9885e1ce2a4ac3",
|
||||
"version" : "0.9.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-nio",
|
||||
"identity" : "swxmlhash",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-nio.git",
|
||||
"location" : "https://github.com/drmohundro/SWXMLHash.git",
|
||||
"state" : {
|
||||
"revision" : "9746cf80e29edfef2a39924a66731249223f42a3",
|
||||
"version" : "2.72.0"
|
||||
"revision" : "4d0f62f561458cbe1f732171e625f03195151b60",
|
||||
"version" : "7.0.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-nio-extras",
|
||||
"identity" : "yams",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-nio-extras.git",
|
||||
"location" : "https://github.com/jpsim/Yams.git",
|
||||
"state" : {
|
||||
"revision" : "d1ead62745cc3269e482f1c51f27608057174379",
|
||||
"version" : "1.24.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-nio-http2",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-nio-http2.git",
|
||||
"state" : {
|
||||
"revision" : "b5f7062b60e4add1e8c343ba4eb8da2e324b3a94",
|
||||
"version" : "1.34.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-nio-ssl",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-nio-ssl.git",
|
||||
"state" : {
|
||||
"revision" : "7b84abbdcef69cc3be6573ac12440220789dcd69",
|
||||
"version" : "2.27.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-nio-transport-services",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-nio-transport-services.git",
|
||||
"state" : {
|
||||
"revision" : "38ac8221dd20674682148d6451367f89c2652980",
|
||||
"version" : "1.21.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-protobuf",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-protobuf.git",
|
||||
"state" : {
|
||||
"revision" : "edb6ed4919f7756157fe02f2552b7e3850a538e5",
|
||||
"version" : "1.28.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-system",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-system.git",
|
||||
"state" : {
|
||||
"revision" : "d2ba781702a1d8285419c15ee62fd734a9437ff5",
|
||||
"version" : "1.3.2"
|
||||
"revision" : "f47ba4838c30dbd59998a4e4c87ab620ff959e8a",
|
||||
"version" : "5.0.5"
|
||||
}
|
||||
}
|
||||
],
|
||||
"version" : 3
|
||||
"version" : 2
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1600"
|
||||
LastUpgradeVersion = "1430"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES"
|
||||
buildArchitectures = "Automatic">
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
|
|
@ -28,20 +27,7 @@
|
|||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "NO">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO"
|
||||
parallelizable = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "D11000082F70000100112233"
|
||||
BuildableName = "BurrowUITests.xctest"
|
||||
BlueprintName = "BurrowUITests"
|
||||
ReferencedContainer = "container:Burrow.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1600"
|
||||
wasCreatedForAppExtension = "YES"
|
||||
LastUpgradeVersion = "1430"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES"
|
||||
buildArchitectures = "Automatic">
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
LD_EXPORT_SYMBOLS = NO
|
||||
|
||||
SKIP_INSTALL = NO
|
||||
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks
|
||||
LD_RUNPATH_SEARCH_PATHS[sdk=iphone*] = $(inherited) @executable_path/Frameworks
|
||||
LD_RUNPATH_SEARCH_PATHS[sdk=macosx*] = $(inherited) @executable_path/../Frameworks
|
||||
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor
|
||||
|
||||
ENABLE_PREVIEWS = YES
|
||||
|
|
|
|||
|
|
@ -1,43 +1,61 @@
|
|||
#include "Identity.xcconfig"
|
||||
#include "Debug.xcconfig"
|
||||
#include "Version.xcconfig"
|
||||
|
||||
SDKROOT = auto
|
||||
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES
|
||||
|
||||
SUPPORTED_PLATFORMS = iphoneos iphonesimulator macosx
|
||||
SWIFT_VERSION = 6.0
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 17.0
|
||||
MACOSX_DEPLOYMENT_TARGET = 14.0
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0
|
||||
MACOSX_DEPLOYMENT_TARGET = 12.0
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO
|
||||
SUPPORTS_MACCATALYST = NO
|
||||
|
||||
ALWAYS_SEARCH_USER_PATHS = NO
|
||||
PRODUCT_NAME = $(TARGET_NAME:c99extidentifier)
|
||||
PRODUCT_BUNDLE_IDENTIFIER = $(APP_BUNDLE_IDENTIFIER).$(PRODUCT_NAME)
|
||||
CURRENT_PROJECT_VERSION = 1
|
||||
MARKETING_VERSION = 0.1
|
||||
|
||||
SKIP_INSTALL = YES
|
||||
|
||||
CODE_SIGN_IDENTITY = Apple Development
|
||||
|
||||
GENERATE_INFOPLIST_FILE = YES
|
||||
INFOPLIST_FILE = Configuration/Info.plist
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = Copyright © 2023-2024 Hack Club
|
||||
GENERATE_INFOPLIST_FILE = YES
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = Copyright © 2023 Hack Club
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Burrow
|
||||
|
||||
ENABLE_APP_SANDBOX[sdk=macosx*] = YES
|
||||
|
||||
ENABLE_BITCODE = NO
|
||||
ALWAYS_SEARCH_USER_PATHS = NO
|
||||
|
||||
ENABLE_APP_SANDBOX[sdk=macosx*] = YES
|
||||
ENABLE_HARDENED_RUNTIME[sdk=macosx*] = YES
|
||||
COMBINE_HIDPI_IMAGES = YES
|
||||
EAGER_LINKING = YES
|
||||
COPY_PHASE_STRIP = NO
|
||||
|
||||
FUSE_BUILD_SCRIPT_PHASES = YES
|
||||
SWIFT_EMIT_LOC_STRINGS = YES
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES
|
||||
ENABLE_DEBUG_DYLIB = NO
|
||||
|
||||
APP_GROUP_IDENTIFIER = group.$(APP_BUNDLE_IDENTIFIER)
|
||||
APP_GROUP_IDENTIFIER[sdk=macosx*] = $(DEVELOPMENT_TEAM).$(APP_BUNDLE_IDENTIFIER)
|
||||
NETWORK_EXTENSION_BUNDLE_IDENTIFIER = $(APP_BUNDLE_IDENTIFIER).network
|
||||
|
||||
OTHER_SWIFT_FLAGS = $(inherited)
|
||||
// Swift
|
||||
SWIFT_VERSION = 5.0
|
||||
SWIFT_EMIT_LOC_STRINGS = YES
|
||||
|
||||
// Release
|
||||
DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
|
||||
SWIFT_COMPILATION_MODE = wholemodule
|
||||
SWIFT_OPTIMIZATION_LEVEL = -Osize
|
||||
LLVM_LTO = YES
|
||||
DEAD_CODE_STRIPPING = YES
|
||||
VALIDATE_PRODUCT = YES
|
||||
|
||||
// Debug
|
||||
ONLY_ACTIVE_ARCH[config=Debug] = YES
|
||||
DEBUG_INFORMATION_FORMAT[config=Debug] = dwarf
|
||||
ENABLE_TESTABILITY[config=Debug] = YES
|
||||
SWIFT_OPTIMIZATION_LEVEL[config=Debug] = -Onone
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS[config=Debug] = DEBUG
|
||||
SWIFT_COMPILATION_MODE[config=Debug] = singlefile
|
||||
LLVM_LTO[config=Debug] = NO
|
||||
DEAD_CODE_STRIPPING[config=Debug] = NO
|
||||
VALIDATE_PRODUCT[config=Debug] = NO
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
#include "Framework.xcconfig"
|
||||
|
||||
SWIFT_INCLUDE_PATHS = $(PROJECT_DIR)/Configuration/Constants
|
||||
GCC_PREPROCESSOR_DEFINITIONS = APP_BUNDLE_IDENTIFIER=$(APP_BUNDLE_IDENTIFIER) APP_GROUP_IDENTIFIER=$(APP_GROUP_IDENTIFIER) NETWORK_EXTENSION_BUNDLE_IDENTIFIER=$(NETWORK_EXTENSION_BUNDLE_IDENTIFIER)
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
#define MACRO_STRING_(m) #m
|
||||
#define MACRO_STRING(m) @MACRO_STRING_(m)
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
static NSString * const AppBundleIdentifier = MACRO_STRING(APP_BUNDLE_IDENTIFIER);
|
||||
static NSString * const AppGroupIdentifier = MACRO_STRING(APP_GROUP_IDENTIFIER);
|
||||
static NSString * const NetworkExtensionBundleIdentifier = MACRO_STRING(NETWORK_EXTENSION_BUNDLE_IDENTIFIER);
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
@_implementationOnly import CConstants
|
||||
import Foundation
|
||||
import OSLog
|
||||
|
||||
public enum Constants {
|
||||
enum Error: Swift.Error {
|
||||
case invalidAppGroupIdentifier
|
||||
}
|
||||
|
||||
public static let bundleIdentifier = AppBundleIdentifier
|
||||
public static let appGroupIdentifier = AppGroupIdentifier
|
||||
public static let networkExtensionBundleIdentifier = NetworkExtensionBundleIdentifier
|
||||
|
||||
public static var socketURL: URL {
|
||||
get throws {
|
||||
try groupContainerURL.appending(component: "burrow.sock", directoryHint: .notDirectory)
|
||||
}
|
||||
}
|
||||
public static var databaseURL: URL {
|
||||
get throws {
|
||||
try groupContainerURL.appending(component: "burrow.db", directoryHint: .notDirectory)
|
||||
}
|
||||
}
|
||||
|
||||
private static var groupContainerURL: URL {
|
||||
get throws { try _groupContainerURL.get() }
|
||||
}
|
||||
private static let _groupContainerURL: Result<URL, Error> = {
|
||||
switch FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupIdentifier) {
|
||||
case .some(let url): .success(url)
|
||||
case .none:
|
||||
fallbackContainerURL().mapError { _ in .invalidAppGroupIdentifier }
|
||||
}
|
||||
}()
|
||||
|
||||
private static func fallbackContainerURL() -> Result<URL, any Swift.Error> {
|
||||
#if targetEnvironment(simulator)
|
||||
Result {
|
||||
// The simulator app's Application Support path lives inside its sandbox container,
|
||||
// so the host daemon cannot reach it. Use a shared host temp location instead.
|
||||
let url = URL(filePath: "/tmp", directoryHint: .isDirectory)
|
||||
.appending(component: bundleIdentifier, directoryHint: .isDirectory)
|
||||
.appending(component: "SimulatorFallback", directoryHint: .isDirectory)
|
||||
try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true)
|
||||
return url
|
||||
}
|
||||
#else
|
||||
.failure(Error.invalidAppGroupIdentifier)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
extension Logger {
|
||||
@_dynamicReplacement(for: subsystem)
|
||||
public static var subsystem: String { Constants.bundleIdentifier }
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
module CConstants {
|
||||
header "Constants.h"
|
||||
export *
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
// Release
|
||||
DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
|
||||
SWIFT_COMPILATION_MODE = wholemodule
|
||||
SWIFT_OPTIMIZATION_LEVEL = -Osize
|
||||
LLVM_LTO = YES
|
||||
DEAD_CODE_STRIPPING = YES
|
||||
STRIP_INSTALLED_PRODUCT = YES
|
||||
STRIP_SWIFT_SYMBOLS = YES
|
||||
COPY_PHASE_STRIP = NO
|
||||
VALIDATE_PRODUCT = YES
|
||||
ENABLE_MODULE_VERIFIER = YES
|
||||
|
||||
// Debug
|
||||
ONLY_ACTIVE_ARCH[config=Debug] = YES
|
||||
DEBUG_INFORMATION_FORMAT[config=Debug] = dwarf
|
||||
ENABLE_TESTABILITY[config=Debug] = YES
|
||||
GCC_PREPROCESSOR_DEFINITIONS[config=Debug] = DEBUG=1 $(inherited)
|
||||
SWIFT_OPTIMIZATION_LEVEL[config=Debug] = -Onone
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS[config=Debug] = DEBUG
|
||||
SWIFT_COMPILATION_MODE[config=Debug] = singlefile
|
||||
LLVM_LTO[config=Debug] = NO
|
||||
DEAD_CODE_STRIPPING[config=Debug] = NO
|
||||
VALIDATE_PRODUCT[config=Debug] = NO
|
||||
STRIP_INSTALLED_PRODUCT[config=Debug] = NO
|
||||
STRIP_SWIFT_SYMBOLS[config=Debug] = NO
|
||||
ENABLE_MODULE_VERIFIER[config=Debug] = NO
|
||||
|
|
@ -1,6 +1,2 @@
|
|||
LD_EXPORT_SYMBOLS = NO
|
||||
|
||||
OTHER_SWIFT_FLAGS = $(inherited) -Xfrontend -disable-autolink-framework -Xfrontend UIKit -Xfrontend -disable-autolink-framework -Xfrontend AppKit -Xfrontend -disable-autolink-framework -Xfrontend SwiftUI
|
||||
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @executable_path/../../Frameworks
|
||||
LD_RUNPATH_SEARCH_PATHS[sdk=macosx*] = $(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks
|
||||
LD_RUNPATH_SEARCH_PATHS[sdk=macos*] = $(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
PRODUCT_NAME = Burrow$(TARGET_NAME:c99extidentifier)
|
||||
PRODUCT_BUNDLE_IDENTIFIER = $(APP_BUNDLE_IDENTIFIER).$(TARGET_NAME:c99extidentifier)
|
||||
APPLICATION_EXTENSION_API_ONLY = YES
|
||||
SWIFT_INSTALL_OBJC_HEADER = NO
|
||||
SWIFT_SKIP_AUTOLINKING_FRAMEWORKS = YES
|
||||
SWIFT_SKIP_AUTOLINKING_LIBRARIES = YES
|
||||
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks
|
||||
LD_RUNPATH_SEARCH_PATHS[sdk=macosx*] = $(inherited) @executable_path/../Frameworks @loader_path/Frameworks
|
||||
|
||||
DYLIB_INSTALL_NAME_BASE = @rpath
|
||||
DYLIB_COMPATIBILITY_VERSION = 1
|
||||
DYLIB_CURRENT_VERSION = 1
|
||||
VERSIONING_SYSTEM =
|
||||
|
|
@ -1,8 +1,5 @@
|
|||
<?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>CFBundleName</key>
|
||||
<string>$(INFOPLIST_KEY_CFBundleDisplayName)</string>
|
||||
</dict>
|
||||
<dict/>
|
||||
</plist>
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
#include "Compiler.xcconfig"
|
||||
|
||||
SUPPORTED_PLATFORMS = iphonesimulator iphoneos
|
||||
TARGETED_DEVICE_FAMILY[sdk=iphone*] = 1,2
|
||||
|
||||
PRODUCT_NAME = $(TARGET_NAME)
|
||||
PRODUCT_BUNDLE_IDENTIFIER = $(APP_BUNDLE_IDENTIFIER).uitests
|
||||
|
||||
STRING_CATALOG_GENERATE_SYMBOLS = NO
|
||||
SWIFT_EMIT_LOC_STRINGS = NO
|
||||
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks
|
||||
TEST_TARGET_NAME = App
|
||||
|
|
@ -1,508 +0,0 @@
|
|||
import Foundation
|
||||
import GRPC
|
||||
import NIOTransportServices
|
||||
import SwiftProtobuf
|
||||
|
||||
public typealias TunnelClient = Burrow_TunnelAsyncClient
|
||||
public typealias NetworksClient = Burrow_NetworksAsyncClient
|
||||
|
||||
public protocol Client {
|
||||
init(channel: GRPCChannel)
|
||||
}
|
||||
|
||||
extension Client {
|
||||
public static func unix(socketURL: URL) -> Self {
|
||||
let group = NIOTSEventLoopGroup()
|
||||
let configuration = ClientConnection.Configuration.default(
|
||||
target: .unixDomainSocket(socketURL.path),
|
||||
eventLoopGroup: group
|
||||
)
|
||||
return Self(channel: ClientConnection(configuration: configuration))
|
||||
}
|
||||
}
|
||||
|
||||
extension TunnelClient: Client {
|
||||
public init(channel: any GRPCChannel) {
|
||||
self.init(channel: channel, defaultCallOptions: .init(), interceptors: .none)
|
||||
}
|
||||
}
|
||||
|
||||
extension NetworksClient: Client {
|
||||
public init(channel: any GRPCChannel) {
|
||||
self.init(channel: channel, defaultCallOptions: .init(), interceptors: .none)
|
||||
}
|
||||
}
|
||||
|
||||
public struct Burrow_TailnetDiscoverRequest: Sendable {
|
||||
public var email: String = ""
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct Burrow_TailnetDiscoverResponse: Sendable {
|
||||
public var domain: String = ""
|
||||
public var authority: String = ""
|
||||
public var oidcIssuer: String = ""
|
||||
public var managed: Bool = false
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct Burrow_TailnetProbeRequest: Sendable {
|
||||
public var authority: String = ""
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct Burrow_TailnetProbeResponse: Sendable {
|
||||
public var authority: String = ""
|
||||
public var statusCode: Int32 = 0
|
||||
public var summary: String = ""
|
||||
public var detail: String = ""
|
||||
public var reachable: Bool = false
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct Burrow_TailnetLoginStartRequest: Sendable {
|
||||
public var accountName: String = ""
|
||||
public var identityName: String = ""
|
||||
public var hostname: String = ""
|
||||
public var authority: String = ""
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct Burrow_TailnetLoginStatusRequest: Sendable {
|
||||
public var sessionID: String = ""
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct Burrow_TailnetLoginCancelRequest: Sendable {
|
||||
public var sessionID: String = ""
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct Burrow_TailnetLoginStatusResponse: Sendable {
|
||||
public var sessionID: String = ""
|
||||
public var backendState: String = ""
|
||||
public var authURL: String = ""
|
||||
public var running: Bool = false
|
||||
public var needsLogin: Bool = false
|
||||
public var tailnetName: String = ""
|
||||
public var magicDNSSuffix: String = ""
|
||||
public var selfDNSName: String = ""
|
||||
public var tailnetIPs: [String] = []
|
||||
public var health: [String] = []
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct Burrow_TunnelPacket: Sendable {
|
||||
public var payload = Data()
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
extension Burrow_TailnetDiscoverRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = "burrow.TailnetDiscoverRequest"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "email")
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
switch fieldNumber {
|
||||
case 1: try decoder.decodeSingularStringField(value: &self.email)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if !self.email.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.email, fieldNumber: 1)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_TailnetDiscoverResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = "burrow.TailnetDiscoverResponse"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "domain"),
|
||||
2: .same(proto: "authority"),
|
||||
3: .same(proto: "oidc_issuer"),
|
||||
4: .same(proto: "managed"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
switch fieldNumber {
|
||||
case 1: try decoder.decodeSingularStringField(value: &self.domain)
|
||||
case 2: try decoder.decodeSingularStringField(value: &self.authority)
|
||||
case 3: try decoder.decodeSingularStringField(value: &self.oidcIssuer)
|
||||
case 4: try decoder.decodeSingularBoolField(value: &self.managed)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if !self.domain.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.domain, fieldNumber: 1)
|
||||
}
|
||||
if !self.authority.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.authority, fieldNumber: 2)
|
||||
}
|
||||
if !self.oidcIssuer.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.oidcIssuer, fieldNumber: 3)
|
||||
}
|
||||
if self.managed {
|
||||
try visitor.visitSingularBoolField(value: self.managed, fieldNumber: 4)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_TailnetProbeRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = "burrow.TailnetProbeRequest"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "authority")
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
switch fieldNumber {
|
||||
case 1: try decoder.decodeSingularStringField(value: &self.authority)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if !self.authority.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.authority, fieldNumber: 1)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_TailnetProbeResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = "burrow.TailnetProbeResponse"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "authority"),
|
||||
2: .same(proto: "status_code"),
|
||||
3: .same(proto: "summary"),
|
||||
4: .same(proto: "detail"),
|
||||
5: .same(proto: "reachable"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
switch fieldNumber {
|
||||
case 1: try decoder.decodeSingularStringField(value: &self.authority)
|
||||
case 2: try decoder.decodeSingularInt32Field(value: &self.statusCode)
|
||||
case 3: try decoder.decodeSingularStringField(value: &self.summary)
|
||||
case 4: try decoder.decodeSingularStringField(value: &self.detail)
|
||||
case 5: try decoder.decodeSingularBoolField(value: &self.reachable)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if !self.authority.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.authority, fieldNumber: 1)
|
||||
}
|
||||
if self.statusCode != 0 {
|
||||
try visitor.visitSingularInt32Field(value: self.statusCode, fieldNumber: 2)
|
||||
}
|
||||
if !self.summary.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.summary, fieldNumber: 3)
|
||||
}
|
||||
if !self.detail.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.detail, fieldNumber: 4)
|
||||
}
|
||||
if self.reachable {
|
||||
try visitor.visitSingularBoolField(value: self.reachable, fieldNumber: 5)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_TailnetLoginStartRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = "burrow.TailnetLoginStartRequest"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .standard(proto: "account_name"),
|
||||
2: .standard(proto: "identity_name"),
|
||||
3: .same(proto: "hostname"),
|
||||
4: .same(proto: "authority"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
switch fieldNumber {
|
||||
case 1: try decoder.decodeSingularStringField(value: &self.accountName)
|
||||
case 2: try decoder.decodeSingularStringField(value: &self.identityName)
|
||||
case 3: try decoder.decodeSingularStringField(value: &self.hostname)
|
||||
case 4: try decoder.decodeSingularStringField(value: &self.authority)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if !self.accountName.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.accountName, fieldNumber: 1)
|
||||
}
|
||||
if !self.identityName.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.identityName, fieldNumber: 2)
|
||||
}
|
||||
if !self.hostname.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.hostname, fieldNumber: 3)
|
||||
}
|
||||
if !self.authority.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.authority, fieldNumber: 4)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_TailnetLoginStatusRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = "burrow.TailnetLoginStatusRequest"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .standard(proto: "session_id")
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
switch fieldNumber {
|
||||
case 1: try decoder.decodeSingularStringField(value: &self.sessionID)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if !self.sessionID.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.sessionID, fieldNumber: 1)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_TailnetLoginCancelRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = "burrow.TailnetLoginCancelRequest"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .standard(proto: "session_id")
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
switch fieldNumber {
|
||||
case 1: try decoder.decodeSingularStringField(value: &self.sessionID)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if !self.sessionID.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.sessionID, fieldNumber: 1)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_TailnetLoginStatusResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = "burrow.TailnetLoginStatusResponse"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .standard(proto: "session_id"),
|
||||
2: .standard(proto: "backend_state"),
|
||||
3: .standard(proto: "auth_url"),
|
||||
4: .same(proto: "running"),
|
||||
5: .standard(proto: "needs_login"),
|
||||
6: .standard(proto: "tailnet_name"),
|
||||
7: .standard(proto: "magic_dns_suffix"),
|
||||
8: .standard(proto: "self_dns_name"),
|
||||
9: .standard(proto: "tailnet_ips"),
|
||||
10: .same(proto: "health"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
switch fieldNumber {
|
||||
case 1: try decoder.decodeSingularStringField(value: &self.sessionID)
|
||||
case 2: try decoder.decodeSingularStringField(value: &self.backendState)
|
||||
case 3: try decoder.decodeSingularStringField(value: &self.authURL)
|
||||
case 4: try decoder.decodeSingularBoolField(value: &self.running)
|
||||
case 5: try decoder.decodeSingularBoolField(value: &self.needsLogin)
|
||||
case 6: try decoder.decodeSingularStringField(value: &self.tailnetName)
|
||||
case 7: try decoder.decodeSingularStringField(value: &self.magicDNSSuffix)
|
||||
case 8: try decoder.decodeSingularStringField(value: &self.selfDNSName)
|
||||
case 9: try decoder.decodeRepeatedStringField(value: &self.tailnetIPs)
|
||||
case 10: try decoder.decodeRepeatedStringField(value: &self.health)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if !self.sessionID.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.sessionID, fieldNumber: 1)
|
||||
}
|
||||
if !self.backendState.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.backendState, fieldNumber: 2)
|
||||
}
|
||||
if !self.authURL.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.authURL, fieldNumber: 3)
|
||||
}
|
||||
if self.running {
|
||||
try visitor.visitSingularBoolField(value: self.running, fieldNumber: 4)
|
||||
}
|
||||
if self.needsLogin {
|
||||
try visitor.visitSingularBoolField(value: self.needsLogin, fieldNumber: 5)
|
||||
}
|
||||
if !self.tailnetName.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.tailnetName, fieldNumber: 6)
|
||||
}
|
||||
if !self.magicDNSSuffix.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.magicDNSSuffix, fieldNumber: 7)
|
||||
}
|
||||
if !self.selfDNSName.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.selfDNSName, fieldNumber: 8)
|
||||
}
|
||||
if !self.tailnetIPs.isEmpty {
|
||||
try visitor.visitRepeatedStringField(value: self.tailnetIPs, fieldNumber: 9)
|
||||
}
|
||||
if !self.health.isEmpty {
|
||||
try visitor.visitRepeatedStringField(value: self.health, fieldNumber: 10)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_TunnelPacket: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = "burrow.TunnelPacket"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "payload")
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
switch fieldNumber {
|
||||
case 1: try decoder.decodeSingularBytesField(value: &self.payload)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if !self.payload.isEmpty {
|
||||
try visitor.visitSingularBytesField(value: self.payload, fieldNumber: 1)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
}
|
||||
|
||||
public struct TailnetClient: Client, GRPCClient {
|
||||
public let channel: GRPCChannel
|
||||
public var defaultCallOptions: CallOptions
|
||||
|
||||
public init(channel: any GRPCChannel) {
|
||||
self.channel = channel
|
||||
self.defaultCallOptions = .init()
|
||||
}
|
||||
|
||||
public func discover(
|
||||
_ request: Burrow_TailnetDiscoverRequest,
|
||||
callOptions: CallOptions? = nil
|
||||
) async throws -> Burrow_TailnetDiscoverResponse {
|
||||
try await self.performAsyncUnaryCall(
|
||||
path: "/burrow.TailnetControl/Discover",
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: []
|
||||
)
|
||||
}
|
||||
|
||||
public func probe(
|
||||
_ request: Burrow_TailnetProbeRequest,
|
||||
callOptions: CallOptions? = nil
|
||||
) async throws -> Burrow_TailnetProbeResponse {
|
||||
try await self.performAsyncUnaryCall(
|
||||
path: "/burrow.TailnetControl/Probe",
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: []
|
||||
)
|
||||
}
|
||||
|
||||
public func loginStart(
|
||||
_ request: Burrow_TailnetLoginStartRequest,
|
||||
callOptions: CallOptions? = nil
|
||||
) async throws -> Burrow_TailnetLoginStatusResponse {
|
||||
try await self.performAsyncUnaryCall(
|
||||
path: "/burrow.TailnetControl/LoginStart",
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: []
|
||||
)
|
||||
}
|
||||
|
||||
public func loginStatus(
|
||||
_ request: Burrow_TailnetLoginStatusRequest,
|
||||
callOptions: CallOptions? = nil
|
||||
) async throws -> Burrow_TailnetLoginStatusResponse {
|
||||
try await self.performAsyncUnaryCall(
|
||||
path: "/burrow.TailnetControl/LoginStatus",
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: []
|
||||
)
|
||||
}
|
||||
|
||||
public func loginCancel(
|
||||
_ request: Burrow_TailnetLoginCancelRequest,
|
||||
callOptions: CallOptions? = nil
|
||||
) async throws -> Burrow_Empty {
|
||||
try await self.performAsyncUnaryCall(
|
||||
path: "/burrow.TailnetControl/LoginCancel",
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: []
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public struct TunnelPacketClient: Client, GRPCClient {
|
||||
public let channel: GRPCChannel
|
||||
public var defaultCallOptions: CallOptions
|
||||
|
||||
public init(channel: any GRPCChannel) {
|
||||
self.channel = channel
|
||||
self.defaultCallOptions = .init()
|
||||
}
|
||||
|
||||
public func makeTunnelPacketsCall(
|
||||
callOptions: CallOptions? = nil
|
||||
) -> GRPCAsyncBidirectionalStreamingCall<Burrow_TunnelPacket, Burrow_TunnelPacket> {
|
||||
self.makeAsyncBidirectionalStreamingCall(
|
||||
path: "/burrow.Tunnel/TunnelPackets",
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: []
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,761 +0,0 @@
|
|||
//
|
||||
// DO NOT EDIT.
|
||||
// swift-format-ignore-file
|
||||
//
|
||||
// Generated by the protocol buffer compiler.
|
||||
// Source: burrow.proto
|
||||
//
|
||||
import GRPC
|
||||
import NIO
|
||||
import NIOConcurrencyHelpers
|
||||
import SwiftProtobuf
|
||||
|
||||
|
||||
/// Usage: instantiate `Burrow_TunnelClient`, then call methods of this protocol to make API calls.
|
||||
public protocol Burrow_TunnelClientProtocol: GRPCClient {
|
||||
var serviceName: String { get }
|
||||
var interceptors: Burrow_TunnelClientInterceptorFactoryProtocol? { get }
|
||||
|
||||
func tunnelConfiguration(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions?,
|
||||
handler: @escaping (Burrow_TunnelConfigurationResponse) -> Void
|
||||
) -> ServerStreamingCall<Burrow_Empty, Burrow_TunnelConfigurationResponse>
|
||||
|
||||
func tunnelStart(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions?
|
||||
) -> UnaryCall<Burrow_Empty, Burrow_Empty>
|
||||
|
||||
func tunnelStop(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions?
|
||||
) -> UnaryCall<Burrow_Empty, Burrow_Empty>
|
||||
|
||||
func tunnelStatus(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions?,
|
||||
handler: @escaping (Burrow_TunnelStatusResponse) -> Void
|
||||
) -> ServerStreamingCall<Burrow_Empty, Burrow_TunnelStatusResponse>
|
||||
}
|
||||
|
||||
extension Burrow_TunnelClientProtocol {
|
||||
public var serviceName: String {
|
||||
return "burrow.Tunnel"
|
||||
}
|
||||
|
||||
/// Server streaming call to TunnelConfiguration
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - request: Request to send to TunnelConfiguration.
|
||||
/// - callOptions: Call options.
|
||||
/// - handler: A closure called when each response is received from the server.
|
||||
/// - Returns: A `ServerStreamingCall` with futures for the metadata and status.
|
||||
public func tunnelConfiguration(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil,
|
||||
handler: @escaping (Burrow_TunnelConfigurationResponse) -> Void
|
||||
) -> ServerStreamingCall<Burrow_Empty, Burrow_TunnelConfigurationResponse> {
|
||||
return self.makeServerStreamingCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelConfiguration.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelConfigurationInterceptors() ?? [],
|
||||
handler: handler
|
||||
)
|
||||
}
|
||||
|
||||
/// Unary call to TunnelStart
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - request: Request to send to TunnelStart.
|
||||
/// - callOptions: Call options.
|
||||
/// - Returns: A `UnaryCall` with futures for the metadata, status and response.
|
||||
public func tunnelStart(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> UnaryCall<Burrow_Empty, Burrow_Empty> {
|
||||
return self.makeUnaryCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelStart.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelStartInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
/// Unary call to TunnelStop
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - request: Request to send to TunnelStop.
|
||||
/// - callOptions: Call options.
|
||||
/// - Returns: A `UnaryCall` with futures for the metadata, status and response.
|
||||
public func tunnelStop(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> UnaryCall<Burrow_Empty, Burrow_Empty> {
|
||||
return self.makeUnaryCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelStop.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelStopInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
/// Server streaming call to TunnelStatus
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - request: Request to send to TunnelStatus.
|
||||
/// - callOptions: Call options.
|
||||
/// - handler: A closure called when each response is received from the server.
|
||||
/// - Returns: A `ServerStreamingCall` with futures for the metadata and status.
|
||||
public func tunnelStatus(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil,
|
||||
handler: @escaping (Burrow_TunnelStatusResponse) -> Void
|
||||
) -> ServerStreamingCall<Burrow_Empty, Burrow_TunnelStatusResponse> {
|
||||
return self.makeServerStreamingCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelStatus.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelStatusInterceptors() ?? [],
|
||||
handler: handler
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@available(*, deprecated)
|
||||
extension Burrow_TunnelClient: @unchecked Sendable {}
|
||||
|
||||
@available(*, deprecated, renamed: "Burrow_TunnelNIOClient")
|
||||
public final class Burrow_TunnelClient: Burrow_TunnelClientProtocol {
|
||||
private let lock = Lock()
|
||||
private var _defaultCallOptions: CallOptions
|
||||
private var _interceptors: Burrow_TunnelClientInterceptorFactoryProtocol?
|
||||
public let channel: GRPCChannel
|
||||
public var defaultCallOptions: CallOptions {
|
||||
get { self.lock.withLock { return self._defaultCallOptions } }
|
||||
set { self.lock.withLockVoid { self._defaultCallOptions = newValue } }
|
||||
}
|
||||
public var interceptors: Burrow_TunnelClientInterceptorFactoryProtocol? {
|
||||
get { self.lock.withLock { return self._interceptors } }
|
||||
set { self.lock.withLockVoid { self._interceptors = newValue } }
|
||||
}
|
||||
|
||||
/// Creates a client for the burrow.Tunnel service.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - channel: `GRPCChannel` to the service host.
|
||||
/// - defaultCallOptions: Options to use for each service call if the user doesn't provide them.
|
||||
/// - interceptors: A factory providing interceptors for each RPC.
|
||||
public init(
|
||||
channel: GRPCChannel,
|
||||
defaultCallOptions: CallOptions = CallOptions(),
|
||||
interceptors: Burrow_TunnelClientInterceptorFactoryProtocol? = nil
|
||||
) {
|
||||
self.channel = channel
|
||||
self._defaultCallOptions = defaultCallOptions
|
||||
self._interceptors = interceptors
|
||||
}
|
||||
}
|
||||
|
||||
public struct Burrow_TunnelNIOClient: Burrow_TunnelClientProtocol {
|
||||
public var channel: GRPCChannel
|
||||
public var defaultCallOptions: CallOptions
|
||||
public var interceptors: Burrow_TunnelClientInterceptorFactoryProtocol?
|
||||
|
||||
/// Creates a client for the burrow.Tunnel service.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - channel: `GRPCChannel` to the service host.
|
||||
/// - defaultCallOptions: Options to use for each service call if the user doesn't provide them.
|
||||
/// - interceptors: A factory providing interceptors for each RPC.
|
||||
public init(
|
||||
channel: GRPCChannel,
|
||||
defaultCallOptions: CallOptions = CallOptions(),
|
||||
interceptors: Burrow_TunnelClientInterceptorFactoryProtocol? = nil
|
||||
) {
|
||||
self.channel = channel
|
||||
self.defaultCallOptions = defaultCallOptions
|
||||
self.interceptors = interceptors
|
||||
}
|
||||
}
|
||||
|
||||
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
|
||||
public protocol Burrow_TunnelAsyncClientProtocol: GRPCClient {
|
||||
static var serviceDescriptor: GRPCServiceDescriptor { get }
|
||||
var interceptors: Burrow_TunnelClientInterceptorFactoryProtocol? { get }
|
||||
|
||||
func makeTunnelConfigurationCall(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions?
|
||||
) -> GRPCAsyncServerStreamingCall<Burrow_Empty, Burrow_TunnelConfigurationResponse>
|
||||
|
||||
func makeTunnelStartCall(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions?
|
||||
) -> GRPCAsyncUnaryCall<Burrow_Empty, Burrow_Empty>
|
||||
|
||||
func makeTunnelStopCall(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions?
|
||||
) -> GRPCAsyncUnaryCall<Burrow_Empty, Burrow_Empty>
|
||||
|
||||
func makeTunnelStatusCall(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions?
|
||||
) -> GRPCAsyncServerStreamingCall<Burrow_Empty, Burrow_TunnelStatusResponse>
|
||||
}
|
||||
|
||||
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
|
||||
extension Burrow_TunnelAsyncClientProtocol {
|
||||
public static var serviceDescriptor: GRPCServiceDescriptor {
|
||||
return Burrow_TunnelClientMetadata.serviceDescriptor
|
||||
}
|
||||
|
||||
public var interceptors: Burrow_TunnelClientInterceptorFactoryProtocol? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public func makeTunnelConfigurationCall(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> GRPCAsyncServerStreamingCall<Burrow_Empty, Burrow_TunnelConfigurationResponse> {
|
||||
return self.makeAsyncServerStreamingCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelConfiguration.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelConfigurationInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func makeTunnelStartCall(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> GRPCAsyncUnaryCall<Burrow_Empty, Burrow_Empty> {
|
||||
return self.makeAsyncUnaryCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelStart.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelStartInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func makeTunnelStopCall(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> GRPCAsyncUnaryCall<Burrow_Empty, Burrow_Empty> {
|
||||
return self.makeAsyncUnaryCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelStop.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelStopInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func makeTunnelStatusCall(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> GRPCAsyncServerStreamingCall<Burrow_Empty, Burrow_TunnelStatusResponse> {
|
||||
return self.makeAsyncServerStreamingCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelStatus.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelStatusInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
|
||||
extension Burrow_TunnelAsyncClientProtocol {
|
||||
public func tunnelConfiguration(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> GRPCAsyncResponseStream<Burrow_TunnelConfigurationResponse> {
|
||||
return self.performAsyncServerStreamingCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelConfiguration.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelConfigurationInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func tunnelStart(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) async throws -> Burrow_Empty {
|
||||
return try await self.performAsyncUnaryCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelStart.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelStartInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func tunnelStop(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) async throws -> Burrow_Empty {
|
||||
return try await self.performAsyncUnaryCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelStop.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelStopInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func tunnelStatus(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> GRPCAsyncResponseStream<Burrow_TunnelStatusResponse> {
|
||||
return self.performAsyncServerStreamingCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelStatus.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelStatusInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
|
||||
public struct Burrow_TunnelAsyncClient: Burrow_TunnelAsyncClientProtocol {
|
||||
public var channel: GRPCChannel
|
||||
public var defaultCallOptions: CallOptions
|
||||
public var interceptors: Burrow_TunnelClientInterceptorFactoryProtocol?
|
||||
|
||||
public init(
|
||||
channel: GRPCChannel,
|
||||
defaultCallOptions: CallOptions = CallOptions(),
|
||||
interceptors: Burrow_TunnelClientInterceptorFactoryProtocol? = nil
|
||||
) {
|
||||
self.channel = channel
|
||||
self.defaultCallOptions = defaultCallOptions
|
||||
self.interceptors = interceptors
|
||||
}
|
||||
}
|
||||
|
||||
public protocol Burrow_TunnelClientInterceptorFactoryProtocol: Sendable {
|
||||
|
||||
/// - Returns: Interceptors to use when invoking 'tunnelConfiguration'.
|
||||
func makeTunnelConfigurationInterceptors() -> [ClientInterceptor<Burrow_Empty, Burrow_TunnelConfigurationResponse>]
|
||||
|
||||
/// - Returns: Interceptors to use when invoking 'tunnelStart'.
|
||||
func makeTunnelStartInterceptors() -> [ClientInterceptor<Burrow_Empty, Burrow_Empty>]
|
||||
|
||||
/// - Returns: Interceptors to use when invoking 'tunnelStop'.
|
||||
func makeTunnelStopInterceptors() -> [ClientInterceptor<Burrow_Empty, Burrow_Empty>]
|
||||
|
||||
/// - Returns: Interceptors to use when invoking 'tunnelStatus'.
|
||||
func makeTunnelStatusInterceptors() -> [ClientInterceptor<Burrow_Empty, Burrow_TunnelStatusResponse>]
|
||||
}
|
||||
|
||||
public enum Burrow_TunnelClientMetadata {
|
||||
public static let serviceDescriptor = GRPCServiceDescriptor(
|
||||
name: "Tunnel",
|
||||
fullName: "burrow.Tunnel",
|
||||
methods: [
|
||||
Burrow_TunnelClientMetadata.Methods.tunnelConfiguration,
|
||||
Burrow_TunnelClientMetadata.Methods.tunnelStart,
|
||||
Burrow_TunnelClientMetadata.Methods.tunnelStop,
|
||||
Burrow_TunnelClientMetadata.Methods.tunnelStatus,
|
||||
]
|
||||
)
|
||||
|
||||
public enum Methods {
|
||||
public static let tunnelConfiguration = GRPCMethodDescriptor(
|
||||
name: "TunnelConfiguration",
|
||||
path: "/burrow.Tunnel/TunnelConfiguration",
|
||||
type: GRPCCallType.serverStreaming
|
||||
)
|
||||
|
||||
public static let tunnelStart = GRPCMethodDescriptor(
|
||||
name: "TunnelStart",
|
||||
path: "/burrow.Tunnel/TunnelStart",
|
||||
type: GRPCCallType.unary
|
||||
)
|
||||
|
||||
public static let tunnelStop = GRPCMethodDescriptor(
|
||||
name: "TunnelStop",
|
||||
path: "/burrow.Tunnel/TunnelStop",
|
||||
type: GRPCCallType.unary
|
||||
)
|
||||
|
||||
public static let tunnelStatus = GRPCMethodDescriptor(
|
||||
name: "TunnelStatus",
|
||||
path: "/burrow.Tunnel/TunnelStatus",
|
||||
type: GRPCCallType.serverStreaming
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Usage: instantiate `Burrow_NetworksClient`, then call methods of this protocol to make API calls.
|
||||
public protocol Burrow_NetworksClientProtocol: GRPCClient {
|
||||
var serviceName: String { get }
|
||||
var interceptors: Burrow_NetworksClientInterceptorFactoryProtocol? { get }
|
||||
|
||||
func networkAdd(
|
||||
_ request: Burrow_Network,
|
||||
callOptions: CallOptions?
|
||||
) -> UnaryCall<Burrow_Network, Burrow_Empty>
|
||||
|
||||
func networkList(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions?,
|
||||
handler: @escaping (Burrow_NetworkListResponse) -> Void
|
||||
) -> ServerStreamingCall<Burrow_Empty, Burrow_NetworkListResponse>
|
||||
|
||||
func networkReorder(
|
||||
_ request: Burrow_NetworkReorderRequest,
|
||||
callOptions: CallOptions?
|
||||
) -> UnaryCall<Burrow_NetworkReorderRequest, Burrow_Empty>
|
||||
|
||||
func networkDelete(
|
||||
_ request: Burrow_NetworkDeleteRequest,
|
||||
callOptions: CallOptions?
|
||||
) -> UnaryCall<Burrow_NetworkDeleteRequest, Burrow_Empty>
|
||||
}
|
||||
|
||||
extension Burrow_NetworksClientProtocol {
|
||||
public var serviceName: String {
|
||||
return "burrow.Networks"
|
||||
}
|
||||
|
||||
/// Unary call to NetworkAdd
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - request: Request to send to NetworkAdd.
|
||||
/// - callOptions: Call options.
|
||||
/// - Returns: A `UnaryCall` with futures for the metadata, status and response.
|
||||
public func networkAdd(
|
||||
_ request: Burrow_Network,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> UnaryCall<Burrow_Network, Burrow_Empty> {
|
||||
return self.makeUnaryCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkAdd.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkAddInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
/// Server streaming call to NetworkList
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - request: Request to send to NetworkList.
|
||||
/// - callOptions: Call options.
|
||||
/// - handler: A closure called when each response is received from the server.
|
||||
/// - Returns: A `ServerStreamingCall` with futures for the metadata and status.
|
||||
public func networkList(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil,
|
||||
handler: @escaping (Burrow_NetworkListResponse) -> Void
|
||||
) -> ServerStreamingCall<Burrow_Empty, Burrow_NetworkListResponse> {
|
||||
return self.makeServerStreamingCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkList.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkListInterceptors() ?? [],
|
||||
handler: handler
|
||||
)
|
||||
}
|
||||
|
||||
/// Unary call to NetworkReorder
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - request: Request to send to NetworkReorder.
|
||||
/// - callOptions: Call options.
|
||||
/// - Returns: A `UnaryCall` with futures for the metadata, status and response.
|
||||
public func networkReorder(
|
||||
_ request: Burrow_NetworkReorderRequest,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> UnaryCall<Burrow_NetworkReorderRequest, Burrow_Empty> {
|
||||
return self.makeUnaryCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkReorder.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkReorderInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
/// Unary call to NetworkDelete
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - request: Request to send to NetworkDelete.
|
||||
/// - callOptions: Call options.
|
||||
/// - Returns: A `UnaryCall` with futures for the metadata, status and response.
|
||||
public func networkDelete(
|
||||
_ request: Burrow_NetworkDeleteRequest,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> UnaryCall<Burrow_NetworkDeleteRequest, Burrow_Empty> {
|
||||
return self.makeUnaryCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkDelete.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkDeleteInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@available(*, deprecated)
|
||||
extension Burrow_NetworksClient: @unchecked Sendable {}
|
||||
|
||||
@available(*, deprecated, renamed: "Burrow_NetworksNIOClient")
|
||||
public final class Burrow_NetworksClient: Burrow_NetworksClientProtocol {
|
||||
private let lock = Lock()
|
||||
private var _defaultCallOptions: CallOptions
|
||||
private var _interceptors: Burrow_NetworksClientInterceptorFactoryProtocol?
|
||||
public let channel: GRPCChannel
|
||||
public var defaultCallOptions: CallOptions {
|
||||
get { self.lock.withLock { return self._defaultCallOptions } }
|
||||
set { self.lock.withLockVoid { self._defaultCallOptions = newValue } }
|
||||
}
|
||||
public var interceptors: Burrow_NetworksClientInterceptorFactoryProtocol? {
|
||||
get { self.lock.withLock { return self._interceptors } }
|
||||
set { self.lock.withLockVoid { self._interceptors = newValue } }
|
||||
}
|
||||
|
||||
/// Creates a client for the burrow.Networks service.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - channel: `GRPCChannel` to the service host.
|
||||
/// - defaultCallOptions: Options to use for each service call if the user doesn't provide them.
|
||||
/// - interceptors: A factory providing interceptors for each RPC.
|
||||
public init(
|
||||
channel: GRPCChannel,
|
||||
defaultCallOptions: CallOptions = CallOptions(),
|
||||
interceptors: Burrow_NetworksClientInterceptorFactoryProtocol? = nil
|
||||
) {
|
||||
self.channel = channel
|
||||
self._defaultCallOptions = defaultCallOptions
|
||||
self._interceptors = interceptors
|
||||
}
|
||||
}
|
||||
|
||||
public struct Burrow_NetworksNIOClient: Burrow_NetworksClientProtocol {
|
||||
public var channel: GRPCChannel
|
||||
public var defaultCallOptions: CallOptions
|
||||
public var interceptors: Burrow_NetworksClientInterceptorFactoryProtocol?
|
||||
|
||||
/// Creates a client for the burrow.Networks service.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - channel: `GRPCChannel` to the service host.
|
||||
/// - defaultCallOptions: Options to use for each service call if the user doesn't provide them.
|
||||
/// - interceptors: A factory providing interceptors for each RPC.
|
||||
public init(
|
||||
channel: GRPCChannel,
|
||||
defaultCallOptions: CallOptions = CallOptions(),
|
||||
interceptors: Burrow_NetworksClientInterceptorFactoryProtocol? = nil
|
||||
) {
|
||||
self.channel = channel
|
||||
self.defaultCallOptions = defaultCallOptions
|
||||
self.interceptors = interceptors
|
||||
}
|
||||
}
|
||||
|
||||
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
|
||||
public protocol Burrow_NetworksAsyncClientProtocol: GRPCClient {
|
||||
static var serviceDescriptor: GRPCServiceDescriptor { get }
|
||||
var interceptors: Burrow_NetworksClientInterceptorFactoryProtocol? { get }
|
||||
|
||||
func makeNetworkAddCall(
|
||||
_ request: Burrow_Network,
|
||||
callOptions: CallOptions?
|
||||
) -> GRPCAsyncUnaryCall<Burrow_Network, Burrow_Empty>
|
||||
|
||||
func makeNetworkListCall(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions?
|
||||
) -> GRPCAsyncServerStreamingCall<Burrow_Empty, Burrow_NetworkListResponse>
|
||||
|
||||
func makeNetworkReorderCall(
|
||||
_ request: Burrow_NetworkReorderRequest,
|
||||
callOptions: CallOptions?
|
||||
) -> GRPCAsyncUnaryCall<Burrow_NetworkReorderRequest, Burrow_Empty>
|
||||
|
||||
func makeNetworkDeleteCall(
|
||||
_ request: Burrow_NetworkDeleteRequest,
|
||||
callOptions: CallOptions?
|
||||
) -> GRPCAsyncUnaryCall<Burrow_NetworkDeleteRequest, Burrow_Empty>
|
||||
}
|
||||
|
||||
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
|
||||
extension Burrow_NetworksAsyncClientProtocol {
|
||||
public static var serviceDescriptor: GRPCServiceDescriptor {
|
||||
return Burrow_NetworksClientMetadata.serviceDescriptor
|
||||
}
|
||||
|
||||
public var interceptors: Burrow_NetworksClientInterceptorFactoryProtocol? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public func makeNetworkAddCall(
|
||||
_ request: Burrow_Network,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> GRPCAsyncUnaryCall<Burrow_Network, Burrow_Empty> {
|
||||
return self.makeAsyncUnaryCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkAdd.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkAddInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func makeNetworkListCall(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> GRPCAsyncServerStreamingCall<Burrow_Empty, Burrow_NetworkListResponse> {
|
||||
return self.makeAsyncServerStreamingCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkList.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkListInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func makeNetworkReorderCall(
|
||||
_ request: Burrow_NetworkReorderRequest,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> GRPCAsyncUnaryCall<Burrow_NetworkReorderRequest, Burrow_Empty> {
|
||||
return self.makeAsyncUnaryCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkReorder.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkReorderInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func makeNetworkDeleteCall(
|
||||
_ request: Burrow_NetworkDeleteRequest,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> GRPCAsyncUnaryCall<Burrow_NetworkDeleteRequest, Burrow_Empty> {
|
||||
return self.makeAsyncUnaryCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkDelete.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkDeleteInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
|
||||
extension Burrow_NetworksAsyncClientProtocol {
|
||||
public func networkAdd(
|
||||
_ request: Burrow_Network,
|
||||
callOptions: CallOptions? = nil
|
||||
) async throws -> Burrow_Empty {
|
||||
return try await self.performAsyncUnaryCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkAdd.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkAddInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func networkList(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> GRPCAsyncResponseStream<Burrow_NetworkListResponse> {
|
||||
return self.performAsyncServerStreamingCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkList.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkListInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func networkReorder(
|
||||
_ request: Burrow_NetworkReorderRequest,
|
||||
callOptions: CallOptions? = nil
|
||||
) async throws -> Burrow_Empty {
|
||||
return try await self.performAsyncUnaryCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkReorder.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkReorderInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func networkDelete(
|
||||
_ request: Burrow_NetworkDeleteRequest,
|
||||
callOptions: CallOptions? = nil
|
||||
) async throws -> Burrow_Empty {
|
||||
return try await self.performAsyncUnaryCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkDelete.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkDeleteInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
|
||||
public struct Burrow_NetworksAsyncClient: Burrow_NetworksAsyncClientProtocol {
|
||||
public var channel: GRPCChannel
|
||||
public var defaultCallOptions: CallOptions
|
||||
public var interceptors: Burrow_NetworksClientInterceptorFactoryProtocol?
|
||||
|
||||
public init(
|
||||
channel: GRPCChannel,
|
||||
defaultCallOptions: CallOptions = CallOptions(),
|
||||
interceptors: Burrow_NetworksClientInterceptorFactoryProtocol? = nil
|
||||
) {
|
||||
self.channel = channel
|
||||
self.defaultCallOptions = defaultCallOptions
|
||||
self.interceptors = interceptors
|
||||
}
|
||||
}
|
||||
|
||||
public protocol Burrow_NetworksClientInterceptorFactoryProtocol: Sendable {
|
||||
|
||||
/// - Returns: Interceptors to use when invoking 'networkAdd'.
|
||||
func makeNetworkAddInterceptors() -> [ClientInterceptor<Burrow_Network, Burrow_Empty>]
|
||||
|
||||
/// - Returns: Interceptors to use when invoking 'networkList'.
|
||||
func makeNetworkListInterceptors() -> [ClientInterceptor<Burrow_Empty, Burrow_NetworkListResponse>]
|
||||
|
||||
/// - Returns: Interceptors to use when invoking 'networkReorder'.
|
||||
func makeNetworkReorderInterceptors() -> [ClientInterceptor<Burrow_NetworkReorderRequest, Burrow_Empty>]
|
||||
|
||||
/// - Returns: Interceptors to use when invoking 'networkDelete'.
|
||||
func makeNetworkDeleteInterceptors() -> [ClientInterceptor<Burrow_NetworkDeleteRequest, Burrow_Empty>]
|
||||
}
|
||||
|
||||
public enum Burrow_NetworksClientMetadata {
|
||||
public static let serviceDescriptor = GRPCServiceDescriptor(
|
||||
name: "Networks",
|
||||
fullName: "burrow.Networks",
|
||||
methods: [
|
||||
Burrow_NetworksClientMetadata.Methods.networkAdd,
|
||||
Burrow_NetworksClientMetadata.Methods.networkList,
|
||||
Burrow_NetworksClientMetadata.Methods.networkReorder,
|
||||
Burrow_NetworksClientMetadata.Methods.networkDelete,
|
||||
]
|
||||
)
|
||||
|
||||
public enum Methods {
|
||||
public static let networkAdd = GRPCMethodDescriptor(
|
||||
name: "NetworkAdd",
|
||||
path: "/burrow.Networks/NetworkAdd",
|
||||
type: GRPCCallType.unary
|
||||
)
|
||||
|
||||
public static let networkList = GRPCMethodDescriptor(
|
||||
name: "NetworkList",
|
||||
path: "/burrow.Networks/NetworkList",
|
||||
type: GRPCCallType.serverStreaming
|
||||
)
|
||||
|
||||
public static let networkReorder = GRPCMethodDescriptor(
|
||||
name: "NetworkReorder",
|
||||
path: "/burrow.Networks/NetworkReorder",
|
||||
type: GRPCCallType.unary
|
||||
)
|
||||
|
||||
public static let networkDelete = GRPCMethodDescriptor(
|
||||
name: "NetworkDelete",
|
||||
path: "/burrow.Networks/NetworkDelete",
|
||||
type: GRPCCallType.unary
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,598 +0,0 @@
|
|||
// DO NOT EDIT.
|
||||
// swift-format-ignore-file
|
||||
// swiftlint:disable all
|
||||
//
|
||||
// Generated by the Swift generator plugin for the protocol buffer compiler.
|
||||
// Source: burrow.proto
|
||||
//
|
||||
// For information on using the generated types, please see the documentation:
|
||||
// https://github.com/apple/swift-protobuf/
|
||||
|
||||
import Foundation
|
||||
import SwiftProtobuf
|
||||
|
||||
// If the compiler emits an error on this type, it is because this file
|
||||
// was generated by a version of the `protoc` Swift plug-in that is
|
||||
// incompatible with the version of SwiftProtobuf to which you are linking.
|
||||
// Please ensure that you are building against the same version of the API
|
||||
// that was used to generate this file.
|
||||
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
|
||||
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
|
||||
typealias Version = _2
|
||||
}
|
||||
|
||||
public enum Burrow_NetworkType: SwiftProtobuf.Enum, Swift.CaseIterable {
|
||||
public typealias RawValue = Int
|
||||
case wireGuard // = 0
|
||||
case tailnet // = 1
|
||||
case UNRECOGNIZED(Int)
|
||||
|
||||
public init() {
|
||||
self = .wireGuard
|
||||
}
|
||||
|
||||
public init?(rawValue: Int) {
|
||||
switch rawValue {
|
||||
case 0: self = .wireGuard
|
||||
case 1: self = .tailnet
|
||||
default: self = .UNRECOGNIZED(rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
public var rawValue: Int {
|
||||
switch self {
|
||||
case .wireGuard: return 0
|
||||
case .tailnet: return 1
|
||||
case .UNRECOGNIZED(let i): return i
|
||||
}
|
||||
}
|
||||
|
||||
// The compiler won't synthesize support with the UNRECOGNIZED case.
|
||||
public static let allCases: [Burrow_NetworkType] = [
|
||||
.wireGuard,
|
||||
.tailnet,
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
public enum Burrow_State: SwiftProtobuf.Enum, Swift.CaseIterable {
|
||||
public typealias RawValue = Int
|
||||
case stopped // = 0
|
||||
case running // = 1
|
||||
case UNRECOGNIZED(Int)
|
||||
|
||||
public init() {
|
||||
self = .stopped
|
||||
}
|
||||
|
||||
public init?(rawValue: Int) {
|
||||
switch rawValue {
|
||||
case 0: self = .stopped
|
||||
case 1: self = .running
|
||||
default: self = .UNRECOGNIZED(rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
public var rawValue: Int {
|
||||
switch self {
|
||||
case .stopped: return 0
|
||||
case .running: return 1
|
||||
case .UNRECOGNIZED(let i): return i
|
||||
}
|
||||
}
|
||||
|
||||
// The compiler won't synthesize support with the UNRECOGNIZED case.
|
||||
public static let allCases: [Burrow_State] = [
|
||||
.stopped,
|
||||
.running,
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
public struct Burrow_NetworkReorderRequest: Sendable {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
public var id: Int32 = 0
|
||||
|
||||
public var index: Int32 = 0
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct Burrow_WireGuardPeer: Sendable {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
public var endpoint: String = String()
|
||||
|
||||
public var subnet: [String] = []
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct Burrow_WireGuardNetwork: Sendable {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
public var address: String = String()
|
||||
|
||||
public var dns: String = String()
|
||||
|
||||
public var peer: [Burrow_WireGuardPeer] = []
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct Burrow_NetworkDeleteRequest: Sendable {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
public var id: Int32 = 0
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct Burrow_Network: @unchecked Sendable {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
public var id: Int32 = 0
|
||||
|
||||
public var type: Burrow_NetworkType = .wireGuard
|
||||
|
||||
public var payload: Data = Data()
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct Burrow_NetworkListResponse: Sendable {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
public var network: [Burrow_Network] = []
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct Burrow_Empty: Sendable {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct Burrow_TunnelStatusResponse: Sendable {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
public var state: Burrow_State = .stopped
|
||||
|
||||
public var start: SwiftProtobuf.Google_Protobuf_Timestamp {
|
||||
get {return _start ?? SwiftProtobuf.Google_Protobuf_Timestamp()}
|
||||
set {_start = newValue}
|
||||
}
|
||||
/// Returns true if `start` has been explicitly set.
|
||||
public var hasStart: Bool {return self._start != nil}
|
||||
/// Clears the value of `start`. Subsequent reads from it will return its default value.
|
||||
public mutating func clearStart() {self._start = nil}
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
|
||||
fileprivate var _start: SwiftProtobuf.Google_Protobuf_Timestamp? = nil
|
||||
}
|
||||
|
||||
public struct Burrow_TunnelConfigurationResponse: Sendable {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
public var addresses: [String] = []
|
||||
|
||||
public var mtu: Int32 = 0
|
||||
|
||||
public var routes: [String] = []
|
||||
|
||||
public var dnsServers: [String] = []
|
||||
|
||||
public var searchDomains: [String] = []
|
||||
|
||||
public var includeDefaultRoute: Bool = false
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
// MARK: - Code below here is support for the SwiftProtobuf runtime.
|
||||
|
||||
fileprivate let _protobuf_package = "burrow"
|
||||
|
||||
extension Burrow_NetworkType: SwiftProtobuf._ProtoNameProviding {
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
0: .same(proto: "WireGuard"),
|
||||
1: .same(proto: "Tailnet"),
|
||||
]
|
||||
}
|
||||
|
||||
extension Burrow_State: SwiftProtobuf._ProtoNameProviding {
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
0: .same(proto: "Stopped"),
|
||||
1: .same(proto: "Running"),
|
||||
]
|
||||
}
|
||||
|
||||
extension Burrow_NetworkReorderRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".NetworkReorderRequest"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "id"),
|
||||
2: .same(proto: "index"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularInt32Field(value: &self.id) }()
|
||||
case 2: try { try decoder.decodeSingularInt32Field(value: &self.index) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if self.id != 0 {
|
||||
try visitor.visitSingularInt32Field(value: self.id, fieldNumber: 1)
|
||||
}
|
||||
if self.index != 0 {
|
||||
try visitor.visitSingularInt32Field(value: self.index, fieldNumber: 2)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: Burrow_NetworkReorderRequest, rhs: Burrow_NetworkReorderRequest) -> Bool {
|
||||
if lhs.id != rhs.id {return false}
|
||||
if lhs.index != rhs.index {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_WireGuardPeer: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".WireGuardPeer"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "endpoint"),
|
||||
2: .same(proto: "subnet"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularStringField(value: &self.endpoint) }()
|
||||
case 2: try { try decoder.decodeRepeatedStringField(value: &self.subnet) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if !self.endpoint.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.endpoint, fieldNumber: 1)
|
||||
}
|
||||
if !self.subnet.isEmpty {
|
||||
try visitor.visitRepeatedStringField(value: self.subnet, fieldNumber: 2)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: Burrow_WireGuardPeer, rhs: Burrow_WireGuardPeer) -> Bool {
|
||||
if lhs.endpoint != rhs.endpoint {return false}
|
||||
if lhs.subnet != rhs.subnet {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_WireGuardNetwork: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".WireGuardNetwork"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "address"),
|
||||
2: .same(proto: "dns"),
|
||||
3: .same(proto: "peer"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularStringField(value: &self.address) }()
|
||||
case 2: try { try decoder.decodeSingularStringField(value: &self.dns) }()
|
||||
case 3: try { try decoder.decodeRepeatedMessageField(value: &self.peer) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if !self.address.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.address, fieldNumber: 1)
|
||||
}
|
||||
if !self.dns.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.dns, fieldNumber: 2)
|
||||
}
|
||||
if !self.peer.isEmpty {
|
||||
try visitor.visitRepeatedMessageField(value: self.peer, fieldNumber: 3)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: Burrow_WireGuardNetwork, rhs: Burrow_WireGuardNetwork) -> Bool {
|
||||
if lhs.address != rhs.address {return false}
|
||||
if lhs.dns != rhs.dns {return false}
|
||||
if lhs.peer != rhs.peer {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_NetworkDeleteRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".NetworkDeleteRequest"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "id"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularInt32Field(value: &self.id) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if self.id != 0 {
|
||||
try visitor.visitSingularInt32Field(value: self.id, fieldNumber: 1)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: Burrow_NetworkDeleteRequest, rhs: Burrow_NetworkDeleteRequest) -> Bool {
|
||||
if lhs.id != rhs.id {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_Network: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".Network"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "id"),
|
||||
2: .same(proto: "type"),
|
||||
3: .same(proto: "payload"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularInt32Field(value: &self.id) }()
|
||||
case 2: try { try decoder.decodeSingularEnumField(value: &self.type) }()
|
||||
case 3: try { try decoder.decodeSingularBytesField(value: &self.payload) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if self.id != 0 {
|
||||
try visitor.visitSingularInt32Field(value: self.id, fieldNumber: 1)
|
||||
}
|
||||
if self.type != .wireGuard {
|
||||
try visitor.visitSingularEnumField(value: self.type, fieldNumber: 2)
|
||||
}
|
||||
if !self.payload.isEmpty {
|
||||
try visitor.visitSingularBytesField(value: self.payload, fieldNumber: 3)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: Burrow_Network, rhs: Burrow_Network) -> Bool {
|
||||
if lhs.id != rhs.id {return false}
|
||||
if lhs.type != rhs.type {return false}
|
||||
if lhs.payload != rhs.payload {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_NetworkListResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".NetworkListResponse"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "network"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeRepeatedMessageField(value: &self.network) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if !self.network.isEmpty {
|
||||
try visitor.visitRepeatedMessageField(value: self.network, fieldNumber: 1)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: Burrow_NetworkListResponse, rhs: Burrow_NetworkListResponse) -> Bool {
|
||||
if lhs.network != rhs.network {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_Empty: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".Empty"
|
||||
public static let _protobuf_nameMap = SwiftProtobuf._NameMap()
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
// Load everything into unknown fields
|
||||
while try decoder.nextFieldNumber() != nil {}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: Burrow_Empty, rhs: Burrow_Empty) -> Bool {
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_TunnelStatusResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".TunnelStatusResponse"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "state"),
|
||||
2: .same(proto: "start"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularEnumField(value: &self.state) }()
|
||||
case 2: try { try decoder.decodeSingularMessageField(value: &self._start) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
if self.state != .stopped {
|
||||
try visitor.visitSingularEnumField(value: self.state, fieldNumber: 1)
|
||||
}
|
||||
try { if let v = self._start {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: Burrow_TunnelStatusResponse, rhs: Burrow_TunnelStatusResponse) -> Bool {
|
||||
if lhs.state != rhs.state {return false}
|
||||
if lhs._start != rhs._start {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_TunnelConfigurationResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".TunnelConfigurationResponse"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "addresses"),
|
||||
2: .same(proto: "mtu"),
|
||||
3: .same(proto: "routes"),
|
||||
4: .standard(proto: "dns_servers"),
|
||||
5: .standard(proto: "search_domains"),
|
||||
6: .standard(proto: "include_default_route"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeRepeatedStringField(value: &self.addresses) }()
|
||||
case 2: try { try decoder.decodeSingularInt32Field(value: &self.mtu) }()
|
||||
case 3: try { try decoder.decodeRepeatedStringField(value: &self.routes) }()
|
||||
case 4: try { try decoder.decodeRepeatedStringField(value: &self.dnsServers) }()
|
||||
case 5: try { try decoder.decodeRepeatedStringField(value: &self.searchDomains) }()
|
||||
case 6: try { try decoder.decodeSingularBoolField(value: &self.includeDefaultRoute) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if !self.addresses.isEmpty {
|
||||
try visitor.visitRepeatedStringField(value: self.addresses, fieldNumber: 1)
|
||||
}
|
||||
if self.mtu != 0 {
|
||||
try visitor.visitSingularInt32Field(value: self.mtu, fieldNumber: 2)
|
||||
}
|
||||
if !self.routes.isEmpty {
|
||||
try visitor.visitRepeatedStringField(value: self.routes, fieldNumber: 3)
|
||||
}
|
||||
if !self.dnsServers.isEmpty {
|
||||
try visitor.visitRepeatedStringField(value: self.dnsServers, fieldNumber: 4)
|
||||
}
|
||||
if !self.searchDomains.isEmpty {
|
||||
try visitor.visitRepeatedStringField(value: self.searchDomains, fieldNumber: 5)
|
||||
}
|
||||
if self.includeDefaultRoute {
|
||||
try visitor.visitSingularBoolField(value: self.includeDefaultRoute, fieldNumber: 6)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: Burrow_TunnelConfigurationResponse, rhs: Burrow_TunnelConfigurationResponse) -> Bool {
|
||||
if lhs.addresses != rhs.addresses {return false}
|
||||
if lhs.mtu != rhs.mtu {return false}
|
||||
if lhs.routes != rhs.routes {return false}
|
||||
if lhs.dnsServers != rhs.dnsServers {return false}
|
||||
if lhs.searchDomains != rhs.searchDomains {return false}
|
||||
if lhs.includeDefaultRoute != rhs.includeDefaultRoute {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
../../../proto/burrow.proto
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.protobuf;
|
||||
|
||||
option cc_enable_arenas = true;
|
||||
option go_package = "google.golang.org/protobuf/types/known/timestamppb";
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "TimestampProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
|
||||
// A Timestamp represents a point in time independent of any time zone or local
|
||||
// calendar, encoded as a count of seconds and fractions of seconds at
|
||||
// nanosecond resolution. The count is relative to an epoch at UTC midnight on
|
||||
// January 1, 1970, in the proleptic Gregorian calendar which extends the
|
||||
// Gregorian calendar backwards to year one.
|
||||
//
|
||||
// All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap
|
||||
// second table is needed for interpretation, using a 24-hour linear smear.
|
||||
//
|
||||
// The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By
|
||||
// restricting to that range, we ensure that we can convert to and from RFC
|
||||
// 3339 date strings.
|
||||
message Timestamp {
|
||||
// Represents seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z.
|
||||
// Must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive.
|
||||
int64 seconds = 1;
|
||||
|
||||
// Non-negative fractions of a second at nanosecond resolution. Negative
|
||||
// second values with fractions must still have non-negative nanos values
|
||||
// that count forward in time. Must be from 0 to 999,999,999 inclusive.
|
||||
int32 nanos = 2;
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
import os
|
||||
@_exported import OSLog
|
||||
|
||||
extension Logger {
|
||||
private static let loggers: OSAllocatedUnfairLock<[String: Logger]> = OSAllocatedUnfairLock(initialState: [:])
|
||||
|
||||
public dynamic static var subsystem: String { "com.hackclub.burrow" }
|
||||
|
||||
public static func logger(for type: Any.Type) -> Logger {
|
||||
let category = String(describing: type)
|
||||
let logger = loggers.withLock { loggers in
|
||||
if let logger = loggers[category] { return logger }
|
||||
let logger = Logger(subsystem: subsystem, category: category)
|
||||
loggers[category] = logger
|
||||
return logger
|
||||
}
|
||||
return logger
|
||||
}
|
||||
}
|
||||
|
|
@ -2,8 +2,6 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(INFOPLIST_KEY_CFBundleDisplayName)</string>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionPointIdentifier</key>
|
||||
|
|
|
|||
|
|
@ -6,15 +6,9 @@
|
|||
<array>
|
||||
<string>packet-tunnel-provider</string>
|
||||
</array>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>$(APP_GROUP_IDENTIFIER)</string>
|
||||
<string>group.com.hackclub.burrow</string>
|
||||
</array>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,6 @@ PRODUCT_BUNDLE_IDENTIFIER = $(NETWORK_EXTENSION_BUNDLE_IDENTIFIER)
|
|||
INFOPLIST_FILE = NetworkExtension/Info.plist
|
||||
|
||||
CODE_SIGN_ENTITLEMENTS = NetworkExtension/NetworkExtension-iOS.entitlements
|
||||
CODE_SIGN_ENTITLEMENTS[sdk=macosx*] = NetworkExtension/NetworkExtension-macOS.entitlements
|
||||
CODE_SIGN_ENTITLEMENTS[sdk=macos*] = NetworkExtension/NetworkExtension-macOS.entitlements
|
||||
|
||||
SWIFT_INCLUDE_PATHS = $(inherited) $(PROJECT_DIR)/NetworkExtension
|
||||
|
|
|
|||
|
|
@ -1,326 +1,24 @@
|
|||
import AsyncAlgorithms
|
||||
import BurrowConfiguration
|
||||
import BurrowCore
|
||||
import GRPC
|
||||
import libburrow
|
||||
import NetworkExtension
|
||||
import os
|
||||
|
||||
private final class SendableCallbackBox<Callback>: @unchecked Sendable {
|
||||
let callback: Callback
|
||||
class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
override func startTunnel(options: [String: NSObject]?, completionHandler: @escaping (Error?) -> Void) {
|
||||
completionHandler(nil)
|
||||
}
|
||||
|
||||
init(_ callback: Callback) {
|
||||
self.callback = callback
|
||||
override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
|
||||
completionHandler()
|
||||
}
|
||||
|
||||
override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)?) {
|
||||
if let handler = completionHandler {
|
||||
handler(messageData)
|
||||
}
|
||||
}
|
||||
|
||||
final class PacketTunnelProvider: NEPacketTunnelProvider, @unchecked Sendable {
|
||||
enum Error: Swift.Error {
|
||||
case missingTunnelConfiguration
|
||||
override func sleep(completionHandler: @escaping () -> Void) {
|
||||
completionHandler()
|
||||
}
|
||||
|
||||
private let logger = Logger.logger(for: PacketTunnelProvider.self)
|
||||
private var packetCall: GRPCAsyncBidirectionalStreamingCall<Burrow_TunnelPacket, Burrow_TunnelPacket>?
|
||||
private var inboundPacketTask: Task<Void, Never>?
|
||||
private var outboundPacketTask: Task<Void, Never>?
|
||||
|
||||
private var client: TunnelClient {
|
||||
get throws { try _client.get() }
|
||||
}
|
||||
private let _client: Result<TunnelClient, Swift.Error> = Result {
|
||||
try TunnelClient.unix(socketURL: Constants.socketURL)
|
||||
}
|
||||
|
||||
override init() {
|
||||
do {
|
||||
libburrow.spawnInProcess(
|
||||
socketPath: try Constants.socketURL.path(percentEncoded: false),
|
||||
databasePath: try Constants.databaseURL.path(percentEncoded: false)
|
||||
)
|
||||
} catch {
|
||||
logger.error("Failed to spawn networking thread: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
override func startTunnel(
|
||||
options: [String: NSObject]?,
|
||||
completionHandler: @escaping (Swift.Error?) -> Void
|
||||
) {
|
||||
let completion = SendableCallbackBox(completionHandler)
|
||||
Task {
|
||||
do {
|
||||
_ = try await client.tunnelStart(.init())
|
||||
let configuration = try await Array(client.tunnelConfiguration(.init()).prefix(1)).first
|
||||
guard let settings = configuration?.settings else {
|
||||
throw Error.missingTunnelConfiguration
|
||||
}
|
||||
try await setTunnelNetworkSettings(settings)
|
||||
try startPacketBridge()
|
||||
logger.log("Started tunnel with network settings: \(settings)")
|
||||
completion.callback(nil)
|
||||
} catch {
|
||||
logger.error("Failed to start tunnel: \(error)")
|
||||
stopPacketBridge()
|
||||
completion.callback(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func stopTunnel(
|
||||
with reason: NEProviderStopReason,
|
||||
completionHandler: @escaping () -> Void
|
||||
) {
|
||||
let completion = SendableCallbackBox(completionHandler)
|
||||
Task {
|
||||
stopPacketBridge()
|
||||
do {
|
||||
_ = try await client.tunnelStop(.init())
|
||||
logger.log("Stopped client")
|
||||
} catch {
|
||||
logger.error("Failed to stop tunnel: \(error)")
|
||||
}
|
||||
completion.callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension PacketTunnelProvider {
|
||||
private func startPacketBridge() throws {
|
||||
stopPacketBridge()
|
||||
|
||||
let packetClient = TunnelPacketClient.unix(socketURL: try Constants.socketURL)
|
||||
let call = packetClient.makeTunnelPacketsCall()
|
||||
self.packetCall = call
|
||||
|
||||
inboundPacketTask = Task { [weak self] in
|
||||
guard let self else { return }
|
||||
do {
|
||||
for try await packet in call.responseStream {
|
||||
let payload = packet.payload
|
||||
self.packetFlow.writePackets(
|
||||
[payload],
|
||||
withProtocols: [Self.protocolNumber(for: payload)]
|
||||
)
|
||||
}
|
||||
} catch {
|
||||
guard !Task.isCancelled else { return }
|
||||
self.logger.error("Tunnel packet receive loop failed: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
outboundPacketTask = Task { [weak self] in
|
||||
guard let self else { return }
|
||||
defer { call.requestStream.finish() }
|
||||
do {
|
||||
while !Task.isCancelled {
|
||||
let packets = await self.readPacketsBatch()
|
||||
for (payload, _) in packets {
|
||||
var packet = Burrow_TunnelPacket()
|
||||
packet.payload = payload
|
||||
try await call.requestStream.send(packet)
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
guard !Task.isCancelled else { return }
|
||||
self.logger.error("Tunnel packet send loop failed: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func stopPacketBridge() {
|
||||
inboundPacketTask?.cancel()
|
||||
inboundPacketTask = nil
|
||||
outboundPacketTask?.cancel()
|
||||
outboundPacketTask = nil
|
||||
packetCall?.cancel()
|
||||
packetCall = nil
|
||||
}
|
||||
|
||||
private func readPacketsBatch() async -> [(Data, NSNumber)] {
|
||||
await withCheckedContinuation { continuation in
|
||||
packetFlow.readPackets { packets, protocols in
|
||||
continuation.resume(returning: Array(zip(packets, protocols)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static func protocolNumber(for payload: Data) -> NSNumber {
|
||||
guard let version = payload.first.map({ $0 >> 4 }) else {
|
||||
return NSNumber(value: AF_INET)
|
||||
}
|
||||
switch version {
|
||||
case 6:
|
||||
return NSNumber(value: AF_INET6)
|
||||
default:
|
||||
return NSNumber(value: AF_INET)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_TunnelConfigurationResponse {
|
||||
fileprivate var settings: NEPacketTunnelNetworkSettings {
|
||||
let parsedAddresses = addresses.compactMap(ParsedTunnelAddress.init(rawValue:))
|
||||
let ipv4Addresses = parsedAddresses.compactMap(\.ipv4Address)
|
||||
let ipv6Addresses = parsedAddresses.compactMap(\.ipv6Address)
|
||||
let parsedRoutes = routes.compactMap(ParsedTunnelRoute.init(rawValue:))
|
||||
var ipv4Routes = parsedRoutes.compactMap(\.ipv4Route)
|
||||
var ipv6Routes = parsedRoutes.compactMap(\.ipv6Route)
|
||||
if includeDefaultRoute {
|
||||
ipv4Routes.append(.default())
|
||||
ipv6Routes.append(.default())
|
||||
}
|
||||
|
||||
let settings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "1.1.1.1")
|
||||
settings.mtu = NSNumber(value: mtu)
|
||||
if !ipv4Addresses.isEmpty {
|
||||
let ipv4Settings = NEIPv4Settings(
|
||||
addresses: ipv4Addresses.map(\.address),
|
||||
subnetMasks: ipv4Addresses.map(\.subnetMask)
|
||||
)
|
||||
if !ipv4Routes.isEmpty {
|
||||
ipv4Settings.includedRoutes = ipv4Routes
|
||||
}
|
||||
settings.ipv4Settings = ipv4Settings
|
||||
}
|
||||
if !ipv6Addresses.isEmpty {
|
||||
let ipv6Settings = NEIPv6Settings(
|
||||
addresses: ipv6Addresses.map(\.address),
|
||||
networkPrefixLengths: ipv6Addresses.map(\.prefixLength)
|
||||
)
|
||||
if !ipv6Routes.isEmpty {
|
||||
ipv6Settings.includedRoutes = ipv6Routes
|
||||
}
|
||||
settings.ipv6Settings = ipv6Settings
|
||||
}
|
||||
if !dnsServers.isEmpty {
|
||||
let dnsSettings = NEDNSSettings(servers: dnsServers)
|
||||
if !searchDomains.isEmpty {
|
||||
dnsSettings.matchDomains = searchDomains
|
||||
}
|
||||
settings.dnsSettings = dnsSettings
|
||||
}
|
||||
return settings
|
||||
}
|
||||
}
|
||||
|
||||
private struct ParsedTunnelAddress {
|
||||
struct IPv4AddressSetting {
|
||||
let address: String
|
||||
let subnetMask: String
|
||||
}
|
||||
|
||||
struct IPv6AddressSetting {
|
||||
let address: String
|
||||
let prefixLength: NSNumber
|
||||
}
|
||||
|
||||
let ipv4Address: IPv4AddressSetting?
|
||||
let ipv6Address: IPv6AddressSetting?
|
||||
|
||||
init?(rawValue: String) {
|
||||
let components = rawValue.split(separator: "/", maxSplits: 1).map(String.init)
|
||||
let address = components.first?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
||||
guard !address.isEmpty else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let prefix = components.count == 2 ? Int(components[1]) : nil
|
||||
if IPv4Address(address) != nil {
|
||||
let prefixLength = prefix ?? 32
|
||||
guard (0 ... 32).contains(prefixLength) else {
|
||||
return nil
|
||||
}
|
||||
ipv4Address = IPv4AddressSetting(
|
||||
address: address,
|
||||
subnetMask: Self.ipv4SubnetMask(prefixLength: prefixLength)
|
||||
)
|
||||
ipv6Address = nil
|
||||
return
|
||||
}
|
||||
|
||||
if IPv6Address(address) != nil {
|
||||
let prefixLength = prefix ?? 128
|
||||
guard (0 ... 128).contains(prefixLength) else {
|
||||
return nil
|
||||
}
|
||||
ipv4Address = nil
|
||||
ipv6Address = IPv6AddressSetting(
|
||||
address: address,
|
||||
prefixLength: NSNumber(value: prefixLength)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
private static func ipv4SubnetMask(prefixLength: Int) -> String {
|
||||
guard prefixLength > 0 else {
|
||||
return "0.0.0.0"
|
||||
}
|
||||
let mask = UInt32.max << (32 - prefixLength)
|
||||
let octets = [
|
||||
(mask >> 24) & 0xff,
|
||||
(mask >> 16) & 0xff,
|
||||
(mask >> 8) & 0xff,
|
||||
mask & 0xff,
|
||||
]
|
||||
return octets.map(String.init).joined(separator: ".")
|
||||
}
|
||||
}
|
||||
|
||||
private struct ParsedTunnelRoute {
|
||||
let ipv4Route: NEIPv4Route?
|
||||
let ipv6Route: NEIPv6Route?
|
||||
|
||||
init?(rawValue: String) {
|
||||
let components = rawValue.split(separator: "/", maxSplits: 1).map(String.init)
|
||||
let address = components.first?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
||||
guard !address.isEmpty else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let prefix = components.count == 2 ? Int(components[1]) : nil
|
||||
if IPv4Address(address) != nil {
|
||||
let prefixLength = prefix ?? 32
|
||||
guard (0 ... 32).contains(prefixLength) else {
|
||||
return nil
|
||||
}
|
||||
ipv4Route = NEIPv4Route(
|
||||
destinationAddress: address,
|
||||
subnetMask: Self.ipv4SubnetMask(prefixLength: prefixLength)
|
||||
)
|
||||
ipv6Route = nil
|
||||
return
|
||||
}
|
||||
|
||||
if IPv6Address(address) != nil {
|
||||
let prefixLength = prefix ?? 128
|
||||
guard (0 ... 128).contains(prefixLength) else {
|
||||
return nil
|
||||
}
|
||||
ipv4Route = nil
|
||||
ipv6Route = NEIPv6Route(
|
||||
destinationAddress: address,
|
||||
networkPrefixLength: NSNumber(value: prefixLength)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
private static func ipv4SubnetMask(prefixLength: Int) -> String {
|
||||
var mask = UInt32.max << (32 - prefixLength)
|
||||
if prefixLength == 0 {
|
||||
mask = 0
|
||||
}
|
||||
let octets = [
|
||||
String((mask >> 24) & 0xff),
|
||||
String((mask >> 16) & 0xff),
|
||||
String((mask >> 8) & 0xff),
|
||||
String(mask & 0xff),
|
||||
]
|
||||
return octets.joined(separator: ".")
|
||||
override func wake() {
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,10 +56,10 @@ CARGO_ARGS+=("--lib")
|
|||
|
||||
# Pass the configuration (Debug or Release) through to cargo
|
||||
if [[ $SWIFT_ACTIVE_COMPILATION_CONDITIONS == *DEBUG* ]]; then
|
||||
CARGO_TARGET_SUBDIR="debug"
|
||||
CARGO_DIR="debug"
|
||||
else
|
||||
CARGO_ARGS+=("--release")
|
||||
CARGO_TARGET_SUBDIR="release"
|
||||
CARGO_DIR="release"
|
||||
fi
|
||||
|
||||
if [[ -x "$(command -v rustup)" ]]; then
|
||||
|
|
@ -68,30 +68,13 @@ else
|
|||
CARGO_PATH="$(dirname $(readlink -f $(which cargo))):/usr/bin"
|
||||
fi
|
||||
|
||||
PROTOC=$(readlink -f $(which protoc))
|
||||
CARGO_PATH="$(dirname $PROTOC):$CARGO_PATH"
|
||||
|
||||
# Run cargo without the various environment variables set by Xcode.
|
||||
# Those variables can confuse cargo and the build scripts it runs.
|
||||
CARGO_ENV=(
|
||||
"PATH=$CARGO_PATH"
|
||||
"PROTOC=$PROTOC"
|
||||
"CARGO_TARGET_DIR=${CONFIGURATION_TEMP_DIR}/target"
|
||||
)
|
||||
|
||||
if [[ -n "$IPHONEOS_DEPLOYMENT_TARGET" ]]; then
|
||||
CARGO_ENV+=("IPHONEOS_DEPLOYMENT_TARGET=$IPHONEOS_DEPLOYMENT_TARGET")
|
||||
fi
|
||||
|
||||
if [[ -n "$MACOSX_DEPLOYMENT_TARGET" ]]; then
|
||||
CARGO_ENV+=("MACOSX_DEPLOYMENT_TARGET=$MACOSX_DEPLOYMENT_TARGET")
|
||||
fi
|
||||
|
||||
env -i "${CARGO_ENV[@]}" cargo build "${CARGO_ARGS[@]}"
|
||||
env -i PATH="$CARGO_PATH" cargo build "${CARGO_ARGS[@]}"
|
||||
|
||||
mkdir -p "${BUILT_PRODUCTS_DIR}"
|
||||
|
||||
# Use `lipo` to merge the architectures together into BUILT_PRODUCTS_DIR
|
||||
/usr/bin/xcrun --sdk $PLATFORM_NAME lipo \
|
||||
-create $(printf "${CONFIGURATION_TEMP_DIR}/target/%q/${CARGO_TARGET_SUBDIR}/libburrow.a " "${RUST_TARGETS[@]}") \
|
||||
-create $(printf "${PROJECT_DIR}/../target/%q/${CARGO_DIR}/libburrow.a " "${RUST_TARGETS[@]}") \
|
||||
-output "${BUILT_PRODUCTS_DIR}/libburrow.a"
|
||||
|
|
|
|||
|
|
@ -1,2 +1 @@
|
|||
__attribute__((__swift_name__("spawnInProcess(socketPath:databasePath:)")))
|
||||
extern void spawn_in_process(const char * __nullable socket_path, const char * __nullable db_path);
|
||||
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 95 KiB |
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 684 B |
|
Before Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 927 B |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |