mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-08 22:33:26 +01:00
Compare commits
34 Commits
alpha
...
feature/Ro
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4c2d17ffc | ||
|
|
2c829895c9 | ||
|
|
5463f2b935 | ||
|
|
d644ee7ab0 | ||
|
|
351d4fd631 | ||
|
|
128b180c1f | ||
|
|
1f2693bea6 | ||
|
|
452cf89c95 | ||
|
|
90ac0fb025 | ||
|
|
10f5ee1548 | ||
|
|
478b30c8fd | ||
|
|
207f6aac32 | ||
|
|
e1ed6f5ba3 | ||
|
|
444aac1210 | ||
|
|
f49fa24743 | ||
|
|
4c9c5b1a56 | ||
|
|
365cadbb31 | ||
|
|
36e03a52a7 | ||
|
|
19cf1722fa | ||
|
|
c28a45f100 | ||
|
|
df5b0c3af1 | ||
|
|
8b1e87d2dd | ||
|
|
e036f07875 | ||
|
|
2d232fa702 | ||
|
|
686d1ab42a | ||
|
|
d22d12c234 | ||
|
|
364b11ec9d | ||
|
|
f3a70e1e47 | ||
|
|
493b3783f0 | ||
|
|
4669227567 | ||
|
|
dfcc6e714e | ||
|
|
3b824eac96 | ||
|
|
a6559d8bb9 | ||
|
|
f270ecc537 |
21
.codecov.yml
Normal file
21
.codecov.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
# https://docs.codecov.io/docs/codecov-yaml
|
||||
|
||||
codecov:
|
||||
require_ci_to_pass: true
|
||||
|
||||
coverage:
|
||||
precision: 2
|
||||
round: down
|
||||
range: "70...100"
|
||||
ignore:
|
||||
- Dependencies
|
||||
status:
|
||||
patch:
|
||||
default:
|
||||
if_no_uploads: error
|
||||
changes: true
|
||||
project:
|
||||
default:
|
||||
target: auto
|
||||
if_no_uploads: error
|
||||
comment: false
|
||||
@@ -1,39 +1,35 @@
|
||||
# EditorConfig is awesome: https://EditorConfig.org
|
||||
# http://editorconfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
indent_style = space
|
||||
charset = utf-8
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
# Matches multiple files with brace expansion notation
|
||||
# Set default charset
|
||||
[*.{js,py}]
|
||||
charset = utf-8# 4 space indentation
|
||||
[*.{md,markdown}]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
# Swift files
|
||||
[*.swift]
|
||||
[*.{c,h,m,mm}]
|
||||
trim_trailing_whitespace = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
charset = utf-8# 4 space indentation
|
||||
indent_size = 2
|
||||
|
||||
# 4 space indentation
|
||||
[*.py]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
[*.js]
|
||||
indent_size = 2
|
||||
|
||||
# Tab indentation (no size specified)
|
||||
[Makefile]
|
||||
[*.{swift}]
|
||||
trim_trailing_whitespace = true
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
# Indentation override for all JS under lib directory
|
||||
[lib/**.js]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
[Makefile]
|
||||
trim_trailing_whitespace = true
|
||||
indent_style = tab
|
||||
indent_size = 8
|
||||
|
||||
# Matches the exact files either package.json or .travis.yml
|
||||
[{package.json,.travis.yml}]
|
||||
indent_style = space
|
||||
[*.{yaml|yml}]
|
||||
indent_size = 2
|
||||
|
||||
20
.github/workflows/.disabled/sidestore-project.yml
vendored
Normal file
20
.github/workflows/.disabled/sidestore-project.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
# .github/workflows/sidestore-project.yml
|
||||
name: SideStore Project
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: tuist/tuist-action@0.13.0
|
||||
with:
|
||||
command: 'build'
|
||||
arguments: ''
|
||||
|
||||
112
.github/workflows/beta.yml
vendored
112
.github/workflows/beta.yml
vendored
@@ -2,7 +2,7 @@ name: Beta SideStore build
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+' # example: 1.0.0-beta.1
|
||||
- '[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+' # example: 1.0.0-beta.1
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -11,41 +11,41 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: 'macos-12'
|
||||
version: '14.2'
|
||||
- os: 'macos-12'
|
||||
version: '14.2'
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install dependencies
|
||||
run: brew install ldid
|
||||
- name: Install dependencies
|
||||
run: brew install ldid
|
||||
|
||||
- name: Change version to tag
|
||||
run: sed -e '/MARKETING_VERSION = .*/s/= .*/= ${{ github.ref_name }}/' -i '' Build.xcconfig
|
||||
- name: Change version to tag
|
||||
run: sed -e '/MARKETING_VERSION = .*/s/= .*/= ${{ github.ref_name }}/' -i '' Build.xcconfig
|
||||
|
||||
- name: Setup Xcode
|
||||
uses: maxim-lobanov/setup-xcode@v1.4.1
|
||||
with:
|
||||
xcode-version: ${{ matrix.version }}
|
||||
- name: Setup Xcode
|
||||
uses: maxim-lobanov/setup-xcode@v1.4.1
|
||||
with:
|
||||
xcode-version: ${{ matrix.version }}
|
||||
|
||||
- name: Build SideStore
|
||||
run: make build | xcpretty && exit ${PIPESTATUS[0]}
|
||||
- name: Build SideStore
|
||||
run: make build | xcpretty && exit ${PIPESTATUS[0]}
|
||||
|
||||
- name: Fakesign app
|
||||
run: make fakesign
|
||||
- name: Fakesign app
|
||||
run: make fakesign
|
||||
|
||||
- name: Convert to IPA
|
||||
run: make ipa
|
||||
- name: Convert to IPA
|
||||
run: make ipa
|
||||
|
||||
- name: Upload SideStore.ipa Artifact
|
||||
uses: actions/upload-artifact@v3.1.0
|
||||
with:
|
||||
name: SideStore.ipa
|
||||
path: SideStore.ipa
|
||||
uses: actions/upload-artifact@v3.1.0
|
||||
with:
|
||||
name: SideStore.ipa
|
||||
path: SideStore.ipa
|
||||
|
||||
- name: Upload *.dSYM Artifact
|
||||
uses: actions/upload-artifact@v3.1.0
|
||||
@@ -53,38 +53,38 @@ jobs:
|
||||
name: SideStore-dSYM
|
||||
path: ./*.dSYM/
|
||||
|
||||
- name: Get version
|
||||
id: version
|
||||
run: echo "version=$(grep MARKETING_VERSION Build.xcconfig | sed -e "s/MARKETING_VERSION = //g")" >> $GITHUB_OUTPUT
|
||||
- name: Get version
|
||||
id: version
|
||||
run: echo "version=$(grep MARKETING_VERSION Build.xcconfig | sed -e "s/MARKETING_VERSION = //g")" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Get current date
|
||||
id: date
|
||||
run: echo "date=$(date -u +'%c')" >> $GITHUB_OUTPUT
|
||||
- name: Get current date
|
||||
id: date
|
||||
run: echo "date=$(date -u +'%c')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Get current date in AltStore date form
|
||||
id: date_altstore
|
||||
run: echo "date=$(date -u +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
- name: Get current date in SideStore date form
|
||||
id: date_sidestore
|
||||
run: echo "date=$(date -u +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Upload to new beta release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: ${{ steps.version.outputs.version }}
|
||||
tag_name: ${{ github.ref_name }}
|
||||
draft: true
|
||||
prerelease: true
|
||||
files: SideStore.ipa
|
||||
body: |
|
||||
<!-- NOTE: to reset SideSource cache, go to `https://apps.sidestore.io/reset-cache/nightly/<sidesource key>`. This is not included in the GitHub Action since it makes draft releases so they can be edited and have a changelog. -->
|
||||
Beta builds are hand-picked builds from development commits that will allow you to try out new features earlier than normal. However, **they might contain bugs and other issues. Use at your own risk!**
|
||||
- name: Upload to new beta release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: ${{ steps.version.outputs.version }}
|
||||
tag_name: ${{ github.ref_name }}
|
||||
draft: true
|
||||
prerelease: true
|
||||
files: SideStore.ipa
|
||||
body: |
|
||||
<!-- NOTE: to reset SideSource cache, go to `https://apps.sidestore.io/reset-cache/nightly/<sidesource key>`. This is not included in the GitHub Action since it makes draft releases so they can be edited and have a changelog. -->
|
||||
Beta builds are hand-picked builds from development commits that will allow you to try out new features earlier than normal. However, **they might contain bugs and other issues. Use at your own risk!**
|
||||
|
||||
## Changelog
|
||||
|
||||
- TODO
|
||||
|
||||
## Build Info
|
||||
|
||||
Built at (UTC): `${{ steps.date.outputs.date }}`
|
||||
Built at (UTC date): `${{ steps.date_altstore.outputs.date }}`
|
||||
Commit SHA: `${{ github.sha }}`
|
||||
Version: `${{ steps.version.outputs.version }}`
|
||||
## Changelog
|
||||
|
||||
- TODO
|
||||
|
||||
## Build Info
|
||||
|
||||
Built at (UTC): `${{ steps.date.outputs.date }}`
|
||||
Built at (UTC date): `${{ steps.date_sidestore.outputs.date }}`
|
||||
Commit SHA: `${{ github.sha }}`
|
||||
Version: `${{ steps.version.outputs.version }}`
|
||||
|
||||
124
.github/workflows/nightly.yml
vendored
124
.github/workflows/nightly.yml
vendored
@@ -2,7 +2,7 @@ name: Nightly SideStore build
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
- develop
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -14,47 +14,47 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: 'macos-12'
|
||||
version: '14.2'
|
||||
- os: 'macos-12'
|
||||
version: '14.2'
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install dependencies
|
||||
run: brew install ldid
|
||||
- name: Install dependencies
|
||||
run: brew install ldid
|
||||
|
||||
- name: Cache .nightly-build-num
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: .nightly-build-num
|
||||
key: nightly-build-num
|
||||
- name: Cache .nightly-build-num
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: .nightly-build-num
|
||||
key: nightly-build-num
|
||||
|
||||
- name: Increase nightly build number and set as version
|
||||
run: bash .github/workflows/increase-nightly-build-num.sh
|
||||
- name: Increase nightly build number and set as version
|
||||
run: bash .github/workflows/increase-nightly-build-num.sh
|
||||
|
||||
- name: Setup Xcode
|
||||
uses: maxim-lobanov/setup-xcode@v1.4.1
|
||||
with:
|
||||
xcode-version: ${{ matrix.version }}
|
||||
- name: Setup Xcode
|
||||
uses: maxim-lobanov/setup-xcode@v1.4.1
|
||||
with:
|
||||
xcode-version: ${{ matrix.version }}
|
||||
|
||||
- name: Build SideStore
|
||||
run: make build | xcpretty && exit ${PIPESTATUS[0]}
|
||||
- name: Build SideStore
|
||||
run: make build | xcpretty && exit ${PIPESTATUS[0]}
|
||||
|
||||
- name: Fakesign app
|
||||
run: make fakesign
|
||||
- name: Fakesign app
|
||||
run: make fakesign
|
||||
|
||||
- name: Convert to IPA
|
||||
run: make ipa
|
||||
- name: Convert to IPA
|
||||
run: make ipa
|
||||
|
||||
- name: Upload SideStore.ipa Artifact
|
||||
uses: actions/upload-artifact@v3.1.0
|
||||
with:
|
||||
name: SideStore.ipa
|
||||
path: SideStore.ipa
|
||||
uses: actions/upload-artifact@v3.1.0
|
||||
with:
|
||||
name: SideStore.ipa
|
||||
path: SideStore.ipa
|
||||
|
||||
- name: Upload *.dSYM Artifact
|
||||
uses: actions/upload-artifact@v3.1.0
|
||||
@@ -62,39 +62,39 @@ jobs:
|
||||
name: SideStore-dSYM
|
||||
path: ./*.dSYM/
|
||||
|
||||
- name: Get version
|
||||
id: version
|
||||
run: echo "version=$(grep MARKETING_VERSION Build.xcconfig | sed -e "s/MARKETING_VERSION = //g")" >> $GITHUB_OUTPUT
|
||||
- name: Get version
|
||||
id: version
|
||||
run: echo "version=$(grep MARKETING_VERSION Build.xcconfig | sed -e "s/MARKETING_VERSION = //g")" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Get current date
|
||||
id: date
|
||||
run: echo "date=$(date -u +'%c')" >> $GITHUB_OUTPUT
|
||||
- name: Get current date
|
||||
id: date
|
||||
run: echo "date=$(date -u +'%c')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Get current date in AltStore date form
|
||||
id: date_altstore
|
||||
run: echo "date=$(date -u +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
- name: Get current date in SideStore date form
|
||||
id: date_sidestore
|
||||
run: echo "date=$(date -u +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Upload to nightly release
|
||||
uses: IsaacShelton/update-existing-release@v1.3.1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
release: "Nightly"
|
||||
tag: "nightly"
|
||||
prerelease: true
|
||||
files: SideStore.ipa
|
||||
body: |
|
||||
This is an ⚠️ **EXPERIMENTAL** ⚠️ nightly build for commit [${{ github.sha }}](https://github.com/${{ github.repository }}/commit/${{ github.sha }}).
|
||||
|
||||
Nightly builds are **extremely experimental builds only meant to be used by developers and alpha testers. They often contain bugs and experimental features. Use at your own risk!**
|
||||
|
||||
If you want to try out new features early but want a lower chance of bugs, you can look at [SideStore Beta](https://github.com/${{ github.repository }}/releases?q=beta).
|
||||
|
||||
## Build Info
|
||||
|
||||
Built at (UTC): `${{ steps.date.outputs.date }}`
|
||||
Built at (UTC date): `${{ steps.date_altstore.outputs.date }}`
|
||||
Commit SHA: `${{ github.sha }}`
|
||||
Version: `${{ steps.version.outputs.version }}`
|
||||
- name: Upload to nightly release
|
||||
uses: IsaacShelton/update-existing-release@v1.3.1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
release: "Nightly"
|
||||
tag: "nightly"
|
||||
prerelease: true
|
||||
files: SideStore.ipa
|
||||
body: |
|
||||
This is an ⚠️ **EXPERIMENTAL** ⚠️ nightly build for commit [${{ github.sha }}](https://github.com/${{ github.repository }}/commit/${{ github.sha }}).
|
||||
|
||||
- name: Reset cache for apps.sidestore.io/nightly
|
||||
run: sleep 10 && curl https://apps.sidestore.io/reset-cache/nightly/${{ secrets.SIDESOURCE_KEY }}
|
||||
Nightly builds are **extremely experimental builds only meant to be used by developers and alpha testers. They often contain bugs and experimental features. Use at your own risk!**
|
||||
|
||||
If you want to try out new features early but want a lower chance of bugs, you can look at [SideStore Beta](https://github.com/${{ github.repository }}/releases?q=beta).
|
||||
|
||||
## Build Info
|
||||
|
||||
Built at (UTC): `${{ steps.date.outputs.date }}`
|
||||
Built at (UTC date): `${{ steps.date_sidestore.outputs.date }}`
|
||||
Commit SHA: `${{ github.sha }}`
|
||||
Version: `${{ steps.version.outputs.version }}`
|
||||
|
||||
- name: Reset cache for apps.sidestore.io/nightly
|
||||
run: sleep 10 && curl https://apps.sidestore.io/reset-cache/nightly/${{ secrets.SIDESOURCE_KEY }}
|
||||
|
||||
108
.github/workflows/stable.yml
vendored
108
.github/workflows/stable.yml
vendored
@@ -2,7 +2,7 @@ name: Stable SideStore build
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '[0-9]+.[0-9]+.[0-9]+' # example: 1.0.0
|
||||
- '[0-9]+.[0-9]+.[0-9]+' # example: 1.0.0
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -11,41 +11,41 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: 'macos-12'
|
||||
version: '14.2'
|
||||
- os: 'macos-12'
|
||||
version: '14.2'
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install dependencies
|
||||
run: brew install ldid
|
||||
- name: Install dependencies
|
||||
run: brew install ldid
|
||||
|
||||
- name: Change version to tag
|
||||
run: sed -e '/MARKETING_VERSION = .*/s/= .*/= ${{ github.ref_name }}/' -i '' Build.xcconfig
|
||||
- name: Change version to tag
|
||||
run: sed -e '/MARKETING_VERSION = .*/s/= .*/= ${{ github.ref_name }}/' -i '' Build.xcconfig
|
||||
|
||||
- name: Setup Xcode
|
||||
uses: maxim-lobanov/setup-xcode@v1.4.1
|
||||
with:
|
||||
xcode-version: ${{ matrix.version }}
|
||||
- name: Setup Xcode
|
||||
uses: maxim-lobanov/setup-xcode@v1.4.1
|
||||
with:
|
||||
xcode-version: ${{ matrix.version }}
|
||||
|
||||
- name: Build SideStore
|
||||
run: make build | xcpretty && exit ${PIPESTATUS[0]}
|
||||
- name: Build SideStore
|
||||
run: make build | xcpretty && exit ${PIPESTATUS[0]}
|
||||
|
||||
- name: Fakesign app
|
||||
run: make fakesign
|
||||
- name: Fakesign app
|
||||
run: make fakesign
|
||||
|
||||
- name: Convert to IPA
|
||||
run: make ipa
|
||||
- name: Convert to IPA
|
||||
run: make ipa
|
||||
|
||||
- name: Upload SideStore.ipa Artifact
|
||||
uses: actions/upload-artifact@v3.1.0
|
||||
with:
|
||||
name: SideStore.ipa
|
||||
path: SideStore.ipa
|
||||
uses: actions/upload-artifact@v3.1.0
|
||||
with:
|
||||
name: SideStore.ipa
|
||||
path: SideStore.ipa
|
||||
|
||||
- name: Upload *.dSYM Artifact
|
||||
uses: actions/upload-artifact@v3.1.0
|
||||
@@ -53,35 +53,35 @@ jobs:
|
||||
name: SideStore-dSYM
|
||||
path: ./*.dSYM/
|
||||
|
||||
- name: Get version
|
||||
id: version
|
||||
run: echo "version=$(grep MARKETING_VERSION Build.xcconfig | sed -e "s/MARKETING_VERSION = //g")" >> $GITHUB_OUTPUT
|
||||
- name: Get version
|
||||
id: version
|
||||
run: echo "version=$(grep MARKETING_VERSION Build.xcconfig | sed -e "s/MARKETING_VERSION = //g")" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Get current date
|
||||
id: date
|
||||
run: echo "date=$(date -u +'%c')" >> $GITHUB_OUTPUT
|
||||
- name: Get current date
|
||||
id: date
|
||||
run: echo "date=$(date -u +'%c')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Get current date in AltStore date form
|
||||
id: date_altstore
|
||||
run: echo "date=$(date -u +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
- name: Get current date in SideStore date form
|
||||
id: date_sidestore
|
||||
run: echo "date=$(date -u +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Upload to new stable release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: ${{ steps.version.outputs.version }}
|
||||
tag_name: ${{ github.ref_name }}
|
||||
draft: true
|
||||
files: SideStore.ipa
|
||||
body: |
|
||||
<!-- NOTE: to reset SideSource cache, go to `https://apps.sidestore.io/reset-cache/nightly/<sidesource key>`. This is not included in the GitHub Action since it makes draft releases so they can be edited and have a changelog. -->
|
||||
## Changelog
|
||||
|
||||
- TODO
|
||||
|
||||
## Build Info
|
||||
|
||||
Built at (UTC): `${{ steps.date.outputs.date }}`
|
||||
Built at (UTC date): `${{ steps.date_altstore.outputs.date }}`
|
||||
Commit SHA: `${{ github.sha }}`
|
||||
Version: `${{ steps.version.outputs.version }}`
|
||||
- name: Upload to new stable release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: ${{ steps.version.outputs.version }}
|
||||
tag_name: ${{ github.ref_name }}
|
||||
draft: true
|
||||
files: SideStore.ipa
|
||||
body: |
|
||||
<!-- NOTE: to reset SideSource cache, go to `https://apps.sidestore.io/reset-cache/nightly/<sidesource key>`. This is not included in the GitHub Action since it makes draft releases so they can be edited and have a changelog. -->
|
||||
## Changelog
|
||||
|
||||
- TODO
|
||||
|
||||
## Build Info
|
||||
|
||||
Built at (UTC): `${{ steps.date.outputs.date }}`
|
||||
Built at (UTC date): `${{ steps.date_sidestore.outputs.date }}`
|
||||
Commit SHA: `${{ github.sha }}`
|
||||
Version: `${{ steps.version.outputs.version }}`
|
||||
|
||||
27
.gitmodules
vendored
27
.gitmodules
vendored
@@ -1,21 +1,6 @@
|
||||
[submodule "Dependencies/Roxas"]
|
||||
path = Dependencies/Roxas
|
||||
url = https://github.com/rileytestut/Roxas.git
|
||||
[submodule "Dependencies/libimobiledevice"]
|
||||
path = Dependencies/libimobiledevice
|
||||
url = https://github.com/libimobiledevice/libimobiledevice
|
||||
[submodule "Dependencies/libusbmuxd"]
|
||||
path = Dependencies/libusbmuxd
|
||||
url = https://github.com/libimobiledevice/libusbmuxd.git
|
||||
[submodule "Dependencies/libplist"]
|
||||
path = Dependencies/libplist
|
||||
url = https://github.com/libimobiledevice/libplist.git
|
||||
[submodule "Dependencies/MarkdownAttributedString"]
|
||||
path = Dependencies/MarkdownAttributedString
|
||||
url = https://github.com/chockenberry/MarkdownAttributedString.git
|
||||
[submodule "Dependencies/libimobiledevice-glue"]
|
||||
path = Dependencies/libimobiledevice-glue
|
||||
url = https://github.com/libimobiledevice/libimobiledevice-glue
|
||||
[submodule "Dependencies/libfragmentzip"]
|
||||
path = Dependencies/libfragmentzip
|
||||
url = https://github.com/SideStore/libfragmentzip.git
|
||||
[submodule "Dependencies/em_proxy"]
|
||||
path = SideStoreApp/Dependencies/em_proxy
|
||||
url = https://github.com/SideStore/em_proxy.git
|
||||
[submodule "Dependencies/minimuxer"]
|
||||
path = SideStoreApp/Dependencies/minimuxer
|
||||
url = https://github.com/SideStore/minimuxer.git
|
||||
|
||||
28
.jazzy.yaml
Normal file
28
.jazzy.yaml
Normal file
@@ -0,0 +1,28 @@
|
||||
# ---- About ----
|
||||
module: SideStore
|
||||
module_version: 1.0,0
|
||||
author: SideStore
|
||||
readme: README.md
|
||||
copyright: 'See [license](https://github.com/SideStore/SideStore/blob/develop/LICENSE) for more details.'
|
||||
|
||||
# ---- URLs ----
|
||||
author_url: https://sidestore.io
|
||||
dash_url: https://sidestore.io/docsets/SideStore.xml
|
||||
github_url: https://github.com/SideStore/SideStore/
|
||||
github_file_prefix: https://github.com/SideStore/SideStore/tree/1.0.2/
|
||||
|
||||
# ---- Sources ----
|
||||
source_directory: Sources
|
||||
documentation: .build/x86_64-apple-macosx/debug/SideStore.docc
|
||||
|
||||
# ---- Generation ----
|
||||
clean: true
|
||||
output: docs
|
||||
min_acl: public
|
||||
hide_documentation_coverage: false
|
||||
skip_undocumented: false
|
||||
objc: false
|
||||
swift_version: 5.1.0
|
||||
|
||||
# ---- Formatting ----
|
||||
theme: fullwidth
|
||||
42
.swiftformat
Normal file
42
.swiftformat
Normal file
@@ -0,0 +1,42 @@
|
||||
# .swiftformat
|
||||
|
||||
## file options
|
||||
|
||||
--exclude .build,.github,.swiftpm,.vscode,Configurations,Dependencies
|
||||
|
||||
## format options
|
||||
|
||||
--allman false
|
||||
--binarygrouping 4,8
|
||||
--commas always
|
||||
--comments indent
|
||||
--decimalgrouping 3,6
|
||||
--elseposition same-line
|
||||
--empty void
|
||||
--exponentcase lowercase
|
||||
--exponentgrouping disabled
|
||||
--fractiongrouping disabled
|
||||
--header ignore
|
||||
--hexgrouping 4,8
|
||||
--hexliteralcase uppercase
|
||||
--ifdef indent
|
||||
--importgrouping testable-bottom
|
||||
--indent 4
|
||||
--indentcase false
|
||||
--linebreaks lf
|
||||
--maxwidth none
|
||||
--octalgrouping 4,8
|
||||
--operatorfunc spaced
|
||||
--patternlet hoist
|
||||
--ranges spaced
|
||||
--self remove
|
||||
--semicolons inline
|
||||
--stripunusedargs always
|
||||
--swiftversion 5.1
|
||||
--trimwhitespace always
|
||||
--wraparguments preserve
|
||||
--wrapcollections preserve
|
||||
|
||||
## rules
|
||||
|
||||
--enable isEmpty,andOperator,assertionFailures
|
||||
76
.swiftlint.yml
Normal file
76
.swiftlint.yml
Normal file
@@ -0,0 +1,76 @@
|
||||
disabled_rules:
|
||||
- block_based_kvo
|
||||
- colon
|
||||
- control_statement
|
||||
- cyclomatic_complexity
|
||||
- discarded_notification_center_observer
|
||||
- file_length
|
||||
- function_parameter_count
|
||||
- generic_type_name
|
||||
- identifier_name
|
||||
- multiple_closures_with_trailing_closure
|
||||
- nesting
|
||||
- switch_case_alignment
|
||||
- todo
|
||||
- type_name
|
||||
- type_body_length
|
||||
- function_body_length
|
||||
- unused_closure_parameter
|
||||
|
||||
# parameterized rules can be customized from this configuration file
|
||||
line_length: 200
|
||||
# parameterized rules are first parameterized as a warning level, then error level.
|
||||
type_body_length:
|
||||
- 300 # warning
|
||||
- 600 # error
|
||||
# parameterized rules are first parameterized as a warning level, then error level.
|
||||
# identifier_name_max_length:
|
||||
# - 40 # warning
|
||||
# - 60 # error
|
||||
# # parameterized rules are first parameterized as a warning level, then error level.
|
||||
# identifier_name_min_length:
|
||||
# - 3 # warning
|
||||
# - 2 # error
|
||||
function_body_length:
|
||||
- 200 # warning
|
||||
- 500 # error
|
||||
large_tuple:
|
||||
- 4 # warning
|
||||
- 6 # error
|
||||
|
||||
opt_in_rules:
|
||||
- empty_count
|
||||
- force_unwrapping
|
||||
|
||||
excluded: # paths to ignore during linting. overridden byincluded.
|
||||
- .build
|
||||
- .github
|
||||
- .swiftpm
|
||||
- .vscode
|
||||
- Dependencies
|
||||
|
||||
analyzer_rules: # Rules run by `swiftlint analyze` (experimental)
|
||||
- explicit_self
|
||||
|
||||
# Override these rules to be warnings for now
|
||||
force_cast: warning
|
||||
force_try: warning
|
||||
empty_count: warning
|
||||
|
||||
reporter: "xcode" # reporter type (xcode, json, csv, checkstyle, junit)
|
||||
|
||||
custom_rules:
|
||||
placeholders_in_comments:
|
||||
included: ".*\\.swift"
|
||||
name: "No Placeholders in Comments"
|
||||
regex: "<#([^#]+)#>"
|
||||
match_kinds:
|
||||
- comment
|
||||
- doccomment
|
||||
message: "Placeholder left in comment."
|
||||
tiles_deprecated:
|
||||
included: ".*\\.swift"
|
||||
name: "Tiles are deprecated in favor of Frame"
|
||||
regex: "([T,t]ile$|^[T,t]il[e,es])"
|
||||
message: "Tiles are deprecated in favor of Frame"
|
||||
severity: warning
|
||||
@@ -1,3 +0,0 @@
|
||||
#include "Build.xcconfig"
|
||||
|
||||
PRODUCT_BUNDLE_IDENTIFIER = $(PRODUCT_BUNDLE_IDENTIFIER).AltBackup
|
||||
@@ -1,206 +0,0 @@
|
||||
//
|
||||
// ViewController.swift
|
||||
// AltBackup
|
||||
//
|
||||
// Created by Riley Testut on 5/11/20.
|
||||
// Copyright © 2020 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
extension Bundle
|
||||
{
|
||||
var appName: String? {
|
||||
let appName =
|
||||
Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String ??
|
||||
Bundle.main.object(forInfoDictionaryKey: kCFBundleNameKey as String) as? String
|
||||
return appName
|
||||
}
|
||||
}
|
||||
|
||||
extension ViewController
|
||||
{
|
||||
enum BackupOperation
|
||||
{
|
||||
case backup
|
||||
case restore
|
||||
}
|
||||
}
|
||||
|
||||
class ViewController: UIViewController
|
||||
{
|
||||
private let backupController = BackupController()
|
||||
|
||||
private var currentOperation: BackupOperation? {
|
||||
didSet {
|
||||
DispatchQueue.main.async {
|
||||
self.update()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var textLabel: UILabel!
|
||||
private var detailTextLabel: UILabel!
|
||||
private var activityIndicatorView: UIActivityIndicatorView!
|
||||
|
||||
override var preferredStatusBarStyle: UIStatusBarStyle {
|
||||
return .lightContent
|
||||
}
|
||||
|
||||
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)
|
||||
{
|
||||
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.backup), name: AppDelegate.startBackupNotification, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.restore), name: AppDelegate.startRestoreNotification, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.didEnterBackground(_:)), name: UIApplication.didEnterBackgroundNotification, object: nil)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
override func viewDidLoad()
|
||||
{
|
||||
super.viewDidLoad()
|
||||
|
||||
self.view.backgroundColor = .altstoreBackground
|
||||
|
||||
self.textLabel = UILabel(frame: .zero)
|
||||
self.textLabel.font = UIFont.preferredFont(forTextStyle: .title2)
|
||||
self.textLabel.textColor = .altstoreText
|
||||
self.textLabel.textAlignment = .center
|
||||
self.textLabel.numberOfLines = 0
|
||||
|
||||
self.detailTextLabel = UILabel(frame: .zero)
|
||||
self.detailTextLabel.font = UIFont.preferredFont(forTextStyle: .body)
|
||||
self.detailTextLabel.textColor = .altstoreText
|
||||
self.detailTextLabel.textAlignment = .center
|
||||
self.detailTextLabel.numberOfLines = 0
|
||||
|
||||
self.activityIndicatorView = UIActivityIndicatorView(style: .whiteLarge)
|
||||
self.activityIndicatorView.color = .altstoreText
|
||||
self.activityIndicatorView.startAnimating()
|
||||
|
||||
#if DEBUG
|
||||
let button1 = UIButton(type: .system)
|
||||
button1.setTitle("Backup", for: .normal)
|
||||
button1.setTitleColor(.white, for: .normal)
|
||||
button1.titleLabel?.font = UIFont.preferredFont(forTextStyle: .body)
|
||||
button1.addTarget(self, action: #selector(ViewController.backup), for: .primaryActionTriggered)
|
||||
|
||||
let button2 = UIButton(type: .system)
|
||||
button2.setTitle("Restore", for: .normal)
|
||||
button2.setTitleColor(.white, for: .normal)
|
||||
button2.titleLabel?.font = UIFont.preferredFont(forTextStyle: .body)
|
||||
button2.addTarget(self, action: #selector(ViewController.restore), for: .primaryActionTriggered)
|
||||
|
||||
let arrangedSubviews = [self.textLabel!, self.detailTextLabel!, self.activityIndicatorView!, button1, button2]
|
||||
#else
|
||||
let arrangedSubviews = [self.textLabel!, self.detailTextLabel!, self.activityIndicatorView!]
|
||||
#endif
|
||||
|
||||
let stackView = UIStackView(arrangedSubviews: arrangedSubviews)
|
||||
stackView.translatesAutoresizingMaskIntoConstraints = false
|
||||
stackView.spacing = 22
|
||||
stackView.axis = .vertical
|
||||
stackView.alignment = .center
|
||||
self.view.addSubview(stackView)
|
||||
|
||||
NSLayoutConstraint.activate([stackView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
|
||||
stackView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
|
||||
stackView.leadingAnchor.constraint(greaterThanOrEqualToSystemSpacingAfter: self.view.safeAreaLayoutGuide.leadingAnchor, multiplier: 1.0),
|
||||
self.view.safeAreaLayoutGuide.trailingAnchor.constraint(greaterThanOrEqualToSystemSpacingAfter: stackView.trailingAnchor, multiplier: 1.0)])
|
||||
|
||||
self.update()
|
||||
}
|
||||
}
|
||||
|
||||
private extension ViewController
|
||||
{
|
||||
@objc func backup()
|
||||
{
|
||||
self.currentOperation = .backup
|
||||
|
||||
self.backupController.performBackup { (result) in
|
||||
let appName = Bundle.main.appName ?? NSLocalizedString("App", comment: "")
|
||||
|
||||
let title = String(format: NSLocalizedString("%@ could not be backed up.", comment: ""), appName)
|
||||
self.process(result, errorTitle: title)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func restore()
|
||||
{
|
||||
self.currentOperation = .restore
|
||||
|
||||
self.backupController.restoreBackup { (result) in
|
||||
let appName = Bundle.main.appName ?? NSLocalizedString("App", comment: "")
|
||||
|
||||
let title = String(format: NSLocalizedString("%@ could not be restored.", comment: ""), appName)
|
||||
self.process(result, errorTitle: title)
|
||||
}
|
||||
}
|
||||
|
||||
func update()
|
||||
{
|
||||
switch self.currentOperation
|
||||
{
|
||||
case .backup:
|
||||
self.textLabel.text = NSLocalizedString("Backing up app data…", comment: "")
|
||||
self.detailTextLabel.isHidden = true
|
||||
self.activityIndicatorView.startAnimating()
|
||||
|
||||
case .restore:
|
||||
self.textLabel.text = NSLocalizedString("Restoring app data…", comment: "")
|
||||
self.detailTextLabel.isHidden = true
|
||||
self.activityIndicatorView.startAnimating()
|
||||
|
||||
case .none:
|
||||
self.textLabel.text = String(format: NSLocalizedString("%@ is inactive.", comment: ""),
|
||||
Bundle.main.appName ?? NSLocalizedString("App", comment: ""))
|
||||
|
||||
self.detailTextLabel.text = String(format: NSLocalizedString("Refresh %@ in SideStore to continue using it.", comment: ""),
|
||||
Bundle.main.appName ?? NSLocalizedString("this app", comment: ""))
|
||||
|
||||
self.detailTextLabel.isHidden = false
|
||||
self.activityIndicatorView.stopAnimating()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension ViewController
|
||||
{
|
||||
func process(_ result: Result<Void, Error>, errorTitle: String)
|
||||
{
|
||||
DispatchQueue.main.async {
|
||||
switch result
|
||||
{
|
||||
case .success: break
|
||||
case .failure(let error as NSError):
|
||||
let message: String
|
||||
|
||||
if let sourceDescription = error.sourceDescription
|
||||
{
|
||||
message = error.localizedDescription + "\n\n" + sourceDescription
|
||||
}
|
||||
else
|
||||
{
|
||||
message = error.localizedDescription
|
||||
}
|
||||
|
||||
let alertController = UIAlertController(title: errorTitle, message: message, preferredStyle: .alert)
|
||||
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
|
||||
self.present(alertController, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
NotificationCenter.default.post(name: AppDelegate.operationDidFinishNotification, object: nil, userInfo: [AppDelegate.operationResultKey: result])
|
||||
}
|
||||
}
|
||||
|
||||
@objc func didEnterBackground(_ notification: Notification)
|
||||
{
|
||||
// Reset UI once we've left app (but not before).
|
||||
self.currentOperation = nil
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
#include "Build.xcconfig"
|
||||
|
||||
PRODUCT_BUNDLE_IDENTIFIER = $(ORG_PREFIX).$(PRODUCT_NAME)
|
||||
@@ -1,8 +0,0 @@
|
||||
//
|
||||
// Use this file to import your target's public headers that you would like to expose to Swift.
|
||||
//
|
||||
|
||||
#import "NSAttributedString+Markdown.h"
|
||||
#import "ALTAppPatcher.h"
|
||||
|
||||
#include "fragmentzip.h"
|
||||
@@ -1,570 +0,0 @@
|
||||
//
|
||||
// AppViewController.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 7/22/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
import AltStoreCore
|
||||
import Roxas
|
||||
|
||||
import Nuke
|
||||
|
||||
final class AppViewController: UIViewController
|
||||
{
|
||||
var app: StoreApp!
|
||||
|
||||
private var contentViewController: AppContentViewController!
|
||||
private var contentViewControllerShadowView: UIView!
|
||||
|
||||
private var blurAnimator: UIViewPropertyAnimator?
|
||||
private var navigationBarAnimator: UIViewPropertyAnimator?
|
||||
|
||||
private var contentSizeObservation: NSKeyValueObservation?
|
||||
|
||||
@IBOutlet private var scrollView: UIScrollView!
|
||||
@IBOutlet private var contentView: UIView!
|
||||
|
||||
@IBOutlet private var bannerView: AppBannerView!
|
||||
|
||||
@IBOutlet private var backButton: UIButton!
|
||||
@IBOutlet private var backButtonContainerView: UIVisualEffectView!
|
||||
|
||||
@IBOutlet private var backgroundAppIconImageView: UIImageView!
|
||||
@IBOutlet private var backgroundBlurView: UIVisualEffectView!
|
||||
|
||||
@IBOutlet private var navigationBarTitleView: UIView!
|
||||
@IBOutlet private var navigationBarDownloadButton: PillButton!
|
||||
@IBOutlet private var navigationBarAppIconImageView: UIImageView!
|
||||
@IBOutlet private var navigationBarAppNameLabel: UILabel!
|
||||
|
||||
private var _shouldResetLayout = false
|
||||
private var _backgroundBlurEffect: UIBlurEffect?
|
||||
private var _backgroundBlurTintColor: UIColor?
|
||||
|
||||
private var _preferredStatusBarStyle: UIStatusBarStyle = .default
|
||||
|
||||
override var preferredStatusBarStyle: UIStatusBarStyle {
|
||||
return _preferredStatusBarStyle
|
||||
}
|
||||
|
||||
override func viewDidLoad()
|
||||
{
|
||||
super.viewDidLoad()
|
||||
|
||||
self.navigationBarTitleView.sizeToFit()
|
||||
self.navigationItem.titleView = self.navigationBarTitleView
|
||||
|
||||
self.contentViewControllerShadowView = UIView()
|
||||
self.contentViewControllerShadowView.backgroundColor = .white
|
||||
self.contentViewControllerShadowView.layer.cornerRadius = 38
|
||||
self.contentViewControllerShadowView.layer.shadowColor = UIColor.black.cgColor
|
||||
self.contentViewControllerShadowView.layer.shadowOffset = CGSize(width: 0, height: -1)
|
||||
self.contentViewControllerShadowView.layer.shadowRadius = 10
|
||||
self.contentViewControllerShadowView.layer.shadowOpacity = 0.3
|
||||
self.contentViewController.view.superview?.insertSubview(self.contentViewControllerShadowView, at: 0)
|
||||
|
||||
self.contentView.addGestureRecognizer(self.scrollView.panGestureRecognizer)
|
||||
|
||||
self.contentViewController.view.layer.cornerRadius = 38
|
||||
self.contentViewController.view.layer.masksToBounds = true
|
||||
|
||||
self.contentViewController.tableView.panGestureRecognizer.require(toFail: self.scrollView.panGestureRecognizer)
|
||||
self.contentViewController.tableView.showsVerticalScrollIndicator = false
|
||||
|
||||
// Bring to front so the scroll indicators are visible.
|
||||
self.view.bringSubviewToFront(self.scrollView)
|
||||
self.scrollView.isUserInteractionEnabled = false
|
||||
|
||||
self.bannerView.frame = CGRect(x: 0, y: 0, width: 300, height: 93)
|
||||
self.bannerView.backgroundEffectView.effect = UIBlurEffect(style: .regular)
|
||||
self.bannerView.backgroundEffectView.backgroundColor = .clear
|
||||
self.bannerView.iconImageView.image = nil
|
||||
self.bannerView.iconImageView.tintColor = self.app.tintColor
|
||||
self.bannerView.button.tintColor = self.app.tintColor
|
||||
self.bannerView.tintColor = self.app.tintColor
|
||||
|
||||
self.bannerView.configure(for: self.app)
|
||||
self.bannerView.accessibilityTraits.remove(.button)
|
||||
|
||||
self.bannerView.button.addTarget(self, action: #selector(AppViewController.performAppAction(_:)), for: .primaryActionTriggered)
|
||||
|
||||
self.backButtonContainerView.tintColor = self.app.tintColor
|
||||
|
||||
self.navigationController?.navigationBar.tintColor = self.app.tintColor
|
||||
self.navigationBarDownloadButton.tintColor = self.app.tintColor
|
||||
self.navigationBarAppNameLabel.text = self.app.name
|
||||
self.navigationBarAppIconImageView.tintColor = self.app.tintColor
|
||||
|
||||
self.contentSizeObservation = self.contentViewController.tableView.observe(\.contentSize) { [weak self] (tableView, change) in
|
||||
self?.view.setNeedsLayout()
|
||||
self?.view.layoutIfNeeded()
|
||||
}
|
||||
|
||||
self.update()
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(AppViewController.didChangeApp(_:)), name: .NSManagedObjectContextObjectsDidChange, object: DatabaseManager.shared.viewContext)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(AppViewController.willEnterForeground(_:)), name: UIApplication.willEnterForegroundNotification, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(AppViewController.didBecomeActive(_:)), name: UIApplication.didBecomeActiveNotification, object: nil)
|
||||
|
||||
self._backgroundBlurEffect = self.backgroundBlurView.effect as? UIBlurEffect
|
||||
self._backgroundBlurTintColor = self.backgroundBlurView.contentView.backgroundColor
|
||||
|
||||
// Load Images
|
||||
for imageView in [self.bannerView.iconImageView!, self.backgroundAppIconImageView!, self.navigationBarAppIconImageView!]
|
||||
{
|
||||
imageView.isIndicatingActivity = true
|
||||
|
||||
Nuke.loadImage(with: self.app.iconURL, options: .shared, into: imageView, progress: nil) { [weak imageView] (response, error) in
|
||||
if response?.image != nil
|
||||
{
|
||||
imageView?.isIndicatingActivity = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool)
|
||||
{
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
self.prepareBlur()
|
||||
|
||||
// Update blur immediately.
|
||||
self.view.setNeedsLayout()
|
||||
self.view.layoutIfNeeded()
|
||||
|
||||
self.transitionCoordinator?.animate(alongsideTransition: { (context) in
|
||||
self.hideNavigationBar()
|
||||
}, completion: nil)
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool)
|
||||
{
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
self._shouldResetLayout = true
|
||||
self.view.setNeedsLayout()
|
||||
self.view.layoutIfNeeded()
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool)
|
||||
{
|
||||
super.viewWillDisappear(animated)
|
||||
|
||||
// Guard against "dismissing" when presenting via 3D Touch pop.
|
||||
guard self.navigationController != nil else { return }
|
||||
|
||||
// Store reference since self.navigationController will be nil after disappearing.
|
||||
let navigationController = self.navigationController
|
||||
navigationController?.navigationBar.barStyle = .default // Don't animate, or else status bar might appear messed-up.
|
||||
|
||||
self.transitionCoordinator?.animate(alongsideTransition: { (context) in
|
||||
self.showNavigationBar(for: navigationController)
|
||||
}, completion: { (context) in
|
||||
if !context.isCancelled
|
||||
{
|
||||
self.showNavigationBar(for: navigationController)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override func viewDidDisappear(_ animated: Bool)
|
||||
{
|
||||
super.viewDidDisappear(animated)
|
||||
|
||||
if self.navigationController == nil
|
||||
{
|
||||
self.resetNavigationBarAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
|
||||
{
|
||||
guard segue.identifier == "embedAppContentViewController" else { return }
|
||||
|
||||
self.contentViewController = segue.destination as? AppContentViewController
|
||||
self.contentViewController.app = self.app
|
||||
|
||||
if #available(iOS 15, *)
|
||||
{
|
||||
// Fix navigation bar + tab bar appearance on iOS 15.
|
||||
self.setContentScrollView(self.scrollView)
|
||||
self.navigationItem.scrollEdgeAppearance = self.navigationController?.navigationBar.standardAppearance
|
||||
}
|
||||
}
|
||||
|
||||
override func viewDidLayoutSubviews()
|
||||
{
|
||||
super.viewDidLayoutSubviews()
|
||||
|
||||
if self._shouldResetLayout
|
||||
{
|
||||
// Various events can cause UI to mess up, so reset affected components now.
|
||||
|
||||
if self.navigationController?.topViewController == self
|
||||
{
|
||||
self.hideNavigationBar()
|
||||
}
|
||||
|
||||
self.prepareBlur()
|
||||
|
||||
// Reset navigation bar animation, and create a new one later in this method if necessary.
|
||||
self.resetNavigationBarAnimation()
|
||||
|
||||
self._shouldResetLayout = false
|
||||
}
|
||||
|
||||
let statusBarHeight = UIApplication.shared.statusBarFrame.height
|
||||
let cornerRadius = self.contentViewControllerShadowView.layer.cornerRadius
|
||||
|
||||
let inset = 12 as CGFloat
|
||||
let padding = 20 as CGFloat
|
||||
|
||||
let backButtonSize = self.backButton.sizeThatFits(CGSize(width: 1000, height: 1000))
|
||||
var backButtonFrame = CGRect(x: inset, y: statusBarHeight,
|
||||
width: backButtonSize.width + 20, height: backButtonSize.height + 20)
|
||||
|
||||
var headerFrame = CGRect(x: inset, y: 0, width: self.view.bounds.width - inset * 2, height: self.bannerView.bounds.height)
|
||||
var contentFrame = CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.view.bounds.height)
|
||||
var backgroundIconFrame = CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.view.bounds.width)
|
||||
|
||||
let minimumHeaderY = backButtonFrame.maxY + 8
|
||||
|
||||
let minimumContentY = minimumHeaderY + headerFrame.height + padding
|
||||
let maximumContentY = self.view.bounds.width * 0.667
|
||||
|
||||
// A full blur is too much, so we reduce the visible blur by 0.3, resulting in 70% blur.
|
||||
let minimumBlurFraction = 0.3 as CGFloat
|
||||
|
||||
contentFrame.origin.y = maximumContentY - self.scrollView.contentOffset.y
|
||||
headerFrame.origin.y = contentFrame.origin.y - padding - headerFrame.height
|
||||
|
||||
// Stretch the app icon image to fill additional vertical space if necessary.
|
||||
let height = max(contentFrame.origin.y + cornerRadius * 2, backgroundIconFrame.height)
|
||||
backgroundIconFrame.size.height = height
|
||||
|
||||
let blurThreshold = 0 as CGFloat
|
||||
if self.scrollView.contentOffset.y < blurThreshold
|
||||
{
|
||||
// Determine how much to lessen blur by.
|
||||
|
||||
let range = 75 as CGFloat
|
||||
let difference = -self.scrollView.contentOffset.y
|
||||
|
||||
let fraction = min(difference, range) / range
|
||||
|
||||
let fractionComplete = (fraction * (1.0 - minimumBlurFraction)) + minimumBlurFraction
|
||||
self.blurAnimator?.fractionComplete = fractionComplete
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set blur to default.
|
||||
|
||||
self.blurAnimator?.fractionComplete = minimumBlurFraction
|
||||
}
|
||||
|
||||
// Animate navigation bar.
|
||||
let showNavigationBarThreshold = (maximumContentY - minimumContentY) + backButtonFrame.origin.y
|
||||
if self.scrollView.contentOffset.y > showNavigationBarThreshold
|
||||
{
|
||||
if self.navigationBarAnimator == nil
|
||||
{
|
||||
self.prepareNavigationBarAnimation()
|
||||
}
|
||||
|
||||
let difference = self.scrollView.contentOffset.y - showNavigationBarThreshold
|
||||
let range = (headerFrame.height + padding) - (self.navigationController?.navigationBar.bounds.height ?? self.view.safeAreaInsets.top)
|
||||
|
||||
let fractionComplete = min(difference, range) / range
|
||||
self.navigationBarAnimator?.fractionComplete = fractionComplete
|
||||
}
|
||||
else
|
||||
{
|
||||
self.resetNavigationBarAnimation()
|
||||
}
|
||||
|
||||
let beginMovingBackButtonThreshold = (maximumContentY - minimumContentY)
|
||||
if self.scrollView.contentOffset.y > beginMovingBackButtonThreshold
|
||||
{
|
||||
let difference = self.scrollView.contentOffset.y - beginMovingBackButtonThreshold
|
||||
backButtonFrame.origin.y -= difference
|
||||
}
|
||||
|
||||
let pinContentToTopThreshold = maximumContentY
|
||||
if self.scrollView.contentOffset.y > pinContentToTopThreshold
|
||||
{
|
||||
contentFrame.origin.y = 0
|
||||
backgroundIconFrame.origin.y = 0
|
||||
|
||||
let difference = self.scrollView.contentOffset.y - pinContentToTopThreshold
|
||||
self.contentViewController.tableView.contentOffset.y = difference
|
||||
}
|
||||
else
|
||||
{
|
||||
// Keep content table view's content offset at the top.
|
||||
self.contentViewController.tableView.contentOffset.y = 0
|
||||
}
|
||||
|
||||
// Keep background app icon centered in gap between top of content and top of screen.
|
||||
backgroundIconFrame.origin.y = (contentFrame.origin.y / 2) - backgroundIconFrame.height / 2
|
||||
|
||||
// Set frames.
|
||||
self.contentViewController.view.superview?.frame = contentFrame
|
||||
self.bannerView.frame = headerFrame
|
||||
self.backgroundAppIconImageView.frame = backgroundIconFrame
|
||||
self.backgroundBlurView.frame = backgroundIconFrame
|
||||
self.backButtonContainerView.frame = backButtonFrame
|
||||
|
||||
self.contentViewControllerShadowView.frame = self.contentViewController.view.frame
|
||||
|
||||
self.backButtonContainerView.layer.cornerRadius = self.backButtonContainerView.bounds.midY
|
||||
|
||||
self.scrollView.scrollIndicatorInsets.top = statusBarHeight
|
||||
|
||||
// Adjust content offset + size.
|
||||
let contentOffset = self.scrollView.contentOffset
|
||||
|
||||
var contentSize = self.contentViewController.tableView.contentSize
|
||||
contentSize.height += maximumContentY
|
||||
|
||||
self.scrollView.contentSize = contentSize
|
||||
self.scrollView.contentOffset = contentOffset
|
||||
|
||||
self.bannerView.backgroundEffectView.backgroundColor = .clear
|
||||
}
|
||||
|
||||
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)
|
||||
{
|
||||
super.traitCollectionDidChange(previousTraitCollection)
|
||||
self._shouldResetLayout = true
|
||||
}
|
||||
|
||||
deinit
|
||||
{
|
||||
self.blurAnimator?.stopAnimation(true)
|
||||
self.navigationBarAnimator?.stopAnimation(true)
|
||||
}
|
||||
}
|
||||
|
||||
extension AppViewController
|
||||
{
|
||||
final class func makeAppViewController(app: StoreApp) -> AppViewController
|
||||
{
|
||||
let storyboard = UIStoryboard(name: "Main", bundle: nil)
|
||||
|
||||
let appViewController = storyboard.instantiateViewController(withIdentifier: "appViewController") as! AppViewController
|
||||
appViewController.app = app
|
||||
return appViewController
|
||||
}
|
||||
}
|
||||
|
||||
private extension AppViewController
|
||||
{
|
||||
func update()
|
||||
{
|
||||
for button in [self.bannerView.button!, self.navigationBarDownloadButton!]
|
||||
{
|
||||
button.tintColor = self.app.tintColor
|
||||
button.isIndicatingActivity = false
|
||||
|
||||
if self.app.installedApp == nil
|
||||
{
|
||||
button.setTitle(NSLocalizedString("FREE", comment: ""), for: .normal)
|
||||
}
|
||||
else
|
||||
{
|
||||
button.setTitle(NSLocalizedString("OPEN", comment: ""), for: .normal)
|
||||
}
|
||||
|
||||
let progress = AppManager.shared.installationProgress(for: self.app)
|
||||
button.progress = progress
|
||||
}
|
||||
|
||||
if let versionDate = self.app.latestVersion?.date, versionDate > Date()
|
||||
{
|
||||
self.bannerView.button.countdownDate = versionDate
|
||||
self.navigationBarDownloadButton.countdownDate = versionDate
|
||||
}
|
||||
else
|
||||
{
|
||||
self.bannerView.button.countdownDate = nil
|
||||
self.navigationBarDownloadButton.countdownDate = nil
|
||||
}
|
||||
|
||||
let barButtonItem = self.navigationItem.rightBarButtonItem
|
||||
self.navigationItem.rightBarButtonItem = nil
|
||||
self.navigationItem.rightBarButtonItem = barButtonItem
|
||||
}
|
||||
|
||||
func showNavigationBar(for navigationController: UINavigationController? = nil)
|
||||
{
|
||||
let navigationController = navigationController ?? self.navigationController
|
||||
navigationController?.navigationBar.alpha = 1.0
|
||||
navigationController?.navigationBar.tintColor = .altPrimary
|
||||
navigationController?.navigationBar.setNeedsLayout()
|
||||
|
||||
if self.traitCollection.userInterfaceStyle == .dark
|
||||
{
|
||||
self._preferredStatusBarStyle = .lightContent
|
||||
}
|
||||
else
|
||||
{
|
||||
self._preferredStatusBarStyle = .default
|
||||
}
|
||||
|
||||
navigationController?.setNeedsStatusBarAppearanceUpdate()
|
||||
}
|
||||
|
||||
func hideNavigationBar(for navigationController: UINavigationController? = nil)
|
||||
{
|
||||
let navigationController = navigationController ?? self.navigationController
|
||||
navigationController?.navigationBar.alpha = 0.0
|
||||
|
||||
self._preferredStatusBarStyle = .lightContent
|
||||
navigationController?.setNeedsStatusBarAppearanceUpdate()
|
||||
}
|
||||
|
||||
func prepareBlur()
|
||||
{
|
||||
if let animator = self.blurAnimator
|
||||
{
|
||||
animator.stopAnimation(true)
|
||||
}
|
||||
|
||||
self.backgroundBlurView.effect = self._backgroundBlurEffect
|
||||
self.backgroundBlurView.contentView.backgroundColor = self._backgroundBlurTintColor
|
||||
|
||||
self.blurAnimator = UIViewPropertyAnimator(duration: 1.0, curve: .linear) { [weak self] in
|
||||
self?.backgroundBlurView.effect = nil
|
||||
self?.backgroundBlurView.contentView.backgroundColor = .clear
|
||||
}
|
||||
|
||||
self.blurAnimator?.startAnimation()
|
||||
self.blurAnimator?.pauseAnimation()
|
||||
}
|
||||
|
||||
func prepareNavigationBarAnimation()
|
||||
{
|
||||
self.resetNavigationBarAnimation()
|
||||
|
||||
self.navigationBarAnimator = UIViewPropertyAnimator(duration: 1.0, curve: .linear) { [weak self] in
|
||||
self?.showNavigationBar()
|
||||
self?.navigationController?.navigationBar.tintColor = self?.app.tintColor
|
||||
self?.navigationController?.navigationBar.barTintColor = nil
|
||||
self?.contentViewController.view.layer.cornerRadius = 0
|
||||
}
|
||||
|
||||
self.navigationBarAnimator?.startAnimation()
|
||||
self.navigationBarAnimator?.pauseAnimation()
|
||||
|
||||
self.update()
|
||||
}
|
||||
|
||||
func resetNavigationBarAnimation()
|
||||
{
|
||||
self.navigationBarAnimator?.stopAnimation(true)
|
||||
self.navigationBarAnimator = nil
|
||||
|
||||
self.hideNavigationBar()
|
||||
|
||||
self.contentViewController.view.layer.cornerRadius = self.contentViewControllerShadowView.layer.cornerRadius
|
||||
}
|
||||
}
|
||||
|
||||
extension AppViewController
|
||||
{
|
||||
@IBAction func popViewController(_ sender: UIButton)
|
||||
{
|
||||
self.navigationController?.popViewController(animated: true)
|
||||
}
|
||||
|
||||
@IBAction func performAppAction(_ sender: PillButton)
|
||||
{
|
||||
if let installedApp = self.app.installedApp
|
||||
{
|
||||
self.open(installedApp)
|
||||
}
|
||||
else
|
||||
{
|
||||
self.downloadApp()
|
||||
}
|
||||
}
|
||||
|
||||
func downloadApp()
|
||||
{
|
||||
guard self.app.installedApp == nil else { return }
|
||||
|
||||
let group = AppManager.shared.install(self.app, presentingViewController: self) { (result) in
|
||||
do
|
||||
{
|
||||
_ = try result.get()
|
||||
}
|
||||
catch OperationError.cancelled
|
||||
{
|
||||
// Ignore
|
||||
}
|
||||
catch
|
||||
{
|
||||
DispatchQueue.main.async {
|
||||
let toastView = ToastView(error: error)
|
||||
toastView.show(in: self)
|
||||
}
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.bannerView.button.progress = nil
|
||||
self.navigationBarDownloadButton.progress = nil
|
||||
self.update()
|
||||
}
|
||||
}
|
||||
|
||||
self.bannerView.button.progress = group.progress
|
||||
self.navigationBarDownloadButton.progress = group.progress
|
||||
}
|
||||
|
||||
func open(_ installedApp: InstalledApp)
|
||||
{
|
||||
UIApplication.shared.open(installedApp.openAppURL)
|
||||
}
|
||||
}
|
||||
|
||||
private extension AppViewController
|
||||
{
|
||||
@objc func didChangeApp(_ notification: Notification)
|
||||
{
|
||||
// Async so that AppManager.installationProgress(for:) is nil when we update.
|
||||
DispatchQueue.main.async {
|
||||
self.update()
|
||||
}
|
||||
}
|
||||
|
||||
@objc func willEnterForeground(_ notification: Notification)
|
||||
{
|
||||
guard let navigationController = self.navigationController, navigationController.topViewController == self else { return }
|
||||
|
||||
self._shouldResetLayout = true
|
||||
self.view.setNeedsLayout()
|
||||
}
|
||||
|
||||
@objc func didBecomeActive(_ notification: Notification)
|
||||
{
|
||||
guard let navigationController = self.navigationController, navigationController.topViewController == self else { return }
|
||||
|
||||
// Fixes Navigation Bar appearing after app becomes inactive -> active again.
|
||||
self._shouldResetLayout = true
|
||||
self.view.setNeedsLayout()
|
||||
}
|
||||
}
|
||||
|
||||
extension AppViewController: UIScrollViewDelegate
|
||||
{
|
||||
func scrollViewDidScroll(_ scrollView: UIScrollView)
|
||||
{
|
||||
self.view.setNeedsLayout()
|
||||
self.view.layoutIfNeeded()
|
||||
}
|
||||
}
|
||||
@@ -1,241 +0,0 @@
|
||||
//
|
||||
// AppIDsViewController.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 1/27/20.
|
||||
// Copyright © 2020 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
import AltStoreCore
|
||||
import Roxas
|
||||
|
||||
final class AppIDsViewController: UICollectionViewController
|
||||
{
|
||||
private lazy var dataSource = self.makeDataSource()
|
||||
|
||||
private var didInitialFetch = false
|
||||
private var isLoading = false {
|
||||
didSet {
|
||||
self.update()
|
||||
}
|
||||
}
|
||||
|
||||
@IBOutlet var activityIndicatorBarButtonItem: UIBarButtonItem!
|
||||
|
||||
override func viewDidLoad()
|
||||
{
|
||||
super.viewDidLoad()
|
||||
|
||||
self.collectionView.dataSource = self.dataSource
|
||||
|
||||
self.activityIndicatorBarButtonItem.isIndicatingActivity = true
|
||||
|
||||
let refreshControl = UIRefreshControl()
|
||||
refreshControl.addTarget(self, action: #selector(AppIDsViewController.fetchAppIDs), for: .primaryActionTriggered)
|
||||
self.collectionView.refreshControl = refreshControl
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool)
|
||||
{
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
if !self.didInitialFetch
|
||||
{
|
||||
self.fetchAppIDs()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension AppIDsViewController
|
||||
{
|
||||
func makeDataSource() -> RSTFetchedResultsCollectionViewDataSource<AppID>
|
||||
{
|
||||
let fetchRequest = AppID.fetchRequest() as NSFetchRequest<AppID>
|
||||
fetchRequest.sortDescriptors = [NSSortDescriptor(keyPath: \AppID.name, ascending: true),
|
||||
NSSortDescriptor(keyPath: \AppID.bundleIdentifier, ascending: true),
|
||||
NSSortDescriptor(keyPath: \AppID.expirationDate, ascending: true)]
|
||||
fetchRequest.returnsObjectsAsFaults = false
|
||||
|
||||
if let team = DatabaseManager.shared.activeTeam()
|
||||
{
|
||||
fetchRequest.predicate = NSPredicate(format: "%K == %@", #keyPath(AppID.team), team)
|
||||
}
|
||||
else
|
||||
{
|
||||
fetchRequest.predicate = NSPredicate(value: false)
|
||||
}
|
||||
|
||||
let dataSource = RSTFetchedResultsCollectionViewDataSource<AppID>(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.shared.viewContext)
|
||||
dataSource.proxy = self
|
||||
dataSource.cellConfigurationHandler = { (cell, appID, indexPath) in
|
||||
let tintColor = UIColor.altPrimary
|
||||
|
||||
let cell = cell as! BannerCollectionViewCell
|
||||
cell.layoutMargins.left = self.view.layoutMargins.left
|
||||
cell.layoutMargins.right = self.view.layoutMargins.right
|
||||
cell.tintColor = tintColor
|
||||
|
||||
cell.bannerView.iconImageView.isHidden = true
|
||||
cell.bannerView.button.isIndicatingActivity = false
|
||||
|
||||
cell.bannerView.buttonLabel.text = NSLocalizedString("Expires in", comment: "")
|
||||
|
||||
let attributedAccessibilityLabel = NSMutableAttributedString(string: appID.name + ". ")
|
||||
|
||||
if let expirationDate = appID.expirationDate
|
||||
{
|
||||
cell.bannerView.button.isHidden = false
|
||||
cell.bannerView.button.isUserInteractionEnabled = false
|
||||
|
||||
cell.bannerView.buttonLabel.isHidden = false
|
||||
|
||||
let currentDate = Date()
|
||||
|
||||
let numberOfDays = expirationDate.numberOfCalendarDays(since: currentDate)
|
||||
let numberOfDaysText = (numberOfDays == 1) ? NSLocalizedString("1 day", comment: "") : String(format: NSLocalizedString("%@ days", comment: ""), NSNumber(value: numberOfDays))
|
||||
cell.bannerView.button.setTitle(numberOfDaysText.uppercased(), for: .normal)
|
||||
|
||||
attributedAccessibilityLabel.mutableString.append(String(format: NSLocalizedString("Expires in %@.", comment: ""), numberOfDaysText) + " ")
|
||||
}
|
||||
else
|
||||
{
|
||||
cell.bannerView.button.isHidden = true
|
||||
cell.bannerView.button.isUserInteractionEnabled = true
|
||||
|
||||
cell.bannerView.buttonLabel.isHidden = true
|
||||
}
|
||||
|
||||
cell.bannerView.titleLabel.text = appID.name
|
||||
cell.bannerView.subtitleLabel.text = appID.bundleIdentifier
|
||||
cell.bannerView.subtitleLabel.numberOfLines = 2
|
||||
|
||||
let attributedBundleIdentifier = NSMutableAttributedString(string: appID.bundleIdentifier.lowercased(), attributes: [.accessibilitySpeechPunctuation: true])
|
||||
|
||||
if let team = appID.team, let range = attributedBundleIdentifier.string.range(of: team.identifier.lowercased()), #available(iOS 13, *)
|
||||
{
|
||||
// Prefer to speak the team ID one character at a time.
|
||||
let nsRange = NSRange(range, in: attributedBundleIdentifier.string)
|
||||
attributedBundleIdentifier.addAttributes([.accessibilitySpeechSpellOut: true], range: nsRange)
|
||||
}
|
||||
|
||||
attributedAccessibilityLabel.append(attributedBundleIdentifier)
|
||||
cell.bannerView.accessibilityAttributedLabel = attributedAccessibilityLabel
|
||||
|
||||
// Make sure refresh button is correct size.
|
||||
cell.layoutIfNeeded()
|
||||
}
|
||||
|
||||
return dataSource
|
||||
}
|
||||
|
||||
@objc func fetchAppIDs()
|
||||
{
|
||||
guard !self.isLoading else { return }
|
||||
self.isLoading = true
|
||||
|
||||
AppManager.shared.fetchAppIDs { (result) in
|
||||
do
|
||||
{
|
||||
let (_, context) = try result.get()
|
||||
try context.save()
|
||||
}
|
||||
catch
|
||||
{
|
||||
DispatchQueue.main.async {
|
||||
let toastView = ToastView(error: error)
|
||||
toastView.show(in: self)
|
||||
}
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.isLoading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func update()
|
||||
{
|
||||
if !self.isLoading
|
||||
{
|
||||
self.collectionView.refreshControl?.endRefreshing()
|
||||
self.activityIndicatorBarButtonItem.isIndicatingActivity = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension AppIDsViewController: UICollectionViewDelegateFlowLayout
|
||||
{
|
||||
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
|
||||
{
|
||||
return CGSize(width: collectionView.bounds.width, height: 80)
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize
|
||||
{
|
||||
let indexPath = IndexPath(row: 0, section: section)
|
||||
let headerView = self.collectionView(collectionView, viewForSupplementaryElementOfKind: UICollectionView.elementKindSectionHeader, at: indexPath)
|
||||
|
||||
// Use this view to calculate the optimal size based on the collection view's width
|
||||
let size = headerView.systemLayoutSizeFitting(CGSize(width: collectionView.frame.width, height: UIView.layoutFittingExpandedSize.height),
|
||||
withHorizontalFittingPriority: .required, // Width is fixed
|
||||
verticalFittingPriority: .fittingSizeLevel) // Height can be as large as needed
|
||||
return size
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize
|
||||
{
|
||||
return CGSize(width: collectionView.bounds.width, height: 50)
|
||||
}
|
||||
|
||||
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView
|
||||
{
|
||||
switch kind
|
||||
{
|
||||
case UICollectionView.elementKindSectionHeader:
|
||||
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "Header", for: indexPath) as! TextCollectionReusableView
|
||||
headerView.layoutMargins.left = self.view.layoutMargins.left
|
||||
headerView.layoutMargins.right = self.view.layoutMargins.right
|
||||
|
||||
if let activeTeam = DatabaseManager.shared.activeTeam(), activeTeam.type == .free
|
||||
{
|
||||
let text = NSLocalizedString("""
|
||||
Each app and app extension installed with SideStore must register an App ID with Apple. Apple limits non-developer Apple IDs to 10 App IDs at a time.
|
||||
|
||||
**App IDs can't be deleted**, but they do expire after one week. SideStore will automatically renew App IDs for all active apps once they've expired.
|
||||
""", comment: "")
|
||||
|
||||
let attributedText = NSAttributedString(markdownRepresentation: text, attributes: [.font: headerView.textLabel.font as Any])
|
||||
headerView.textLabel.attributedText = attributedText
|
||||
}
|
||||
else
|
||||
{
|
||||
headerView.textLabel.text = NSLocalizedString("""
|
||||
Each app and app extension installed with SideStore must register an App ID with Apple.
|
||||
|
||||
App IDs for paid developer accounts never expire, and there is no limit to how many you can create.
|
||||
""", comment: "")
|
||||
}
|
||||
|
||||
return headerView
|
||||
|
||||
case UICollectionView.elementKindSectionFooter:
|
||||
let footerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "Footer", for: indexPath) as! TextCollectionReusableView
|
||||
|
||||
let count = self.dataSource.itemCount
|
||||
if count == 1
|
||||
{
|
||||
footerView.textLabel.text = NSLocalizedString("1 App ID", comment: "")
|
||||
}
|
||||
else
|
||||
{
|
||||
footerView.textLabel.text = String(format: NSLocalizedString("%@ App IDs", comment: ""), NSNumber(value: count))
|
||||
}
|
||||
|
||||
return footerView
|
||||
|
||||
default: fatalError()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
//
|
||||
// AuthenticationViewController.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 9/5/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
import AltSign
|
||||
|
||||
final class AuthenticationViewController: UIViewController
|
||||
{
|
||||
var authenticationHandler: ((String, String, @escaping (Result<(ALTAccount, ALTAppleAPISession), Error>) -> Void) -> Void)?
|
||||
var completionHandler: (((ALTAccount, ALTAppleAPISession, String)?) -> Void)?
|
||||
|
||||
private weak var toastView: ToastView?
|
||||
|
||||
@IBOutlet private var appleIDTextField: UITextField!
|
||||
@IBOutlet private var passwordTextField: UITextField!
|
||||
@IBOutlet private var signInButton: UIButton!
|
||||
|
||||
@IBOutlet private var appleIDBackgroundView: UIView!
|
||||
@IBOutlet private var passwordBackgroundView: UIView!
|
||||
|
||||
@IBOutlet private var scrollView: UIScrollView!
|
||||
@IBOutlet private var contentStackView: UIStackView!
|
||||
|
||||
override func viewDidLoad()
|
||||
{
|
||||
super.viewDidLoad()
|
||||
|
||||
self.signInButton.activityIndicatorView.style = .medium
|
||||
|
||||
for view in [self.appleIDBackgroundView!, self.passwordBackgroundView!, self.signInButton!]
|
||||
{
|
||||
view.clipsToBounds = true
|
||||
view.layer.cornerRadius = 16
|
||||
}
|
||||
|
||||
if UIScreen.main.isExtraCompactHeight
|
||||
{
|
||||
self.contentStackView.spacing = 20
|
||||
}
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(AuthenticationViewController.textFieldDidChangeText(_:)), name: UITextField.textDidChangeNotification, object: self.appleIDTextField)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(AuthenticationViewController.textFieldDidChangeText(_:)), name: UITextField.textDidChangeNotification, object: self.passwordTextField)
|
||||
|
||||
self.update()
|
||||
}
|
||||
|
||||
override func viewDidDisappear(_ animated: Bool)
|
||||
{
|
||||
super.viewDidDisappear(animated)
|
||||
|
||||
self.signInButton.isIndicatingActivity = false
|
||||
self.toastView?.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
private extension AuthenticationViewController
|
||||
{
|
||||
func update()
|
||||
{
|
||||
if let _ = self.validate()
|
||||
{
|
||||
self.signInButton.isEnabled = true
|
||||
self.signInButton.alpha = 1.0
|
||||
}
|
||||
else
|
||||
{
|
||||
self.signInButton.isEnabled = false
|
||||
self.signInButton.alpha = 0.6
|
||||
}
|
||||
}
|
||||
|
||||
func validate() -> (String, String)?
|
||||
{
|
||||
guard
|
||||
let emailAddress = self.appleIDTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines), !emailAddress.isEmpty,
|
||||
let password = self.passwordTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines), !password.isEmpty
|
||||
else { return nil }
|
||||
|
||||
return (emailAddress, password)
|
||||
}
|
||||
}
|
||||
|
||||
private extension AuthenticationViewController
|
||||
{
|
||||
@IBAction func authenticate()
|
||||
{
|
||||
guard let (emailAddress, password) = self.validate() else { return }
|
||||
|
||||
self.appleIDTextField.resignFirstResponder()
|
||||
self.passwordTextField.resignFirstResponder()
|
||||
|
||||
self.signInButton.isIndicatingActivity = true
|
||||
|
||||
self.authenticationHandler?(emailAddress, password) { (result) in
|
||||
switch result
|
||||
{
|
||||
case .failure(ALTAppleAPIError.requiresTwoFactorAuthentication):
|
||||
// Ignore
|
||||
DispatchQueue.main.async {
|
||||
self.signInButton.isIndicatingActivity = false
|
||||
}
|
||||
|
||||
case .failure(let error as NSError):
|
||||
DispatchQueue.main.async {
|
||||
let error = error.withLocalizedFailure(NSLocalizedString("Failed to Log In", comment: ""))
|
||||
|
||||
let toastView = ToastView(error: error)
|
||||
toastView.textLabel.textColor = .altPink
|
||||
toastView.detailTextLabel.textColor = .altPink
|
||||
toastView.show(in: self)
|
||||
self.toastView = toastView
|
||||
|
||||
self.signInButton.isIndicatingActivity = false
|
||||
}
|
||||
|
||||
case .success((let account, let session)):
|
||||
self.completionHandler?((account, session, password))
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.scrollView.setContentOffset(CGPoint(x: 0, y: -self.view.safeAreaInsets.top), animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func cancel(_ sender: UIBarButtonItem)
|
||||
{
|
||||
self.completionHandler?(nil)
|
||||
}
|
||||
}
|
||||
|
||||
extension AuthenticationViewController: UITextFieldDelegate
|
||||
{
|
||||
func textFieldShouldReturn(_ textField: UITextField) -> Bool
|
||||
{
|
||||
switch textField
|
||||
{
|
||||
case self.appleIDTextField: self.passwordTextField.becomeFirstResponder()
|
||||
case self.passwordTextField: self.authenticate()
|
||||
default: break
|
||||
}
|
||||
|
||||
self.update()
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func textFieldDidBeginEditing(_ textField: UITextField)
|
||||
{
|
||||
guard UIScreen.main.isExtraCompactHeight else { return }
|
||||
|
||||
// Position all the controls within visible frame.
|
||||
var contentOffset = self.scrollView.contentOffset
|
||||
contentOffset.y = 44
|
||||
self.scrollView.setContentOffset(contentOffset, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
extension AuthenticationViewController
|
||||
{
|
||||
@objc func textFieldDidChangeText(_ notification: Notification)
|
||||
{
|
||||
self.update()
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
//
|
||||
// InstructionsViewController.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 9/6/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
final class InstructionsViewController: UIViewController
|
||||
{
|
||||
var completionHandler: (() -> Void)?
|
||||
|
||||
var showsBottomButton: Bool = false
|
||||
|
||||
@IBOutlet private var contentStackView: UIStackView!
|
||||
@IBOutlet private var dismissButton: UIButton!
|
||||
|
||||
override var preferredStatusBarStyle: UIStatusBarStyle {
|
||||
return .lightContent
|
||||
}
|
||||
|
||||
override func viewDidLoad()
|
||||
{
|
||||
super.viewDidLoad()
|
||||
|
||||
if UIScreen.main.isExtraCompactHeight
|
||||
{
|
||||
self.contentStackView.layoutMargins.top = 0
|
||||
self.contentStackView.layoutMargins.bottom = self.contentStackView.layoutMargins.left
|
||||
}
|
||||
|
||||
self.dismissButton.clipsToBounds = true
|
||||
self.dismissButton.layer.cornerRadius = 16
|
||||
|
||||
if self.showsBottomButton
|
||||
{
|
||||
self.navigationItem.hidesBackButton = true
|
||||
}
|
||||
else
|
||||
{
|
||||
self.dismissButton.isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension InstructionsViewController
|
||||
{
|
||||
@IBAction func dismiss()
|
||||
{
|
||||
self.completionHandler?()
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
//
|
||||
// SelectTeamViewController.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Megarushing on 4/26/21.
|
||||
// Copyright © 2021 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SafariServices
|
||||
import MessageUI
|
||||
import Intents
|
||||
import IntentsUI
|
||||
|
||||
import AltSign
|
||||
|
||||
final class SelectTeamViewController: UITableViewController
|
||||
{
|
||||
public var teams: [ALTTeam]?
|
||||
public var completionHandler: ((Result<ALTTeam, Swift.Error>) -> Void)?
|
||||
|
||||
private var prototypeHeaderFooterView: SettingsHeaderFooterView!
|
||||
|
||||
override var preferredStatusBarStyle: UIStatusBarStyle {
|
||||
return .lightContent
|
||||
}
|
||||
|
||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return 1
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return teams?.count ?? 0
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
return self.completionHandler!(.success((self.teams?[indexPath.row])!))
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "TeamCell", for: indexPath) as! InsetGroupTableViewCell
|
||||
|
||||
cell.textLabel?.text = self.teams?[indexPath.row].name
|
||||
cell.detailTextLabel?.text = self.teams?[indexPath.row].type.localizedDescription
|
||||
if indexPath.row == 0
|
||||
{
|
||||
cell.style = InsetGroupTableViewCell.Style.top
|
||||
} else if indexPath.row == self.tableView(self.tableView, numberOfRowsInSection: indexPath.section) - 1 {
|
||||
cell.style = InsetGroupTableViewCell.Style.bottom
|
||||
} else {
|
||||
cell.style = InsetGroupTableViewCell.Style.middle
|
||||
}
|
||||
|
||||
return cell
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
"Teams"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
//
|
||||
// ScreenshotCollectionViewCell.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 7/15/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
import Roxas
|
||||
|
||||
@objc(ScreenshotCollectionViewCell)
|
||||
class ScreenshotCollectionViewCell: UICollectionViewCell
|
||||
{
|
||||
let imageView = UIImageView(image: nil)
|
||||
|
||||
override init(frame: CGRect)
|
||||
{
|
||||
super.init(frame: frame)
|
||||
|
||||
self.initialize()
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder)
|
||||
{
|
||||
super.init(coder: aDecoder)
|
||||
|
||||
self.initialize()
|
||||
}
|
||||
|
||||
private func initialize()
|
||||
{
|
||||
self.imageView.layer.masksToBounds = true
|
||||
self.addSubview(self.imageView, pinningEdgesWith: .zero)
|
||||
}
|
||||
|
||||
override func layoutSubviews()
|
||||
{
|
||||
super.layoutSubviews()
|
||||
|
||||
self.imageView.layer.cornerRadius = 4
|
||||
}
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
//
|
||||
// AppBannerView.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 8/29/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
import AltStoreCore
|
||||
import Roxas
|
||||
|
||||
class AppBannerView: RSTNibView
|
||||
{
|
||||
override var accessibilityLabel: String? {
|
||||
get { return self.accessibilityView?.accessibilityLabel }
|
||||
set { self.accessibilityView?.accessibilityLabel = newValue }
|
||||
}
|
||||
|
||||
override open var accessibilityAttributedLabel: NSAttributedString? {
|
||||
get { return self.accessibilityView?.accessibilityAttributedLabel }
|
||||
set { self.accessibilityView?.accessibilityAttributedLabel = newValue }
|
||||
}
|
||||
|
||||
override var accessibilityValue: String? {
|
||||
get { return self.accessibilityView?.accessibilityValue }
|
||||
set { self.accessibilityView?.accessibilityValue = newValue }
|
||||
}
|
||||
|
||||
override open var accessibilityAttributedValue: NSAttributedString? {
|
||||
get { return self.accessibilityView?.accessibilityAttributedValue }
|
||||
set { self.accessibilityView?.accessibilityAttributedValue = newValue }
|
||||
}
|
||||
|
||||
override open var accessibilityTraits: UIAccessibilityTraits {
|
||||
get { return self.accessibilityView?.accessibilityTraits ?? [] }
|
||||
set { self.accessibilityView?.accessibilityTraits = newValue }
|
||||
}
|
||||
|
||||
private var originalTintColor: UIColor?
|
||||
|
||||
@IBOutlet var titleLabel: UILabel!
|
||||
@IBOutlet var subtitleLabel: UILabel!
|
||||
@IBOutlet var iconImageView: AppIconImageView!
|
||||
@IBOutlet var button: PillButton!
|
||||
@IBOutlet var buttonLabel: UILabel!
|
||||
@IBOutlet var betaBadgeView: UIView!
|
||||
|
||||
@IBOutlet var backgroundEffectView: UIVisualEffectView!
|
||||
|
||||
@IBOutlet private var vibrancyView: UIVisualEffectView!
|
||||
@IBOutlet private var accessibilityView: UIView!
|
||||
|
||||
override init(frame: CGRect)
|
||||
{
|
||||
super.init(frame: frame)
|
||||
|
||||
self.initialize()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder)
|
||||
{
|
||||
super.init(coder: coder)
|
||||
|
||||
self.initialize()
|
||||
}
|
||||
|
||||
private func initialize()
|
||||
{
|
||||
self.accessibilityView.accessibilityTraits.formUnion(.button)
|
||||
|
||||
self.isAccessibilityElement = false
|
||||
self.accessibilityElements = [self.accessibilityView, self.button].compactMap { $0 }
|
||||
|
||||
self.betaBadgeView.isHidden = true
|
||||
}
|
||||
|
||||
override func tintColorDidChange()
|
||||
{
|
||||
super.tintColorDidChange()
|
||||
|
||||
if self.tintAdjustmentMode != .dimmed
|
||||
{
|
||||
self.originalTintColor = self.tintColor
|
||||
}
|
||||
|
||||
self.update()
|
||||
}
|
||||
}
|
||||
|
||||
extension AppBannerView
|
||||
{
|
||||
func configure(for app: AppProtocol)
|
||||
{
|
||||
struct AppValues
|
||||
{
|
||||
var name: String
|
||||
var developerName: String? = nil
|
||||
var isBeta: Bool = false
|
||||
|
||||
init(app: AppProtocol)
|
||||
{
|
||||
self.name = app.name
|
||||
|
||||
guard let storeApp = (app as? StoreApp) ?? (app as? InstalledApp)?.storeApp else { return }
|
||||
self.developerName = storeApp.developerName
|
||||
|
||||
if storeApp.isBeta
|
||||
{
|
||||
self.name = String(format: NSLocalizedString("%@ beta", comment: ""), app.name)
|
||||
self.isBeta = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let values = AppValues(app: app)
|
||||
self.titleLabel.text = app.name // Don't use values.name since that already includes "beta".
|
||||
self.betaBadgeView.isHidden = !values.isBeta
|
||||
|
||||
if let developerName = values.developerName
|
||||
{
|
||||
self.subtitleLabel.text = developerName
|
||||
self.accessibilityLabel = String(format: NSLocalizedString("%@ by %@", comment: ""), values.name, developerName)
|
||||
}
|
||||
else
|
||||
{
|
||||
self.subtitleLabel.text = NSLocalizedString("Sideloaded", comment: "")
|
||||
self.accessibilityLabel = values.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension AppBannerView
|
||||
{
|
||||
func update()
|
||||
{
|
||||
self.clipsToBounds = true
|
||||
self.layer.cornerRadius = 22
|
||||
|
||||
self.subtitleLabel.textColor = self.originalTintColor ?? self.tintColor
|
||||
self.backgroundEffectView.backgroundColor = self.originalTintColor ?? self.tintColor
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
//
|
||||
// AppIconImageView.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 5/9/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
final class AppIconImageView: UIImageView
|
||||
{
|
||||
override func awakeFromNib()
|
||||
{
|
||||
super.awakeFromNib()
|
||||
|
||||
self.contentMode = .scaleAspectFill
|
||||
self.clipsToBounds = true
|
||||
|
||||
self.backgroundColor = .white
|
||||
|
||||
if #available(iOS 13, *)
|
||||
{
|
||||
self.layer.cornerCurve = .continuous
|
||||
}
|
||||
else
|
||||
{
|
||||
if self.layer.responds(to: Selector(("continuousCorners")))
|
||||
{
|
||||
self.layer.setValue(true, forKey: "continuousCorners")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func layoutSubviews()
|
||||
{
|
||||
super.layoutSubviews()
|
||||
|
||||
// Based off of 60pt icon having 12pt radius.
|
||||
let radius = self.bounds.height / 5
|
||||
self.layer.cornerRadius = radius
|
||||
}
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
//
|
||||
// CollapsingTextView.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 7/23/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
final class CollapsingTextView: UITextView
|
||||
{
|
||||
var isCollapsed = true {
|
||||
didSet {
|
||||
self.setNeedsLayout()
|
||||
}
|
||||
}
|
||||
|
||||
var maximumNumberOfLines = 2 {
|
||||
didSet {
|
||||
self.setNeedsLayout()
|
||||
}
|
||||
}
|
||||
|
||||
var lineSpacing: CGFloat = 2 {
|
||||
didSet {
|
||||
self.setNeedsLayout()
|
||||
}
|
||||
}
|
||||
|
||||
let moreButton = UIButton(type: .system)
|
||||
|
||||
override func awakeFromNib()
|
||||
{
|
||||
super.awakeFromNib()
|
||||
|
||||
self.layoutManager.delegate = self
|
||||
|
||||
self.textContainerInset = .zero
|
||||
self.textContainer.lineFragmentPadding = 0
|
||||
self.textContainer.lineBreakMode = .byTruncatingTail
|
||||
self.textContainer.heightTracksTextView = true
|
||||
self.textContainer.widthTracksTextView = true
|
||||
|
||||
self.moreButton.setTitle(NSLocalizedString("More", comment: ""), for: .normal)
|
||||
self.moreButton.addTarget(self, action: #selector(CollapsingTextView.toggleCollapsed(_:)), for: .primaryActionTriggered)
|
||||
self.addSubview(self.moreButton)
|
||||
|
||||
self.setNeedsLayout()
|
||||
}
|
||||
|
||||
override func layoutSubviews()
|
||||
{
|
||||
super.layoutSubviews()
|
||||
|
||||
guard let font = self.font else { return }
|
||||
|
||||
let buttonFont = UIFont.systemFont(ofSize: font.pointSize, weight: .medium)
|
||||
self.moreButton.titleLabel?.font = buttonFont
|
||||
|
||||
let buttonY = (font.lineHeight + self.lineSpacing) * CGFloat(self.maximumNumberOfLines - 1)
|
||||
let size = self.moreButton.sizeThatFits(CGSize(width: 1000, height: 1000))
|
||||
|
||||
let moreButtonFrame = CGRect(x: self.bounds.width - self.moreButton.bounds.width,
|
||||
y: buttonY,
|
||||
width: size.width,
|
||||
height: font.lineHeight)
|
||||
self.moreButton.frame = moreButtonFrame
|
||||
|
||||
if self.isCollapsed
|
||||
{
|
||||
self.textContainer.maximumNumberOfLines = self.maximumNumberOfLines
|
||||
|
||||
let boundingSize = self.attributedText.boundingRect(with: CGSize(width: self.textContainer.size.width, height: .infinity), options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil)
|
||||
let maximumCollapsedHeight = font.lineHeight * Double(self.maximumNumberOfLines)
|
||||
|
||||
if boundingSize.height.rounded() > maximumCollapsedHeight.rounded()
|
||||
{
|
||||
var exclusionFrame = moreButtonFrame
|
||||
exclusionFrame.origin.y += self.moreButton.bounds.midY
|
||||
exclusionFrame.size.width = self.bounds.width // Extra wide to make sure it wraps to next line.
|
||||
self.textContainer.exclusionPaths = [UIBezierPath(rect: exclusionFrame)]
|
||||
|
||||
self.moreButton.isHidden = false
|
||||
}
|
||||
else
|
||||
{
|
||||
self.textContainer.exclusionPaths = []
|
||||
|
||||
self.moreButton.isHidden = true
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.textContainer.maximumNumberOfLines = 0
|
||||
self.textContainer.exclusionPaths = []
|
||||
|
||||
self.moreButton.isHidden = true
|
||||
}
|
||||
|
||||
self.invalidateIntrinsicContentSize()
|
||||
}
|
||||
}
|
||||
|
||||
private extension CollapsingTextView
|
||||
{
|
||||
@objc func toggleCollapsed(_ sender: UIButton)
|
||||
{
|
||||
self.isCollapsed.toggle()
|
||||
}
|
||||
}
|
||||
|
||||
extension CollapsingTextView: NSLayoutManagerDelegate
|
||||
{
|
||||
func layoutManager(_ layoutManager: NSLayoutManager, lineSpacingAfterGlyphAt glyphIndex: Int, withProposedLineFragmentRect rect: CGRect) -> CGFloat
|
||||
{
|
||||
return self.lineSpacing
|
||||
}
|
||||
}
|
||||
@@ -1,192 +0,0 @@
|
||||
//
|
||||
// PillButton.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 7/15/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
final class PillButton: UIButton
|
||||
{
|
||||
override var accessibilityValue: String? {
|
||||
get {
|
||||
guard self.progress != nil else { return super.accessibilityValue }
|
||||
return self.progressView.accessibilityValue
|
||||
}
|
||||
set { super.accessibilityValue = newValue }
|
||||
}
|
||||
|
||||
var progress: Progress? {
|
||||
didSet {
|
||||
self.progressView.progress = Float(self.progress?.fractionCompleted ?? 0)
|
||||
self.progressView.observedProgress = self.progress
|
||||
|
||||
let isUserInteractionEnabled = self.isUserInteractionEnabled
|
||||
self.isIndicatingActivity = (self.progress != nil)
|
||||
self.isUserInteractionEnabled = isUserInteractionEnabled
|
||||
|
||||
self.update()
|
||||
}
|
||||
}
|
||||
|
||||
var progressTintColor: UIColor? {
|
||||
get {
|
||||
return self.progressView.progressTintColor
|
||||
}
|
||||
set {
|
||||
self.progressView.progressTintColor = newValue
|
||||
}
|
||||
}
|
||||
|
||||
var countdownDate: Date? {
|
||||
didSet {
|
||||
self.isEnabled = (self.countdownDate == nil)
|
||||
self.displayLink.isPaused = (self.countdownDate == nil)
|
||||
|
||||
if self.countdownDate == nil
|
||||
{
|
||||
self.setTitle(nil, for: .disabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private let progressView = UIProgressView(progressViewStyle: .default)
|
||||
|
||||
private lazy var displayLink: CADisplayLink = {
|
||||
let displayLink = CADisplayLink(target: self, selector: #selector(PillButton.updateCountdown))
|
||||
displayLink.preferredFramesPerSecond = 15
|
||||
displayLink.isPaused = true
|
||||
displayLink.add(to: .main, forMode: .common)
|
||||
return displayLink
|
||||
}()
|
||||
|
||||
private let dateComponentsFormatter: DateComponentsFormatter = {
|
||||
let dateComponentsFormatter = DateComponentsFormatter()
|
||||
dateComponentsFormatter.zeroFormattingBehavior = [.pad]
|
||||
dateComponentsFormatter.collapsesLargestUnit = false
|
||||
return dateComponentsFormatter
|
||||
}()
|
||||
|
||||
override var intrinsicContentSize: CGSize {
|
||||
var size = super.intrinsicContentSize
|
||||
size.width += 26
|
||||
size.height += 3
|
||||
return size
|
||||
}
|
||||
|
||||
deinit
|
||||
{
|
||||
self.displayLink.remove(from: .main, forMode: RunLoop.Mode.default)
|
||||
}
|
||||
|
||||
override func awakeFromNib()
|
||||
{
|
||||
super.awakeFromNib()
|
||||
|
||||
self.layer.masksToBounds = true
|
||||
self.accessibilityTraits.formUnion([.updatesFrequently, .button])
|
||||
|
||||
self.activityIndicatorView.style = .medium
|
||||
self.activityIndicatorView.isUserInteractionEnabled = false
|
||||
|
||||
self.progressView.progress = 0
|
||||
self.progressView.trackImage = UIImage()
|
||||
self.progressView.isUserInteractionEnabled = false
|
||||
self.addSubview(self.progressView)
|
||||
|
||||
self.update()
|
||||
}
|
||||
|
||||
override func layoutSubviews()
|
||||
{
|
||||
super.layoutSubviews()
|
||||
|
||||
self.progressView.bounds.size.width = self.bounds.width
|
||||
|
||||
let scale = self.bounds.height / self.progressView.bounds.height
|
||||
|
||||
self.progressView.transform = CGAffineTransform.identity.scaledBy(x: 1, y: scale)
|
||||
self.progressView.center = CGPoint(x: self.bounds.midX, y: self.bounds.midY)
|
||||
|
||||
self.layer.cornerRadius = self.bounds.midY
|
||||
}
|
||||
|
||||
override func tintColorDidChange()
|
||||
{
|
||||
super.tintColorDidChange()
|
||||
|
||||
self.update()
|
||||
}
|
||||
}
|
||||
|
||||
private extension PillButton
|
||||
{
|
||||
func update()
|
||||
{
|
||||
if self.progress == nil
|
||||
{
|
||||
self.setTitleColor(.white, for: .normal)
|
||||
self.backgroundColor = self.tintColor
|
||||
}
|
||||
else
|
||||
{
|
||||
self.setTitleColor(self.tintColor, for: .normal)
|
||||
self.backgroundColor = self.tintColor.withAlphaComponent(0.15)
|
||||
}
|
||||
|
||||
self.progressView.progressTintColor = self.tintColor
|
||||
}
|
||||
|
||||
@objc func updateCountdown()
|
||||
{
|
||||
guard let endDate = self.countdownDate else { return }
|
||||
|
||||
let startDate = Date()
|
||||
|
||||
let interval = endDate.timeIntervalSince(startDate)
|
||||
guard interval > 0 else {
|
||||
self.isEnabled = true
|
||||
return
|
||||
}
|
||||
|
||||
let text: String?
|
||||
|
||||
if interval < (1 * 60 * 60)
|
||||
{
|
||||
self.dateComponentsFormatter.unitsStyle = .positional
|
||||
self.dateComponentsFormatter.allowedUnits = [.minute, .second]
|
||||
|
||||
text = self.dateComponentsFormatter.string(from: startDate, to: endDate)
|
||||
}
|
||||
else if interval < (2 * 24 * 60 * 60)
|
||||
{
|
||||
self.dateComponentsFormatter.unitsStyle = .positional
|
||||
self.dateComponentsFormatter.allowedUnits = [.hour, .minute, .second]
|
||||
|
||||
text = self.dateComponentsFormatter.string(from: startDate, to: endDate)
|
||||
}
|
||||
else
|
||||
{
|
||||
self.dateComponentsFormatter.unitsStyle = .full
|
||||
self.dateComponentsFormatter.allowedUnits = [.day]
|
||||
|
||||
let numberOfDays = endDate.numberOfCalendarDays(since: startDate)
|
||||
text = String(format: NSLocalizedString("%@ DAYS", comment: ""), NSNumber(value: numberOfDays))
|
||||
}
|
||||
|
||||
if let text = text
|
||||
{
|
||||
UIView.performWithoutAnimation {
|
||||
self.isEnabled = false
|
||||
self.setTitle(text, for: .disabled)
|
||||
self.layoutIfNeeded()
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.isEnabled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
//
|
||||
// Proxy.swift
|
||||
// SideStore
|
||||
//
|
||||
// Created by Joseph Mattiello on 11/7/22.
|
||||
// Copyright © 2022 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public extension Consts {
|
||||
enum Proxy {
|
||||
static let address = "127.0.0.1"
|
||||
static let port = "51820"
|
||||
static let serverURL = "\(address):\(port)"
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
//
|
||||
// AppManagerErrors.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 8/27/20.
|
||||
// Copyright © 2020 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
import AltStoreCore
|
||||
|
||||
extension AppManager
|
||||
{
|
||||
struct FetchSourcesError: LocalizedError, CustomNSError
|
||||
{
|
||||
var primaryError: Error?
|
||||
|
||||
var sources: Set<Source>?
|
||||
var errors = [Source: Error]()
|
||||
|
||||
var managedObjectContext: NSManagedObjectContext?
|
||||
|
||||
var errorDescription: String? {
|
||||
if let error = self.primaryError
|
||||
{
|
||||
return error.localizedDescription
|
||||
}
|
||||
else
|
||||
{
|
||||
var localizedDescription: String?
|
||||
|
||||
self.managedObjectContext?.performAndWait {
|
||||
if self.sources?.count == 1
|
||||
{
|
||||
localizedDescription = NSLocalizedString("Could not refresh store.", comment: "")
|
||||
}
|
||||
else if self.errors.count == 1
|
||||
{
|
||||
guard let source = self.errors.keys.first else { return }
|
||||
localizedDescription = String(format: NSLocalizedString("Could not refresh source “%@”.", comment: ""), source.name)
|
||||
}
|
||||
else
|
||||
{
|
||||
localizedDescription = String(format: NSLocalizedString("Could not refresh %@ sources.", comment: ""), NSNumber(value: self.errors.count))
|
||||
}
|
||||
}
|
||||
|
||||
return localizedDescription
|
||||
}
|
||||
}
|
||||
|
||||
var recoverySuggestion: String? {
|
||||
if let error = self.primaryError as NSError?
|
||||
{
|
||||
return error.localizedRecoverySuggestion
|
||||
}
|
||||
else if self.errors.count == 1
|
||||
{
|
||||
return nil
|
||||
}
|
||||
else
|
||||
{
|
||||
return NSLocalizedString("Tap to view source errors.", comment: "")
|
||||
}
|
||||
}
|
||||
|
||||
var errorUserInfo: [String : Any] {
|
||||
guard let error = self.errors.values.first, self.errors.count == 1 else { return [:] }
|
||||
return [NSUnderlyingErrorKey: error]
|
||||
}
|
||||
|
||||
init(_ error: Error)
|
||||
{
|
||||
self.primaryError = error
|
||||
}
|
||||
|
||||
init(sources: Set<Source>, errors: [Source: Error], context: NSManagedObjectContext)
|
||||
{
|
||||
self.sources = sources
|
||||
self.errors = errors
|
||||
self.managedObjectContext = context
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
//
|
||||
// InstalledAppsCollectionHeaderView.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 3/9/20.
|
||||
// Copyright © 2020 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
final class InstalledAppsCollectionHeaderView: UICollectionReusableView
|
||||
{
|
||||
let textLabel: UILabel
|
||||
let button: UIButton
|
||||
|
||||
override init(frame: CGRect)
|
||||
{
|
||||
self.textLabel = UILabel()
|
||||
self.textLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
self.textLabel.font = UIFont.systemFont(ofSize: 24, weight: .bold)
|
||||
self.textLabel.accessibilityTraits.insert(.header)
|
||||
|
||||
self.button = UIButton(type: .system)
|
||||
self.button.translatesAutoresizingMaskIntoConstraints = false
|
||||
self.button.titleLabel?.font = UIFont.systemFont(ofSize: 16, weight: .medium)
|
||||
|
||||
super.init(frame: frame)
|
||||
|
||||
self.addSubview(self.textLabel)
|
||||
self.addSubview(self.button)
|
||||
|
||||
NSLayoutConstraint.activate([self.textLabel.leadingAnchor.constraint(equalTo: self.layoutMarginsGuide.leadingAnchor),
|
||||
self.textLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor)])
|
||||
|
||||
NSLayoutConstraint.activate([self.button.trailingAnchor.constraint(equalTo: self.layoutMarginsGuide.trailingAnchor),
|
||||
self.button.firstBaselineAnchor.constraint(equalTo: self.textLabel.firstBaselineAnchor)])
|
||||
|
||||
self.preservesSuperviewLayoutMargins = true
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
//
|
||||
// UpdateCollectionViewCell.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 7/16/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
extension UpdateCollectionViewCell
|
||||
{
|
||||
enum Mode
|
||||
{
|
||||
case collapsed
|
||||
case expanded
|
||||
}
|
||||
}
|
||||
|
||||
@objc final class UpdateCollectionViewCell: UICollectionViewCell
|
||||
{
|
||||
var mode: Mode = .expanded {
|
||||
didSet {
|
||||
self.update()
|
||||
}
|
||||
}
|
||||
|
||||
@IBOutlet var bannerView: AppBannerView!
|
||||
@IBOutlet var versionDescriptionTitleLabel: UILabel!
|
||||
@IBOutlet var versionDescriptionTextView: CollapsingTextView!
|
||||
|
||||
@IBOutlet private var blurView: UIVisualEffectView!
|
||||
|
||||
private var originalTintColor: UIColor?
|
||||
|
||||
override func awakeFromNib()
|
||||
{
|
||||
super.awakeFromNib()
|
||||
|
||||
// Prevent temporary unsatisfiable constraint errors due to UIView-Encapsulated-Layout constraints.
|
||||
self.contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
self.contentView.preservesSuperviewLayoutMargins = true
|
||||
|
||||
self.bannerView.backgroundEffectView.isHidden = true
|
||||
self.bannerView.button.setTitle(NSLocalizedString("UPDATE", comment: ""), for: .normal)
|
||||
|
||||
self.blurView.layer.cornerRadius = 20
|
||||
self.blurView.layer.masksToBounds = true
|
||||
|
||||
self.update()
|
||||
}
|
||||
|
||||
override func tintColorDidChange()
|
||||
{
|
||||
super.tintColorDidChange()
|
||||
|
||||
if self.tintAdjustmentMode != .dimmed
|
||||
{
|
||||
self.originalTintColor = self.tintColor
|
||||
}
|
||||
|
||||
self.update()
|
||||
}
|
||||
|
||||
override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes)
|
||||
{
|
||||
// Animates transition to new attributes.
|
||||
let animator = UIViewPropertyAnimator(springTimingParameters: UISpringTimingParameters()) {
|
||||
self.layoutIfNeeded()
|
||||
}
|
||||
animator.startAnimation()
|
||||
}
|
||||
|
||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView?
|
||||
{
|
||||
let view = super.hitTest(point, with: event)
|
||||
|
||||
if view == self.versionDescriptionTextView
|
||||
{
|
||||
// Forward touches on the text view (but not on the nested "more" button)
|
||||
// so cell selection works as expected.
|
||||
return self
|
||||
}
|
||||
else
|
||||
{
|
||||
return view
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension UpdateCollectionViewCell
|
||||
{
|
||||
func update()
|
||||
{
|
||||
switch self.mode
|
||||
{
|
||||
case .collapsed: self.versionDescriptionTextView.isCollapsed = true
|
||||
case .expanded: self.versionDescriptionTextView.isCollapsed = false
|
||||
}
|
||||
|
||||
self.versionDescriptionTitleLabel.textColor = self.originalTintColor ?? self.tintColor
|
||||
self.blurView.backgroundColor = self.originalTintColor ?? self.tintColor
|
||||
self.bannerView.button.progressTintColor = self.originalTintColor ?? self.tintColor
|
||||
|
||||
self.setNeedsLayout()
|
||||
self.layoutIfNeeded()
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
//
|
||||
// NewsCollectionViewCell.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 8/29/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
final class NewsCollectionViewCell: UICollectionViewCell
|
||||
{
|
||||
@IBOutlet var titleLabel: UILabel!
|
||||
@IBOutlet var captionLabel: UILabel!
|
||||
@IBOutlet var imageView: UIImageView!
|
||||
@IBOutlet var contentBackgroundView: UIView!
|
||||
|
||||
override func awakeFromNib()
|
||||
{
|
||||
super.awakeFromNib()
|
||||
|
||||
self.contentView.preservesSuperviewLayoutMargins = true
|
||||
|
||||
self.contentBackgroundView.layer.cornerRadius = 30
|
||||
self.contentBackgroundView.clipsToBounds = true
|
||||
|
||||
self.imageView.layer.cornerRadius = 30
|
||||
self.imageView.clipsToBounds = true
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
//
|
||||
// Operation.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 6/7/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Roxas
|
||||
|
||||
class ResultOperation<ResultType>: Operation
|
||||
{
|
||||
var resultHandler: ((Result<ResultType, Error>) -> Void)?
|
||||
|
||||
@available(*, unavailable)
|
||||
override func finish()
|
||||
{
|
||||
super.finish()
|
||||
}
|
||||
|
||||
func finish(_ result: Result<ResultType, Error>)
|
||||
{
|
||||
guard !self.isFinished else { return }
|
||||
|
||||
if self.isCancelled
|
||||
{
|
||||
self.resultHandler?(.failure(OperationError.cancelled))
|
||||
}
|
||||
else
|
||||
{
|
||||
self.resultHandler?(result)
|
||||
}
|
||||
|
||||
super.finish()
|
||||
}
|
||||
}
|
||||
|
||||
class Operation: RSTOperation, ProgressReporting
|
||||
{
|
||||
let progress = Progress.discreteProgress(totalUnitCount: 1)
|
||||
|
||||
private var backgroundTaskID: UIBackgroundTaskIdentifier?
|
||||
|
||||
override var isAsynchronous: Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
override init()
|
||||
{
|
||||
super.init()
|
||||
|
||||
self.progress.cancellationHandler = { [weak self] in self?.cancel() }
|
||||
}
|
||||
|
||||
override func cancel()
|
||||
{
|
||||
super.cancel()
|
||||
|
||||
if !self.progress.isCancelled
|
||||
{
|
||||
self.progress.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
override func main()
|
||||
{
|
||||
super.main()
|
||||
|
||||
let name = "com.altstore." + NSStringFromClass(type(of: self))
|
||||
self.backgroundTaskID = UIApplication.shared.beginBackgroundTask(withName: name) { [weak self] in
|
||||
guard let backgroundTask = self?.backgroundTaskID else { return }
|
||||
|
||||
self?.cancel()
|
||||
|
||||
UIApplication.shared.endBackgroundTask(backgroundTask)
|
||||
self?.backgroundTaskID = .invalid
|
||||
}
|
||||
}
|
||||
|
||||
override func finish()
|
||||
{
|
||||
guard !self.isFinished else { return }
|
||||
|
||||
super.finish()
|
||||
|
||||
if let backgroundTaskID = self.backgroundTaskID
|
||||
{
|
||||
UIApplication.shared.endBackgroundTask(backgroundTaskID)
|
||||
self.backgroundTaskID = .invalid
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,499 +0,0 @@
|
||||
//
|
||||
// PatchViewController.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 10/20/21.
|
||||
// Copyright © 2021 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Combine
|
||||
|
||||
import AltStoreCore
|
||||
import AltSign
|
||||
import Roxas
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
extension PatchViewController
|
||||
{
|
||||
enum Step
|
||||
{
|
||||
case confirm
|
||||
case install
|
||||
case openApp
|
||||
case patchApp
|
||||
case reboot
|
||||
case refresh
|
||||
case finish
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
final class PatchViewController: UIViewController
|
||||
{
|
||||
var patchApp: AnyApp?
|
||||
var installedApp: InstalledApp?
|
||||
|
||||
var completionHandler: ((Result<Void, Error>) -> Void)?
|
||||
|
||||
private let context = AuthenticatedOperationContext()
|
||||
|
||||
private var currentStep: Step = .confirm {
|
||||
didSet {
|
||||
DispatchQueue.main.async {
|
||||
self.update()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var buttonHandler: (() -> Void)?
|
||||
private var resignedApp: ALTApplication?
|
||||
|
||||
private lazy var temporaryDirectory: URL = FileManager.default.uniqueTemporaryURL()
|
||||
|
||||
private var didEnterBackgroundObservation: NSObjectProtocol?
|
||||
private weak var cancellableProgress: Progress?
|
||||
|
||||
@IBOutlet private var placeholderView: RSTPlaceholderView!
|
||||
@IBOutlet private var taskDescriptionLabel: UILabel!
|
||||
@IBOutlet private var pillButton: PillButton!
|
||||
@IBOutlet private var cancelBarButtonItem: UIBarButtonItem!
|
||||
@IBOutlet private var cancelButton: UIButton!
|
||||
|
||||
override func viewDidLoad()
|
||||
{
|
||||
super.viewDidLoad()
|
||||
|
||||
self.isModalInPresentation = true
|
||||
|
||||
self.placeholderView.stackView.spacing = 20
|
||||
self.placeholderView.textLabel.textColor = .white
|
||||
|
||||
self.placeholderView.detailTextLabel.textAlignment = .left
|
||||
self.placeholderView.detailTextLabel.textColor = UIColor.white.withAlphaComponent(0.6)
|
||||
|
||||
self.buttonHandler = { [weak self] in
|
||||
self?.startProcess()
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
try FileManager.default.createDirectory(at: self.temporaryDirectory, withIntermediateDirectories: true, attributes: nil)
|
||||
}
|
||||
catch
|
||||
{
|
||||
print("Failed to create temporary directory:", error)
|
||||
}
|
||||
|
||||
self.update()
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool)
|
||||
{
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
if self.installedApp != nil
|
||||
{
|
||||
self.refreshApp()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
private extension PatchViewController
|
||||
{
|
||||
func update()
|
||||
{
|
||||
self.cancelButton.alpha = 0.0
|
||||
|
||||
switch self.currentStep
|
||||
{
|
||||
case .confirm:
|
||||
guard let app = self.patchApp else { break }
|
||||
|
||||
if UIDevice.current.isUntetheredJailbreakRequired
|
||||
{
|
||||
self.placeholderView.textLabel.text = NSLocalizedString("Jailbreak Requires Untethering", comment: "")
|
||||
self.placeholderView.detailTextLabel.text = String(format: NSLocalizedString("This jailbreak is untethered, which means %@ will never expire — even after 7 days or rebooting the device.\n\nInstalling an untethered jailbreak requires a few extra steps, but SideStore will walk you through the process.\n\nWould you like to continue? ", comment: ""), app.name)
|
||||
}
|
||||
else
|
||||
{
|
||||
self.placeholderView.textLabel.text = NSLocalizedString("Jailbreak Supports Untethering", comment: "")
|
||||
self.placeholderView.detailTextLabel.text = String(format: NSLocalizedString("This jailbreak has an untethered version, which means %@ will never expire — even after 7 days or rebooting the device.\n\nInstalling an untethered jailbreak requires a few extra steps, but SideStore will walk you through the process.\n\nWould you like to continue? ", comment: ""), app.name)
|
||||
}
|
||||
|
||||
self.pillButton.setTitle(NSLocalizedString("Install Untethered Jailbreak", comment: ""), for: .normal)
|
||||
|
||||
self.cancelButton.alpha = 1.0
|
||||
|
||||
case .install:
|
||||
guard let app = self.patchApp else { break }
|
||||
|
||||
self.placeholderView.textLabel.text = String(format: NSLocalizedString("Installing %@ placeholder…", comment: ""), app.name)
|
||||
self.placeholderView.detailTextLabel.text = NSLocalizedString("A placeholder app needs to be installed in order to prepare your device for untethering.\n\nThis may take a few moments.", comment: "")
|
||||
|
||||
case .openApp:
|
||||
self.placeholderView.textLabel.text = NSLocalizedString("Continue in App", comment: "")
|
||||
self.placeholderView.detailTextLabel.text = NSLocalizedString("Please open the placeholder app and follow the instructions to continue jailbreaking your device.", comment: "")
|
||||
|
||||
self.pillButton.setTitle(NSLocalizedString("Open Placeholder", comment: ""), for: .normal)
|
||||
|
||||
case .patchApp:
|
||||
guard let app = self.patchApp else { break }
|
||||
|
||||
self.placeholderView.textLabel.text = String(format: NSLocalizedString("Patching %@ placeholder…", comment: ""), app.name)
|
||||
self.placeholderView.detailTextLabel.text = NSLocalizedString("This will take a few moments. Please do not turn off the screen or leave the app until patching is complete.", comment: "")
|
||||
|
||||
self.pillButton.setTitle(NSLocalizedString("Patch Placeholder", comment: ""), for: .normal)
|
||||
|
||||
case .reboot:
|
||||
self.placeholderView.textLabel.text = NSLocalizedString("Continue in App", comment: "")
|
||||
self.placeholderView.detailTextLabel.text = NSLocalizedString("Please open the placeholder app and follow the instructions to continue jailbreaking your device.", comment: "")
|
||||
|
||||
self.pillButton.setTitle(NSLocalizedString("Open Placeholder", comment: ""), for: .normal)
|
||||
|
||||
case .refresh:
|
||||
guard let installedApp = self.installedApp else { break }
|
||||
|
||||
self.placeholderView.textLabel.text = String(format: NSLocalizedString("Finish installing %@?", comment: ""), installedApp.name)
|
||||
self.placeholderView.detailTextLabel.text = String(format: NSLocalizedString("In order to finish jailbreaking this device, you need to install %@ then follow the instructions in the app.", comment: ""), installedApp.name)
|
||||
|
||||
self.pillButton.setTitle(String(format: NSLocalizedString("Install %@", comment: ""), installedApp.name), for: .normal)
|
||||
|
||||
case .finish:
|
||||
guard let installedApp = self.installedApp else { break }
|
||||
|
||||
self.placeholderView.textLabel.text = String(format: NSLocalizedString("Finish in %@", comment: ""), installedApp.name)
|
||||
self.placeholderView.detailTextLabel.text = String(format: NSLocalizedString("Follow the instructions in %@ to finish jailbreaking this device.", comment: ""), installedApp.name)
|
||||
|
||||
self.pillButton.setTitle(String(format: NSLocalizedString("Open %@", comment: ""), installedApp.name), for: .normal)
|
||||
}
|
||||
}
|
||||
|
||||
func present(_ error: Error, title: String)
|
||||
{
|
||||
DispatchQueue.main.async {
|
||||
let nsError = error as NSError
|
||||
|
||||
let alertController = UIAlertController(title: nsError.localizedFailure ?? title, message: error.localizedDescription, preferredStyle: .alert)
|
||||
alertController.addAction(.ok)
|
||||
self.present(alertController, animated: true, completion: nil)
|
||||
|
||||
self.setProgress(nil, description: nil)
|
||||
}
|
||||
}
|
||||
|
||||
func setProgress(_ progress: Progress?, description: String?)
|
||||
{
|
||||
DispatchQueue.main.async {
|
||||
self.pillButton.progress = progress
|
||||
self.taskDescriptionLabel.text = description ?? " " // Use non-empty string to prevent label resizing itself.
|
||||
}
|
||||
}
|
||||
|
||||
func finish(with result: Result<Void, Error>)
|
||||
{
|
||||
do
|
||||
{
|
||||
try FileManager.default.removeItem(at: self.temporaryDirectory)
|
||||
}
|
||||
catch
|
||||
{
|
||||
print("Failed to remove temporary directory:", error)
|
||||
}
|
||||
|
||||
if let observation = self.didEnterBackgroundObservation
|
||||
{
|
||||
NotificationCenter.default.removeObserver(observation)
|
||||
}
|
||||
|
||||
self.completionHandler?(result)
|
||||
self.completionHandler = nil
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
private extension PatchViewController
|
||||
{
|
||||
@IBAction func performButtonAction()
|
||||
{
|
||||
self.buttonHandler?()
|
||||
}
|
||||
|
||||
@IBAction func cancel()
|
||||
{
|
||||
self.finish(with: .success(()))
|
||||
|
||||
self.cancellableProgress?.cancel()
|
||||
}
|
||||
|
||||
@IBAction func installRegularJailbreak()
|
||||
{
|
||||
guard let app = self.patchApp else { return }
|
||||
|
||||
let title: String
|
||||
let message: String
|
||||
|
||||
if UIDevice.current.isUntetheredJailbreakRequired
|
||||
{
|
||||
title = NSLocalizedString("Untethering Required", comment: "")
|
||||
message = String(format: NSLocalizedString("%@ can not jailbreak this device unless you untether it first. Are you sure you want to install without untethering?", comment: ""), app.name)
|
||||
}
|
||||
else
|
||||
{
|
||||
title = NSLocalizedString("Untethering Recommended", comment: "")
|
||||
message = String(format: NSLocalizedString("Untethering this jailbreak will prevent %@ from expiring, even after 7 days or rebooting the device. Are you sure you want to install without untethering?", comment: ""), app.name)
|
||||
}
|
||||
|
||||
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||
alertController.addAction(UIAlertAction(title: NSLocalizedString("Install Without Untethering", comment: ""), style: .default) { _ in
|
||||
self.finish(with: .failure(OperationError.cancelled))
|
||||
})
|
||||
alertController.addAction(.cancel)
|
||||
self.present(alertController, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
private extension PatchViewController
|
||||
{
|
||||
func startProcess()
|
||||
{
|
||||
guard let patchApp = self.patchApp else { return }
|
||||
|
||||
self.currentStep = .install
|
||||
|
||||
if let progress = AppManager.shared.installationProgress(for: patchApp)
|
||||
{
|
||||
// Cancel pending jailbreak app installation so we can start a new one.
|
||||
progress.cancel()
|
||||
}
|
||||
|
||||
let appURL = InstalledApp.fileURL(for: patchApp)
|
||||
let cachedAppURL = self.temporaryDirectory.appendingPathComponent("Cached.app")
|
||||
|
||||
do
|
||||
{
|
||||
// Make copy of original app, so we can replace the cached patch app with it later.
|
||||
try FileManager.default.copyItem(at: appURL, to: cachedAppURL, shouldReplace: true)
|
||||
}
|
||||
catch
|
||||
{
|
||||
self.present(error, title: NSLocalizedString("Could not back up jailbreak app.", comment: ""))
|
||||
return
|
||||
}
|
||||
|
||||
var unzippingError: Error?
|
||||
let refreshGroup = AppManager.shared.install(patchApp, presentingViewController: self, context: self.context) { result in
|
||||
do
|
||||
{
|
||||
_ = try result.get()
|
||||
|
||||
if let unzippingError = unzippingError
|
||||
{
|
||||
throw unzippingError
|
||||
}
|
||||
|
||||
// Replace cached patch app with original app so we can resume installing it post-reboot.
|
||||
try FileManager.default.copyItem(at: cachedAppURL, to: appURL, shouldReplace: true)
|
||||
|
||||
self.openApp()
|
||||
}
|
||||
catch
|
||||
{
|
||||
self.present(error, title: String(format: NSLocalizedString("Could not install %@ placeholder.", comment: ""), patchApp.name))
|
||||
}
|
||||
}
|
||||
refreshGroup.beginInstallationHandler = { (installedApp) in
|
||||
do
|
||||
{
|
||||
// Replace patch app name with correct name.
|
||||
installedApp.name = patchApp.name
|
||||
|
||||
let ipaURL = installedApp.refreshedIPAURL
|
||||
let resignedAppURL = try FileManager.default.unzipAppBundle(at: ipaURL, toDirectory: self.temporaryDirectory)
|
||||
|
||||
self.resignedApp = ALTApplication(fileURL: resignedAppURL)
|
||||
}
|
||||
catch
|
||||
{
|
||||
print("Error unzipping app bundle:", error)
|
||||
unzippingError = error
|
||||
}
|
||||
}
|
||||
self.setProgress(refreshGroup.progress, description: nil)
|
||||
|
||||
self.cancellableProgress = refreshGroup.progress
|
||||
}
|
||||
|
||||
func openApp()
|
||||
{
|
||||
guard let patchApp = self.patchApp else { return }
|
||||
|
||||
self.setProgress(nil, description: nil)
|
||||
self.currentStep = .openApp
|
||||
|
||||
// This observation is willEnterForeground because patching starts immediately upon return.
|
||||
self.didEnterBackgroundObservation = NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification, object: nil, queue: .main) { (notification) in
|
||||
self.didEnterBackgroundObservation.map { NotificationCenter.default.removeObserver($0) }
|
||||
self.patchApplication()
|
||||
}
|
||||
|
||||
self.buttonHandler = { [weak self] in
|
||||
guard let self = self else { return }
|
||||
|
||||
#if !targetEnvironment(simulator)
|
||||
|
||||
let openURL = InstalledApp.openAppURL(for: patchApp)
|
||||
UIApplication.shared.open(openURL) { success in
|
||||
guard !success else { return }
|
||||
self.present(OperationError.openAppFailed(name: patchApp.name), title: String(format: NSLocalizedString("Could not open %@ placeholder.", comment: ""), patchApp.name))
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
func patchApplication()
|
||||
{
|
||||
guard let resignedApp = self.resignedApp else { return }
|
||||
|
||||
self.currentStep = .patchApp
|
||||
|
||||
self.buttonHandler = { [weak self] in
|
||||
self?.patchApplication()
|
||||
}
|
||||
|
||||
let patchAppOperation = AppManager.shared.patch(resignedApp: resignedApp, presentingViewController: self, context: self.context) { result in
|
||||
switch result
|
||||
{
|
||||
case .failure(let error): self.present(error, title: String(format: NSLocalizedString("Could not patch %@ placeholder.", comment: ""), resignedApp.name))
|
||||
case .success: self.rebootDevice()
|
||||
}
|
||||
}
|
||||
patchAppOperation.progressHandler = { (progress, description) in
|
||||
self.setProgress(progress, description: description)
|
||||
}
|
||||
self.cancellableProgress = patchAppOperation.progress
|
||||
}
|
||||
|
||||
func rebootDevice()
|
||||
{
|
||||
guard let patchApp = self.patchApp else { return }
|
||||
|
||||
self.setProgress(nil, description: nil)
|
||||
self.currentStep = .reboot
|
||||
|
||||
self.didEnterBackgroundObservation = NotificationCenter.default.addObserver(forName: UIApplication.didEnterBackgroundNotification, object: nil, queue: .main) { (notification) in
|
||||
self.didEnterBackgroundObservation.map { NotificationCenter.default.removeObserver($0) }
|
||||
|
||||
var patchedApps = UserDefaults.standard.patchedApps ?? []
|
||||
if !patchedApps.contains(patchApp.bundleIdentifier)
|
||||
{
|
||||
patchedApps.append(patchApp.bundleIdentifier)
|
||||
UserDefaults.standard.patchedApps = patchedApps
|
||||
}
|
||||
|
||||
self.finish(with: .success(()))
|
||||
}
|
||||
|
||||
self.buttonHandler = { [weak self] in
|
||||
guard let self = self else { return }
|
||||
|
||||
#if !targetEnvironment(simulator)
|
||||
|
||||
let openURL = InstalledApp.openAppURL(for: patchApp)
|
||||
UIApplication.shared.open(openURL) { success in
|
||||
guard !success else { return }
|
||||
self.present(OperationError.openAppFailed(name: patchApp.name), title: String(format: NSLocalizedString("Could not open %@ placeholder.", comment: ""), patchApp.name))
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
func refreshApp()
|
||||
{
|
||||
guard let installedApp = self.installedApp else { return }
|
||||
|
||||
self.currentStep = .refresh
|
||||
|
||||
self.buttonHandler = { [weak self] in
|
||||
guard let self = self else { return }
|
||||
DatabaseManager.shared.persistentContainer.performBackgroundTask { context in
|
||||
let tempApp = context.object(with: installedApp.objectID) as! InstalledApp
|
||||
tempApp.needsResign = true
|
||||
|
||||
let errorTitle = String(format: NSLocalizedString("Could not install %@.", comment: ""), tempApp.name)
|
||||
|
||||
do
|
||||
{
|
||||
try context.save()
|
||||
|
||||
installedApp.managedObjectContext?.perform {
|
||||
// Refreshing ensures we don't attempt to patch the app again,
|
||||
// since that is only checked when installing a new app.
|
||||
let refreshGroup = AppManager.shared.refresh([installedApp], presentingViewController: self, group: nil)
|
||||
refreshGroup.completionHandler = { [weak refreshGroup, weak self] (results) in
|
||||
guard let self = self else { return }
|
||||
|
||||
do
|
||||
{
|
||||
guard let (bundleIdentifier, result) = results.first else { throw refreshGroup?.context.error ?? OperationError.unknown }
|
||||
_ = try result.get()
|
||||
|
||||
if var patchedApps = UserDefaults.standard.patchedApps, let index = patchedApps.firstIndex(of: bundleIdentifier)
|
||||
{
|
||||
patchedApps.remove(at: index)
|
||||
UserDefaults.standard.patchedApps = patchedApps
|
||||
}
|
||||
|
||||
self.finish()
|
||||
}
|
||||
catch
|
||||
{
|
||||
self.present(error, title: errorTitle)
|
||||
}
|
||||
}
|
||||
self.setProgress(refreshGroup.progress, description: String(format: NSLocalizedString("Installing %@...", comment: ""), installedApp.name))
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
self.present(error, title: errorTitle)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func finish()
|
||||
{
|
||||
guard let installedApp = self.installedApp else { return }
|
||||
|
||||
self.setProgress(nil, description: nil)
|
||||
self.currentStep = .finish
|
||||
|
||||
self.didEnterBackgroundObservation = NotificationCenter.default.addObserver(forName: UIApplication.didEnterBackgroundNotification, object: nil, queue: .main) { (notification) in
|
||||
self.didEnterBackgroundObservation.map { NotificationCenter.default.removeObserver($0) }
|
||||
self.finish(with: .success(()))
|
||||
}
|
||||
|
||||
installedApp.managedObjectContext?.perform {
|
||||
let appName = installedApp.name
|
||||
let openURL = installedApp.openAppURL
|
||||
|
||||
self.buttonHandler = { [weak self] in
|
||||
guard let self = self else { return }
|
||||
|
||||
#if !targetEnvironment(simulator)
|
||||
|
||||
UIApplication.shared.open(openURL) { success in
|
||||
guard !success else { return }
|
||||
self.present(OperationError.openAppFailed(name: appName), title: String(format: NSLocalizedString("Could not open %@.", comment: ""), appName))
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
//
|
||||
// fragmentzip.h
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 10/25/21.
|
||||
// Copyright © 2021 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef fragmentzip_h
|
||||
#define fragmentzip_h
|
||||
|
||||
typedef void fragmentzip_t;
|
||||
typedef void (*fragmentzip_process_callback_t)(unsigned int progress);
|
||||
fragmentzip_t *fragmentzip_open(const char *url);
|
||||
int fragmentzip_download_file(fragmentzip_t *info, const char *remotepath, const char *savepath, fragmentzip_process_callback_t callback);
|
||||
void fragmentzip_close(fragmentzip_t *info);
|
||||
|
||||
#endif /* fragmentzip_h */
|
||||
@@ -1,77 +0,0 @@
|
||||
//
|
||||
// RemoveAppBackupOperation.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 5/13/20.
|
||||
// Copyright © 2020 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objc(RemoveAppBackupOperation)
|
||||
final class RemoveAppBackupOperation: ResultOperation<Void>
|
||||
{
|
||||
let context: InstallAppOperationContext
|
||||
|
||||
private let coordinator = NSFileCoordinator()
|
||||
private let coordinatorQueue = OperationQueue()
|
||||
|
||||
init(context: InstallAppOperationContext)
|
||||
{
|
||||
self.context = context
|
||||
|
||||
super.init()
|
||||
|
||||
self.coordinatorQueue.name = "AltStore - RemoveAppBackupOperation Queue"
|
||||
}
|
||||
|
||||
override func main()
|
||||
{
|
||||
super.main()
|
||||
|
||||
if let error = self.context.error
|
||||
{
|
||||
self.finish(.failure(error))
|
||||
return
|
||||
}
|
||||
|
||||
guard let installedApp = self.context.installedApp else { return self.finish(.failure(OperationError.invalidParameters)) }
|
||||
installedApp.managedObjectContext?.perform {
|
||||
guard let backupDirectoryURL = FileManager.default.backupDirectoryURL(for: installedApp) else { return self.finish(.failure(OperationError.missingAppGroup)) }
|
||||
|
||||
let intent = NSFileAccessIntent.writingIntent(with: backupDirectoryURL, options: [.forDeleting])
|
||||
self.coordinator.coordinate(with: [intent], queue: self.coordinatorQueue) { (error) in
|
||||
do
|
||||
{
|
||||
if let error = error
|
||||
{
|
||||
throw error
|
||||
}
|
||||
|
||||
try FileManager.default.removeItem(at: intent.url)
|
||||
|
||||
self.finish(.success(()))
|
||||
}
|
||||
catch let error as CocoaError where error.code == CocoaError.Code.fileNoSuchFile
|
||||
{
|
||||
#if DEBUG
|
||||
|
||||
// When debugging, it's expected that app groups don't match, so ignore.
|
||||
self.finish(.success(()))
|
||||
|
||||
#else
|
||||
|
||||
print("Failed to remove app backup directory:", error)
|
||||
self.finish(.failure(error))
|
||||
|
||||
#endif
|
||||
}
|
||||
catch
|
||||
{
|
||||
print("Failed to remove app backup directory:", error)
|
||||
self.finish(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -1,132 +0,0 @@
|
||||
//
|
||||
// InsetGroupTableViewCell.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 8/31/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
extension InsetGroupTableViewCell
|
||||
{
|
||||
@objc enum Style: Int
|
||||
{
|
||||
case single
|
||||
case top
|
||||
case middle
|
||||
case bottom
|
||||
}
|
||||
}
|
||||
|
||||
final class InsetGroupTableViewCell: UITableViewCell
|
||||
{
|
||||
#if !TARGET_INTERFACE_BUILDER
|
||||
@IBInspectable var style: Style = .single {
|
||||
didSet {
|
||||
self.update()
|
||||
}
|
||||
}
|
||||
#else
|
||||
@IBInspectable var style: Int = 0
|
||||
#endif
|
||||
|
||||
@IBInspectable var isSelectable: Bool = false
|
||||
|
||||
private let separatorView = UIView()
|
||||
private let insetView = UIView()
|
||||
|
||||
override func awakeFromNib()
|
||||
{
|
||||
super.awakeFromNib()
|
||||
|
||||
self.selectionStyle = .none
|
||||
|
||||
self.separatorView.translatesAutoresizingMaskIntoConstraints = false
|
||||
self.separatorView.backgroundColor = UIColor.white.withAlphaComponent(0.25)
|
||||
self.addSubview(self.separatorView)
|
||||
|
||||
self.insetView.layer.masksToBounds = true
|
||||
self.insetView.layer.cornerRadius = 16
|
||||
|
||||
// Get the preferred background color from Interface Builder.
|
||||
self.insetView.backgroundColor = self.backgroundColor
|
||||
self.backgroundColor = nil
|
||||
|
||||
self.addSubview(self.insetView, pinningEdgesWith: UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 15))
|
||||
self.sendSubviewToBack(self.insetView)
|
||||
|
||||
NSLayoutConstraint.activate([self.separatorView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 30),
|
||||
self.separatorView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -30),
|
||||
self.separatorView.bottomAnchor.constraint(equalTo: self.bottomAnchor),
|
||||
self.separatorView.heightAnchor.constraint(equalToConstant: 1)])
|
||||
|
||||
self.update()
|
||||
}
|
||||
|
||||
override func setSelected(_ selected: Bool, animated: Bool)
|
||||
{
|
||||
super.setSelected(selected, animated: animated)
|
||||
|
||||
if animated
|
||||
{
|
||||
UIView.animate(withDuration: 0.4) {
|
||||
self.update()
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.update()
|
||||
}
|
||||
}
|
||||
|
||||
override func setHighlighted(_ highlighted: Bool, animated: Bool)
|
||||
{
|
||||
super.setHighlighted(highlighted, animated: animated)
|
||||
|
||||
if animated
|
||||
{
|
||||
UIView.animate(withDuration: 0.4) {
|
||||
self.update()
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.update()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension InsetGroupTableViewCell
|
||||
{
|
||||
func update()
|
||||
{
|
||||
switch self.style
|
||||
{
|
||||
case .single:
|
||||
self.insetView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMaxYCorner]
|
||||
self.separatorView.isHidden = true
|
||||
|
||||
case .top:
|
||||
self.insetView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
|
||||
self.separatorView.isHidden = false
|
||||
|
||||
case .middle:
|
||||
self.insetView.layer.maskedCorners = []
|
||||
self.separatorView.isHidden = false
|
||||
|
||||
case .bottom:
|
||||
self.insetView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
|
||||
self.separatorView.isHidden = true
|
||||
}
|
||||
|
||||
if self.isSelectable && (self.isHighlighted || self.isSelected)
|
||||
{
|
||||
self.insetView.backgroundColor = UIColor.white.withAlphaComponent(0.55)
|
||||
}
|
||||
else
|
||||
{
|
||||
self.insetView.backgroundColor = UIColor.white.withAlphaComponent(0.25)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
//
|
||||
// LicensesViewController.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 9/6/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
final class LicensesViewController: UIViewController
|
||||
{
|
||||
private var _didAppear = false
|
||||
|
||||
@IBOutlet private var textView: UITextView!
|
||||
|
||||
override var preferredStatusBarStyle: UIStatusBarStyle {
|
||||
return .lightContent
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool)
|
||||
{
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
self.view.setNeedsLayout()
|
||||
self.view.layoutIfNeeded()
|
||||
|
||||
// Fix incorrect initial offset on iPhone SE.
|
||||
self.textView.contentOffset.y = 0
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool)
|
||||
{
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
_didAppear = true
|
||||
}
|
||||
|
||||
override func viewDidLayoutSubviews()
|
||||
{
|
||||
super.viewDidLayoutSubviews()
|
||||
|
||||
self.textView.textContainerInset.left = self.view.layoutMargins.left
|
||||
self.textView.textContainerInset.right = self.view.layoutMargins.right
|
||||
self.textView.textContainer.lineFragmentPadding = 0
|
||||
|
||||
if !_didAppear
|
||||
{
|
||||
// Fix incorrect initial offset on iPhone SE.
|
||||
self.textView.contentOffset.y = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
//
|
||||
// PatreonComponents.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 9/5/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
final class PatronCollectionViewCell: UICollectionViewCell
|
||||
{
|
||||
@IBOutlet var textLabel: UILabel!
|
||||
}
|
||||
|
||||
final class PatronsHeaderView: UICollectionReusableView
|
||||
{
|
||||
let textLabel = UILabel()
|
||||
|
||||
override init(frame: CGRect)
|
||||
{
|
||||
super.init(frame: frame)
|
||||
|
||||
self.textLabel.font = UIFont.boldSystemFont(ofSize: 17)
|
||||
self.textLabel.textColor = .white
|
||||
self.addSubview(self.textLabel, pinningEdgesWith: UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20))
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
|
||||
final class PatronsFooterView: UICollectionReusableView
|
||||
{
|
||||
let button = UIButton(type: .system)
|
||||
|
||||
override init(frame: CGRect)
|
||||
{
|
||||
super.init(frame: frame)
|
||||
|
||||
self.button.translatesAutoresizingMaskIntoConstraints = false
|
||||
self.button.activityIndicatorView.style = .medium
|
||||
self.button.titleLabel?.textColor = .white
|
||||
self.addSubview(self.button)
|
||||
|
||||
NSLayoutConstraint.activate([self.button.centerXAnchor.constraint(equalTo: self.centerXAnchor),
|
||||
self.button.centerYAnchor.constraint(equalTo: self.centerYAnchor)])
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
|
||||
final class AboutPatreonHeaderView: UICollectionReusableView
|
||||
{
|
||||
@IBOutlet var supportButton: UIButton!
|
||||
@IBOutlet var accountButton: UIButton!
|
||||
@IBOutlet var textView: UITextView!
|
||||
|
||||
@IBOutlet private var rileyLabel: UILabel!
|
||||
@IBOutlet private var shaneLabel: UILabel!
|
||||
|
||||
@IBOutlet private var rileyImageView: UIImageView!
|
||||
@IBOutlet private var shaneImageView: UIImageView!
|
||||
|
||||
override func awakeFromNib()
|
||||
{
|
||||
super.awakeFromNib()
|
||||
|
||||
self.textView.clipsToBounds = true
|
||||
self.textView.layer.cornerRadius = 20
|
||||
self.textView.textContainer.lineFragmentPadding = 0
|
||||
|
||||
for imageView in [self.rileyImageView, self.shaneImageView].compactMap({ $0 })
|
||||
{
|
||||
imageView.clipsToBounds = true
|
||||
imageView.layer.cornerRadius = imageView.bounds.midY
|
||||
}
|
||||
|
||||
for button in [self.supportButton, self.accountButton].compactMap({ $0 })
|
||||
{
|
||||
button.clipsToBounds = true
|
||||
button.layer.cornerRadius = 16
|
||||
}
|
||||
}
|
||||
|
||||
override func layoutMarginsDidChange()
|
||||
{
|
||||
super.layoutMarginsDidChange()
|
||||
|
||||
self.textView.textContainerInset = UIEdgeInsets(top: self.layoutMargins.left, left: self.layoutMargins.left, bottom: self.layoutMargins.right, right: self.layoutMargins.right)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
//
|
||||
// SettingsHeaderFooterView.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 8/31/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
import Roxas
|
||||
|
||||
final class SettingsHeaderFooterView: UITableViewHeaderFooterView
|
||||
{
|
||||
@IBOutlet var primaryLabel: UILabel!
|
||||
@IBOutlet var secondaryLabel: UILabel!
|
||||
@IBOutlet var button: UIButton!
|
||||
|
||||
@IBOutlet private var stackView: UIStackView!
|
||||
|
||||
override func awakeFromNib()
|
||||
{
|
||||
super.awakeFromNib()
|
||||
|
||||
self.contentView.layoutMargins = .zero
|
||||
self.contentView.preservesSuperviewLayoutMargins = true
|
||||
|
||||
self.stackView.translatesAutoresizingMaskIntoConstraints = false
|
||||
self.contentView.addSubview(self.stackView)
|
||||
|
||||
NSLayoutConstraint.activate([self.stackView.leadingAnchor.constraint(equalTo: self.contentView.layoutMarginsGuide.leadingAnchor),
|
||||
self.stackView.trailingAnchor.constraint(equalTo: self.contentView.layoutMarginsGuide.trailingAnchor),
|
||||
self.stackView.topAnchor.constraint(equalTo: self.contentView.layoutMarginsGuide.topAnchor),
|
||||
self.stackView.bottomAnchor.constraint(equalTo: self.contentView.layoutMarginsGuide.bottomAnchor)])
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
#include "Build.xcconfig"
|
||||
|
||||
PRODUCT_BUNDLE_IDENTIFIER = $(PRODUCT_BUNDLE_IDENTIFIER).AltStoreCore
|
||||
@@ -1,27 +0,0 @@
|
||||
//
|
||||
// AltStoreCore.h
|
||||
// AltStoreCore
|
||||
//
|
||||
// Created by Riley Testut on 9/3/20.
|
||||
// Copyright © 2020 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
//! Project version number for AltStoreCore.
|
||||
FOUNDATION_EXPORT double AltStoreCoreVersionNumber;
|
||||
|
||||
//! Project version string for AltStoreCore.
|
||||
FOUNDATION_EXPORT const unsigned char AltStoreCoreVersionString[];
|
||||
|
||||
// In this header, you should import all the public headers of your framework using statements like #import <AltStoreCore/PublicHeader.h>
|
||||
|
||||
#import <AltStoreCore/ALTAppPermission.h>
|
||||
#import <AltStoreCore/ALTSourceUserInfoKey.h>
|
||||
#import <AltStoreCore/ALTPatreonBenefitType.h>
|
||||
|
||||
// Shared
|
||||
#import <AltStoreCore/ALTConstants.h>
|
||||
#import <AltStoreCore/ALTConnection.h>
|
||||
#import <AltStoreCore/NSError+ALTServerError.h>
|
||||
#import <AltStoreCore/CFNotificationName+AltStore.h>
|
||||
@@ -1,30 +0,0 @@
|
||||
//
|
||||
// FileManager+SharedDirectories.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 5/14/20.
|
||||
// Copyright © 2020 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public extension FileManager
|
||||
{
|
||||
var altstoreSharedDirectory: URL? {
|
||||
guard let appGroup = Bundle.main.appGroups.first else { return nil }
|
||||
|
||||
let sharedDirectoryURL = self.containerURL(forSecurityApplicationGroupIdentifier: appGroup)
|
||||
return sharedDirectoryURL
|
||||
}
|
||||
|
||||
var appBackupsDirectory: URL? {
|
||||
let appBackupsDirectory = self.altstoreSharedDirectory?.appendingPathComponent("Backups", isDirectory: true)
|
||||
return appBackupsDirectory
|
||||
}
|
||||
|
||||
func backupDirectoryURL(for app: InstalledApp) -> URL?
|
||||
{
|
||||
let backupDirectoryURL = self.appBackupsDirectory?.appendingPathComponent(app.bundleIdentifier, isDirectory: true)
|
||||
return backupDirectoryURL
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
//
|
||||
// UIColor+Hex.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 7/15/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
public extension UIColor
|
||||
{
|
||||
// Borrowed from https://stackoverflow.com/a/26341062
|
||||
var hexString: String {
|
||||
let components = self.cgColor.components
|
||||
let r: CGFloat = components?[0] ?? 0.0
|
||||
let g: CGFloat = components?[1] ?? 0.0
|
||||
let b: CGFloat = components?[2] ?? 0.0
|
||||
|
||||
let hexString = String.init(format: "%02lX%02lX%02lX", lroundf(Float(r * 255)), lroundf(Float(g * 255)), lroundf(Float(b * 255)))
|
||||
return hexString
|
||||
}
|
||||
|
||||
// Borrowed from https://stackoverflow.com/a/33397427
|
||||
convenience init?(hexString: String)
|
||||
{
|
||||
let hex = hexString.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
|
||||
var int = UInt32()
|
||||
Scanner(string: hex).scanHexInt32(&int)
|
||||
let a, r, g, b: UInt32
|
||||
switch hex.count {
|
||||
case 3: // RGB (12-bit)
|
||||
(a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
|
||||
case 6: // RGB (24-bit)
|
||||
(a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
|
||||
case 8: // ARGB (32-bit)
|
||||
(a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
self.init(red: CGFloat(r) / 255, green: CGFloat(g) / 255, blue: CGFloat(b) / 255, alpha: CGFloat(a) / 255)
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
//
|
||||
// InstalledExtension.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 1/7/20.
|
||||
// Copyright © 2020 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
import AltSign
|
||||
|
||||
@objc(InstalledExtension)
|
||||
public class InstalledExtension: NSManagedObject, InstalledAppProtocol
|
||||
{
|
||||
/* Properties */
|
||||
@NSManaged public var name: String
|
||||
@NSManaged public var bundleIdentifier: String
|
||||
@NSManaged public var resignedBundleIdentifier: String
|
||||
@NSManaged public var version: String
|
||||
|
||||
@NSManaged public var refreshedDate: Date
|
||||
@NSManaged public var expirationDate: Date
|
||||
@NSManaged public var installedDate: Date
|
||||
|
||||
/* Relationships */
|
||||
@NSManaged public var parentApp: InstalledApp?
|
||||
|
||||
private override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?)
|
||||
{
|
||||
super.init(entity: entity, insertInto: context)
|
||||
}
|
||||
|
||||
public init(resignedAppExtension: ALTApplication, originalBundleIdentifier: String, context: NSManagedObjectContext)
|
||||
{
|
||||
super.init(entity: InstalledExtension.entity(), insertInto: context)
|
||||
|
||||
self.bundleIdentifier = originalBundleIdentifier
|
||||
|
||||
self.refreshedDate = Date()
|
||||
self.installedDate = Date()
|
||||
|
||||
self.expirationDate = self.refreshedDate.addingTimeInterval(60 * 60 * 24 * 7) // Rough estimate until we get real values from provisioning profile.
|
||||
|
||||
self.update(resignedAppExtension: resignedAppExtension)
|
||||
}
|
||||
|
||||
public func update(resignedAppExtension: ALTApplication)
|
||||
{
|
||||
self.name = resignedAppExtension.name
|
||||
|
||||
self.resignedBundleIdentifier = resignedAppExtension.bundleIdentifier
|
||||
self.version = resignedAppExtension.version
|
||||
|
||||
if let provisioningProfile = resignedAppExtension.provisioningProfile
|
||||
{
|
||||
self.update(provisioningProfile: provisioningProfile)
|
||||
}
|
||||
}
|
||||
|
||||
public func update(provisioningProfile: ALTProvisioningProfile)
|
||||
{
|
||||
self.refreshedDate = provisioningProfile.creationDate
|
||||
self.expirationDate = provisioningProfile.expirationDate
|
||||
}
|
||||
}
|
||||
|
||||
public extension InstalledExtension
|
||||
{
|
||||
@nonobjc class func fetchRequest() -> NSFetchRequest<InstalledExtension>
|
||||
{
|
||||
return NSFetchRequest<InstalledExtension>(entityName: "InstalledExtension")
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
//
|
||||
// Benefit.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 8/21/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension PatreonAPI
|
||||
{
|
||||
struct BenefitResponse: Decodable
|
||||
{
|
||||
var id: String
|
||||
}
|
||||
}
|
||||
|
||||
public struct Benefit: Hashable
|
||||
{
|
||||
public var type: ALTPatreonBenefitType
|
||||
|
||||
init(response: PatreonAPI.BenefitResponse)
|
||||
{
|
||||
self.type = ALTPatreonBenefitType(response.id)
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
//
|
||||
// Tier.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 8/21/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension PatreonAPI
|
||||
{
|
||||
struct TierResponse: Decodable
|
||||
{
|
||||
struct Attributes: Decodable
|
||||
{
|
||||
var title: String
|
||||
}
|
||||
|
||||
struct Relationships: Decodable
|
||||
{
|
||||
struct Benefits: Decodable
|
||||
{
|
||||
var data: [BenefitResponse]
|
||||
}
|
||||
|
||||
var benefits: Benefits
|
||||
}
|
||||
|
||||
var id: String
|
||||
var attributes: Attributes
|
||||
|
||||
var relationships: Relationships
|
||||
}
|
||||
}
|
||||
|
||||
public struct Tier
|
||||
{
|
||||
public var name: String
|
||||
public var identifier: String
|
||||
|
||||
public var benefits: [Benefit] = []
|
||||
|
||||
init(response: PatreonAPI.TierResponse)
|
||||
{
|
||||
self.name = response.attributes.title
|
||||
self.identifier = response.id
|
||||
self.benefits = response.relationships.benefits.data.map(Benefit.init(response:))
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
//
|
||||
// ALTAppPermission.h
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 7/23/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
typedef NSString *ALTAppPermissionType NS_TYPED_EXTENSIBLE_ENUM;
|
||||
extern ALTAppPermissionType const ALTAppPermissionTypePhotos;
|
||||
extern ALTAppPermissionType const ALTAppPermissionTypeCamera;
|
||||
extern ALTAppPermissionType const ALTAppPermissionTypeLocation;
|
||||
extern ALTAppPermissionType const ALTAppPermissionTypeContacts;
|
||||
extern ALTAppPermissionType const ALTAppPermissionTypeReminders;
|
||||
extern ALTAppPermissionType const ALTAppPermissionTypeAppleMusic;
|
||||
extern ALTAppPermissionType const ALTAppPermissionTypeMicrophone;
|
||||
extern ALTAppPermissionType const ALTAppPermissionTypeSpeechRecognition;
|
||||
extern ALTAppPermissionType const ALTAppPermissionTypeBackgroundAudio;
|
||||
extern ALTAppPermissionType const ALTAppPermissionTypeBackgroundFetch;
|
||||
extern ALTAppPermissionType const ALTAppPermissionTypeBluetooth;
|
||||
extern ALTAppPermissionType const ALTAppPermissionTypeNetwork;
|
||||
extern ALTAppPermissionType const ALTAppPermissionTypeCalendars;
|
||||
extern ALTAppPermissionType const ALTAppPermissionTypeTouchID;
|
||||
extern ALTAppPermissionType const ALTAppPermissionTypeFaceID;
|
||||
extern ALTAppPermissionType const ALTAppPermissionTypeSiri;
|
||||
extern ALTAppPermissionType const ALTAppPermissionTypeMotion;
|
||||
@@ -1,27 +0,0 @@
|
||||
//
|
||||
// ALTAppPermission.m
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 7/23/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
#import "ALTAppPermission.h"
|
||||
|
||||
ALTAppPermissionType const ALTAppPermissionTypePhotos = @"photos";
|
||||
ALTAppPermissionType const ALTAppPermissionTypeCamera = @"camera";
|
||||
ALTAppPermissionType const ALTAppPermissionTypeLocation = @"location";
|
||||
ALTAppPermissionType const ALTAppPermissionTypeContacts = @"contacts";
|
||||
ALTAppPermissionType const ALTAppPermissionTypeReminders = @"reminders";
|
||||
ALTAppPermissionType const ALTAppPermissionTypeAppleMusic = @"music";
|
||||
ALTAppPermissionType const ALTAppPermissionTypeMicrophone = @"microphone";
|
||||
ALTAppPermissionType const ALTAppPermissionTypeSpeechRecognition = @"speech-recognition";
|
||||
ALTAppPermissionType const ALTAppPermissionTypeBackgroundAudio = @"background-audio";
|
||||
ALTAppPermissionType const ALTAppPermissionTypeBackgroundFetch = @"background-fetch";
|
||||
ALTAppPermissionType const ALTAppPermissionTypeBluetooth = @"bluetooth";
|
||||
ALTAppPermissionType const ALTAppPermissionTypeNetwork = @"network";
|
||||
ALTAppPermissionType const ALTAppPermissionTypeCalendars = @"calendars";
|
||||
ALTAppPermissionType const ALTAppPermissionTypeTouchID = @"touchid";
|
||||
ALTAppPermissionType const ALTAppPermissionTypeFaceID = @"faceid";
|
||||
ALTAppPermissionType const ALTAppPermissionTypeSiri = @"siri";
|
||||
ALTAppPermissionType const ALTAppPermissionTypeMotion = @"motion";
|
||||
@@ -1,13 +0,0 @@
|
||||
//
|
||||
// ALTPatreonBenefitType.h
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 8/27/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
typedef NSString *ALTPatreonBenefitType NS_TYPED_EXTENSIBLE_ENUM;
|
||||
extern ALTPatreonBenefitType const ALTPatreonBenefitTypeBetaAccess;
|
||||
extern ALTPatreonBenefitType const ALTPatreonBenefitTypeCredits;
|
||||
@@ -1,12 +0,0 @@
|
||||
//
|
||||
// ALTPatreonBenefitType.m
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 8/27/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
#import "ALTPatreonBenefitType.h"
|
||||
|
||||
ALTPatreonBenefitType const ALTPatreonBenefitTypeBetaAccess = @"1186336";
|
||||
ALTPatreonBenefitType const ALTPatreonBenefitTypeCredits = @"1186340";
|
||||
@@ -1,12 +0,0 @@
|
||||
//
|
||||
// ALTSourceUserInfoKey.h
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 11/4/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
typedef NSString *ALTSourceUserInfoKey NS_TYPED_EXTENSIBLE_ENUM;
|
||||
extern ALTSourceUserInfoKey const ALTSourceUserInfoKeyPatreonAccessToken;
|
||||
@@ -1,11 +0,0 @@
|
||||
//
|
||||
// ALTSourceUserInfoKey.m
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 11/4/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
#import "ALTSourceUserInfoKey.h"
|
||||
|
||||
ALTSourceUserInfoKey const ALTSourceUserInfoKeyPatreonAccessToken = @"patreonAccessToken";
|
||||
@@ -1,3 +0,0 @@
|
||||
#include "Build.xcconfig"
|
||||
|
||||
PRODUCT_BUNDLE_IDENTIFIER = $(PRODUCT_BUNDLE_IDENTIFIER).AltWidget
|
||||
@@ -6,19 +6,26 @@ CURRENT_PROJECT_VERSION = 3050
|
||||
|
||||
// Vars to be overwritten by `CodeSigning.xcconfig` if exists
|
||||
DEVELOPMENT_TEAM = S32Z3HMYVQ
|
||||
ORG_IDENTIFIER = com.SideStore
|
||||
ORG_IDENTIFIER = com.$(PROJECT_NAME)
|
||||
|
||||
// Codesigning settings defined optionally, see `CodeSigning.xcconfig.example`
|
||||
#include? "CodeSigning.xcconfig"
|
||||
|
||||
ORG_PREFIX = $(ORG_IDENTIFIER)
|
||||
|
||||
PRODUCT_NAME = SideStore
|
||||
EXTENSION_PREFIX = $(ORG_PREFIX).SideStore
|
||||
//PRODUCT_NAME[configuration=Debug] = Prov Debug
|
||||
|
||||
PRODUCT_BUNDLE_IDENTIFIER = $(ORG_PREFIX).SideStore
|
||||
//PRODUCT_BUNDLE_IDENTIFIER[configuration=Debug] = $(ORG_PREFIX).$(PROJECT_NAME:lower)-debug
|
||||
|
||||
APP_GROUP_IDENTIFIER = $(ORG_PREFIX).SideStore
|
||||
APP_GROUP_IDENTIFIER = $(ORG_PREFIX).$(PROJECT_NAME)
|
||||
ICLOUD_CONTAINER_IDENTIFIER = iCloud.$(ORG_PREFIX).$(PROJECT_NAME)
|
||||
|
||||
PRODUCT_NAME = $(PROJECT_NAME)
|
||||
PRODUCT_NAME[config=Debug] = $(PROJECT_NAME) Debug
|
||||
|
||||
EXTENSION_PREFIX = $(ORG_PREFIX).$(PROJECT_NAME)
|
||||
|
||||
PRODUCT_BUNDLE_IDENTIFIER = $(ORG_PREFIX).$(PROJECT_NAME:lower)
|
||||
PRODUCT_BUNDLE_IDENTIFIER[config=Debug] = $(ORG_PREFIX).$(PROJECT_NAME:lower)-debug
|
||||
|
||||
// MARK: - XCode / Swift
|
||||
|
||||
// Clang and the build system support a new mode for building module dependencies called explicit modules
|
||||
// which improves build performance, reliability, and correctness.
|
||||
// https://developer.apple.com/documentation/xcode-release-notes/xcode-14_3-release-notes#New-Features-in-Xcode-143-Beta-2
|
||||
_EXPERIMENTAL_CLANG_EXPLICIT_MODULES = YES
|
||||
|
||||
22
Configurations/SideStore.xcconfig
Normal file
22
Configurations/SideStore.xcconfig
Normal file
@@ -0,0 +1,22 @@
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES=YES
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME=AppIcon
|
||||
CLANG_ENABLE_MODULES=YES
|
||||
CODE_SIGN_ENTITLEMENTS=Sources/SideStore/Resources/AltStore.entitlements
|
||||
CODE_SIGN_IDENTITY=iPhone Developer
|
||||
CODE_SIGN_STYLE=Automatic
|
||||
DEVELOPMENT_TEAM=$(DEVELOPMENT_TEAM)
|
||||
ENABLE_BITCODE=NO
|
||||
INFOPLIST_FILE=Sources/SideStore/Resources/Info.plist
|
||||
IPHONEOS_DEPLOYMENT_TARGET=14.0
|
||||
PRODUCT_BUNDLE_IDENTIFIER=$(PRODUCT_BUNDLE_IDENTIFIER)
|
||||
PRODUCT_NAME=$(TARGET_NAME)
|
||||
PROVISIONING_PROFILE_SPECIFIER=
|
||||
SUPPORTED_PLATFORMS=iphonesimulator iphoneos
|
||||
SWIFT_VERSION=5.0
|
||||
TARGETED_DEVICE_FAMILY=1,2
|
||||
|
||||
LD_RUNPATH_SEARCH_PATHS[config=Debug]=["$(inherited)", "@executable_path/Frameworks"]
|
||||
LD_RUNPATH_SEARCH_PATHS[config=Release]=["$(inherited)", "@executable_path/Frameworks"]
|
||||
LIBRARY_SEARCH_PATHS[config=Debug]=["$(inherited)", "$(PROJECT_DIR)/Dependencies/fragmentzip", "$(PROJECT_DIR)/Dependencies/libcurl"]
|
||||
LIBRARY_SEARCH_PATHS[config=Release]=["$(inherited)", "$(PROJECT_DIR)/Dependencies/fragmentzip", "$(PROJECT_DIR)/Dependencies/libcurl"]
|
||||
SWIFT_OPTIMIZATION_LEVEL[config=Debug]=-Onone
|
||||
62
Configurations/SideStoreProject.xcconfig
Normal file
62
Configurations/SideStoreProject.xcconfig
Normal file
@@ -0,0 +1,62 @@
|
||||
ALWAYS_SEARCH_USER_PATHS=NO
|
||||
CLANG_ANALYZER_NONNULL=YES
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION=YES_AGGRESSIVE
|
||||
CLANG_CXX_LANGUAGE_STANDARD=gnu++14
|
||||
CLANG_CXX_LIBRARY=libc++
|
||||
CLANG_ENABLE_MODULES=YES
|
||||
CLANG_ENABLE_OBJC_ARC=YES
|
||||
CLANG_ENABLE_OBJC_WEAK=YES
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING=YES
|
||||
CLANG_WARN_BOOL_CONVERSION=YES
|
||||
CLANG_WARN_COMMA=YES
|
||||
CLANG_WARN_CONSTANT_CONVERSION=YES
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS=YES
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE=YES_ERROR
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS=NO
|
||||
CLANG_WARN_EMPTY_BODY=YES
|
||||
CLANG_WARN_ENUM_CONVERSION=YES
|
||||
CLANG_WARN_INFINITE_RECURSION=YES
|
||||
CLANG_WARN_INT_CONVERSION=YES
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION=YES
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF=YES
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION=YES
|
||||
CLANG_WARN_OBJC_ROOT_CLASS=YES_ERROR
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS=YES
|
||||
CLANG_WARN_STRICT_PROTOTYPES=YES
|
||||
CLANG_WARN_SUSPICIOUS_MOVE=YES
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY=YES_AGGRESSIVE
|
||||
CLANG_WARN_UNREACHABLE_CODE=YES
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH=YES
|
||||
CODE_SIGN_IDENTITY=iPhone Developer
|
||||
COPY_PHASE_STRIP=NO
|
||||
DEBUG_INFORMATION_FORMAT=dwarf-with-dsym
|
||||
ENABLE_STRICT_OBJC_MSGSEND=YES
|
||||
GCC_C_LANGUAGE_STANDARD=gnu11
|
||||
GCC_NO_COMMON_BLOCKS=YES
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION=YES
|
||||
GCC_WARN_ABOUT_RETURN_TYPE=YES_ERROR
|
||||
GCC_WARN_UNDECLARED_SELECTOR=YES
|
||||
GCC_WARN_UNINITIALIZED_AUTOS=YES_AGGRESSIVE
|
||||
GCC_WARN_UNUSED_FUNCTION=YES
|
||||
GCC_WARN_UNUSED_VARIABLE=YES
|
||||
IPHONEOS_DEPLOYMENT_TARGET=12.2
|
||||
MTL_FAST_MATH=YES
|
||||
SDKROOT=iphoneos
|
||||
SUPPORTED_PLATFORMS=iphonesimulator iphoneos macosx
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS=DEBUG BETA
|
||||
SYSTEM_HEADER_SEARCH_PATHS="$(SRCROOT)/Dependencies/AltSign/Dependencies"
|
||||
|
||||
ENABLE_NS_ASSERTIONS[config=Release]=NO
|
||||
ENABLE_TESTABILITY[config=Debug]=YES
|
||||
GCC_DYNAMIC_NO_PIC[config=Debug]=NO
|
||||
GCC_OPTIMIZATION_LEVEL[config=Debug]=0
|
||||
GCC_PREPROCESSOR_DEFINITIONS[config=Debug]=["DEBUG=1", "$(inherited)"]
|
||||
MTL_ENABLE_DEBUG_INFO[config=Debug]=INCLUDE_SOURCE
|
||||
MTL_ENABLE_DEBUG_INFO[config=Release]=NO
|
||||
ONLY_ACTIVE_ARCH[config=Debug]=YES
|
||||
OTHER_CPLUSPLUSFLAGS[config=Debug]=["$(OTHER_CFLAGS)", "-Wno-module-import-in-extern-c"]
|
||||
OTHER_CPLUSPLUSFLAGS[config=Release]=["$(OTHER_CFLAGS)", "-Wno-module-import-in-extern-c"]
|
||||
SWIFT_COMPILATION_MODE[config=Release]=wholemodule
|
||||
SWIFT_OPTIMIZATION_LEVEL[config=Debug]=-Onone
|
||||
SWIFT_OPTIMIZATION_LEVEL[config=Release]=-O
|
||||
VALIDATE_PRODUCT[config=Release]=YES
|
||||
15
Dangerfile.swift
Normal file
15
Dangerfile.swift
Normal file
@@ -0,0 +1,15 @@
|
||||
import DangerSwiftCoverage // package: https://github.com/f-meloni/danger-swift-coverage.git
|
||||
import DangerSwiftLint // package: https://github.com/ashfurrow/danger-swiftlint.git
|
||||
import DangerXCodeSummary // package: https://github.com/f-meloni/danger-swift-xcodesummary.git
|
||||
|
||||
let danger = Danger()
|
||||
|
||||
// swift run danger-swift [ci, pr] --dangerfile ./Dangerfile.swift
|
||||
// xcodebuild test -scheme DangerSwiftCoverage-Package -derivedDataPath Build/ -enableCodeCoverage YES
|
||||
// (Recommended) Cache the ~/.danger-swift folder
|
||||
|
||||
Coverage.xcodeBuildCoverage(.derivedDataFolder("Build"),
|
||||
minimumCoverage: 50,
|
||||
excludedTargets: ["DangerSwiftCoverageTests.xctest"])
|
||||
|
||||
SwiftLint.lint(directory: "SideStoreApp", configFile: ".swiftlint.yml")
|
||||
1
Dependencies/MarkdownAttributedString
vendored
1
Dependencies/MarkdownAttributedString
vendored
Submodule Dependencies/MarkdownAttributedString deleted from 750e8d5cb4
1
Dependencies/Roxas
vendored
1
Dependencies/Roxas
vendored
Submodule Dependencies/Roxas deleted from ac906cf490
343
Dependencies/em_proxy.xcodeproj/project.pbxproj
vendored
343
Dependencies/em_proxy.xcodeproj/project.pbxproj
vendored
@@ -1,343 +0,0 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 53;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
9987603429A4555300818586 /* em_proxy.h in Sources */ = {isa = PBXBuildFile; fileRef = 9999259129A45319005CF020 /* em_proxy.h */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXBuildRule section */
|
||||
CA6094FFF692AC6C1400ACA8 /* PBXBuildRule */ = {
|
||||
isa = PBXBuildRule;
|
||||
compilerSpec = com.apple.compilers.proxy.script;
|
||||
filePatterns = "*/em_proxy.h";
|
||||
fileType = pattern.proxy;
|
||||
inputFiles = (
|
||||
);
|
||||
isEditable = 0;
|
||||
name = "Cargo project build";
|
||||
outputFiles = (
|
||||
"$(OBJECT_FILE_DIR)/$(CARGO_XCODE_TARGET_ARCH)-$(EXECUTABLE_NAME)",
|
||||
);
|
||||
script = "# generated with cargo-xcode 1.5.0\n# modified to use prebuilt binaries\n\nset -eu;\n\nBUILT_SRC=\"./em_proxy/$LIB_FILE_NAME.a\"\nln -f -- \"$BUILT_SRC\" \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\" || cp \"$BUILT_SRC\" \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\necho \"$BUILT_SRC -> $TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\n\n# xcode generates dep file, but for its own path, so append our rename to it\n#DEP_FILE_SRC=\"minimuxer/target/${CARGO_XCODE_TARGET_TRIPLE}/release/${CARGO_XCODE_CARGO_DEP_FILE_NAME}\"\n#if [ -f \"$DEP_FILE_SRC\" ]; then\n# DEP_FILE_DST=\"${DERIVED_FILE_DIR}/${CARGO_XCODE_TARGET_ARCH}-${EXECUTABLE_NAME}.d\"\n# cp -f \"$DEP_FILE_SRC\" \"$DEP_FILE_DST\"\n# echo >> \"$DEP_FILE_DST\" \"$SCRIPT_OUTPUT_FILE_0: $BUILT_SRC\"\n#fi\n\n# lipo script needs to know all the platform-specific files that have been built\n# archs is in the file name, so that paths don't stay around after archs change\n# must match input for LipoScript\n#FILE_LIST=\"${DERIVED_FILE_DIR}/${ARCHS}-${EXECUTABLE_NAME}.xcfilelist\"\n#touch \"$FILE_LIST\"\n#if ! egrep -q \"$SCRIPT_OUTPUT_FILE_0\" \"$FILE_LIST\" ; then\n# echo >> \"$FILE_LIST\" \"$SCRIPT_OUTPUT_FILE_0\"\n#fi\n";
|
||||
};
|
||||
/* End PBXBuildRule section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
9999259129A45319005CF020 /* em_proxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = em_proxy.h; path = em_proxy/em_proxy.h; sourceTree = "<group>"; };
|
||||
ADDEDBA66A6E1 /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libresolv.tbd; path = usr/lib/libresolv.tbd; sourceTree = SDKROOT; };
|
||||
CA60058A9FBE4D17AF51A7D5 /* run */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = run; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
CA60C44C93D7916DE57E6EBD /* libem_proxy_static.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libem_proxy_static.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
ADDEDBA66A6E2 /* Required for static linking */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
ADDEDBA66A6E1 /* libresolv.tbd */,
|
||||
);
|
||||
name = "Required for static linking";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CA6094FFF69222869D176AE5 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CA60C44C93D7916DE57E6EBD /* libem_proxy_static.a */,
|
||||
CA60058A9FBE4D17AF51A7D5 /* run */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CA6094FFF69298AF0B5890DB /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
ADDEDBA66A6E2 /* Required for static linking */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CA6094FFF692D65BC3C892A8 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9999259129A45319005CF020 /* em_proxy.h */,
|
||||
CA6094FFF69222869D176AE5 /* Products */,
|
||||
CA6094FFF69298AF0B5890DB /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
CA60058A9FBE37FC563E4BCC /* run-bin */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = CA603DD75FB437FC563E4BCC /* Build configuration list for PBXNativeTarget "run-bin" */;
|
||||
buildPhases = (
|
||||
CA60445C303637FC563E4BCC /* Sources */,
|
||||
CA6094FFF692AF6EBB7F357C /* Universal Binary lipo */,
|
||||
);
|
||||
buildRules = (
|
||||
CA6094FFF692AC6C1400ACA8 /* PBXBuildRule */,
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "run-bin";
|
||||
productName = run;
|
||||
productReference = CA60058A9FBE4D17AF51A7D5 /* run */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
CA60C44C93D7A30E3695DD59 /* em_proxy-staticlib */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = CA603DD75FB4A30E3695DD59 /* Build configuration list for PBXNativeTarget "em_proxy-staticlib" */;
|
||||
buildPhases = (
|
||||
9987603529A4610700818586 /* ShellScript */,
|
||||
CA60445C3036A30E3695DD59 /* Sources */,
|
||||
CA6094FFF692AF6EBB7F357C /* Universal Binary lipo */,
|
||||
);
|
||||
buildRules = (
|
||||
CA6094FFF692AC6C1400ACA8 /* PBXBuildRule */,
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "em_proxy-staticlib";
|
||||
productName = libem_proxy_static.a;
|
||||
productReference = CA60C44C93D7916DE57E6EBD /* libem_proxy_static.a */;
|
||||
productType = "com.apple.product-type.library.static";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
CA6094FFF692E04653AD465F /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1300;
|
||||
TargetAttributes = {
|
||||
CA60058A9FBE37FC563E4BCC = {
|
||||
CreatedOnToolsVersion = 9.2;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
CA60C44C93D7A30E3695DD59 = {
|
||||
CreatedOnToolsVersion = 9.2;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = CA6094FFF69280E02D6C7F57 /* Build configuration list for PBXProject "em_proxy" */;
|
||||
compatibilityVersion = "Xcode 11.4";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = CA6094FFF692D65BC3C892A8;
|
||||
productRefGroup = CA6094FFF69222869D176AE5 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
CA60C44C93D7A30E3695DD59 /* em_proxy-staticlib */,
|
||||
CA60058A9FBE37FC563E4BCC /* run-bin */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
9987603529A4610700818586 /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
./em_proxy/em_proxy.h,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "bash ./fetch-prebuilt.sh em_proxy\n";
|
||||
};
|
||||
CA6094FFF692AF6EBB7F357C /* Universal Binary lipo */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/$(ARCHS)-$(EXECUTABLE_NAME).xcfilelist",
|
||||
);
|
||||
name = "Universal Binary lipo";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(TARGET_BUILD_DIR)/$(EXECUTABLE_PATH)",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "# generated with cargo-xcode 1.5.0\n\n#set -eux; cat \"$DERIVED_FILE_DIR/$ARCHS-$EXECUTABLE_NAME.xcfilelist\" | tr '\\n' '\\0' | xargs -0 lipo -create -output \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\n#if [ ${LD_DYLIB_INSTALL_NAME:+1} ]; then\n# install_name_tool -id \"$LD_DYLIB_INSTALL_NAME\" \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\n#fi\n";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
CA60445C303637FC563E4BCC /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
CA60445C3036A30E3695DD59 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9987603429A4555300818586 /* em_proxy.h in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
CA604DFE779B37FC563E4BCC /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CARGO_XCODE_CARGO_DEP_FILE_NAME = run.d;
|
||||
CARGO_XCODE_CARGO_FILE_NAME = run;
|
||||
PRODUCT_NAME = run;
|
||||
SUPPORTED_PLATFORMS = macosx;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
CA604DFE779BA30E3695DD59 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CARGO_XCODE_CARGO_DEP_FILE_NAME = libem_proxy.d;
|
||||
CARGO_XCODE_CARGO_FILE_NAME = libem_proxy.a;
|
||||
INSTALL_GROUP = "";
|
||||
INSTALL_MODE_FLAG = "";
|
||||
INSTALL_OWNER = "";
|
||||
LIB_FILE_NAME = "";
|
||||
"LIB_FILE_NAME[sdk=iphoneos*]" = libem_proxy;
|
||||
"LIB_FILE_NAME[sdk=iphonesimulator*]" = "libem_proxy-sim";
|
||||
PRODUCT_NAME = em_proxy_static;
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos appletvsimulator appletvos";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
CA609A517351228BE02872F8 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CARGO_TARGET_DIR = "$(PROJECT_TEMP_DIR)/cargo_target";
|
||||
CARGO_XCODE_BUILD_MODE = debug;
|
||||
CARGO_XCODE_FEATURES = "";
|
||||
"CARGO_XCODE_TARGET_ARCH[arch=arm64*]" = aarch64;
|
||||
"CARGO_XCODE_TARGET_ARCH[arch=i386]" = i686;
|
||||
"CARGO_XCODE_TARGET_ARCH[arch=x86_64*]" = x86_64;
|
||||
"CARGO_XCODE_TARGET_OS[sdk=appletvos*]" = tvos;
|
||||
"CARGO_XCODE_TARGET_OS[sdk=appletvsimulator*]" = tvos;
|
||||
"CARGO_XCODE_TARGET_OS[sdk=iphoneos*]" = ios;
|
||||
"CARGO_XCODE_TARGET_OS[sdk=iphonesimulator*]" = "ios-sim";
|
||||
"CARGO_XCODE_TARGET_OS[sdk=iphonesimulator*][arch=x86_64*]" = ios;
|
||||
"CARGO_XCODE_TARGET_OS[sdk=macosx*]" = darwin;
|
||||
CURRENT_PROJECT_VERSION = 0.1;
|
||||
MARKETING_VERSION = 0.1.0;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRODUCT_NAME = em_proxy;
|
||||
SDKROOT = macosx;
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
CA609A5173513CC16B37690B /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CARGO_TARGET_DIR = "$(PROJECT_TEMP_DIR)/cargo_target";
|
||||
CARGO_XCODE_BUILD_MODE = release;
|
||||
CARGO_XCODE_FEATURES = "";
|
||||
"CARGO_XCODE_TARGET_ARCH[arch=arm64*]" = aarch64;
|
||||
"CARGO_XCODE_TARGET_ARCH[arch=i386]" = i686;
|
||||
"CARGO_XCODE_TARGET_ARCH[arch=x86_64*]" = x86_64;
|
||||
"CARGO_XCODE_TARGET_OS[sdk=appletvos*]" = tvos;
|
||||
"CARGO_XCODE_TARGET_OS[sdk=appletvsimulator*]" = tvos;
|
||||
"CARGO_XCODE_TARGET_OS[sdk=iphoneos*]" = ios;
|
||||
"CARGO_XCODE_TARGET_OS[sdk=iphonesimulator*]" = "ios-sim";
|
||||
"CARGO_XCODE_TARGET_OS[sdk=iphonesimulator*][arch=x86_64*]" = ios;
|
||||
"CARGO_XCODE_TARGET_OS[sdk=macosx*]" = darwin;
|
||||
CURRENT_PROJECT_VERSION = 0.1;
|
||||
MARKETING_VERSION = 0.1.0;
|
||||
PRODUCT_NAME = em_proxy;
|
||||
SDKROOT = macosx;
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
CA60DE07A83F37FC563E4BCC /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CARGO_XCODE_CARGO_DEP_FILE_NAME = run.d;
|
||||
CARGO_XCODE_CARGO_FILE_NAME = run;
|
||||
PRODUCT_NAME = run;
|
||||
SUPPORTED_PLATFORMS = macosx;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
CA60DE07A83FA30E3695DD59 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CARGO_XCODE_CARGO_DEP_FILE_NAME = libem_proxy.d;
|
||||
CARGO_XCODE_CARGO_FILE_NAME = libem_proxy.a;
|
||||
INSTALL_GROUP = "";
|
||||
INSTALL_MODE_FLAG = "";
|
||||
INSTALL_OWNER = "";
|
||||
LIB_FILE_NAME = "";
|
||||
"LIB_FILE_NAME[sdk=iphoneos*]" = libem_proxy;
|
||||
"LIB_FILE_NAME[sdk=iphonesimulator*]" = "libem_proxy-sim";
|
||||
PRODUCT_NAME = em_proxy_static;
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos appletvsimulator appletvos";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
CA603DD75FB437FC563E4BCC /* Build configuration list for PBXNativeTarget "run-bin" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
CA604DFE779B37FC563E4BCC /* Release */,
|
||||
CA60DE07A83F37FC563E4BCC /* Debug */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
CA603DD75FB4A30E3695DD59 /* Build configuration list for PBXNativeTarget "em_proxy-staticlib" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
CA604DFE779BA30E3695DD59 /* Release */,
|
||||
CA60DE07A83FA30E3695DD59 /* Debug */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
CA6094FFF69280E02D6C7F57 /* Build configuration list for PBXProject "em_proxy" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
CA609A5173513CC16B37690B /* Release */,
|
||||
CA609A517351228BE02872F8 /* Debug */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = CA6094FFF692E04653AD465F /* Project object */;
|
||||
}
|
||||
1
Dependencies/em_proxy/.gitkeep
vendored
1
Dependencies/em_proxy/.gitkeep
vendored
@@ -1 +0,0 @@
|
||||
Use ../fetch-prebuilt.sh to fetch prebuilt Rust dependencies
|
||||
52
Dependencies/fetch-prebuilt.sh
vendored
52
Dependencies/fetch-prebuilt.sh
vendored
@@ -1,52 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Ensure we are in Dependencies directory
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
check_for_update() {
|
||||
if [ -f ".skip-prebuilt-fetch-$1" ]; then
|
||||
echo "Skipping prebuilt fetch for $1 since .skip-prebuilt-fetch-$1 exists. If you are developing $1 alongside SideStore, don't remove this file, or this script will replace your locally built binaries with the ones built by GitHub Actions."
|
||||
return
|
||||
fi
|
||||
|
||||
if [ ! -f ".last-prebuilt-fetch-$1" ]; then
|
||||
echo "0,none" > ".last-prebuilt-fetch-$1"
|
||||
fi
|
||||
|
||||
LAST_FETCH=`cat .last-prebuilt-fetch-$1 | perl -n -e '/([0-9]*),([^ ]*)$/ && print $1'`
|
||||
LAST_COMMIT=`cat .last-prebuilt-fetch-$1 | perl -n -e '/([0-9]*),([^ ]*)$/ && print $2'`
|
||||
|
||||
# fetch if last fetch was over 6 hours ago
|
||||
if [[ $LAST_FETCH -lt $(expr $(date +%s) - 21600) ]] || [[ "$2" == "force" ]]; then
|
||||
echo "Checking $1 for update"
|
||||
echo
|
||||
LATEST_COMMIT=`curl https://api.github.com/repos/SideStore/$1/releases/latest | perl -n -e '/Commit: https:\\/\\/github\\.com\\/[^\\/]*\\/[^\\/]*\\/commit\\/([^"]*)/ && print $1'`
|
||||
echo
|
||||
echo "Last commit: $LAST_COMMIT"
|
||||
echo "Latest commit: $LATEST_COMMIT"
|
||||
if [[ "$LAST_COMMIT" != "$LATEST_COMMIT" ]]; then
|
||||
echo "Found update, downloading binaries"
|
||||
echo
|
||||
wget -O "$1/lib$1.a" "https://github.com/SideStore/$1/releases/latest/download/lib$1.a"
|
||||
wget -O "$1/lib$1-sim.a" "https://github.com/SideStore/$1/releases/latest/download/lib$1-sim.a"
|
||||
wget -O "$1/$1.h" "https://github.com/SideStore/$1/releases/latest/download/$1.h"
|
||||
echo
|
||||
else
|
||||
echo "Up-to-date"
|
||||
fi
|
||||
echo "$(date +%s),$LATEST_COMMIT" > ".last-prebuilt-fetch-$1"
|
||||
else
|
||||
echo "It hasn't been 6 hours and force was not specified, skipping update check for $1"
|
||||
fi
|
||||
}
|
||||
|
||||
# Allow for Xcode to check minimuxer and em_proxy separately by skipping the update check if the other one is specified as an argument
|
||||
if [[ "$1" != "em_proxy" ]]; then
|
||||
check_for_update minimuxer "$1"
|
||||
if [[ "$1" != "minimuxer" ]]; then
|
||||
echo
|
||||
fi
|
||||
fi
|
||||
if [[ "$1" != "minimuxer" ]]; then
|
||||
check_for_update em_proxy "$1"
|
||||
fi
|
||||
BIN
Dependencies/libcurl/libcurl.a
vendored
BIN
Dependencies/libcurl/libcurl.a
vendored
Binary file not shown.
1
Dependencies/libfragmentzip
vendored
1
Dependencies/libfragmentzip
vendored
Submodule Dependencies/libfragmentzip deleted from 9a899fde3c
1
Dependencies/libimobiledevice
vendored
1
Dependencies/libimobiledevice
vendored
Submodule Dependencies/libimobiledevice deleted from b314f04bd7
1
Dependencies/libimobiledevice-glue
vendored
1
Dependencies/libimobiledevice-glue
vendored
Submodule Dependencies/libimobiledevice-glue deleted from 7eaa28ea95
1
Dependencies/libplist
vendored
1
Dependencies/libplist
vendored
Submodule Dependencies/libplist deleted from c3af449543
1
Dependencies/libusbmuxd
vendored
1
Dependencies/libusbmuxd
vendored
Submodule Dependencies/libusbmuxd deleted from 6426362e5c
283
Dependencies/minimuxer.xcodeproj/project.pbxproj
vendored
283
Dependencies/minimuxer.xcodeproj/project.pbxproj
vendored
@@ -1,283 +0,0 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 53;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
9987603329A454B500818586 /* minimuxer.h in Sources */ = {isa = PBXBuildFile; fileRef = 9987603229A454B500818586 /* minimuxer.h */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXBuildRule section */
|
||||
CA6012A875F9AC6C1400ACA8 /* PBXBuildRule */ = {
|
||||
isa = PBXBuildRule;
|
||||
compilerSpec = com.apple.compilers.proxy.script;
|
||||
filePatterns = "*/minimuxer.h";
|
||||
fileType = pattern.proxy;
|
||||
inputFiles = (
|
||||
);
|
||||
isEditable = 0;
|
||||
name = "Cargo project build";
|
||||
outputFiles = (
|
||||
"$(OBJECT_FILE_DIR)/$(CARGO_XCODE_TARGET_ARCH)-$(EXECUTABLE_NAME)",
|
||||
);
|
||||
script = "# generated with cargo-xcode 1.5.0\n# modified to use prebuilt binaries\n\nset -eu;\n\nBUILT_SRC=\"./minimuxer/$LIB_FILE_NAME.a\"\nln -f -- \"$BUILT_SRC\" \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\" || cp \"$BUILT_SRC\" \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\necho \"$BUILT_SRC -> $TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\n\n# xcode generates dep file, but for its own path, so append our rename to it\n#DEP_FILE_SRC=\"minimuxer/target/${CARGO_XCODE_TARGET_TRIPLE}/release/${CARGO_XCODE_CARGO_DEP_FILE_NAME}\"\n#if [ -f \"$DEP_FILE_SRC\" ]; then\n# DEP_FILE_DST=\"${DERIVED_FILE_DIR}/${CARGO_XCODE_TARGET_ARCH}-${EXECUTABLE_NAME}.d\"\n# cp -f \"$DEP_FILE_SRC\" \"$DEP_FILE_DST\"\n# echo >> \"$DEP_FILE_DST\" \"$SCRIPT_OUTPUT_FILE_0: $BUILT_SRC\"\n#fi\n\n# lipo script needs to know all the platform-specific files that have been built\n# archs is in the file name, so that paths don't stay around after archs change\n# must match input for LipoScript\n#FILE_LIST=\"${DERIVED_FILE_DIR}/${ARCHS}-${EXECUTABLE_NAME}.xcfilelist\"\n#touch \"$FILE_LIST\"\n#if ! egrep -q \"$SCRIPT_OUTPUT_FILE_0\" \"$FILE_LIST\" ; then\n# echo >> \"$FILE_LIST\" \"$SCRIPT_OUTPUT_FILE_0\"\n#fi\n";
|
||||
};
|
||||
/* End PBXBuildRule section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
9987603229A454B500818586 /* minimuxer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = minimuxer.h; path = minimuxer/minimuxer.h; sourceTree = "<group>"; };
|
||||
ADDEDBA66A6E1 /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libresolv.tbd; path = usr/lib/libresolv.tbd; sourceTree = SDKROOT; };
|
||||
CA609C732349C7AAD9FA67C4 /* libminimuxer_static.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libminimuxer_static.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
ADDEDBA66A6E2 /* Required for static linking */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
ADDEDBA66A6E1 /* libresolv.tbd */,
|
||||
);
|
||||
name = "Required for static linking";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CA6012A875F922869D176AE5 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CA609C732349C7AAD9FA67C4 /* libminimuxer_static.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CA6012A875F998AF0B5890DB /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
ADDEDBA66A6E2 /* Required for static linking */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CA6012A875F9D65BC3C892A8 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9987603229A454B500818586 /* minimuxer.h */,
|
||||
CA6012A875F922869D176AE5 /* Products */,
|
||||
CA6012A875F998AF0B5890DB /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
CA609C732349A560B9642892 /* minimuxer-staticlib */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = CA600589A243A560B9642892 /* Build configuration list for PBXNativeTarget "minimuxer-staticlib" */;
|
||||
buildPhases = (
|
||||
9987603629A4611D00818586 /* ShellScript */,
|
||||
CA600F638141A560B9642892 /* Sources */,
|
||||
CA6012A875F9AF6EBB7F357C /* Universal Binary lipo */,
|
||||
);
|
||||
buildRules = (
|
||||
CA6012A875F9AC6C1400ACA8 /* PBXBuildRule */,
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "minimuxer-staticlib";
|
||||
productName = libminimuxer_static.a;
|
||||
productReference = CA609C732349C7AAD9FA67C4 /* libminimuxer_static.a */;
|
||||
productType = "com.apple.product-type.library.static";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
CA6012A875F9E04653AD465F /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1300;
|
||||
TargetAttributes = {
|
||||
CA609C732349A560B9642892 = {
|
||||
CreatedOnToolsVersion = 9.2;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = CA6012A875F980E02D6C7F57 /* Build configuration list for PBXProject "minimuxer" */;
|
||||
compatibilityVersion = "Xcode 11.4";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = CA6012A875F9D65BC3C892A8;
|
||||
productRefGroup = CA6012A875F922869D176AE5 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
CA609C732349A560B9642892 /* minimuxer-staticlib */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
9987603629A4611D00818586 /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
./minimuxer/minimuxer.h,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "bash ./fetch-prebuilt.sh minimuxer\n";
|
||||
};
|
||||
CA6012A875F9AF6EBB7F357C /* Universal Binary lipo */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/$(ARCHS)-$(EXECUTABLE_NAME).xcfilelist",
|
||||
);
|
||||
name = "Universal Binary lipo";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(TARGET_BUILD_DIR)/$(EXECUTABLE_PATH)",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "# generated with cargo-xcode 1.5.0\n\n#set -eux; cat \"$DERIVED_FILE_DIR/$ARCHS-$EXECUTABLE_NAME.xcfilelist\" | tr '\\n' '\\0' | xargs -0 lipo -create -output \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\n#if [ ${LD_DYLIB_INSTALL_NAME:+1} ]; then\n# install_name_tool -id \"$LD_DYLIB_INSTALL_NAME\" \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\n#fi\n";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
CA600F638141A560B9642892 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9987603329A454B500818586 /* minimuxer.h in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
CA6008D36272A560B9642892 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CARGO_XCODE_CARGO_DEP_FILE_NAME = libminimuxer.d;
|
||||
CARGO_XCODE_CARGO_FILE_NAME = libminimuxer.a;
|
||||
INSTALL_GROUP = "";
|
||||
INSTALL_MODE_FLAG = "";
|
||||
INSTALL_OWNER = "";
|
||||
LIB_FILE_NAME = "";
|
||||
"LIB_FILE_NAME[sdk=iphoneos*]" = libminimuxer;
|
||||
"LIB_FILE_NAME[sdk=iphonesimulator*]" = "libminimuxer-sim";
|
||||
PRODUCT_NAME = minimuxer_static;
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos appletvsimulator appletvos";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
CA602DE9FCEDA560B9642892 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CARGO_XCODE_CARGO_DEP_FILE_NAME = libminimuxer.d;
|
||||
CARGO_XCODE_CARGO_FILE_NAME = libminimuxer.a;
|
||||
INSTALL_GROUP = "";
|
||||
INSTALL_MODE_FLAG = "";
|
||||
INSTALL_OWNER = "";
|
||||
LIB_FILE_NAME = "";
|
||||
"LIB_FILE_NAME[sdk=iphoneos*]" = libminimuxer;
|
||||
"LIB_FILE_NAME[sdk=iphonesimulator*]" = "libminimuxer-sim";
|
||||
PRODUCT_NAME = minimuxer_static;
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos appletvsimulator appletvos";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
CA60A20F8EA6228BE02872F8 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CARGO_TARGET_DIR = "$(PROJECT_TEMP_DIR)/cargo_target";
|
||||
CARGO_XCODE_BUILD_MODE = debug;
|
||||
CARGO_XCODE_FEATURES = "";
|
||||
"CARGO_XCODE_TARGET_ARCH[arch=arm64*]" = aarch64;
|
||||
"CARGO_XCODE_TARGET_ARCH[arch=i386]" = i686;
|
||||
"CARGO_XCODE_TARGET_ARCH[arch=x86_64*]" = x86_64;
|
||||
"CARGO_XCODE_TARGET_OS[sdk=appletvos*]" = tvos;
|
||||
"CARGO_XCODE_TARGET_OS[sdk=appletvsimulator*]" = tvos;
|
||||
"CARGO_XCODE_TARGET_OS[sdk=iphoneos*]" = ios;
|
||||
"CARGO_XCODE_TARGET_OS[sdk=iphonesimulator*]" = "ios-sim";
|
||||
"CARGO_XCODE_TARGET_OS[sdk=iphonesimulator*][arch=x86_64*]" = ios;
|
||||
"CARGO_XCODE_TARGET_OS[sdk=macosx*]" = darwin;
|
||||
CURRENT_PROJECT_VERSION = 0.1;
|
||||
MARKETING_VERSION = 0.1.0;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRODUCT_NAME = minimuxer;
|
||||
SDKROOT = macosx;
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
CA60A20F8EA63CC16B37690B /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CARGO_TARGET_DIR = "$(PROJECT_TEMP_DIR)/cargo_target";
|
||||
CARGO_XCODE_BUILD_MODE = release;
|
||||
CARGO_XCODE_FEATURES = "";
|
||||
"CARGO_XCODE_TARGET_ARCH[arch=arm64*]" = aarch64;
|
||||
"CARGO_XCODE_TARGET_ARCH[arch=i386]" = i686;
|
||||
"CARGO_XCODE_TARGET_ARCH[arch=x86_64*]" = x86_64;
|
||||
"CARGO_XCODE_TARGET_OS[sdk=appletvos*]" = tvos;
|
||||
"CARGO_XCODE_TARGET_OS[sdk=appletvsimulator*]" = tvos;
|
||||
"CARGO_XCODE_TARGET_OS[sdk=iphoneos*]" = ios;
|
||||
"CARGO_XCODE_TARGET_OS[sdk=iphonesimulator*]" = "ios-sim";
|
||||
"CARGO_XCODE_TARGET_OS[sdk=iphonesimulator*][arch=x86_64*]" = ios;
|
||||
"CARGO_XCODE_TARGET_OS[sdk=macosx*]" = darwin;
|
||||
CURRENT_PROJECT_VERSION = 0.1;
|
||||
MARKETING_VERSION = 0.1.0;
|
||||
PRODUCT_NAME = minimuxer;
|
||||
SDKROOT = macosx;
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
CA600589A243A560B9642892 /* Build configuration list for PBXNativeTarget "minimuxer-staticlib" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
CA602DE9FCEDA560B9642892 /* Release */,
|
||||
CA6008D36272A560B9642892 /* Debug */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
CA6012A875F980E02D6C7F57 /* Build configuration list for PBXProject "minimuxer" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
CA60A20F8EA63CC16B37690B /* Release */,
|
||||
CA60A20F8EA6228BE02872F8 /* Debug */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = CA6012A875F9E04653AD465F /* Project object */;
|
||||
}
|
||||
1
Dependencies/minimuxer/.gitkeep
vendored
1
Dependencies/minimuxer/.gitkeep
vendored
@@ -1 +0,0 @@
|
||||
Use ../fetch-prebuilt.sh to fetch prebuilt Rust dependencies
|
||||
8
Makefile
8
Makefile
@@ -157,8 +157,8 @@ test:
|
||||
## -- Building --
|
||||
|
||||
build:
|
||||
@xcodebuild -project AltStore.xcodeproj \
|
||||
-scheme AltStore \
|
||||
@xcodebuild -project SideStore.xcodeproj \
|
||||
-scheme SideStore \
|
||||
-sdk iphoneos \
|
||||
archive -archivePath ./archive \
|
||||
CODE_SIGNING_REQUIRED=NO \
|
||||
@@ -169,8 +169,8 @@ build:
|
||||
DWARF_DSYM_FOLDER_PATH="."
|
||||
|
||||
fakesign:
|
||||
rm -rf archive.xcarchive/Products/Applications/SideStore.app/Frameworks/AltStoreCore.framework/Frameworks/
|
||||
ldid -SAltStore/Resources/tempEnt.plist archive.xcarchive/Products/Applications/SideStore.app/SideStore
|
||||
rm -rf archive.xcarchive/Products/Applications/SideStore.app/Frameworks/SideStoreCore.framework/Frameworks/
|
||||
ldid -SSideStoreApp/Sources/SideStore/Resources/tempEnt.plist archive.xcarchive/Products/Applications/SideStore.app/SideStore
|
||||
|
||||
ipa:
|
||||
mkdir Payload
|
||||
|
||||
2
Mintfile
Normal file
2
Mintfile
Normal file
@@ -0,0 +1,2 @@
|
||||
simorgh3196/SecretKeys@0.0.1
|
||||
unsignedapps/swift-create-xcframework@2.3.0
|
||||
95
Project.swift
Normal file
95
Project.swift
Normal file
@@ -0,0 +1,95 @@
|
||||
import ProjectDescription
|
||||
|
||||
let project = Project(
|
||||
name: "SideStore",
|
||||
organizationName: "SideStore.io",
|
||||
targets: [
|
||||
Target(
|
||||
name: "SideStore",
|
||||
platform: .iOS,
|
||||
product: .app,
|
||||
bundleId: "com.SideStore.SideStore",
|
||||
infoPlist: "Info.plist",
|
||||
sources: ["SideStoreApp/Sources/SideStore/**"],
|
||||
resources: ["SideStoreApp/Sources/SideStore/Resources/**"],
|
||||
headers: .headers(
|
||||
public: [],
|
||||
private: [],
|
||||
project: []
|
||||
),
|
||||
entitlements: "SideStoreApp/Sources/SideStore/Resources/SideStore.entitlements",
|
||||
dependencies: [
|
||||
.package(path: "SideStoreApp"),
|
||||
.target(name: "SideWidget"),
|
||||
.sdk(name: "libAppleAcrhive.tbd", status: .required)
|
||||
],
|
||||
settings: .settings(configurations: [
|
||||
.debug(name: "Debug", xcconfig: "SideStoreApp/Configurations/SideStore-Debug.xcconfig"),
|
||||
.release(name: "Release", xcconfig: "SideStoreApp/Configurations/SideStore-Release.xcconfig"),
|
||||
])
|
||||
),
|
||||
|
||||
Target(
|
||||
name: "SideWidget",
|
||||
platform: .iOS,
|
||||
product: .appExtension,
|
||||
bundleId: "com.SideStore.SideStore.SideWidget",
|
||||
infoPlist: .extendingDefault(with: [
|
||||
"ALTAppGroups": [
|
||||
"group.com.SideStore.SideStore",
|
||||
"group.$(APP_GROUP_IDENTIFIER)",
|
||||
],
|
||||
"CFBundleDisplayName": "$(PRODUCT_NAME)",
|
||||
"NSExtension": [
|
||||
"NSExtensionPointIdentifier": "com.apple.widgetkit-extension",
|
||||
"NSExtensionPrincipalClass": "$(PRODUCT_MODULE_NAME).NotificationService"
|
||||
]
|
||||
]),
|
||||
sources: ["SideStoreApp/Sources/SideWidget/**"],
|
||||
entitlements: "SideStoreApp/Sources/SideWidget/Resources/SideWidgetExtension.entitlements",
|
||||
dependencies: [
|
||||
.package(product: "Shared"),
|
||||
.package(product: "AltStoreCore")
|
||||
]
|
||||
),
|
||||
|
||||
// Target(
|
||||
// name: "SideStoreTests",
|
||||
// platform: .iOS,
|
||||
// product: .unitTests,
|
||||
// bundleId: "com.SideStore.SideStoreTests",
|
||||
// infoPlist: "Info.plist",
|
||||
// sources: ["SideStoreApp/Tests/SideStoreAppTests/**"],
|
||||
// dependencies: [
|
||||
// .target(name: "SideStore")
|
||||
// ]
|
||||
// ),
|
||||
// Target(
|
||||
// name: "SideStore",
|
||||
// platform: .tvOS,
|
||||
// product: .app,
|
||||
// bundleId: "com.SideStore.SideStore",
|
||||
// infoPlist: "Info.plist",
|
||||
// sources: ["SideStoreApp/Sources/SideStoreTV/**"],
|
||||
// dependencies: [
|
||||
// .target(name: "TopShelfExtension"),
|
||||
// ]
|
||||
// ),
|
||||
// Target(
|
||||
// name: "TopShelfExtension",
|
||||
// platform: .tvOS,
|
||||
// product: .tvTopShelfExtension,
|
||||
// bundleId: "com.SideStore.SideStore.TopShelfExtension",
|
||||
// infoPlist: .extendingDefault(with: [
|
||||
// "CFBundleDisplayName": "$(PRODUCT_NAME)",
|
||||
// "NSExtension": [
|
||||
// "NSExtensionPointIdentifier": "com.apple.tv-top-shelf",
|
||||
// "NSExtensionPrincipalClass": "$(PRODUCT_MODULE_NAME).ContentProvider",
|
||||
// ],
|
||||
// ]),
|
||||
// sources: "SideStoreApp/Sources/TopShelfExtension/**",
|
||||
// dependencies: [
|
||||
// ]
|
||||
// ),
|
||||
]
|
||||
)
|
||||
@@ -1,11 +0,0 @@
|
||||
//
|
||||
// ALTConstants.h
|
||||
// AltKit
|
||||
//
|
||||
// Created by Riley Testut on 5/30/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
extern uint16_t ALTDeviceListeningSocket;
|
||||
@@ -1,11 +0,0 @@
|
||||
//
|
||||
// ALTConstants.m
|
||||
// AltKit
|
||||
//
|
||||
// Created by Riley Testut on 1/10/20.
|
||||
// Copyright © 2020 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
uint16_t ALTDeviceListeningSocket = 28151;
|
||||
@@ -1,17 +0,0 @@
|
||||
//
|
||||
// CFNotificationName+AltStore.h
|
||||
// AltKit
|
||||
//
|
||||
// Created by Riley Testut on 1/10/20.
|
||||
// Copyright © 2020 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
extern CFNotificationName const ALTWiredServerConnectionAvailableRequest NS_SWIFT_NAME(wiredServerConnectionAvailableRequest);
|
||||
extern CFNotificationName const ALTWiredServerConnectionAvailableResponse NS_SWIFT_NAME(wiredServerConnectionAvailableResponse);
|
||||
extern CFNotificationName const ALTWiredServerConnectionStartRequest NS_SWIFT_NAME(wiredServerConnectionStartRequest);
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -1,13 +0,0 @@
|
||||
//
|
||||
// CFNotificationName+AltStore.m
|
||||
// AltKit
|
||||
//
|
||||
// Created by Riley Testut on 1/10/20.
|
||||
// Copyright © 2020 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
#import "CFNotificationName+AltStore.h"
|
||||
|
||||
CFNotificationName const ALTWiredServerConnectionAvailableRequest = CFSTR("io.altstore.Request.WiredServerConnectionAvailable");
|
||||
CFNotificationName const ALTWiredServerConnectionAvailableResponse = CFSTR("io.altstore.Response.WiredServerConnectionAvailable");
|
||||
CFNotificationName const ALTWiredServerConnectionStartRequest = CFSTR("io.altstore.Request.WiredServerConnectionStart");
|
||||
@@ -1,72 +0,0 @@
|
||||
//
|
||||
// NSError+ALTServerError.h
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 5/30/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
extern NSErrorDomain const AltServerErrorDomain;
|
||||
extern NSErrorDomain const AltServerInstallationErrorDomain;
|
||||
extern NSErrorDomain const AltServerConnectionErrorDomain;
|
||||
|
||||
extern NSErrorUserInfoKey const ALTUnderlyingErrorDomainErrorKey;
|
||||
extern NSErrorUserInfoKey const ALTUnderlyingErrorCodeErrorKey;
|
||||
extern NSErrorUserInfoKey const ALTProvisioningProfileBundleIDErrorKey;
|
||||
extern NSErrorUserInfoKey const ALTAppNameErrorKey;
|
||||
extern NSErrorUserInfoKey const ALTDeviceNameErrorKey;
|
||||
extern NSErrorUserInfoKey const ALTOperatingSystemNameErrorKey;
|
||||
extern NSErrorUserInfoKey const ALTOperatingSystemVersionErrorKey;
|
||||
|
||||
typedef NS_ERROR_ENUM(AltServerErrorDomain, ALTServerError)
|
||||
{
|
||||
ALTServerErrorUnderlyingError = -1,
|
||||
|
||||
ALTServerErrorUnknown = 0,
|
||||
ALTServerErrorConnectionFailed = 1,
|
||||
ALTServerErrorLostConnection = 2,
|
||||
|
||||
ALTServerErrorDeviceNotFound = 3,
|
||||
ALTServerErrorDeviceWriteFailed = 4,
|
||||
|
||||
ALTServerErrorInvalidRequest = 5,
|
||||
ALTServerErrorInvalidResponse = 6,
|
||||
|
||||
ALTServerErrorInvalidApp = 7,
|
||||
ALTServerErrorInstallationFailed = 8,
|
||||
ALTServerErrorMaximumFreeAppLimitReached = 9,
|
||||
ALTServerErrorUnsupportediOSVersion = 10,
|
||||
|
||||
ALTServerErrorUnknownRequest = 11,
|
||||
ALTServerErrorUnknownResponse = 12,
|
||||
|
||||
ALTServerErrorInvalidAnisetteData = 13,
|
||||
ALTServerErrorPluginNotFound = 14,
|
||||
|
||||
ALTServerErrorProfileNotFound = 15,
|
||||
|
||||
ALTServerErrorAppDeletionFailed = 16,
|
||||
|
||||
ALTServerErrorRequestedAppNotRunning = 100,
|
||||
ALTServerErrorIncompatibleDeveloperDisk = 101
|
||||
};
|
||||
|
||||
typedef NS_ERROR_ENUM(AltServerConnectionErrorDomain, ALTServerConnectionError)
|
||||
{
|
||||
ALTServerConnectionErrorUnknown,
|
||||
ALTServerConnectionErrorDeviceLocked,
|
||||
ALTServerConnectionErrorInvalidRequest,
|
||||
ALTServerConnectionErrorInvalidResponse,
|
||||
ALTServerConnectionErrorUsbmuxd,
|
||||
ALTServerConnectionErrorSSL,
|
||||
ALTServerConnectionErrorTimedOut,
|
||||
};
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface NSError (ALTServerError)
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -1,316 +0,0 @@
|
||||
//
|
||||
// NSError+ALTServerError.m
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 5/30/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
#import "NSError+ALTServerError.h"
|
||||
|
||||
NSErrorDomain const AltServerErrorDomain = @"com.rileytestut.AltServer";
|
||||
NSErrorDomain const AltServerInstallationErrorDomain = @"com.rileytestut.AltServer.Installation";
|
||||
NSErrorDomain const AltServerConnectionErrorDomain = @"com.rileytestut.AltServer.Connection";
|
||||
|
||||
NSErrorUserInfoKey const ALTUnderlyingErrorDomainErrorKey = @"underlyingErrorDomain";
|
||||
NSErrorUserInfoKey const ALTUnderlyingErrorCodeErrorKey = @"underlyingErrorCode";
|
||||
NSErrorUserInfoKey const ALTProvisioningProfileBundleIDErrorKey = @"bundleIdentifier";
|
||||
NSErrorUserInfoKey const ALTAppNameErrorKey = @"appName";
|
||||
NSErrorUserInfoKey const ALTDeviceNameErrorKey = @"deviceName";
|
||||
NSErrorUserInfoKey const ALTOperatingSystemNameErrorKey = @"ALTOperatingSystemName";
|
||||
NSErrorUserInfoKey const ALTOperatingSystemVersionErrorKey = @"ALTOperatingSystemVersion";
|
||||
|
||||
@implementation NSError (ALTServerError)
|
||||
|
||||
+ (void)load
|
||||
{
|
||||
[NSError setUserInfoValueProviderForDomain:AltServerErrorDomain provider:^id _Nullable(NSError * _Nonnull error, NSErrorUserInfoKey _Nonnull userInfoKey) {
|
||||
if ([userInfoKey isEqualToString:NSLocalizedFailureReasonErrorKey])
|
||||
{
|
||||
return [error altserver_localizedFailureReason];
|
||||
}
|
||||
else if ([userInfoKey isEqualToString:NSLocalizedRecoverySuggestionErrorKey])
|
||||
{
|
||||
return [error altserver_localizedRecoverySuggestion];
|
||||
}
|
||||
else if ([userInfoKey isEqualToString:NSDebugDescriptionErrorKey])
|
||||
{
|
||||
return [error altserver_localizedDebugDescription];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}];
|
||||
|
||||
[NSError setUserInfoValueProviderForDomain:AltServerConnectionErrorDomain provider:^id _Nullable(NSError * _Nonnull error, NSErrorUserInfoKey _Nonnull userInfoKey) {
|
||||
if ([userInfoKey isEqualToString:NSLocalizedDescriptionKey])
|
||||
{
|
||||
return [error altserver_connection_localizedDescription];
|
||||
}
|
||||
else if ([userInfoKey isEqualToString:NSLocalizedRecoverySuggestionErrorKey])
|
||||
{
|
||||
return [error altserver_connection_localizedRecoverySuggestion];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}];
|
||||
}
|
||||
|
||||
- (nullable NSString *)altserver_localizedFailureReason
|
||||
{
|
||||
switch ((ALTServerError)self.code)
|
||||
{
|
||||
case ALTServerErrorUnderlyingError:
|
||||
{
|
||||
NSError *underlyingError = self.userInfo[NSUnderlyingErrorKey];
|
||||
if (underlyingError.localizedFailureReason != nil)
|
||||
{
|
||||
return underlyingError.localizedFailureReason;
|
||||
}
|
||||
|
||||
NSString *underlyingErrorCode = self.userInfo[ALTUnderlyingErrorCodeErrorKey];
|
||||
if (underlyingErrorCode != nil)
|
||||
{
|
||||
return [NSString stringWithFormat:NSLocalizedString(@"Error code: %@", @""), underlyingErrorCode];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
case ALTServerErrorUnknown:
|
||||
return NSLocalizedString(@"An unknown error occured.", @"");
|
||||
|
||||
case ALTServerErrorConnectionFailed:
|
||||
#if TARGET_OS_OSX
|
||||
return NSLocalizedString(@"There was an error connecting to the device.", @"");
|
||||
#else
|
||||
return NSLocalizedString(@"Could not connect to SideStore.", @"");
|
||||
#endif
|
||||
|
||||
case ALTServerErrorLostConnection:
|
||||
return NSLocalizedString(@"Lost connection to SideStore.", @"");
|
||||
|
||||
case ALTServerErrorDeviceNotFound:
|
||||
return NSLocalizedString(@"SideStore could not find this device.", @"");
|
||||
|
||||
case ALTServerErrorDeviceWriteFailed:
|
||||
return NSLocalizedString(@"Failed to write app data to device.", @"");
|
||||
|
||||
case ALTServerErrorInvalidRequest:
|
||||
return NSLocalizedString(@"SideStore received an invalid request.", @"");
|
||||
|
||||
case ALTServerErrorInvalidResponse:
|
||||
return NSLocalizedString(@"SideStore sent an invalid response.", @"");
|
||||
|
||||
case ALTServerErrorInvalidApp:
|
||||
return NSLocalizedString(@"The app is invalid.", @"");
|
||||
|
||||
case ALTServerErrorInstallationFailed:
|
||||
return NSLocalizedString(@"An error occured while installing the app.", @"");
|
||||
|
||||
case ALTServerErrorMaximumFreeAppLimitReached:
|
||||
return NSLocalizedString(@"Cannot activate more than 3 apps with a non-developer Apple ID.", @"");
|
||||
|
||||
case ALTServerErrorUnsupportediOSVersion:
|
||||
return NSLocalizedString(@"Your device must be running iOS 12.2 or later to install SideStore.", @"");
|
||||
|
||||
case ALTServerErrorUnknownRequest:
|
||||
return NSLocalizedString(@"SideStore does not support this request.", @"");
|
||||
|
||||
case ALTServerErrorUnknownResponse:
|
||||
return NSLocalizedString(@"Received an unknown response from SideStore.", @"");
|
||||
|
||||
case ALTServerErrorInvalidAnisetteData:
|
||||
return NSLocalizedString(@"The provided anisette data is invalid.", @"");
|
||||
|
||||
case ALTServerErrorPluginNotFound:
|
||||
return NSLocalizedString(@"AltServer could not connect to Mail plug-in.", @"");
|
||||
|
||||
case ALTServerErrorProfileNotFound:
|
||||
return [self profileErrorLocalizedDescriptionWithBaseDescription:NSLocalizedString(@"Could not find profile", "")];
|
||||
|
||||
case ALTServerErrorAppDeletionFailed:
|
||||
return NSLocalizedString(@"An error occured while removing the app.", @"");
|
||||
|
||||
case ALTServerErrorRequestedAppNotRunning:
|
||||
{
|
||||
NSString *appName = self.userInfo[ALTAppNameErrorKey] ?: NSLocalizedString(@"The requested app", @"");
|
||||
NSString *deviceName = self.userInfo[ALTDeviceNameErrorKey] ?: NSLocalizedString(@"the device", @"");
|
||||
return [NSString stringWithFormat:NSLocalizedString(@"%@ is not currently running on %@.", ""), appName, deviceName];
|
||||
}
|
||||
|
||||
case ALTServerErrorIncompatibleDeveloperDisk:
|
||||
{
|
||||
NSString *osVersion = [self altserver_osVersion] ?: NSLocalizedString(@"this device's OS version", @"");
|
||||
NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(@"The disk is incompatible with %@.", @""), osVersion];
|
||||
return failureReason;
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (nullable NSString *)altserver_localizedRecoverySuggestion
|
||||
{
|
||||
switch ((ALTServerError)self.code)
|
||||
{
|
||||
case ALTServerErrorConnectionFailed:
|
||||
case ALTServerErrorDeviceNotFound:
|
||||
return NSLocalizedString(@"Make sure you have trusted this device with your computer and Wi-Fi sync is enabled.", @"");
|
||||
|
||||
case ALTServerErrorPluginNotFound:
|
||||
return NSLocalizedString(@"Mail has been automatically opened, try again in a moment. Otherwise, make sure plug-in is enabled in Mail's preferences.", @"");
|
||||
|
||||
case ALTServerErrorMaximumFreeAppLimitReached:
|
||||
#if TARGET_OS_OSX
|
||||
return NSLocalizedString(@"Please deactivate a sideloaded app with SideStore in order to install another app.\n\nIf you're running iOS 13.5 or later, make sure 'Offload Unused Apps' is disabled in Settings > iTunes & App Stores, then install or delete all offloaded apps to prevent them from erroneously counting towards this limit.", @"");
|
||||
#else
|
||||
return NSLocalizedString(@"Please deactivate a sideloaded app in order to install another one.\n\nIf you're running iOS 13.5 or later, make sure “Offload Unused Apps” is disabled in Settings > iTunes & App Stores, then install or delete all offloaded apps.", @"");
|
||||
#endif
|
||||
|
||||
case ALTServerErrorRequestedAppNotRunning:
|
||||
{
|
||||
NSString *deviceName = self.userInfo[ALTDeviceNameErrorKey] ?: NSLocalizedString(@"your device", @"");
|
||||
return [NSString stringWithFormat:NSLocalizedString(@"Make sure the app is running in the foreground on %@ then try again.", @""), deviceName];
|
||||
}
|
||||
|
||||
default:
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (nullable NSString *)altserver_localizedDebugDescription
|
||||
{
|
||||
switch ((ALTServerError)self.code)
|
||||
{
|
||||
case ALTServerErrorIncompatibleDeveloperDisk:
|
||||
{
|
||||
NSString *path = self.userInfo[NSFilePathErrorKey];
|
||||
if (path == nil)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSString *osVersion = [self altserver_osVersion] ?: NSLocalizedString(@"this device's OS version", @"");
|
||||
NSString *debugDescription = [NSString stringWithFormat:NSLocalizedString(@"The Developer disk located at\n\n%@\n\nis incompatible with %@.", @""), path, osVersion];
|
||||
return debugDescription;
|
||||
}
|
||||
|
||||
default:
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)profileErrorLocalizedDescriptionWithBaseDescription:(NSString *)baseDescription
|
||||
{
|
||||
NSString *localizedDescription = nil;
|
||||
|
||||
NSString *bundleID = self.userInfo[ALTProvisioningProfileBundleIDErrorKey];
|
||||
if (bundleID)
|
||||
{
|
||||
localizedDescription = [NSString stringWithFormat:@"%@ “%@”", baseDescription, bundleID];
|
||||
}
|
||||
else
|
||||
{
|
||||
localizedDescription = [NSString stringWithFormat:@"%@.", baseDescription];
|
||||
}
|
||||
|
||||
return localizedDescription;
|
||||
}
|
||||
|
||||
- (nullable NSString *)altserver_osVersion
|
||||
{
|
||||
NSString *osName = self.userInfo[ALTOperatingSystemNameErrorKey];
|
||||
NSString *versionString = self.userInfo[ALTOperatingSystemVersionErrorKey];
|
||||
if (osName == nil || versionString == nil)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSString *osVersion = [NSString stringWithFormat:@"%@ %@", osName, versionString];
|
||||
return osVersion;
|
||||
}
|
||||
|
||||
#pragma mark - AltServerConnectionErrorDomain -
|
||||
|
||||
- (nullable NSString *)altserver_connection_localizedDescription
|
||||
{
|
||||
switch ((ALTServerConnectionError)self.code)
|
||||
{
|
||||
case ALTServerConnectionErrorUnknown:
|
||||
{
|
||||
NSString *underlyingErrorDomain = self.userInfo[ALTUnderlyingErrorDomainErrorKey];
|
||||
NSString *underlyingErrorCode = self.userInfo[ALTUnderlyingErrorCodeErrorKey];
|
||||
|
||||
if (underlyingErrorDomain != nil && underlyingErrorCode != nil)
|
||||
{
|
||||
return [NSString stringWithFormat:NSLocalizedString(@"%@ error %@.", @""), underlyingErrorDomain, underlyingErrorCode];
|
||||
}
|
||||
else if (underlyingErrorCode != nil)
|
||||
{
|
||||
return [NSString stringWithFormat:NSLocalizedString(@"Connection error code: %@", @""), underlyingErrorCode];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
case ALTServerConnectionErrorDeviceLocked:
|
||||
{
|
||||
NSString *deviceName = self.userInfo[ALTDeviceNameErrorKey] ?: NSLocalizedString(@"The device", @"");
|
||||
return [NSString stringWithFormat:NSLocalizedString(@"%@ is currently locked.", @""), deviceName];
|
||||
}
|
||||
|
||||
case ALTServerConnectionErrorInvalidRequest:
|
||||
{
|
||||
NSString *deviceName = self.userInfo[ALTDeviceNameErrorKey] ?: NSLocalizedString(@"The device", @"");
|
||||
return [NSString stringWithFormat:NSLocalizedString(@"%@ received an invalid request from SideStore.", @""), deviceName];
|
||||
}
|
||||
|
||||
case ALTServerConnectionErrorInvalidResponse:
|
||||
{
|
||||
NSString *deviceName = self.userInfo[ALTDeviceNameErrorKey] ?: NSLocalizedString(@"the device", @"");
|
||||
return [NSString stringWithFormat:NSLocalizedString(@"SideStore received an invalid response from %@.", @""), deviceName];
|
||||
}
|
||||
|
||||
case ALTServerConnectionErrorUsbmuxd:
|
||||
{
|
||||
return NSLocalizedString(@"There was an issue communicating with the usbmuxd daemon.", @"");
|
||||
}
|
||||
|
||||
case ALTServerConnectionErrorSSL:
|
||||
{
|
||||
NSString *deviceName = self.userInfo[ALTDeviceNameErrorKey] ?: NSLocalizedString(@"the device", @"");
|
||||
return [NSString stringWithFormat:NSLocalizedString(@"SideStore could not establish a secure connection to %@.", @""), deviceName];
|
||||
}
|
||||
|
||||
case ALTServerConnectionErrorTimedOut:
|
||||
{
|
||||
NSString *deviceName = self.userInfo[ALTDeviceNameErrorKey] ?: NSLocalizedString(@"the device", @"");
|
||||
return [NSString stringWithFormat:NSLocalizedString(@"SideStore's connection to %@ timed out.", @""), deviceName];
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (nullable NSString *)altserver_connection_localizedRecoverySuggestion
|
||||
{
|
||||
switch ((ALTServerConnectionError)self.code)
|
||||
{
|
||||
case ALTServerConnectionErrorDeviceLocked:
|
||||
{
|
||||
return NSLocalizedString(@"Please unlock the device with your passcode and try again.", @"");
|
||||
}
|
||||
|
||||
case ALTServerConnectionErrorUnknown:
|
||||
case ALTServerConnectionErrorInvalidRequest:
|
||||
case ALTServerConnectionErrorInvalidResponse:
|
||||
case ALTServerConnectionErrorUsbmuxd:
|
||||
case ALTServerConnectionErrorSSL:
|
||||
case ALTServerConnectionErrorTimedOut:
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,23 +0,0 @@
|
||||
//
|
||||
// ALTConnection.h
|
||||
// AltKit
|
||||
//
|
||||
// Created by Riley Testut on 6/1/20.
|
||||
// Copyright © 2020 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(Connection)
|
||||
@protocol ALTConnection <NSObject>
|
||||
|
||||
- (void)sendData:(NSData *)data completionHandler:(void (^)(BOOL, NSError * _Nullable))completionHandler NS_REFINED_FOR_SWIFT;
|
||||
- (void)receiveDataWithExpectedSize:(NSInteger)expectedSize completionHandler:(void (^)(NSData * _Nullable, NSError * _Nullable))completionHandler NS_SWIFT_NAME(__receiveData(expectedSize:completionHandler:));
|
||||
|
||||
- (void)disconnect;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -1,113 +0,0 @@
|
||||
//
|
||||
// Connection.swift
|
||||
// AltKit
|
||||
//
|
||||
// Created by Riley Testut on 6/1/20.
|
||||
// Copyright © 2020 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Network
|
||||
|
||||
public extension Connection
|
||||
{
|
||||
func send(_ data: Data, completionHandler: @escaping (Result<Void, ALTServerError>) -> Void)
|
||||
{
|
||||
self.__send(data) { (success, error) in
|
||||
let result = Result(success, error).mapError { (error) -> ALTServerError in
|
||||
guard let nwError = error as? NWError else { return ALTServerError(error) }
|
||||
return ALTServerError(.lostConnection, underlyingError: nwError)
|
||||
}
|
||||
|
||||
completionHandler(result)
|
||||
}
|
||||
}
|
||||
|
||||
func receiveData(expectedSize: Int, completionHandler: @escaping (Result<Data, ALTServerError>) -> Void)
|
||||
{
|
||||
self.__receiveData(expectedSize: expectedSize) { (data, error) in
|
||||
let result = Result(data, error).mapError { (error) -> ALTServerError in
|
||||
guard let nwError = error as? NWError else { return ALTServerError(error) }
|
||||
return ALTServerError(.lostConnection, underlyingError: nwError)
|
||||
}
|
||||
|
||||
completionHandler(result)
|
||||
}
|
||||
}
|
||||
|
||||
func send<T: Encodable>(_ response: T, shouldDisconnect: Bool = false, completionHandler: @escaping (Result<Void, ALTServerError>) -> Void)
|
||||
{
|
||||
func finish(_ result: Result<Void, ALTServerError>)
|
||||
{
|
||||
completionHandler(result)
|
||||
|
||||
if shouldDisconnect
|
||||
{
|
||||
// Add short delay to prevent us from dropping connection too quickly.
|
||||
DispatchQueue.global().asyncAfter(deadline: .now() + 1.0) {
|
||||
self.disconnect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
let data = try JSONEncoder().encode(response)
|
||||
let responseSize = withUnsafeBytes(of: Int32(data.count)) { Data($0) }
|
||||
|
||||
self.send(responseSize) { (result) in
|
||||
switch result
|
||||
{
|
||||
case .failure(let error): finish(.failure(error))
|
||||
case .success:
|
||||
self.send(data) { (result) in
|
||||
switch result
|
||||
{
|
||||
case .failure(let error): finish(.failure(error))
|
||||
case .success: finish(.success(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
finish(.failure(.init(.invalidResponse, underlyingError: error)))
|
||||
}
|
||||
}
|
||||
|
||||
func receiveRequest(completionHandler: @escaping (Result<ServerRequest, ALTServerError>) -> Void)
|
||||
{
|
||||
let size = MemoryLayout<Int32>.size
|
||||
|
||||
print("Receiving request size from connection:", self)
|
||||
self.receiveData(expectedSize: size) { (result) in
|
||||
do
|
||||
{
|
||||
let data = try result.get()
|
||||
|
||||
let expectedSize = Int(data.withUnsafeBytes { $0.load(as: Int32.self) })
|
||||
print("Receiving request from connection: \(self)... (\(expectedSize) bytes)")
|
||||
|
||||
self.receiveData(expectedSize: expectedSize) { (result) in
|
||||
do
|
||||
{
|
||||
let data = try result.get()
|
||||
let request = try JSONDecoder().decode(ServerRequest.self, from: data)
|
||||
|
||||
print("Received request:", request)
|
||||
completionHandler(.success(request))
|
||||
}
|
||||
catch
|
||||
{
|
||||
completionHandler(.failure(ALTServerError(error)))
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
completionHandler(.failure(ALTServerError(error)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
//
|
||||
// NetworkConnection.swift
|
||||
// AltKit
|
||||
//
|
||||
// Created by Riley Testut on 6/1/20.
|
||||
// Copyright © 2020 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Network
|
||||
|
||||
public class NetworkConnection: NSObject, Connection
|
||||
{
|
||||
public let nwConnection: NWConnection
|
||||
|
||||
public init(_ nwConnection: NWConnection)
|
||||
{
|
||||
self.nwConnection = nwConnection
|
||||
}
|
||||
|
||||
public func __send(_ data: Data, completionHandler: @escaping (Bool, Error?) -> Void)
|
||||
{
|
||||
self.nwConnection.send(content: data, completion: .contentProcessed { (error) in
|
||||
completionHandler(error == nil, error)
|
||||
})
|
||||
}
|
||||
|
||||
public func __receiveData(expectedSize: Int, completionHandler: @escaping (Data?, Error?) -> Void)
|
||||
{
|
||||
self.nwConnection.receive(minimumIncompleteLength: expectedSize, maximumLength: expectedSize) { (data, context, isComplete, error) in
|
||||
guard data != nil || error != nil else {
|
||||
return completionHandler(nil, ALTServerError(.lostConnection))
|
||||
}
|
||||
|
||||
completionHandler(data, error)
|
||||
}
|
||||
}
|
||||
|
||||
public func disconnect()
|
||||
{
|
||||
switch self.nwConnection.state
|
||||
{
|
||||
case .cancelled, .failed: break
|
||||
default: self.nwConnection.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension NetworkConnection
|
||||
{
|
||||
override public var description: String {
|
||||
return "\(self.nwConnection.endpoint) (Network)"
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
//
|
||||
// ALTServerError+Conveniences.swift
|
||||
// AltKit
|
||||
//
|
||||
// Created by Riley Testut on 6/4/20.
|
||||
// Copyright © 2020 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import AltSign
|
||||
|
||||
public extension ALTServerError
|
||||
{
|
||||
init<E: Error>(_ error: E)
|
||||
{
|
||||
switch error
|
||||
{
|
||||
case let error as ALTServerError: self = error
|
||||
case let error as ALTServerConnectionError: self = ALTServerError(.connectionFailed, underlyingError: error)
|
||||
case let error as ALTAppleAPIError where error.code == .invalidAnisetteData: self = ALTServerError(.invalidAnisetteData, underlyingError: error)
|
||||
case is DecodingError: self = ALTServerError(.invalidRequest, underlyingError: error)
|
||||
case is EncodingError: self = ALTServerError(.invalidResponse, underlyingError: error)
|
||||
case let error as NSError:
|
||||
var userInfo = error.userInfo
|
||||
if !userInfo.keys.contains(NSUnderlyingErrorKey)
|
||||
{
|
||||
// Assign underlying error (if there isn't already one).
|
||||
userInfo[NSUnderlyingErrorKey] = error
|
||||
}
|
||||
|
||||
self = ALTServerError(.underlyingError, userInfo: userInfo)
|
||||
}
|
||||
}
|
||||
|
||||
init<E: Error>(_ code: ALTServerError.Code, underlyingError: E)
|
||||
{
|
||||
self = ALTServerError(code, userInfo: [NSUnderlyingErrorKey: underlyingError])
|
||||
}
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
//
|
||||
// NSError+AltStore.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 3/11/20.
|
||||
// Copyright © 2020 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension NSError
|
||||
{
|
||||
@objc(alt_localizedFailure)
|
||||
var localizedFailure: String? {
|
||||
let localizedFailure = (self.userInfo[NSLocalizedFailureErrorKey] as? String) ?? (NSError.userInfoValueProvider(forDomain: self.domain)?(self, NSLocalizedFailureErrorKey) as? String)
|
||||
return localizedFailure
|
||||
}
|
||||
|
||||
@objc(alt_localizedDebugDescription)
|
||||
var localizedDebugDescription: String? {
|
||||
let debugDescription = (self.userInfo[NSDebugDescriptionErrorKey] as? String) ?? (NSError.userInfoValueProvider(forDomain: self.domain)?(self, NSDebugDescriptionErrorKey) as? String)
|
||||
return debugDescription
|
||||
}
|
||||
|
||||
@objc(alt_errorWithLocalizedFailure:)
|
||||
func withLocalizedFailure(_ failure: String) -> NSError
|
||||
{
|
||||
var userInfo = self.userInfo
|
||||
userInfo[NSLocalizedFailureErrorKey] = failure
|
||||
|
||||
if let failureReason = self.localizedFailureReason
|
||||
{
|
||||
userInfo[NSLocalizedFailureReasonErrorKey] = failureReason
|
||||
}
|
||||
else if self.localizedFailure == nil && self.localizedFailureReason == nil && self.localizedDescription.contains(self.localizedErrorCode)
|
||||
{
|
||||
// Default localizedDescription, so replace with just the localized error code portion.
|
||||
userInfo[NSLocalizedFailureReasonErrorKey] = "(\(self.localizedErrorCode).)"
|
||||
}
|
||||
else
|
||||
{
|
||||
userInfo[NSLocalizedFailureReasonErrorKey] = self.localizedDescription
|
||||
}
|
||||
|
||||
if let localizedDescription = NSError.userInfoValueProvider(forDomain: self.domain)?(self, NSLocalizedDescriptionKey) as? String
|
||||
{
|
||||
userInfo[NSLocalizedDescriptionKey] = localizedDescription
|
||||
}
|
||||
|
||||
// Don't accidentally remove localizedDescription from dictionary
|
||||
// userInfo[NSLocalizedDescriptionKey] = NSError.userInfoValueProvider(forDomain: self.domain)?(self, NSLocalizedDescriptionKey) as? String
|
||||
|
||||
if let recoverySuggestion = self.localizedRecoverySuggestion
|
||||
{
|
||||
userInfo[NSLocalizedRecoverySuggestionErrorKey] = recoverySuggestion
|
||||
}
|
||||
|
||||
let error = NSError(domain: self.domain, code: self.code, userInfo: userInfo)
|
||||
return error
|
||||
}
|
||||
|
||||
func sanitizedForCoreData() -> NSError
|
||||
{
|
||||
var userInfo = self.userInfo
|
||||
userInfo[NSLocalizedFailureErrorKey] = self.localizedFailure
|
||||
userInfo[NSLocalizedDescriptionKey] = self.localizedDescription
|
||||
userInfo[NSLocalizedFailureReasonErrorKey] = self.localizedFailureReason
|
||||
userInfo[NSLocalizedRecoverySuggestionErrorKey] = self.localizedRecoverySuggestion
|
||||
|
||||
// Remove userInfo values that don't conform to NSSecureEncoding.
|
||||
userInfo = userInfo.filter { (key, value) in
|
||||
return (value as AnyObject) is NSSecureCoding
|
||||
}
|
||||
|
||||
// Sanitize underlying errors.
|
||||
if let underlyingError = userInfo[NSUnderlyingErrorKey] as? Error
|
||||
{
|
||||
let sanitizedError = (underlyingError as NSError).sanitizedForCoreData()
|
||||
userInfo[NSUnderlyingErrorKey] = sanitizedError
|
||||
}
|
||||
|
||||
if #available(iOS 14.5, macOS 11.3, *), let underlyingErrors = userInfo[NSMultipleUnderlyingErrorsKey] as? [Error]
|
||||
{
|
||||
let sanitizedErrors = underlyingErrors.map { ($0 as NSError).sanitizedForCoreData() }
|
||||
userInfo[NSMultipleUnderlyingErrorsKey] = sanitizedErrors
|
||||
}
|
||||
|
||||
let error = NSError(domain: self.domain, code: self.code, userInfo: userInfo)
|
||||
return error
|
||||
}
|
||||
}
|
||||
|
||||
extension Error
|
||||
{
|
||||
var underlyingError: Error? {
|
||||
let underlyingError = (self as NSError).userInfo[NSUnderlyingErrorKey] as? Error
|
||||
return underlyingError
|
||||
}
|
||||
|
||||
var localizedErrorCode: String {
|
||||
let localizedErrorCode = String(format: NSLocalizedString("%@ error %@", comment: ""), (self as NSError).domain, (self as NSError).code as NSNumber)
|
||||
return localizedErrorCode
|
||||
}
|
||||
}
|
||||
|
||||
protocol ALTLocalizedError: LocalizedError, CustomNSError
|
||||
{
|
||||
var failure: String? { get }
|
||||
|
||||
var underlyingError: Error? { get }
|
||||
}
|
||||
|
||||
extension ALTLocalizedError
|
||||
{
|
||||
var errorUserInfo: [String : Any] {
|
||||
let userInfo = ([
|
||||
NSLocalizedDescriptionKey: self.errorDescription,
|
||||
NSLocalizedFailureReasonErrorKey: self.failureReason,
|
||||
NSLocalizedFailureErrorKey: self.failure,
|
||||
NSUnderlyingErrorKey: self.underlyingError
|
||||
] as [String: Any?]).compactMapValues { $0 }
|
||||
return userInfo
|
||||
}
|
||||
|
||||
var underlyingError: Error? {
|
||||
// Error's default implementation calls errorUserInfo,
|
||||
// but ALTLocalizedError.errorUserInfo calls underlyingError.
|
||||
// Return nil to prevent infinite recursion.
|
||||
return nil
|
||||
}
|
||||
|
||||
var errorDescription: String? {
|
||||
guard let errorFailure = self.failure else { return (self.underlyingError as NSError?)?.localizedDescription }
|
||||
guard let failureReason = self.failureReason else { return errorFailure }
|
||||
|
||||
let errorDescription = errorFailure + " " + failureReason
|
||||
return errorDescription
|
||||
}
|
||||
|
||||
var failureReason: String? { (self.underlyingError as NSError?)?.localizedDescription }
|
||||
var recoverySuggestion: String? { (self.underlyingError as NSError?)?.localizedRecoverySuggestion }
|
||||
var helpAnchor: String? { (self.underlyingError as NSError?)?.helpAnchor }
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
//
|
||||
// CodableServerError.swift
|
||||
// AltKit
|
||||
//
|
||||
// Created by Riley Testut on 3/5/20.
|
||||
// Copyright © 2020 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
// Can only automatically conform ALTServerError.Code to Codable, not ALTServerError itself
|
||||
extension ALTServerError.Code: Codable {}
|
||||
|
||||
extension CodableServerError
|
||||
{
|
||||
enum UserInfoValue: Codable
|
||||
{
|
||||
case string(String)
|
||||
case error(NSError)
|
||||
|
||||
public init(from decoder: Decoder) throws
|
||||
{
|
||||
let container = try decoder.singleValueContainer()
|
||||
|
||||
if
|
||||
let data = try? container.decode(Data.self),
|
||||
let error = try? NSKeyedUnarchiver.unarchivedObject(ofClass: NSError.self, from: data)
|
||||
{
|
||||
self = .error(error)
|
||||
}
|
||||
else if let string = try? container.decode(String.self)
|
||||
{
|
||||
self = .string(string)
|
||||
}
|
||||
else
|
||||
{
|
||||
throw DecodingError.dataCorruptedError(in: container, debugDescription: "UserInfoValue value cannot be decoded")
|
||||
}
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws
|
||||
{
|
||||
var container = encoder.singleValueContainer()
|
||||
|
||||
switch self
|
||||
{
|
||||
case .string(let string): try container.encode(string)
|
||||
case .error(let error):
|
||||
guard let data = try? NSKeyedArchiver.archivedData(withRootObject: error, requiringSecureCoding: true) else {
|
||||
let context = EncodingError.Context(codingPath: container.codingPath, debugDescription: "UserInfoValue value \(self) cannot be encoded")
|
||||
throw EncodingError.invalidValue(self, context)
|
||||
}
|
||||
|
||||
try container.encode(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct CodableServerError: Codable
|
||||
{
|
||||
var error: ALTServerError {
|
||||
return ALTServerError(self.errorCode, userInfo: self.userInfo ?? [:])
|
||||
}
|
||||
|
||||
private var errorCode: ALTServerError.Code
|
||||
private var userInfo: [String: Any]?
|
||||
|
||||
private enum CodingKeys: String, CodingKey
|
||||
{
|
||||
case errorCode
|
||||
case userInfo
|
||||
}
|
||||
|
||||
init(error: ALTServerError)
|
||||
{
|
||||
self.errorCode = error.code
|
||||
|
||||
var userInfo = error.userInfo
|
||||
if let localizedRecoverySuggestion = (error as NSError).localizedRecoverySuggestion
|
||||
{
|
||||
userInfo[NSLocalizedRecoverySuggestionErrorKey] = localizedRecoverySuggestion
|
||||
}
|
||||
|
||||
if !userInfo.isEmpty
|
||||
{
|
||||
self.userInfo = userInfo
|
||||
}
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws
|
||||
{
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
let errorCode = try container.decode(Int.self, forKey: .errorCode)
|
||||
self.errorCode = ALTServerError.Code(rawValue: errorCode) ?? .unknown
|
||||
|
||||
let rawUserInfo = try container.decodeIfPresent([String: UserInfoValue].self, forKey: .userInfo)
|
||||
|
||||
let userInfo = rawUserInfo?.mapValues { (value) -> Any in
|
||||
switch value
|
||||
{
|
||||
case .string(let string): return string
|
||||
case .error(let error): return error
|
||||
}
|
||||
}
|
||||
self.userInfo = userInfo
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws
|
||||
{
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(self.error.code.rawValue, forKey: .errorCode)
|
||||
|
||||
let rawUserInfo = self.userInfo?.compactMapValues { (value) -> UserInfoValue? in
|
||||
switch value
|
||||
{
|
||||
case let string as String: return .string(string)
|
||||
case let error as NSError: return .error(error)
|
||||
default: return nil
|
||||
}
|
||||
}
|
||||
try container.encodeIfPresent(rawUserInfo, forKey: .userInfo)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,472 +0,0 @@
|
||||
//
|
||||
// ServerProtocol.swift
|
||||
// AltServer
|
||||
//
|
||||
// Created by Riley Testut on 5/24/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import AltSign
|
||||
|
||||
public let ALTServerServiceType = "_altserver._tcp"
|
||||
|
||||
protocol ServerMessageProtocol: Codable
|
||||
{
|
||||
var version: Int { get }
|
||||
var identifier: String { get }
|
||||
}
|
||||
|
||||
public enum ServerRequest: Decodable
|
||||
{
|
||||
case anisetteData(AnisetteDataRequest)
|
||||
case prepareApp(PrepareAppRequest)
|
||||
case beginInstallation(BeginInstallationRequest)
|
||||
case installProvisioningProfiles(InstallProvisioningProfilesRequest)
|
||||
case removeProvisioningProfiles(RemoveProvisioningProfilesRequest)
|
||||
case removeApp(RemoveAppRequest)
|
||||
case enableUnsignedCodeExecution(EnableUnsignedCodeExecutionRequest)
|
||||
case unknown(identifier: String, version: Int)
|
||||
|
||||
var identifier: String {
|
||||
switch self
|
||||
{
|
||||
case .anisetteData(let request): return request.identifier
|
||||
case .prepareApp(let request): return request.identifier
|
||||
case .beginInstallation(let request): return request.identifier
|
||||
case .installProvisioningProfiles(let request): return request.identifier
|
||||
case .removeProvisioningProfiles(let request): return request.identifier
|
||||
case .removeApp(let request): return request.identifier
|
||||
case .enableUnsignedCodeExecution(let request): return request.identifier
|
||||
case .unknown(let identifier, _): return identifier
|
||||
}
|
||||
}
|
||||
|
||||
var version: Int {
|
||||
switch self
|
||||
{
|
||||
case .anisetteData(let request): return request.version
|
||||
case .prepareApp(let request): return request.version
|
||||
case .beginInstallation(let request): return request.version
|
||||
case .installProvisioningProfiles(let request): return request.version
|
||||
case .removeProvisioningProfiles(let request): return request.version
|
||||
case .removeApp(let request): return request.version
|
||||
case .enableUnsignedCodeExecution(let request): return request.version
|
||||
case .unknown(_, let version): return version
|
||||
}
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey
|
||||
{
|
||||
case identifier
|
||||
case version
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws
|
||||
{
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
let version = try container.decode(Int.self, forKey: .version)
|
||||
|
||||
let identifier = try container.decode(String.self, forKey: .identifier)
|
||||
switch identifier
|
||||
{
|
||||
case "AnisetteDataRequest":
|
||||
let request = try AnisetteDataRequest(from: decoder)
|
||||
self = .anisetteData(request)
|
||||
|
||||
case "PrepareAppRequest":
|
||||
let request = try PrepareAppRequest(from: decoder)
|
||||
self = .prepareApp(request)
|
||||
|
||||
case "BeginInstallationRequest":
|
||||
let request = try BeginInstallationRequest(from: decoder)
|
||||
self = .beginInstallation(request)
|
||||
|
||||
case "InstallProvisioningProfilesRequest":
|
||||
let request = try InstallProvisioningProfilesRequest(from: decoder)
|
||||
self = .installProvisioningProfiles(request)
|
||||
|
||||
case "RemoveProvisioningProfilesRequest":
|
||||
let request = try RemoveProvisioningProfilesRequest(from: decoder)
|
||||
self = .removeProvisioningProfiles(request)
|
||||
|
||||
case "RemoveAppRequest":
|
||||
let request = try RemoveAppRequest(from: decoder)
|
||||
self = .removeApp(request)
|
||||
|
||||
case "EnableUnsignedCodeExecutionRequest":
|
||||
let request = try EnableUnsignedCodeExecutionRequest(from: decoder)
|
||||
self = .enableUnsignedCodeExecution(request)
|
||||
|
||||
default:
|
||||
self = .unknown(identifier: identifier, version: version)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum ServerResponse: Decodable
|
||||
{
|
||||
case anisetteData(AnisetteDataResponse)
|
||||
case installationProgress(InstallationProgressResponse)
|
||||
case installProvisioningProfiles(InstallProvisioningProfilesResponse)
|
||||
case removeProvisioningProfiles(RemoveProvisioningProfilesResponse)
|
||||
case removeApp(RemoveAppResponse)
|
||||
case enableUnsignedCodeExecution(EnableUnsignedCodeExecutionResponse)
|
||||
case error(ErrorResponse)
|
||||
case unknown(identifier: String, version: Int)
|
||||
|
||||
var identifier: String {
|
||||
switch self
|
||||
{
|
||||
case .anisetteData(let response): return response.identifier
|
||||
case .installationProgress(let response): return response.identifier
|
||||
case .installProvisioningProfiles(let response): return response.identifier
|
||||
case .removeProvisioningProfiles(let response): return response.identifier
|
||||
case .removeApp(let response): return response.identifier
|
||||
case .enableUnsignedCodeExecution(let response): return response.identifier
|
||||
case .error(let response): return response.identifier
|
||||
case .unknown(let identifier, _): return identifier
|
||||
}
|
||||
}
|
||||
|
||||
var version: Int {
|
||||
switch self
|
||||
{
|
||||
case .anisetteData(let response): return response.version
|
||||
case .installationProgress(let response): return response.version
|
||||
case .installProvisioningProfiles(let response): return response.version
|
||||
case .removeProvisioningProfiles(let response): return response.version
|
||||
case .removeApp(let response): return response.version
|
||||
case .enableUnsignedCodeExecution(let response): return response.version
|
||||
case .error(let response): return response.version
|
||||
case .unknown(_, let version): return version
|
||||
}
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey
|
||||
{
|
||||
case identifier
|
||||
case version
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws
|
||||
{
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
let version = try container.decode(Int.self, forKey: .version)
|
||||
|
||||
let identifier = try container.decode(String.self, forKey: .identifier)
|
||||
switch identifier
|
||||
{
|
||||
case "AnisetteDataResponse":
|
||||
let response = try AnisetteDataResponse(from: decoder)
|
||||
self = .anisetteData(response)
|
||||
|
||||
case "InstallationProgressResponse":
|
||||
let response = try InstallationProgressResponse(from: decoder)
|
||||
self = .installationProgress(response)
|
||||
|
||||
case "InstallProvisioningProfilesResponse":
|
||||
let response = try InstallProvisioningProfilesResponse(from: decoder)
|
||||
self = .installProvisioningProfiles(response)
|
||||
|
||||
case "RemoveProvisioningProfilesResponse":
|
||||
let response = try RemoveProvisioningProfilesResponse(from: decoder)
|
||||
self = .removeProvisioningProfiles(response)
|
||||
|
||||
case "RemoveAppResponse":
|
||||
let response = try RemoveAppResponse(from: decoder)
|
||||
self = .removeApp(response)
|
||||
|
||||
case "EnableUnsignedCodeExecutionResponse":
|
||||
let response = try EnableUnsignedCodeExecutionResponse(from: decoder)
|
||||
self = .enableUnsignedCodeExecution(response)
|
||||
|
||||
case "ErrorResponse":
|
||||
let response = try ErrorResponse(from: decoder)
|
||||
self = .error(response)
|
||||
|
||||
default:
|
||||
self = .unknown(identifier: identifier, version: version)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// _Don't_ provide generic SuccessResponse, as that would prevent us
|
||||
// from easily changing response format for a request in the future.
|
||||
public struct ErrorResponse: ServerMessageProtocol
|
||||
{
|
||||
public var version = 2
|
||||
public var identifier = "ErrorResponse"
|
||||
|
||||
public var error: ALTServerError {
|
||||
return self.serverError?.error ?? ALTServerError(self.errorCode)
|
||||
}
|
||||
private var serverError: CodableServerError?
|
||||
|
||||
// Legacy (v1)
|
||||
private var errorCode: ALTServerError.Code
|
||||
|
||||
public init(error: ALTServerError)
|
||||
{
|
||||
self.serverError = CodableServerError(error: error)
|
||||
self.errorCode = error.code
|
||||
}
|
||||
}
|
||||
|
||||
public struct AnisetteDataRequest: ServerMessageProtocol
|
||||
{
|
||||
public var version = 1
|
||||
public var identifier = "AnisetteDataRequest"
|
||||
|
||||
public init()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public struct AnisetteDataResponse: ServerMessageProtocol
|
||||
{
|
||||
public var version = 1
|
||||
public var identifier = "AnisetteDataResponse"
|
||||
|
||||
public var anisetteData: ALTAnisetteData
|
||||
|
||||
private enum CodingKeys: String, CodingKey
|
||||
{
|
||||
case identifier
|
||||
case version
|
||||
case anisetteData
|
||||
}
|
||||
|
||||
public init(anisetteData: ALTAnisetteData)
|
||||
{
|
||||
self.anisetteData = anisetteData
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws
|
||||
{
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.version = try container.decode(Int.self, forKey: .version)
|
||||
self.identifier = try container.decode(String.self, forKey: .identifier)
|
||||
|
||||
let json = try container.decode([String: String].self, forKey: .anisetteData)
|
||||
|
||||
if let anisetteData = ALTAnisetteData(json: json)
|
||||
{
|
||||
self.anisetteData = anisetteData
|
||||
}
|
||||
else
|
||||
{
|
||||
throw DecodingError.dataCorruptedError(forKey: CodingKeys.anisetteData, in: container, debugDescription: "Couuld not parse anisette data from JSON")
|
||||
}
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws
|
||||
{
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(self.version, forKey: .version)
|
||||
try container.encode(self.identifier, forKey: .identifier)
|
||||
|
||||
let json = self.anisetteData.json()
|
||||
try container.encode(json, forKey: .anisetteData)
|
||||
}
|
||||
}
|
||||
|
||||
public struct PrepareAppRequest: ServerMessageProtocol
|
||||
{
|
||||
public var version = 1
|
||||
public var identifier = "PrepareAppRequest"
|
||||
|
||||
public var udid: String
|
||||
public var contentSize: Int
|
||||
|
||||
public var fileURL: URL?
|
||||
|
||||
public init(udid: String, contentSize: Int, fileURL: URL? = nil)
|
||||
{
|
||||
self.udid = udid
|
||||
self.contentSize = contentSize
|
||||
self.fileURL = fileURL
|
||||
}
|
||||
}
|
||||
|
||||
public struct BeginInstallationRequest: ServerMessageProtocol
|
||||
{
|
||||
public var version = 3
|
||||
public var identifier = "BeginInstallationRequest"
|
||||
|
||||
// If activeProfiles is non-nil, then AltServer should remove all profiles except active ones.
|
||||
public var activeProfiles: Set<String>?
|
||||
|
||||
public var bundleIdentifier: String?
|
||||
|
||||
public init(activeProfiles: Set<String>?, bundleIdentifier: String?)
|
||||
{
|
||||
self.activeProfiles = activeProfiles
|
||||
self.bundleIdentifier = bundleIdentifier
|
||||
print("BeginInstallationRequest `activeProfiles`: \(String(describing: activeProfiles))")
|
||||
print("BeginInstallationRequest `bundleIdentifier`: \(String(describing: bundleIdentifier))")
|
||||
}
|
||||
}
|
||||
|
||||
public struct InstallationProgressResponse: ServerMessageProtocol
|
||||
{
|
||||
public var version = 1
|
||||
public var identifier = "InstallationProgressResponse"
|
||||
|
||||
public var progress: Double
|
||||
|
||||
public init(progress: Double)
|
||||
{
|
||||
self.progress = progress
|
||||
}
|
||||
}
|
||||
|
||||
public struct InstallProvisioningProfilesRequest: ServerMessageProtocol
|
||||
{
|
||||
public var version = 1
|
||||
public var identifier = "InstallProvisioningProfilesRequest"
|
||||
|
||||
public var udid: String
|
||||
public var provisioningProfiles: Set<ALTProvisioningProfile>
|
||||
|
||||
// If activeProfiles is non-nil, then AltServer should remove all profiles except active ones.
|
||||
public var activeProfiles: Set<String>?
|
||||
|
||||
private enum CodingKeys: String, CodingKey
|
||||
{
|
||||
case identifier
|
||||
case version
|
||||
case udid
|
||||
case provisioningProfiles
|
||||
case activeProfiles
|
||||
}
|
||||
|
||||
public init(udid: String, provisioningProfiles: Set<ALTProvisioningProfile>, activeProfiles: Set<String>?)
|
||||
{
|
||||
self.udid = udid
|
||||
self.provisioningProfiles = provisioningProfiles
|
||||
self.activeProfiles = activeProfiles
|
||||
print("InstallProvisioningProfilesRequest `self.udid`: \(self.udid)")
|
||||
print("InstallProvisioningProfilesRequest `self.provisioningProfiles`: \(self.provisioningProfiles)")
|
||||
print("InstallProvisioningProfilesRequest `self.activeProfiles`: \(String(describing: self.activeProfiles))")
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws
|
||||
{
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.version = try container.decode(Int.self, forKey: .version)
|
||||
self.identifier = try container.decode(String.self, forKey: .identifier)
|
||||
self.udid = try container.decode(String.self, forKey: .udid)
|
||||
|
||||
let rawProvisioningProfiles = try container.decode([Data].self, forKey: .provisioningProfiles)
|
||||
let provisioningProfiles = try rawProvisioningProfiles.map { (data) -> ALTProvisioningProfile in
|
||||
guard let profile = ALTProvisioningProfile(data: data) else {
|
||||
throw DecodingError.dataCorruptedError(forKey: CodingKeys.provisioningProfiles, in: container, debugDescription: "Could not parse provisioning profile from data.")
|
||||
}
|
||||
return profile
|
||||
}
|
||||
|
||||
self.provisioningProfiles = Set(provisioningProfiles)
|
||||
self.activeProfiles = try container.decodeIfPresent(Set<String>.self, forKey: .activeProfiles)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws
|
||||
{
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(self.version, forKey: .version)
|
||||
try container.encode(self.identifier, forKey: .identifier)
|
||||
try container.encode(self.udid, forKey: .udid)
|
||||
|
||||
try container.encode(self.provisioningProfiles.map { $0.data }, forKey: .provisioningProfiles)
|
||||
try container.encodeIfPresent(self.activeProfiles, forKey: .activeProfiles)
|
||||
}
|
||||
}
|
||||
|
||||
public struct InstallProvisioningProfilesResponse: ServerMessageProtocol
|
||||
{
|
||||
public var version = 1
|
||||
public var identifier = "InstallProvisioningProfilesResponse"
|
||||
|
||||
public init()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public struct RemoveProvisioningProfilesRequest: ServerMessageProtocol
|
||||
{
|
||||
public var version = 1
|
||||
public var identifier = "RemoveProvisioningProfilesRequest"
|
||||
|
||||
public var udid: String
|
||||
public var bundleIdentifiers: Set<String>
|
||||
|
||||
public init(udid: String, bundleIdentifiers: Set<String>)
|
||||
{
|
||||
self.udid = udid
|
||||
self.bundleIdentifiers = bundleIdentifiers
|
||||
}
|
||||
}
|
||||
|
||||
public struct RemoveProvisioningProfilesResponse: ServerMessageProtocol
|
||||
{
|
||||
public var version = 1
|
||||
public var identifier = "RemoveProvisioningProfilesResponse"
|
||||
|
||||
public init()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public struct RemoveAppRequest: ServerMessageProtocol
|
||||
{
|
||||
public var version = 1
|
||||
public var identifier = "RemoveAppRequest"
|
||||
|
||||
public var udid: String
|
||||
public var bundleIdentifier: String
|
||||
|
||||
public init(udid: String, bundleIdentifier: String)
|
||||
{
|
||||
self.udid = udid
|
||||
self.bundleIdentifier = bundleIdentifier
|
||||
}
|
||||
}
|
||||
|
||||
public struct RemoveAppResponse: ServerMessageProtocol
|
||||
{
|
||||
public var version = 1
|
||||
public var identifier = "RemoveAppResponse"
|
||||
|
||||
public init()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public struct EnableUnsignedCodeExecutionRequest: ServerMessageProtocol
|
||||
{
|
||||
public var version = 1
|
||||
public var identifier = "EnableUnsignedCodeExecutionRequest"
|
||||
|
||||
public var udid: String
|
||||
public var processID: Int?
|
||||
public var processName: String?
|
||||
|
||||
public init(udid: String, processID: Int? = nil, processName: String? = nil)
|
||||
{
|
||||
self.udid = udid
|
||||
self.processID = processID
|
||||
self.processName = processName
|
||||
}
|
||||
}
|
||||
|
||||
public struct EnableUnsignedCodeExecutionResponse: ServerMessageProtocol
|
||||
{
|
||||
public var version = 1
|
||||
public var identifier = "EnableUnsignedCodeExecutionResponse"
|
||||
|
||||
public init()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
//
|
||||
// AltXPCProtocol.h
|
||||
// AltXPC
|
||||
//
|
||||
// Created by Riley Testut on 12/2/20.
|
||||
// Copyright © 2020 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class ALTAnisetteData;
|
||||
|
||||
@protocol AltXPCProtocol
|
||||
|
||||
- (void)ping:(void (^_Nonnull)(void))completionHandler;
|
||||
- (void)requestAnisetteDataWithCompletionHandler:(void (^_Nonnull)(ALTAnisetteData *_Nullable anisetteData, NSError *_Nullable error))completionHandler;
|
||||
|
||||
@end
|
||||
779
SideStore.xcodeproj/project.pbxproj
Normal file
779
SideStore.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,779 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 55;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
B34AFBFB29B03279000F318E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B34AFBE829B0324C000F318E /* Main.storyboard */; };
|
||||
B34AFBFC29B0327E000F318E /* SettingsHeaderFooterView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B34AFBE329B0324C000F318E /* SettingsHeaderFooterView.xib */; };
|
||||
B34AFBFD29B0327E000F318E /* BrowseCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B34AFBDD29B0324C000F318E /* BrowseCollectionViewCell.xib */; };
|
||||
B34AFBFE29B0327E000F318E /* AppBannerView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B34AFBDE29B0324C000F318E /* AppBannerView.xib */; };
|
||||
B34AFBFF29B0327E000F318E /* AboutPatreonHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B34AFBE029B0324C000F318E /* AboutPatreonHeaderView.xib */; };
|
||||
B34AFC0029B0327E000F318E /* NewsCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B34AFBE229B0324C000F318E /* NewsCollectionViewCell.xib */; };
|
||||
B34AFC0129B0327E000F318E /* UpdateCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B34AFBE129B0324C000F318E /* UpdateCollectionViewCell.xib */; };
|
||||
B34AFC0229B0327E000F318E /* InstalledAppsCollectionHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B34AFBDF29B0324C000F318E /* InstalledAppsCollectionHeaderView.xib */; };
|
||||
B34AFC0329B03283000F318E /* Settings.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B34AFBDB29B0324C000F318E /* Settings.storyboard */; };
|
||||
B34AFC0429B03288000F318E /* Silence.m4a in Resources */ = {isa = PBXBuildFile; fileRef = B34AFBEB29B0324C000F318E /* Silence.m4a */; };
|
||||
B34AFC0529B0328D000F318E /* apps.json in Resources */ = {isa = PBXBuildFile; fileRef = B34AFBED29B0324C000F318E /* apps.json */; };
|
||||
B34AFC0629B0328D000F318E /* apps-alpha.json in Resources */ = {isa = PBXBuildFile; fileRef = B34AFBEE29B0324C000F318E /* apps-alpha.json */; };
|
||||
B34AFC0729B03291000F318E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B34AFBF229B0324C000F318E /* Assets.xcassets */; };
|
||||
B34AFC1429B032DF000F318E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B34AFC0D29B032DF000F318E /* Assets.xcassets */; };
|
||||
B34BA92829B5ED510055A710 /* SideWidgetExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = BF989167250AABF3002ACF50 /* SideWidgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
B371D45129BC0BF900E157A6 /* SideStoreAppKit in Frameworks */ = {isa = PBXBuildFile; productRef = B371D45029BC0BF900E157A6 /* SideStoreAppKit */; };
|
||||
B371D45329BC0C0B00E157A6 /* SideWidgetKit in Frameworks */ = {isa = PBXBuildFile; productRef = B371D45229BC0C0B00E157A6 /* SideWidgetKit */; };
|
||||
B3C40F5329B06A0000C93D50 /* PatchApp.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B34AFBD929B0324C000F318E /* PatchApp.storyboard */; };
|
||||
B3C40F5429B06A2B00C93D50 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B34AFBE629B0324C000F318E /* LaunchScreen.storyboard */; };
|
||||
B3C40F5529B06A3200C93D50 /* Authentication.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B34AFBDA29B0324C000F318E /* Authentication.storyboard */; };
|
||||
B3C40F5729B06A6400C93D50 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = B34AFBE529B0324C000F318E /* Settings.bundle */; };
|
||||
D533E8B72727841800A9B5DD /* libAppleArchive.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D533E8B62727841800A9B5DD /* libAppleArchive.tbd */; settings = {ATTRIBUTES = (Weak, ); }; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
B34BA92929B5ED510055A710 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = BFD247622284B9A500981D42 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = BF989166250AABF3002ACF50;
|
||||
remoteInfo = SideWidgetExtension;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
B34BA92B29B5ED510055A710 /* Embed Foundation Extensions */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 13;
|
||||
files = (
|
||||
B34BA92829B5ED510055A710 /* SideWidgetExtension.appex in Embed Foundation Extensions */,
|
||||
);
|
||||
name = "Embed Foundation Extensions";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
BF088D2B2501A087008082D9 /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
191E5FB5290A5E1F001A3B7C /* libminimuxer.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libminimuxer.a; path = "Dependencies/minimuxer/target/aarch64-apple-ios/debug/libminimuxer.a"; sourceTree = "<group>"; };
|
||||
B343F86C295F759E002B1159 /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libresolv.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.1.sdk/usr/lib/libresolv.tbd; sourceTree = DEVELOPER_DIR; };
|
||||
B347773629B0314A00201FCA /* SideStoreApp */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = SideStoreApp; sourceTree = "<group>"; };
|
||||
B34AFBD929B0324C000F318E /* PatchApp.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = PatchApp.storyboard; sourceTree = "<group>"; };
|
||||
B34AFBDA29B0324C000F318E /* Authentication.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Authentication.storyboard; sourceTree = "<group>"; };
|
||||
B34AFBDB29B0324C000F318E /* Settings.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Settings.storyboard; sourceTree = "<group>"; };
|
||||
B34AFBDD29B0324C000F318E /* BrowseCollectionViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = BrowseCollectionViewCell.xib; sourceTree = "<group>"; };
|
||||
B34AFBDE29B0324C000F318E /* AppBannerView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AppBannerView.xib; sourceTree = "<group>"; };
|
||||
B34AFBDF29B0324C000F318E /* InstalledAppsCollectionHeaderView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = InstalledAppsCollectionHeaderView.xib; sourceTree = "<group>"; };
|
||||
B34AFBE029B0324C000F318E /* AboutPatreonHeaderView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AboutPatreonHeaderView.xib; sourceTree = "<group>"; };
|
||||
B34AFBE129B0324C000F318E /* UpdateCollectionViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = UpdateCollectionViewCell.xib; sourceTree = "<group>"; };
|
||||
B34AFBE229B0324C000F318E /* NewsCollectionViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NewsCollectionViewCell.xib; sourceTree = "<group>"; };
|
||||
B34AFBE329B0324C000F318E /* SettingsHeaderFooterView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SettingsHeaderFooterView.xib; sourceTree = "<group>"; };
|
||||
B34AFBE429B0324C000F318E /* SideStore.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SideStore.entitlements; sourceTree = "<group>"; };
|
||||
B34AFBE529B0324C000F318E /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; };
|
||||
B34AFBE729B0324C000F318E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
B34AFBE929B0324C000F318E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
B34AFBEB29B0324C000F318E /* Silence.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = Silence.m4a; sourceTree = "<group>"; };
|
||||
B34AFBED29B0324C000F318E /* apps.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = apps.json; sourceTree = "<group>"; };
|
||||
B34AFBEE29B0324C000F318E /* apps-alpha.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "apps-alpha.json"; sourceTree = "<group>"; };
|
||||
B34AFBEF29B0324C000F318E /* Info.info */ = {isa = PBXFileReference; lastKnownFileType = text; path = Info.info; sourceTree = "<group>"; };
|
||||
B34AFBF029B0324C000F318E /* tempEnt.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = tempEnt.plist; sourceTree = "<group>"; };
|
||||
B34AFBF229B0324C000F318E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
B34AFBF329B0324C000F318E /* AltBackup.ipa */ = {isa = PBXFileReference; lastKnownFileType = file; path = AltBackup.ipa; sourceTree = "<group>"; };
|
||||
B34AFBF429B0324C000F318E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
B34AFBF529B0324C000F318E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
B34AFBF629B0324C000F318E /* LaunchViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchViewController.swift; sourceTree = "<group>"; };
|
||||
B34AFBF729B0324C000F318E /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
||||
B34AFC0D29B032DF000F318E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
B34AFC0E29B032DF000F318E /* SideWidgetExtension.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = SideWidgetExtension.entitlements; sourceTree = "<group>"; };
|
||||
B34AFC0F29B032DF000F318E /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
B34AFC1929B04EBB000F318E /* Dangerfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dangerfile.swift; sourceTree = "<group>"; };
|
||||
B34AFC1A29B04EBB000F318E /* Project.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Project.swift; sourceTree = "<group>"; };
|
||||
B34BA8E529B0FE8D0055A710 /* AppDelegate+BackgroundFetch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+BackgroundFetch.swift"; sourceTree = "<group>"; };
|
||||
B39575F4284F29E20080B4FF /* Roxas.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Roxas.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
B3C39606284F4C8400DA9E2F /* CodeSigning.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = CodeSigning.xcconfig; sourceTree = "<group>"; };
|
||||
B3C39607284F4C8400DA9E2F /* Build.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Build.xcconfig; sourceTree = "<group>"; };
|
||||
B3C39608284F4C8400DA9E2F /* CodeSigning.xcconfig.sample */ = {isa = PBXFileReference; lastKnownFileType = text; path = CodeSigning.xcconfig.sample; sourceTree = "<group>"; };
|
||||
B3CD301329AF876000374AF8 /* SideBackup.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = SideBackup.xcconfig; sourceTree = "<group>"; };
|
||||
B3CD301429AF876000374AF8 /* SideWidgetExtension.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = SideWidgetExtension.xcconfig; sourceTree = "<group>"; };
|
||||
B3CD301529AF876000374AF8 /* Shared.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
||||
B3CD301629AF876000374AF8 /* Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
|
||||
B3CD301729AF876000374AF8 /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
|
||||
B3CD301829AF876000374AF8 /* SideStore.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = SideStore.xcconfig; sourceTree = "<group>"; };
|
||||
B3CD301929AF876000374AF8 /* Archive.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Archive.xcconfig; sourceTree = "<group>"; };
|
||||
B3CD301A29AF876000374AF8 /* SideStoreCore.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = SideStoreCore.xcconfig; sourceTree = "<group>"; };
|
||||
BF4588872298DD3F00BD7491 /* libxml2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libxml2.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/lib/libxml2.tbd; sourceTree = DEVELOPER_DIR; };
|
||||
BF580497246A3D19008AE704 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
||||
BF989167250AABF3002ACF50 /* SideWidgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = SideWidgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
BFD2476A2284B9A500981D42 /* SideStore.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SideStore.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
BFD247862284BB3B00981D42 /* Roxas.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Roxas.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D533E8B62727841800A9B5DD /* libAppleArchive.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libAppleArchive.tbd; path = usr/lib/libAppleArchive.tbd; sourceTree = SDKROOT; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
BF989164250AABF3002ACF50 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B371D45329BC0C0B00E157A6 /* SideWidgetKit in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
BFD247672284B9A500981D42 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B371D45129BC0BF900E157A6 /* SideStoreAppKit in Frameworks */,
|
||||
D533E8B72727841800A9B5DD /* libAppleArchive.tbd in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
B34AFBD629B0324C000F318E /* SideStore */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B34AFBD729B0324C000F318E /* Resources */,
|
||||
B34AFBF529B0324C000F318E /* AppDelegate.swift */,
|
||||
B34BA8E529B0FE8D0055A710 /* AppDelegate+BackgroundFetch.swift */,
|
||||
B34AFBF629B0324C000F318E /* LaunchViewController.swift */,
|
||||
B34AFBF729B0324C000F318E /* SceneDelegate.swift */,
|
||||
);
|
||||
name = SideStore;
|
||||
path = SideStoreApp/Sources/SideStore;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B34AFBD729B0324C000F318E /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B34AFBD829B0324C000F318E /* Storyboards */,
|
||||
B34AFBDC29B0324C000F318E /* XIB */,
|
||||
B34AFBE429B0324C000F318E /* SideStore.entitlements */,
|
||||
B34AFBE529B0324C000F318E /* Settings.bundle */,
|
||||
B34AFBE629B0324C000F318E /* LaunchScreen.storyboard */,
|
||||
B34AFBE829B0324C000F318E /* Main.storyboard */,
|
||||
B34AFBEA29B0324C000F318E /* Sounds */,
|
||||
B34AFBEC29B0324C000F318E /* JSON */,
|
||||
B34AFBEF29B0324C000F318E /* Info.info */,
|
||||
B34AFBF029B0324C000F318E /* tempEnt.plist */,
|
||||
B34AFBF129B0324C000F318E /* Assets */,
|
||||
B34AFBF329B0324C000F318E /* AltBackup.ipa */,
|
||||
B34AFBF429B0324C000F318E /* Info.plist */,
|
||||
);
|
||||
path = Resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B34AFBD829B0324C000F318E /* Storyboards */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B34AFBD929B0324C000F318E /* PatchApp.storyboard */,
|
||||
B34AFBDA29B0324C000F318E /* Authentication.storyboard */,
|
||||
B34AFBDB29B0324C000F318E /* Settings.storyboard */,
|
||||
);
|
||||
path = Storyboards;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B34AFBDC29B0324C000F318E /* XIB */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B34AFBDD29B0324C000F318E /* BrowseCollectionViewCell.xib */,
|
||||
B34AFBDE29B0324C000F318E /* AppBannerView.xib */,
|
||||
B34AFBDF29B0324C000F318E /* InstalledAppsCollectionHeaderView.xib */,
|
||||
B34AFBE029B0324C000F318E /* AboutPatreonHeaderView.xib */,
|
||||
B34AFBE129B0324C000F318E /* UpdateCollectionViewCell.xib */,
|
||||
B34AFBE229B0324C000F318E /* NewsCollectionViewCell.xib */,
|
||||
B34AFBE329B0324C000F318E /* SettingsHeaderFooterView.xib */,
|
||||
);
|
||||
path = XIB;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B34AFBEA29B0324C000F318E /* Sounds */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B34AFBEB29B0324C000F318E /* Silence.m4a */,
|
||||
);
|
||||
path = Sounds;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B34AFBEC29B0324C000F318E /* JSON */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B34AFBED29B0324C000F318E /* apps.json */,
|
||||
B34AFBEE29B0324C000F318E /* apps-alpha.json */,
|
||||
);
|
||||
path = JSON;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B34AFBF129B0324C000F318E /* Assets */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B34AFBF229B0324C000F318E /* Assets.xcassets */,
|
||||
);
|
||||
path = Assets;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B34AFC0829B032DF000F318E /* SideWidget */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B34AFC0C29B032DF000F318E /* Resources */,
|
||||
);
|
||||
name = SideWidget;
|
||||
path = SideStoreApp/Sources/SideWidget;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B34AFC0C29B032DF000F318E /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B34AFC0D29B032DF000F318E /* Assets.xcassets */,
|
||||
B34AFC0E29B032DF000F318E /* SideWidgetExtension.entitlements */,
|
||||
B34AFC0F29B032DF000F318E /* Info.plist */,
|
||||
);
|
||||
path = Resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B3CD301229AF876000374AF8 /* Configurations */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B3CD301329AF876000374AF8 /* SideBackup.xcconfig */,
|
||||
B3CD301429AF876000374AF8 /* SideWidgetExtension.xcconfig */,
|
||||
B3CD301529AF876000374AF8 /* Shared.xcconfig */,
|
||||
B3CD301629AF876000374AF8 /* Debug.xcconfig */,
|
||||
B3CD301729AF876000374AF8 /* Release.xcconfig */,
|
||||
B3CD301829AF876000374AF8 /* SideStore.xcconfig */,
|
||||
B3CD301929AF876000374AF8 /* Archive.xcconfig */,
|
||||
B3CD301A29AF876000374AF8 /* SideStoreCore.xcconfig */,
|
||||
);
|
||||
name = Configurations;
|
||||
path = SideStoreApp/Configurations;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B3E8749729AF639C00745374 /* Packages */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B347773629B0314A00201FCA /* SideStoreApp */,
|
||||
);
|
||||
name = Packages;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
BFD247612284B9A500981D42 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B3E8749729AF639C00745374 /* Packages */,
|
||||
B3C39607284F4C8400DA9E2F /* Build.xcconfig */,
|
||||
B3C39606284F4C8400DA9E2F /* CodeSigning.xcconfig */,
|
||||
B3C39608284F4C8400DA9E2F /* CodeSigning.xcconfig.sample */,
|
||||
B34AFC1929B04EBB000F318E /* Dangerfile.swift */,
|
||||
B34AFC1A29B04EBB000F318E /* Project.swift */,
|
||||
B34AFBD629B0324C000F318E /* SideStore */,
|
||||
B34AFC0829B032DF000F318E /* SideWidget */,
|
||||
B3CD301229AF876000374AF8 /* Configurations */,
|
||||
BFD247852284BB3300981D42 /* Frameworks */,
|
||||
BFD2476B2284B9A500981D42 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
BFD2476B2284B9A500981D42 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BFD2476A2284B9A500981D42 /* SideStore.app */,
|
||||
BF989167250AABF3002ACF50 /* SideWidgetExtension.appex */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
BFD247852284BB3300981D42 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B343F86C295F759E002B1159 /* libresolv.tbd */,
|
||||
191E5FB5290A5E1F001A3B7C /* libminimuxer.a */,
|
||||
B39575F4284F29E20080B4FF /* Roxas.framework */,
|
||||
D533E8B62727841800A9B5DD /* libAppleArchive.tbd */,
|
||||
BF580497246A3D19008AE704 /* UIKit.framework */,
|
||||
BF4588872298DD3F00BD7491 /* libxml2.tbd */,
|
||||
BFD247862284BB3B00981D42 /* Roxas.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
BF989166250AABF3002ACF50 /* SideWidgetExtension */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = BF989178250AABF4002ACF50 /* Build configuration list for PBXNativeTarget "SideWidgetExtension" */;
|
||||
buildPhases = (
|
||||
BF989163250AABF3002ACF50 /* Sources */,
|
||||
BF989164250AABF3002ACF50 /* Frameworks */,
|
||||
BF989165250AABF3002ACF50 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = SideWidgetExtension;
|
||||
packageProductDependencies = (
|
||||
B371D45229BC0C0B00E157A6 /* SideWidgetKit */,
|
||||
);
|
||||
productName = AltWidgetExtension;
|
||||
productReference = BF989167250AABF3002ACF50 /* SideWidgetExtension.appex */;
|
||||
productType = "com.apple.product-type.app-extension";
|
||||
};
|
||||
BFD247692284B9A500981D42 /* SideStore */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = BFD2477E2284B9A700981D42 /* Build configuration list for PBXNativeTarget "SideStore" */;
|
||||
buildPhases = (
|
||||
BFD247662284B9A500981D42 /* Sources */,
|
||||
BFD247672284B9A500981D42 /* Frameworks */,
|
||||
BFD247682284B9A500981D42 /* Resources */,
|
||||
BF088D2B2501A087008082D9 /* Embed Frameworks */,
|
||||
B34BA92B29B5ED510055A710 /* Embed Foundation Extensions */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
B34BA92A29B5ED510055A710 /* PBXTargetDependency */,
|
||||
);
|
||||
name = SideStore;
|
||||
packageProductDependencies = (
|
||||
B371D45029BC0BF900E157A6 /* SideStoreAppKit */,
|
||||
);
|
||||
productName = AltStore;
|
||||
productReference = BFD2476A2284B9A500981D42 /* SideStore.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
BFD247622284B9A500981D42 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
LastSwiftUpdateCheck = 1400;
|
||||
LastUpgradeCheck = 1420;
|
||||
ORGANIZATIONNAME = SideStore;
|
||||
TargetAttributes = {
|
||||
BF989166250AABF3002ACF50 = {
|
||||
CreatedOnToolsVersion = 12.0;
|
||||
LastSwiftMigration = 1200;
|
||||
};
|
||||
BFD247692284B9A500981D42 = {
|
||||
CreatedOnToolsVersion = 10.2.1;
|
||||
LastSwiftMigration = 1020;
|
||||
SystemCapabilities = {
|
||||
com.apple.BackgroundModes = {
|
||||
enabled = 1;
|
||||
};
|
||||
com.apple.Push = {
|
||||
enabled = 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = BFD247652284B9A500981D42 /* Build configuration list for PBXProject "SideStore" */;
|
||||
compatibilityVersion = "Xcode 13.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = BFD247612284B9A500981D42;
|
||||
packageReferences = (
|
||||
);
|
||||
productRefGroup = BFD2476B2284B9A500981D42 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
BFD247692284B9A500981D42 /* SideStore */,
|
||||
BF989166250AABF3002ACF50 /* SideWidgetExtension */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
BF989165250AABF3002ACF50 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B34AFC1429B032DF000F318E /* Assets.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
BFD247682284B9A500981D42 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B3C40F5729B06A6400C93D50 /* Settings.bundle in Resources */,
|
||||
B3C40F5529B06A3200C93D50 /* Authentication.storyboard in Resources */,
|
||||
B34AFBFE29B0327E000F318E /* AppBannerView.xib in Resources */,
|
||||
B34AFC0129B0327E000F318E /* UpdateCollectionViewCell.xib in Resources */,
|
||||
B34AFC0229B0327E000F318E /* InstalledAppsCollectionHeaderView.xib in Resources */,
|
||||
B3C40F5429B06A2B00C93D50 /* LaunchScreen.storyboard in Resources */,
|
||||
B3C40F5329B06A0000C93D50 /* PatchApp.storyboard in Resources */,
|
||||
B34AFBFF29B0327E000F318E /* AboutPatreonHeaderView.xib in Resources */,
|
||||
B34AFC0429B03288000F318E /* Silence.m4a in Resources */,
|
||||
B34AFBFB29B03279000F318E /* Main.storyboard in Resources */,
|
||||
B34AFC0729B03291000F318E /* Assets.xcassets in Resources */,
|
||||
B34AFC0629B0328D000F318E /* apps-alpha.json in Resources */,
|
||||
B34AFBFC29B0327E000F318E /* SettingsHeaderFooterView.xib in Resources */,
|
||||
B34AFC0529B0328D000F318E /* apps.json in Resources */,
|
||||
B34AFC0329B03283000F318E /* Settings.storyboard in Resources */,
|
||||
B34AFBFD29B0327E000F318E /* BrowseCollectionViewCell.xib in Resources */,
|
||||
B34AFC0029B0327E000F318E /* NewsCollectionViewCell.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
BF989163250AABF3002ACF50 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
BFD247662284B9A500981D42 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
B34BA92A29B5ED510055A710 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = BF989166250AABF3002ACF50 /* SideWidgetExtension */;
|
||||
targetProxy = B34BA92929B5ED510055A710 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
B34AFBE629B0324C000F318E /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
B34AFBE729B0324C000F318E /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B34AFBE829B0324C000F318E /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
B34AFBE929B0324C000F318E /* Base */,
|
||||
);
|
||||
name = Main.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
BF989179250AABF4002ACF50 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = B3CD301429AF876000374AF8 /* SideWidgetExtension.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = SideStoreApp/Sources/SideWidget/Resources/SideWidgetExtension.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)";
|
||||
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||
INFOPLIST_FILE = SideStoreApp/Sources/SideWidget/Resources/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(PRODUCT_BUNDLE_IDENTIFIER)";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
BF98917A250AABF4002ACF50 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = B3CD301429AF876000374AF8 /* SideWidgetExtension.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = SideStoreApp/Sources/SideWidget/Resources/SideWidgetExtension.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)";
|
||||
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||
INFOPLIST_FILE = SideStoreApp/Sources/SideWidget/Resources/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(PRODUCT_BUNDLE_IDENTIFIER)";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
BFD2477C2284B9A700981D42 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = B3C39607284F4C8400DA9E2F /* Build.xcconfig */;
|
||||
buildSettings = {
|
||||
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_CPLUSPLUSFLAGS = (
|
||||
"$(OTHER_CFLAGS)",
|
||||
"-Wno-module-import-in-extern-c",
|
||||
);
|
||||
SDKROOT = auto;
|
||||
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos appletvsimulator appletvos";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG BETA";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SYSTEM_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/Dependencies/AltSign/Dependencies\"";
|
||||
TVOS_DEPLOYMENT_TARGET = 14.2;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
BFD2477D2284B9A700981D42 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = B3C39607284F4C8400DA9E2F /* Build.xcconfig */;
|
||||
buildSettings = {
|
||||
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
OTHER_CPLUSPLUSFLAGS = (
|
||||
"$(OTHER_CFLAGS)",
|
||||
"-Wno-module-import-in-extern-c",
|
||||
);
|
||||
SDKROOT = auto;
|
||||
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos appletvsimulator appletvos";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG BETA";
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
SYSTEM_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/Dependencies/AltSign/Dependencies\"";
|
||||
TVOS_DEPLOYMENT_TARGET = 14.2;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
BFD2477F2284B9A700981D42 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = B3CD301829AF876000374AF8 /* SideStore.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = SideStoreApp/Sources/SideStore/Resources/SideStore.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = S32Z3HMYVQ;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = SideStoreApp/Sources/SideStore/Resources/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = "$(inherited)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(PRODUCT_BUNDLE_IDENTIFIER)";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
BFD247802284B9A700981D42 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = B3CD301829AF876000374AF8 /* SideStore.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = SideStoreApp/Sources/SideStore/Resources/SideStore.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = S32Z3HMYVQ;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = SideStoreApp/Sources/SideStore/Resources/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = "$(inherited)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(PRODUCT_BUNDLE_IDENTIFIER)";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
BF989178250AABF4002ACF50 /* Build configuration list for PBXNativeTarget "SideWidgetExtension" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
BF989179250AABF4002ACF50 /* Debug */,
|
||||
BF98917A250AABF4002ACF50 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
BFD247652284B9A500981D42 /* Build configuration list for PBXProject "SideStore" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
BFD2477C2284B9A700981D42 /* Debug */,
|
||||
BFD2477D2284B9A700981D42 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
BFD2477E2284B9A700981D42 /* Build configuration list for PBXNativeTarget "SideStore" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
BFD2477F2284B9A700981D42 /* Debug */,
|
||||
BFD247802284B9A700981D42 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
B371D45029BC0BF900E157A6 /* SideStoreAppKit */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = SideStoreAppKit;
|
||||
};
|
||||
B371D45229BC0C0B00E157A6 /* SideWidgetKit */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = SideWidgetKit;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
};
|
||||
rootObject = BFD247622284B9A500981D42 /* Project object */;
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
{
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "altsign",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/SideStore/AltSign",
|
||||
"state" : {
|
||||
"revision" : "eb4c74dcf6be2fb00a3edc0381aae59fbbdb4cf3",
|
||||
"version" : "1.0.3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "appcenter-sdk-apple",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/microsoft/appcenter-sdk-apple.git",
|
||||
"state" : {
|
||||
"revision" : "b2dc99cfedead0bad4e6573d86c5228c89cff332",
|
||||
"version" : "4.4.3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "down",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/johnxnguyen/Down",
|
||||
"state" : {
|
||||
"branch" : "master",
|
||||
"revision" : "e754ab1c80920dd51a8e08290c912ac1c2ac8b58"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "imobiledevice.swift",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/SideStore/iMobileDevice.swift",
|
||||
"state" : {
|
||||
"revision" : "74e481106dd155c0cd21bca6795fd9fe5f751654",
|
||||
"version" : "1.0.5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "keychainaccess",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/kishikawakatsumi/KeychainAccess.git",
|
||||
"state" : {
|
||||
"revision" : "84e546727d66f1adc5439debad16270d0fdd04e7",
|
||||
"version" : "4.2.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "launchatlogin",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/sindresorhus/LaunchAtLogin.git",
|
||||
"state" : {
|
||||
"revision" : "7ad6331f9c38953eb1ce8737758e18f7607e984a",
|
||||
"version" : "5.0.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "nuke",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/kean/Nuke.git",
|
||||
"state" : {
|
||||
"revision" : "9318d02a8a6d20af56505c9673261c1fd3b3aebe",
|
||||
"version" : "7.6.3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "openssl",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/krzyzanowskim/OpenSSL",
|
||||
"state" : {
|
||||
"revision" : "87f41bf9488e7dd2b0de2ab97cb3eafc7304e0e6",
|
||||
"version" : "1.1.2000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "plcrashreporter",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/microsoft/PLCrashReporter.git",
|
||||
"state" : {
|
||||
"revision" : "81cdec2b3827feb03286cb297f4c501a8eb98df1",
|
||||
"version" : "1.10.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "roxas",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/JoeMatt/Roxas.git",
|
||||
"state" : {
|
||||
"revision" : "17338c09ec0ffeea4c68135f17c1f801a3d6d10d",
|
||||
"version" : "1.2.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "semanticversion",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/SwiftPackageIndex/SemanticVersion.git",
|
||||
"state" : {
|
||||
"revision" : "fc670910dc0903cc269b3d0b776cda5703979c4e",
|
||||
"version" : "0.3.5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "sidekit",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/SideStore/SideKit",
|
||||
"state" : {
|
||||
"revision" : "7ea34a09b52c104077dea8e0b90f8dc55d43b36b",
|
||||
"version" : "0.1.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swiftpmplugins",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/JoeMatt/SwiftPMPlugins.git",
|
||||
"state" : {
|
||||
"revision" : "2e4833a3ca65d0aaa986138b8ef350b7f549ba28",
|
||||
"version" : "1.0.0"
|
||||
}
|
||||
}
|
||||
],
|
||||
"version" : 2
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1420"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "BFD247692284B9A500981D42"
|
||||
BuildableName = "SideStore.app"
|
||||
BlueprintName = "SideStore"
|
||||
ReferencedContainer = "container:SideStore.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "BFD247692284B9A500981D42"
|
||||
BuildableName = "SideStore.app"
|
||||
BlueprintName = "SideStore"
|
||||
ReferencedContainer = "container:SideStore.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "BFD247692284B9A500981D42"
|
||||
BuildableName = "SideStore.app"
|
||||
BlueprintName = "SideStore"
|
||||
ReferencedContainer = "container:SideStore.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -0,0 +1,113 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1420"
|
||||
wasCreatedForAppExtension = "YES"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "BF989166250AABF3002ACF50"
|
||||
BuildableName = "SideWidgetExtension.appex"
|
||||
BlueprintName = "SideWidgetExtension"
|
||||
ReferencedContainer = "container:SideStore.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "BFD247692284B9A500981D42"
|
||||
BuildableName = "SideStore.app"
|
||||
BlueprintName = "SideStore"
|
||||
ReferencedContainer = "container:SideStore.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = ""
|
||||
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
|
||||
launchStyle = "0"
|
||||
askForAppToLaunch = "Yes"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES"
|
||||
launchAutomaticallySubstyle = "2">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "BFD247692284B9A500981D42"
|
||||
BuildableName = "SideStore.app"
|
||||
BlueprintName = "SideStore"
|
||||
ReferencedContainer = "container:SideStore.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<EnvironmentVariables>
|
||||
<EnvironmentVariable
|
||||
key = "_XCWidgetKind"
|
||||
value = ""
|
||||
isEnabled = "NO">
|
||||
</EnvironmentVariable>
|
||||
<EnvironmentVariable
|
||||
key = "_XCWidgetDefaultView"
|
||||
value = "timeline"
|
||||
isEnabled = "NO">
|
||||
</EnvironmentVariable>
|
||||
<EnvironmentVariable
|
||||
key = "_XCWidgetFamily"
|
||||
value = "medium"
|
||||
isEnabled = "NO">
|
||||
</EnvironmentVariable>
|
||||
</EnvironmentVariables>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
launchAutomaticallySubstyle = "2">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "BFD247692284B9A500981D42"
|
||||
BuildableName = "SideStore.app"
|
||||
BlueprintName = "SideStore"
|
||||
ReferencedContainer = "container:SideStore.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
0
SideStoreApp/.env
Normal file
0
SideStoreApp/.env
Normal file
7
SideStoreApp/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
SideStoreApp/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -0,0 +1,104 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1430"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideBackup"
|
||||
BuildableName = "SideBackup"
|
||||
BlueprintName = "SideBackup"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStoreCoreTests"
|
||||
BuildableName = "SideStoreCoreTests"
|
||||
BlueprintName = "SideStoreCoreTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStoreCoreTests"
|
||||
BuildableName = "SideStoreCoreTests"
|
||||
BlueprintName = "SideStoreCoreTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES"
|
||||
viewDebuggingEnabled = "No">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideBackup"
|
||||
BuildableName = "SideBackup"
|
||||
BlueprintName = "SideBackup"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideBackup"
|
||||
BuildableName = "SideBackup"
|
||||
BlueprintName = "SideBackup"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -0,0 +1,411 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1430"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStore_SideStoreCore"
|
||||
BuildableName = "SideStore_SideStoreCore"
|
||||
BlueprintName = "SideStore_SideStoreCore"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStoreCore"
|
||||
BuildableName = "SideStoreCore"
|
||||
BlueprintName = "SideStoreCore"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStoreCore-Dynamic"
|
||||
BuildableName = "SideStoreCore-Dynamic"
|
||||
BlueprintName = "SideStoreCore-Dynamic"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStoreCore-Static"
|
||||
BuildableName = "SideStoreCore-Static"
|
||||
BlueprintName = "SideStoreCore-Static"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStoreUIKit"
|
||||
BuildableName = "SideStoreUIKit"
|
||||
BlueprintName = "SideStoreUIKit"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStoreUIKit-Dynamic"
|
||||
BuildableName = "SideStoreUIKit-Dynamic"
|
||||
BlueprintName = "SideStoreUIKit-Dynamic"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStoreUIKit-Static"
|
||||
BuildableName = "SideStoreUIKit-Static"
|
||||
BlueprintName = "SideStoreUIKit-Static"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideWidgetKit"
|
||||
BuildableName = "SideWidgetKit"
|
||||
BlueprintName = "SideWidgetKit"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideWidgetKit-Dynamic"
|
||||
BuildableName = "SideWidgetKit-Dynamic"
|
||||
BlueprintName = "SideWidgetKit-Dynamic"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideWidgetKit-Static"
|
||||
BuildableName = "SideWidgetKit-Static"
|
||||
BlueprintName = "SideWidgetKit-Static"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStore_SideStore"
|
||||
BuildableName = "SideStore_SideStore"
|
||||
BlueprintName = "SideStore_SideStore"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideBackup"
|
||||
BuildableName = "SideBackup"
|
||||
BlueprintName = "SideBackup"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStore"
|
||||
BuildableName = "SideStore"
|
||||
BlueprintName = "SideStore"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStore_SideBackup"
|
||||
BuildableName = "SideStore_SideBackup"
|
||||
BlueprintName = "SideStore_SideBackup"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "EmotionalDamage"
|
||||
BuildableName = "EmotionalDamage"
|
||||
BlueprintName = "EmotionalDamage"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "MiniMuxer"
|
||||
BuildableName = "MiniMuxer"
|
||||
BlueprintName = "MiniMuxer"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SidePatcher"
|
||||
BuildableName = "SidePatcher"
|
||||
BlueprintName = "SidePatcher"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "EmotionalDamageTests"
|
||||
BuildableName = "EmotionalDamageTests"
|
||||
BlueprintName = "EmotionalDamageTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "MiniMuxerTests"
|
||||
BuildableName = "MiniMuxerTests"
|
||||
BlueprintName = "MiniMuxerTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SidePatcherTests"
|
||||
BuildableName = "SidePatcherTests"
|
||||
BlueprintName = "SidePatcherTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStoreCoreTests"
|
||||
BuildableName = "SideStoreCoreTests"
|
||||
BlueprintName = "SideStoreCoreTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideUIShared"
|
||||
BuildableName = "SideUIShared"
|
||||
BlueprintName = "SideUIShared"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "EmotionalDamageTests"
|
||||
BuildableName = "EmotionalDamageTests"
|
||||
BlueprintName = "EmotionalDamageTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "MiniMuxerTests"
|
||||
BuildableName = "MiniMuxerTests"
|
||||
BlueprintName = "MiniMuxerTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SidePatcherTests"
|
||||
BuildableName = "SidePatcherTests"
|
||||
BlueprintName = "SidePatcherTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStoreCoreTests"
|
||||
BuildableName = "SideStoreCoreTests"
|
||||
BlueprintName = "SideStoreCoreTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideBackup"
|
||||
BuildableName = "SideBackup"
|
||||
BlueprintName = "SideBackup"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStore"
|
||||
BuildableName = "SideStore"
|
||||
BlueprintName = "SideStore"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -0,0 +1,176 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1430"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStore"
|
||||
BuildableName = "SideStore"
|
||||
BlueprintName = "SideStore"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "EmotionalDamageTests"
|
||||
BuildableName = "EmotionalDamageTests"
|
||||
BlueprintName = "EmotionalDamageTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "MiniMuxerTests"
|
||||
BuildableName = "MiniMuxerTests"
|
||||
BlueprintName = "MiniMuxerTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SidePatcherTests"
|
||||
BuildableName = "SidePatcherTests"
|
||||
BlueprintName = "SidePatcherTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStoreCoreTests"
|
||||
BuildableName = "SideStoreCoreTests"
|
||||
BlueprintName = "SideStoreCoreTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "EmotionalDamageTests"
|
||||
BuildableName = "EmotionalDamageTests"
|
||||
BlueprintName = "EmotionalDamageTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "MiniMuxerTests"
|
||||
BuildableName = "MiniMuxerTests"
|
||||
BlueprintName = "MiniMuxerTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SidePatcherTests"
|
||||
BuildableName = "SidePatcherTests"
|
||||
BlueprintName = "SidePatcherTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStoreCoreTests"
|
||||
BuildableName = "SideStoreCoreTests"
|
||||
BlueprintName = "SideStoreCoreTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES"
|
||||
viewDebuggingEnabled = "No">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStore"
|
||||
BuildableName = "SideStore"
|
||||
BlueprintName = "SideStore"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStore"
|
||||
BuildableName = "SideStore"
|
||||
BlueprintName = "SideStore"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1430"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStoreCore-Dynamic"
|
||||
BuildableName = "SideStoreCore-Dynamic"
|
||||
BlueprintName = "SideStoreCore-Dynamic"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStoreCore-Dynamic"
|
||||
BuildableName = "SideStoreCore-Dynamic"
|
||||
BlueprintName = "SideStoreCore-Dynamic"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1430"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStoreCore-Static"
|
||||
BuildableName = "SideStoreCore-Static"
|
||||
BlueprintName = "SideStoreCore-Static"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "SideStoreCore-Static"
|
||||
BuildableName = "SideStoreCore-Static"
|
||||
BlueprintName = "SideStoreCore-Static"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user