Compare commits

..

7 Commits

Author SHA1 Message Date
Joseph Mattello
e9d3060df7 Swift PM switch roxas fork
Signed-off-by: Joseph Mattello <mail@joemattiello.com>
2023-02-26 21:27:42 -05:00
Joseph Mattello
c59043068e Package.swift Roxas use SideStore port
Signed-off-by: Joseph Mattello <mail@joemattiello.com>
2023-02-26 21:27:42 -05:00
Joseph Mattello
65c43d683c Package.swift builds but errors
Signed-off-by: Joseph Mattello <mail@joemattiello.com>
2023-02-26 21:27:42 -05:00
Joseph Mattello
9e6147c860 Add Package.swift for Danger
Signed-off-by: Joseph Mattello <mail@joemattiello.com>
2023-02-26 21:27:42 -05:00
Joseph Mattello
b3074cadf9 Add Danger github action
Signed-off-by: Joseph Mattello <mail@joemattiello.com>
2023-02-26 21:27:42 -05:00
Joseph Mattello
9c5c597ce6 Add Dangerfile copied from Provenance 2023-02-26 21:27:42 -05:00
Joseph Mattello
977a452605 Add Dangerfile.swift
Signed-off-by: Joseph Mattello <mail@joemattiello.com>
2023-02-26 21:27:40 -05:00
91 changed files with 1550 additions and 2099 deletions

2
.github/CODEOWNERS vendored
View File

@@ -1 +1 @@
* @JoeMatt @lonkelle @nythepegasus @Spidy123222 @SternXD * @JoeMatt @lonkelle

View File

@@ -10,7 +10,7 @@ body:
value: | value: |
Thanks for taking the time to fill out this bug report! Before you continue filling out the report, please **[search in GitHub Issues](https://github.com/SideStore/SideStore/issues?q=is%3Aissue+is%3Aopen) for the bug you are experiencing** in case it has already been reported. Thanks for taking the time to fill out this bug report! Before you continue filling out the report, please **[search in GitHub Issues](https://github.com/SideStore/SideStore/issues?q=is%3Aissue+is%3Aopen) for the bug you are experiencing** in case it has already been reported.
**Please use [Discord](https://discord.gg/sidestore-949183273383395328) or [GitHub Discussions](https://github.com/SideStore/SideStore/discussions) for support.** **Please use [Discord](https://discord.gg/RgpFBX3Q3k) or [GitHub Discussions](https://github.com/SideStore/SideStore/discussions) for support.**
- type: textarea - type: textarea
id: description id: description
attributes: attributes:

View File

@@ -3,7 +3,7 @@ blank_issues_enabled: false
contact_links: contact_links:
- name: Discord - name: Discord
url: https://discord.gg/sidestore-949183273383395328 url: https://discord.gg/RgpFBX3Q3k
about: If you need support, please go here first instead of making an issue! about: If you need support, please go here first instead of making an issue!
- name: GitHub Discussions - name: GitHub Discussions
url: https://github.com/SideStore/SideStore/discussions url: https://github.com/SideStore/SideStore/discussions

View File

@@ -10,7 +10,7 @@ body:
value: | value: |
Thanks for taking the time to fill out this feature request! Before you continue filling out the form, please **[search in GitHub Issues](https://github.com/SideStore/SideStore/issues?q=is%3Aissue+is%3Aopen) for the feature you are suggestion** in case it has already been suggested. Thanks for taking the time to fill out this feature request! Before you continue filling out the form, please **[search in GitHub Issues](https://github.com/SideStore/SideStore/issues?q=is%3Aissue+is%3Aopen) for the feature you are suggestion** in case it has already been suggested.
**Please use [Discord](https://discord.gg/sidestore-949183273383395328) or [GitHub Discussions](https://github.com/SideStore/SideStore/discussions) for support.** **Please use [Discord](https://discord.gg/RgpFBX3Q3k) or [GitHub Discussions](https://github.com/SideStore/SideStore/discussions) for support.**
- type: textarea - type: textarea
id: description id: description
attributes: attributes:

View File

@@ -27,13 +27,6 @@ jobs:
- name: Change version to tag - name: Change version to tag
run: sed -e '/MARKETING_VERSION = .*/s/= .*/= ${{ github.ref_name }}/' -i '' Build.xcconfig run: sed -e '/MARKETING_VERSION = .*/s/= .*/= ${{ github.ref_name }}/' -i '' Build.xcconfig
- name: Get version
id: version
run: echo "version=$(grep MARKETING_VERSION Build.xcconfig | sed -e "s/MARKETING_VERSION = //g")" >> $GITHUB_OUTPUT
- name: Echo version
run: echo "${{ steps.version.outputs.version }}"
- name: Setup Xcode - name: Setup Xcode
uses: maxim-lobanov/setup-xcode@v1.4.1 uses: maxim-lobanov/setup-xcode@v1.4.1
with: with:
@@ -48,6 +41,16 @@ jobs:
- name: Convert to IPA - name: Convert to IPA
run: make ipa run: make ipa
- name: Upload Artifact
uses: actions/upload-artifact@v3.1.0
with:
name: SideStore.ipa
path: SideStore.ipa
- 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 - name: Get current date
id: date id: date
run: echo "date=$(date -u +'%c')" >> $GITHUB_OUTPUT run: echo "date=$(date -u +'%c')" >> $GITHUB_OUTPUT
@@ -79,18 +82,3 @@ jobs:
Built at (UTC date): `${{ steps.date_altstore.outputs.date }}` Built at (UTC date): `${{ steps.date_altstore.outputs.date }}`
Commit SHA: `${{ github.sha }}` Commit SHA: `${{ github.sha }}`
Version: `${{ steps.version.outputs.version }}` Version: `${{ steps.version.outputs.version }}`
- name: Add version to IPA file name
run: mv SideStore.ipa SideStore-${{ steps.version.outputs.version }}.ipa
- name: Upload SideStore.ipa Artifact
uses: actions/upload-artifact@v3.1.0
with:
name: SideStore-${{ steps.version.outputs.version }}.ipa
path: SideStore-${{ steps.version.outputs.version }}.ipa
- name: Upload *.dSYM Artifact
uses: actions/upload-artifact@v3.1.0
with:
name: SideStore-${{ steps.version.outputs.version }}-dSYM
path: ./*.dSYM/

13
.github/workflows/danger.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
name: "Danger Swift"
on: [pull_request]
jobs:
build:
name: Danger JS
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Danger Swift
uses: danger/swift@2.0.3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -7,7 +7,7 @@ DATE=`date -u +'%Y.%m.%d'`
BUILD_NUM=1 BUILD_NUM=1
write() { write() {
sed -e "/MARKETING_VERSION = .*/s/$/-nightly.$DATE.$BUILD_NUM+$(git rev-parse --short HEAD)/" -i '' Build.xcconfig sed -e "/MARKETING_VERSION = .*/s/$/-nightly.$DATE.$BUILD_NUM/" -i '' Build.xcconfig
echo "$DATE,$BUILD_NUM" > .nightly-build-num echo "$DATE,$BUILD_NUM" > .nightly-build-num
} }

View File

@@ -36,13 +36,6 @@ jobs:
- name: Increase nightly build number and set as version - name: Increase nightly build number and set as version
run: bash .github/workflows/increase-nightly-build-num.sh run: bash .github/workflows/increase-nightly-build-num.sh
- name: Get version
id: version
run: echo "version=$(grep MARKETING_VERSION Build.xcconfig | sed -e "s/MARKETING_VERSION = //g")" >> $GITHUB_OUTPUT
- name: Echo version
run: echo "${{ steps.version.outputs.version }}"
- name: Setup Xcode - name: Setup Xcode
uses: maxim-lobanov/setup-xcode@v1.4.1 uses: maxim-lobanov/setup-xcode@v1.4.1
with: with:
@@ -57,6 +50,16 @@ jobs:
- name: Convert to IPA - name: Convert to IPA
run: make ipa run: make ipa
- name: Upload Artifact
uses: actions/upload-artifact@v3.1.0
with:
name: SideStore.ipa
path: SideStore.ipa
- 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 - name: Get current date
id: date id: date
run: echo "date=$(date -u +'%c')" >> $GITHUB_OUTPUT run: echo "date=$(date -u +'%c')" >> $GITHUB_OUTPUT
@@ -87,20 +90,5 @@ jobs:
Commit SHA: `${{ github.sha }}` Commit SHA: `${{ github.sha }}`
Version: `${{ steps.version.outputs.version }}` Version: `${{ steps.version.outputs.version }}`
- name: Add version to IPA file name
run: mv SideStore.ipa SideStore-${{ steps.version.outputs.version }}.ipa
- name: Upload SideStore.ipa Artifact
uses: actions/upload-artifact@v3.1.0
with:
name: SideStore-${{ steps.version.outputs.version }}.ipa
path: SideStore-${{ steps.version.outputs.version }}.ipa
- name: Upload *.dSYM Artifact
uses: actions/upload-artifact@v3.1.0
with:
name: SideStore-${{ steps.version.outputs.version }}-dSYM
path: ./*.dSYM/
- name: Reset cache for apps.sidestore.io/nightly - name: Reset cache for apps.sidestore.io/nightly
run: sleep 10 && curl https://apps.sidestore.io/reset-cache/nightly/${{ secrets.SIDESOURCE_KEY }} run: sleep 10 && curl https://apps.sidestore.io/reset-cache/nightly/${{ secrets.SIDESOURCE_KEY }}

View File

@@ -23,16 +23,7 @@ jobs:
run: brew install ldid run: brew install ldid
- name: Add PR suffix to version - name: Add PR suffix to version
run: sed -e "/MARKETING_VERSION = .*/s/\$/-pr.${{ github.event.pull_request.number }}+$(git rev-parse --short ${COMMIT:-HEAD})/" -i '' Build.xcconfig run: sed -e '/MARKETING_VERSION = .*/s/$/-pr.${{ github.event.pull_request.number }}/' -i '' Build.xcconfig
env:
COMMIT: ${{ github.event.pull_request.head.sha }}
- name: Get version
id: version
run: echo "version=$(grep MARKETING_VERSION Build.xcconfig | sed -e "s/MARKETING_VERSION = //g")" >> $GITHUB_OUTPUT
- name: Echo version
run: echo "${{ steps.version.outputs.version }}"
- name: Setup Xcode - name: Setup Xcode
uses: maxim-lobanov/setup-xcode@v1.4.1 uses: maxim-lobanov/setup-xcode@v1.4.1
@@ -48,17 +39,8 @@ jobs:
- name: Convert to IPA - name: Convert to IPA
run: make ipa run: make ipa
- name: Add version to IPA file name - name: Upload Artifact
run: mv SideStore.ipa SideStore-${{ steps.version.outputs.version }}.ipa
- name: Upload SideStore.ipa Artifact
uses: actions/upload-artifact@v3.1.0 uses: actions/upload-artifact@v3.1.0
with: with:
name: SideStore-${{ steps.version.outputs.version }}.ipa name: SideStore.ipa
path: SideStore-${{ steps.version.outputs.version }}.ipa path: SideStore.ipa
- name: Upload *.dSYM Artifact
uses: actions/upload-artifact@v3.1.0
with:
name: SideStore-${{ steps.version.outputs.version }}-dSYM
path: ./*.dSYM/

View File

@@ -3,7 +3,6 @@ on:
push: push:
tags: tags:
- '[0-9]+.[0-9]+.[0-9]+' # example: 1.0.0 - '[0-9]+.[0-9]+.[0-9]+' # example: 1.0.0
workflow_dispatch:
jobs: jobs:
build: build:
@@ -28,13 +27,6 @@ jobs:
- name: Change version to tag - name: Change version to tag
run: sed -e '/MARKETING_VERSION = .*/s/= .*/= ${{ github.ref_name }}/' -i '' Build.xcconfig run: sed -e '/MARKETING_VERSION = .*/s/= .*/= ${{ github.ref_name }}/' -i '' Build.xcconfig
- name: Get version
id: version
run: echo "version=$(grep MARKETING_VERSION Build.xcconfig | sed -e "s/MARKETING_VERSION = //g")" >> $GITHUB_OUTPUT
- name: Echo version
run: echo "${{ steps.version.outputs.version }}"
- name: Setup Xcode - name: Setup Xcode
uses: maxim-lobanov/setup-xcode@v1.4.1 uses: maxim-lobanov/setup-xcode@v1.4.1
with: with:
@@ -49,6 +41,16 @@ jobs:
- name: Convert to IPA - name: Convert to IPA
run: make ipa run: make ipa
- name: Upload Artifact
uses: actions/upload-artifact@v3.1.0
with:
name: SideStore.ipa
path: SideStore.ipa
- 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 - name: Get current date
id: date id: date
run: echo "date=$(date -u +'%c')" >> $GITHUB_OUTPUT run: echo "date=$(date -u +'%c')" >> $GITHUB_OUTPUT
@@ -77,18 +79,3 @@ jobs:
Built at (UTC date): `${{ steps.date_altstore.outputs.date }}` Built at (UTC date): `${{ steps.date_altstore.outputs.date }}`
Commit SHA: `${{ github.sha }}` Commit SHA: `${{ github.sha }}`
Version: `${{ steps.version.outputs.version }}` Version: `${{ steps.version.outputs.version }}`
- name: Add version to IPA file name
run: mv SideStore.ipa SideStore-${{ steps.version.outputs.version }}.ipa
- name: Upload SideStore.ipa Artifact
uses: actions/upload-artifact@v3.1.0
with:
name: SideStore-${{ steps.version.outputs.version }}.ipa
path: SideStore-${{ steps.version.outputs.version }}.ipa
- name: Upload *.dSYM Artifact
uses: actions/upload-artifact@v3.1.0
with:
name: SideStore-${{ steps.version.outputs.version }}-dSYM
path: ./*.dSYM/

4
.gitignore vendored
View File

@@ -35,10 +35,10 @@ xcuserdata
## AppCode specific ## AppCode specific
.idea/ .idea/
.build
Payload/ Payload/
SideStore.ipa SideStore.ipa
*.dSYM
Dependencies/.*-prebuilt-fetch-* Dependencies/.*-prebuilt-fetch-*
Dependencies/minimuxer/* Dependencies/minimuxer/*
Dependencies/em_proxy/* Dependencies/em_proxy/*

2
.gitmodules vendored
View File

@@ -9,7 +9,7 @@
url = https://github.com/libimobiledevice/libusbmuxd.git url = https://github.com/libimobiledevice/libusbmuxd.git
[submodule "Dependencies/libplist"] [submodule "Dependencies/libplist"]
path = Dependencies/libplist path = Dependencies/libplist
url = https://github.com/SideStore/libplist.git url = https://github.com/libimobiledevice/libplist.git
[submodule "Dependencies/MarkdownAttributedString"] [submodule "Dependencies/MarkdownAttributedString"]
path = Dependencies/MarkdownAttributedString path = Dependencies/MarkdownAttributedString
url = https://github.com/chockenberry/MarkdownAttributedString.git url = https://github.com/chockenberry/MarkdownAttributedString.git

View File

@@ -5,9 +5,9 @@
"color-space" : "srgb", "color-space" : "srgb",
"components" : { "components" : {
"alpha" : "1.000", "alpha" : "1.000",
"blue" : "175", "blue" : "0.518",
"green" : "4", "green" : "0.502",
"red" : "115" "red" : "0.004"
} }
}, },
"idiom" : "universal" "idiom" : "universal"
@@ -23,9 +23,9 @@
"color-space" : "srgb", "color-space" : "srgb",
"components" : { "components" : {
"alpha" : "1.000", "alpha" : "1.000",
"blue" : "150", "blue" : "0.404",
"green" : "3", "green" : "0.322",
"red" : "99" "red" : "0.008"
} }
}, },
"idiom" : "universal" "idiom" : "universal"

View File

@@ -1,3 +1,3 @@
#include "Build.xcconfig" #include "Build.xcconfig"
PRODUCT_BUNDLE_IDENTIFIER = $(PRODUCT_BUNDLE_IDENTIFIER) PRODUCT_BUNDLE_IDENTIFIER = $(ORG_PREFIX).$(PRODUCT_NAME)

View File

@@ -8,49 +8,22 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
03F06CD52942C27E001C4D68 /* Bundle+AltStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF1E314122A05D4C00370A3C /* Bundle+AltStore.swift */; }; 03F06CD52942C27E001C4D68 /* Bundle+AltStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF1E314122A05D4C00370A3C /* Bundle+AltStore.swift */; };
0E1A1F912AE36A9700364CAD /* bytearray.c in Sources */ = {isa = PBXBuildFile; fileRef = 0E1A1F902AE36A9600364CAD /* bytearray.c */; };
0E764E172ADFF5740043DD4E /* AltBackup.ipa in Resources */ = {isa = PBXBuildFile; fileRef = 0E764E162ADFF5740043DD4E /* AltBackup.ipa */; };
0EA1665B2ADFE0D2003015C1 /* out-limd.c in Sources */ = {isa = PBXBuildFile; fileRef = 0EA166472ADFE0D1003015C1 /* out-limd.c */; };
0EA1665C2ADFE0D2003015C1 /* out-default.c in Sources */ = {isa = PBXBuildFile; fileRef = 0EA166522ADFE0D2003015C1 /* out-default.c */; };
0EA1665D2ADFE0D2003015C1 /* out-plutil.c in Sources */ = {isa = PBXBuildFile; fileRef = 0EA166552ADFE0D2003015C1 /* out-plutil.c */; };
0EA1665E2ADFE0D2003015C1 /* oplist.c in Sources */ = {isa = PBXBuildFile; fileRef = 0EA166562ADFE0D2003015C1 /* oplist.c */; };
0EA166682ADFE122003015C1 /* jsmn.h in Headers */ = {isa = PBXBuildFile; fileRef = 0EA166632ADFE122003015C1 /* jsmn.h */; };
0EA166692ADFE140003015C1 /* Array.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0EA166452ADFE0D1003015C1 /* Array.cpp */; };
0EA1666A2ADFE140003015C1 /* String.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0EA166492ADFE0D1003015C1 /* String.cpp */; };
0EA1666B2ADFE140003015C1 /* Boolean.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0EA1664E2ADFE0D1003015C1 /* Boolean.cpp */; };
0EA1666C2ADFE140003015C1 /* Integer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0EA166532ADFE0D2003015C1 /* Integer.cpp */; };
0EA1666D2ADFE140003015C1 /* Data.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0EA166432ADFE0D1003015C1 /* Data.cpp */; };
0EA1666E2ADFE140003015C1 /* ptrarray.c in Sources */ = {isa = PBXBuildFile; fileRef = 0EA166512ADFE0D2003015C1 /* ptrarray.c */; };
0EA1666F2ADFE140003015C1 /* hashtable.c in Sources */ = {isa = PBXBuildFile; fileRef = 0EA1664F2ADFE0D1003015C1 /* hashtable.c */; };
0EA166702ADFE140003015C1 /* Node.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0EA166502ADFE0D2003015C1 /* Node.cpp */; };
0EA166712ADFE140003015C1 /* Key.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0EA166582ADFE0D2003015C1 /* Key.cpp */; };
0EA166732ADFE140003015C1 /* Dictionary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0EA166462ADFE0D1003015C1 /* Dictionary.cpp */; };
0EA166742ADFE140003015C1 /* Date.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0EA166422ADFE0D1003015C1 /* Date.cpp */; };
0EA166752ADFE140003015C1 /* Real.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0EA166542ADFE0D2003015C1 /* Real.cpp */; };
0EA166762ADFE140003015C1 /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = 0EA1664A2ADFE0D1003015C1 /* base64.c */; };
0EA166772ADFE140003015C1 /* jplist.c in Sources */ = {isa = PBXBuildFile; fileRef = 0EA166412ADFE0D1003015C1 /* jplist.c */; };
0EA166782ADFE140003015C1 /* jsmn.c in Sources */ = {isa = PBXBuildFile; fileRef = 0EA166572ADFE0D2003015C1 /* jsmn.c */; };
0EA166792ADFE140003015C1 /* bplist.c in Sources */ = {isa = PBXBuildFile; fileRef = 0EA166442ADFE0D1003015C1 /* bplist.c */; };
0EA1667A2ADFE140003015C1 /* Uid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0EA1664B2ADFE0D1003015C1 /* Uid.cpp */; };
0EA1667B2ADFE140003015C1 /* Structure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0EA1665A2ADFE0D2003015C1 /* Structure.cpp */; };
0EA1667D2ADFE140003015C1 /* xplist.c in Sources */ = {isa = PBXBuildFile; fileRef = 0EA166592ADFE0D2003015C1 /* xplist.c */; };
0EA1667E2ADFE140003015C1 /* time64.c in Sources */ = {isa = PBXBuildFile; fileRef = 0EA1664C2ADFE0D1003015C1 /* time64.c */; };
0EA4B9BC2AE4A414009209CE /* plist.c in Sources */ = {isa = PBXBuildFile; fileRef = 0EA4B9BB2AE4A3F6009209CE /* plist.c */; };
19104D952909BAEA00C49C7B /* libimobiledevice.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BF45872B2298D31600BD7491 /* libimobiledevice.a */; }; 19104D952909BAEA00C49C7B /* libimobiledevice.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BF45872B2298D31600BD7491 /* libimobiledevice.a */; };
19104DB52909C06D00C49C7B /* EmotionalDamage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19104DB42909C06D00C49C7B /* EmotionalDamage.swift */; }; 19104DB52909C06D00C49C7B /* EmotionalDamage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19104DB42909C06D00C49C7B /* EmotionalDamage.swift */; };
19104DBC2909C4E500C49C7B /* libEmotionalDamage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19104DB22909C06C00C49C7B /* libEmotionalDamage.a */; }; 19104DBC2909C4E500C49C7B /* libEmotionalDamage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19104DB22909C06C00C49C7B /* libEmotionalDamage.a */; };
191E5FAE290A5D92001A3B7C /* minimuxer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191E5FAD290A5D92001A3B7C /* minimuxer.swift */; };
191E5FB4290A5DA0001A3B7C /* libminimuxer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 191E5FAB290A5D92001A3B7C /* libminimuxer.a */; }; 191E5FB4290A5DA0001A3B7C /* libminimuxer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 191E5FAB290A5D92001A3B7C /* libminimuxer.a */; };
191E5FDC290AFA5C001A3B7C /* OpenSSL in Frameworks */ = {isa = PBXBuildFile; productRef = 191E5FDB290AFA5C001A3B7C /* OpenSSL */; }; 191E5FDC290AFA5C001A3B7C /* OpenSSL in Frameworks */ = {isa = PBXBuildFile; productRef = 191E5FDB290AFA5C001A3B7C /* OpenSSL */; };
191E607D290B2EA5001A3B7C /* jsmn.c in Sources */ = {isa = PBXBuildFile; fileRef = 191E5FD0290A651D001A3B7C /* jsmn.c */; };
191E607E290B2EA7001A3B7C /* jplist.c in Sources */ = {isa = PBXBuildFile; fileRef = 191E5FCF290A651D001A3B7C /* jplist.c */; };
191E6087290C7B50001A3B7C /* libminimuxer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 191E5FB5290A5E1F001A3B7C /* libminimuxer.a */; };
1920B04F2924AC8300744F60 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 1920B04E2924AC8300744F60 /* Settings.bundle */; }; 1920B04F2924AC8300744F60 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 1920B04E2924AC8300744F60 /* Settings.bundle */; };
19B9B7452845E6DF0076EF69 /* SelectTeamViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B9B7442845E6DF0076EF69 /* SelectTeamViewController.swift */; }; 19B9B7452845E6DF0076EF69 /* SelectTeamViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B9B7442845E6DF0076EF69 /* SelectTeamViewController.swift */; };
4879A95F2861046500FC1BBD /* AltSign in Frameworks */ = {isa = PBXBuildFile; productRef = 4879A95E2861046500FC1BBD /* AltSign */; }; 4879A95F2861046500FC1BBD /* AltSign in Frameworks */ = {isa = PBXBuildFile; productRef = 4879A95E2861046500FC1BBD /* AltSign */; };
4879A9622861049C00FC1BBD /* OpenSSL in Frameworks */ = {isa = PBXBuildFile; productRef = 4879A9612861049C00FC1BBD /* OpenSSL */; }; 4879A9622861049C00FC1BBD /* OpenSSL in Frameworks */ = {isa = PBXBuildFile; productRef = 4879A9612861049C00FC1BBD /* OpenSSL */; };
9922FFEC29B501C50020F868 /* Starscream in Frameworks */ = {isa = PBXBuildFile; productRef = 9922FFEB29B501C50020F868 /* Starscream */; };
99C4EF4D2979132100CB538D /* SemanticVersion in Frameworks */ = {isa = PBXBuildFile; productRef = 99C4EF4C2979132100CB538D /* SemanticVersion */; }; 99C4EF4D2979132100CB538D /* SemanticVersion in Frameworks */ = {isa = PBXBuildFile; productRef = 99C4EF4C2979132100CB538D /* SemanticVersion */; };
99F87D0529D8B4E200B40039 /* minimuxer-helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9961EC2D29BE9F2E00AF2C6F /* minimuxer-helpers.swift */; };
99F87D1829D8E4C900B40039 /* SwiftBridgeCore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99F87D1629D8E4C900B40039 /* SwiftBridgeCore.swift */; };
99F87D1929D8E4C900B40039 /* minimuxer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99F87D1729D8E4C900B40039 /* minimuxer.swift */; };
B3146ED2284F581E00BBC3FD /* Roxas.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B3146ECD284F580500BBC3FD /* Roxas.framework */; }; B3146ED2284F581E00BBC3FD /* Roxas.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B3146ECD284F580500BBC3FD /* Roxas.framework */; };
B3146ED3284F581E00BBC3FD /* Roxas.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B3146ECD284F580500BBC3FD /* Roxas.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
B33FFBA8295F8E98002259E6 /* libfragmentzip.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B343F894295F7F9B002B1159 /* libfragmentzip.a */; }; B33FFBA8295F8E98002259E6 /* libfragmentzip.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B343F894295F7F9B002B1159 /* libfragmentzip.a */; };
B33FFBAA295F8F78002259E6 /* preboard.c in Sources */ = {isa = PBXBuildFile; fileRef = B33FFBA9295F8F78002259E6 /* preboard.c */; }; B33FFBAA295F8F78002259E6 /* preboard.c in Sources */ = {isa = PBXBuildFile; fileRef = B33FFBA9295F8F78002259E6 /* preboard.c */; };
B33FFBAC295F8F98002259E6 /* companion_proxy.c in Sources */ = {isa = PBXBuildFile; fileRef = B33FFBAB295F8F98002259E6 /* companion_proxy.c */; }; B33FFBAC295F8F98002259E6 /* companion_proxy.c in Sources */ = {isa = PBXBuildFile; fileRef = B33FFBAB295F8F98002259E6 /* companion_proxy.c */; };
@@ -99,6 +72,7 @@
BF41B808233433C100C593A3 /* LoadingState.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF41B807233433C100C593A3 /* LoadingState.swift */; }; BF41B808233433C100C593A3 /* LoadingState.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF41B807233433C100C593A3 /* LoadingState.swift */; };
BF42345A25101C35006D1EB2 /* WidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF42345825101C1D006D1EB2 /* WidgetView.swift */; }; BF42345A25101C35006D1EB2 /* WidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF42345825101C1D006D1EB2 /* WidgetView.swift */; };
BF44EEF0246B08BA002A52F2 /* BackupController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF44EEEF246B08BA002A52F2 /* BackupController.swift */; }; BF44EEF0246B08BA002A52F2 /* BackupController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF44EEEF246B08BA002A52F2 /* BackupController.swift */; };
BF44EEF3246B3A17002A52F2 /* AltBackup.ipa in Resources */ = {isa = PBXBuildFile; fileRef = BF44EEF2246B3A17002A52F2 /* AltBackup.ipa */; };
BF44EEFC246B4550002A52F2 /* RemoveAppOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF44EEFB246B4550002A52F2 /* RemoveAppOperation.swift */; }; BF44EEFC246B4550002A52F2 /* RemoveAppOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF44EEFB246B4550002A52F2 /* RemoveAppOperation.swift */; };
BF4587F82298D3AB00BD7491 /* service.h in Headers */ = {isa = PBXBuildFile; fileRef = BF4587C82298D3A800BD7491 /* service.h */; }; BF4587F82298D3AB00BD7491 /* service.h in Headers */ = {isa = PBXBuildFile; fileRef = BF4587C82298D3A800BD7491 /* service.h */; };
BF4587F92298D3AB00BD7491 /* diagnostics_relay.c in Sources */ = {isa = PBXBuildFile; fileRef = BF4587C92298D3A800BD7491 /* diagnostics_relay.c */; }; BF4587F92298D3AB00BD7491 /* diagnostics_relay.c in Sources */ = {isa = PBXBuildFile; fileRef = BF4587C92298D3A800BD7491 /* diagnostics_relay.c */; };
@@ -278,6 +252,34 @@
BFD2477A2284B9A700981D42 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BFD247782284B9A700981D42 /* LaunchScreen.storyboard */; }; BFD2477A2284B9A700981D42 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BFD247782284B9A700981D42 /* LaunchScreen.storyboard */; };
BFD2478C2284C4C300981D42 /* AppIconImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2478B2284C4C300981D42 /* AppIconImageView.swift */; }; BFD2478C2284C4C300981D42 /* AppIconImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2478B2284C4C300981D42 /* AppIconImageView.swift */; };
BFD2478F2284C8F900981D42 /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2478E2284C8F900981D42 /* Button.swift */; }; BFD2478F2284C8F900981D42 /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2478E2284C8F900981D42 /* Button.swift */; };
BFD52C0122A1A9CB000B7ED1 /* ptrarray.c in Sources */ = {isa = PBXBuildFile; fileRef = BFD52BE522A1A9CA000B7ED1 /* ptrarray.c */; };
BFD52C0222A1A9CB000B7ED1 /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = BFD52BE622A1A9CA000B7ED1 /* base64.c */; };
BFD52C0322A1A9CB000B7ED1 /* hashtable.c in Sources */ = {isa = PBXBuildFile; fileRef = BFD52BE722A1A9CA000B7ED1 /* hashtable.c */; };
BFD52C0422A1A9CB000B7ED1 /* Dictionary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFD52BE822A1A9CA000B7ED1 /* Dictionary.cpp */; };
BFD52C0522A1A9CB000B7ED1 /* ptrarray.h in Headers */ = {isa = PBXBuildFile; fileRef = BFD52BE922A1A9CA000B7ED1 /* ptrarray.h */; };
BFD52C0622A1A9CB000B7ED1 /* bplist.c in Sources */ = {isa = PBXBuildFile; fileRef = BFD52BEA22A1A9CA000B7ED1 /* bplist.c */; };
BFD52C0722A1A9CB000B7ED1 /* String.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFD52BEB22A1A9CA000B7ED1 /* String.cpp */; };
BFD52C0822A1A9CB000B7ED1 /* time64.c in Sources */ = {isa = PBXBuildFile; fileRef = BFD52BEC22A1A9CA000B7ED1 /* time64.c */; };
BFD52C0922A1A9CB000B7ED1 /* plist.h in Headers */ = {isa = PBXBuildFile; fileRef = BFD52BED22A1A9CA000B7ED1 /* plist.h */; };
BFD52C0A22A1A9CB000B7ED1 /* plist.c in Sources */ = {isa = PBXBuildFile; fileRef = BFD52BEE22A1A9CA000B7ED1 /* plist.c */; };
BFD52C0B22A1A9CB000B7ED1 /* hashtable.h in Headers */ = {isa = PBXBuildFile; fileRef = BFD52BEF22A1A9CA000B7ED1 /* hashtable.h */; };
BFD52C0C22A1A9CB000B7ED1 /* Date.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFD52BF022A1A9CA000B7ED1 /* Date.cpp */; };
BFD52C0D22A1A9CB000B7ED1 /* Uid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFD52BF122A1A9CA000B7ED1 /* Uid.cpp */; };
BFD52C0E22A1A9CB000B7ED1 /* Boolean.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFD52BF222A1A9CA000B7ED1 /* Boolean.cpp */; };
BFD52C0F22A1A9CB000B7ED1 /* Real.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFD52BF322A1A9CA000B7ED1 /* Real.cpp */; };
BFD52C1022A1A9CB000B7ED1 /* strbuf.h in Headers */ = {isa = PBXBuildFile; fileRef = BFD52BF422A1A9CA000B7ED1 /* strbuf.h */; };
BFD52C1122A1A9CB000B7ED1 /* bytearray.c in Sources */ = {isa = PBXBuildFile; fileRef = BFD52BF522A1A9CA000B7ED1 /* bytearray.c */; };
BFD52C1222A1A9CB000B7ED1 /* base64.h in Headers */ = {isa = PBXBuildFile; fileRef = BFD52BF622A1A9CA000B7ED1 /* base64.h */; };
BFD52C1322A1A9CB000B7ED1 /* Data.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFD52BF722A1A9CA000B7ED1 /* Data.cpp */; };
BFD52C1422A1A9CB000B7ED1 /* Array.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFD52BF822A1A9CB000B7ED1 /* Array.cpp */; };
BFD52C1522A1A9CB000B7ED1 /* Node.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFD52BF922A1A9CB000B7ED1 /* Node.cpp */; };
BFD52C1622A1A9CB000B7ED1 /* bytearray.h in Headers */ = {isa = PBXBuildFile; fileRef = BFD52BFA22A1A9CB000B7ED1 /* bytearray.h */; };
BFD52C1722A1A9CB000B7ED1 /* Key.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFD52BFB22A1A9CB000B7ED1 /* Key.cpp */; };
BFD52C1822A1A9CB000B7ED1 /* Integer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFD52BFC22A1A9CB000B7ED1 /* Integer.cpp */; };
BFD52C1922A1A9CB000B7ED1 /* Structure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFD52BFD22A1A9CB000B7ED1 /* Structure.cpp */; };
BFD52C1A22A1A9CB000B7ED1 /* time64_limits.h in Headers */ = {isa = PBXBuildFile; fileRef = BFD52BFE22A1A9CB000B7ED1 /* time64_limits.h */; };
BFD52C1B22A1A9CB000B7ED1 /* time64.h in Headers */ = {isa = PBXBuildFile; fileRef = BFD52BFF22A1A9CB000B7ED1 /* time64.h */; };
BFD52C1C22A1A9CB000B7ED1 /* xplist.c in Sources */ = {isa = PBXBuildFile; fileRef = BFD52C0022A1A9CB000B7ED1 /* xplist.c */; };
BFD52C2022A1A9EC000B7ED1 /* node.c in Sources */ = {isa = PBXBuildFile; fileRef = BFD52C1D22A1A9EC000B7ED1 /* node.c */; }; BFD52C2022A1A9EC000B7ED1 /* node.c in Sources */ = {isa = PBXBuildFile; fileRef = BFD52C1D22A1A9EC000B7ED1 /* node.c */; };
BFD52C2122A1A9EC000B7ED1 /* node_list.c in Sources */ = {isa = PBXBuildFile; fileRef = BFD52C1E22A1A9EC000B7ED1 /* node_list.c */; }; BFD52C2122A1A9EC000B7ED1 /* node_list.c in Sources */ = {isa = PBXBuildFile; fileRef = BFD52C1E22A1A9EC000B7ED1 /* node_list.c */; };
BFD52C2222A1A9EC000B7ED1 /* cnary.c in Sources */ = {isa = PBXBuildFile; fileRef = BFD52C1F22A1A9EC000B7ED1 /* cnary.c */; }; BFD52C2222A1A9EC000B7ED1 /* cnary.c in Sources */ = {isa = PBXBuildFile; fileRef = BFD52C1F22A1A9EC000B7ED1 /* cnary.c */; };
@@ -332,7 +334,6 @@
D57FE84428C7DB7100216002 /* ErrorLogViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D57FE84328C7DB7100216002 /* ErrorLogViewController.swift */; }; D57FE84428C7DB7100216002 /* ErrorLogViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D57FE84328C7DB7100216002 /* ErrorLogViewController.swift */; };
D58916FE28C7C55C00E39C8B /* LoggedError.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58916FD28C7C55C00E39C8B /* LoggedError.swift */; }; D58916FE28C7C55C00E39C8B /* LoggedError.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58916FD28C7C55C00E39C8B /* LoggedError.swift */; };
D593F1942717749A006E82DE /* PatchAppOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D593F1932717749A006E82DE /* PatchAppOperation.swift */; }; D593F1942717749A006E82DE /* PatchAppOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D593F1932717749A006E82DE /* PatchAppOperation.swift */; };
D5ACE84528E3B8450021CAB9 /* ClearAppCacheOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5ACE84428E3B8450021CAB9 /* ClearAppCacheOperation.swift */; };
D5CA0C4B280E141900469595 /* ManagedPatron.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5CA0C4A280E141900469595 /* ManagedPatron.swift */; }; D5CA0C4B280E141900469595 /* ManagedPatron.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5CA0C4A280E141900469595 /* ManagedPatron.swift */; };
D5CA0C4E280E249E00469595 /* AltStore9ToAltStore10.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = D5CA0C4D280E249E00469595 /* AltStore9ToAltStore10.xcmappingmodel */; }; D5CA0C4E280E249E00469595 /* AltStore9ToAltStore10.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = D5CA0C4D280E249E00469595 /* AltStore9ToAltStore10.xcmappingmodel */; };
D5DAE0942804B0B80034D8D4 /* ScreenshotProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5DAE0932804B0B80034D8D4 /* ScreenshotProcessor.swift */; }; D5DAE0942804B0B80034D8D4 /* ScreenshotProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5DAE0932804B0B80034D8D4 /* ScreenshotProcessor.swift */; };
@@ -479,6 +480,7 @@
dstPath = ""; dstPath = "";
dstSubfolderSpec = 10; dstSubfolderSpec = 10;
files = ( files = (
B3146ED3284F581E00BBC3FD /* Roxas.framework in Embed Frameworks */,
BF1614F2250822F100767AEA /* Roxas.framework in Embed Frameworks */, BF1614F2250822F100767AEA /* Roxas.framework in Embed Frameworks */,
BF66EE862501AE50007EE018 /* AltStoreCore.framework in Embed Frameworks */, BF66EE862501AE50007EE018 /* AltStoreCore.framework in Embed Frameworks */,
); );
@@ -499,50 +501,16 @@
/* End PBXCopyFilesBuildPhase section */ /* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
0E1A1F902AE36A9600364CAD /* bytearray.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = bytearray.c; path = src/bytearray.c; sourceTree = "<group>"; };
0E764E162ADFF5740043DD4E /* AltBackup.ipa */ = {isa = PBXFileReference; lastKnownFileType = file; name = AltBackup.ipa; path = AltStore/Resources/AltBackup.ipa; sourceTree = SOURCE_ROOT; };
0EA166412ADFE0D1003015C1 /* jplist.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = jplist.c; path = Dependencies/libplist/src/jplist.c; sourceTree = SOURCE_ROOT; };
0EA166422ADFE0D1003015C1 /* Date.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Date.cpp; path = Dependencies/libplist/src/Date.cpp; sourceTree = SOURCE_ROOT; };
0EA166432ADFE0D1003015C1 /* Data.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Data.cpp; path = Dependencies/libplist/src/Data.cpp; sourceTree = SOURCE_ROOT; };
0EA166442ADFE0D1003015C1 /* bplist.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = bplist.c; path = Dependencies/libplist/src/bplist.c; sourceTree = SOURCE_ROOT; };
0EA166452ADFE0D1003015C1 /* Array.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Array.cpp; path = Dependencies/libplist/src/Array.cpp; sourceTree = SOURCE_ROOT; };
0EA166462ADFE0D1003015C1 /* Dictionary.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Dictionary.cpp; path = Dependencies/libplist/src/Dictionary.cpp; sourceTree = SOURCE_ROOT; };
0EA166472ADFE0D1003015C1 /* out-limd.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = "out-limd.c"; path = "Dependencies/libplist/src/out-limd.c"; sourceTree = SOURCE_ROOT; };
0EA166492ADFE0D1003015C1 /* String.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = String.cpp; path = Dependencies/libplist/src/String.cpp; sourceTree = SOURCE_ROOT; };
0EA1664A2ADFE0D1003015C1 /* base64.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = base64.c; path = Dependencies/libplist/src/base64.c; sourceTree = SOURCE_ROOT; };
0EA1664B2ADFE0D1003015C1 /* Uid.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Uid.cpp; path = Dependencies/libplist/src/Uid.cpp; sourceTree = SOURCE_ROOT; };
0EA1664C2ADFE0D1003015C1 /* time64.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = time64.c; path = Dependencies/libplist/src/time64.c; sourceTree = SOURCE_ROOT; };
0EA1664E2ADFE0D1003015C1 /* Boolean.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Boolean.cpp; path = Dependencies/libplist/src/Boolean.cpp; sourceTree = SOURCE_ROOT; };
0EA1664F2ADFE0D1003015C1 /* hashtable.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = hashtable.c; path = Dependencies/libplist/src/hashtable.c; sourceTree = SOURCE_ROOT; };
0EA166502ADFE0D2003015C1 /* Node.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Node.cpp; path = Dependencies/libplist/src/Node.cpp; sourceTree = SOURCE_ROOT; };
0EA166512ADFE0D2003015C1 /* ptrarray.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = ptrarray.c; path = Dependencies/libplist/src/ptrarray.c; sourceTree = SOURCE_ROOT; };
0EA166522ADFE0D2003015C1 /* out-default.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = "out-default.c"; path = "Dependencies/libplist/src/out-default.c"; sourceTree = SOURCE_ROOT; };
0EA166532ADFE0D2003015C1 /* Integer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Integer.cpp; path = Dependencies/libplist/src/Integer.cpp; sourceTree = SOURCE_ROOT; };
0EA166542ADFE0D2003015C1 /* Real.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Real.cpp; path = Dependencies/libplist/src/Real.cpp; sourceTree = SOURCE_ROOT; };
0EA166552ADFE0D2003015C1 /* out-plutil.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = "out-plutil.c"; path = "Dependencies/libplist/src/out-plutil.c"; sourceTree = SOURCE_ROOT; };
0EA166562ADFE0D2003015C1 /* oplist.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = oplist.c; path = Dependencies/libplist/src/oplist.c; sourceTree = SOURCE_ROOT; };
0EA166572ADFE0D2003015C1 /* jsmn.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = jsmn.c; path = Dependencies/libplist/src/jsmn.c; sourceTree = SOURCE_ROOT; };
0EA166582ADFE0D2003015C1 /* Key.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Key.cpp; path = Dependencies/libplist/src/Key.cpp; sourceTree = SOURCE_ROOT; };
0EA166592ADFE0D2003015C1 /* xplist.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = xplist.c; path = Dependencies/libplist/src/xplist.c; sourceTree = SOURCE_ROOT; };
0EA1665A2ADFE0D2003015C1 /* Structure.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Structure.cpp; path = Dependencies/libplist/src/Structure.cpp; sourceTree = SOURCE_ROOT; };
0EA1665F2ADFE122003015C1 /* time64_limits.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = time64_limits.h; path = Dependencies/libplist/src/time64_limits.h; sourceTree = SOURCE_ROOT; };
0EA166602ADFE122003015C1 /* time64.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = time64.h; path = Dependencies/libplist/src/time64.h; sourceTree = SOURCE_ROOT; };
0EA166612ADFE122003015C1 /* bytearray.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = bytearray.h; path = Dependencies/libplist/src/bytearray.h; sourceTree = SOURCE_ROOT; };
0EA166622ADFE122003015C1 /* ptrarray.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ptrarray.h; path = Dependencies/libplist/src/ptrarray.h; sourceTree = SOURCE_ROOT; };
0EA166632ADFE122003015C1 /* jsmn.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jsmn.h; path = Dependencies/libplist/src/jsmn.h; sourceTree = SOURCE_ROOT; };
0EA166642ADFE122003015C1 /* plist.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = plist.h; path = Dependencies/libplist/src/plist.h; sourceTree = SOURCE_ROOT; };
0EA166652ADFE122003015C1 /* hashtable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = hashtable.h; path = Dependencies/libplist/src/hashtable.h; sourceTree = SOURCE_ROOT; };
0EA166662ADFE122003015C1 /* base64.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = base64.h; path = Dependencies/libplist/src/base64.h; sourceTree = SOURCE_ROOT; };
0EA166672ADFE122003015C1 /* strbuf.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = strbuf.h; path = Dependencies/libplist/src/strbuf.h; sourceTree = SOURCE_ROOT; };
0EA4B9BB2AE4A3F6009209CE /* plist.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = plist.c; path = Dependencies/libplist/src/plist.c; sourceTree = SOURCE_ROOT; };
19104DB22909C06C00C49C7B /* libEmotionalDamage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libEmotionalDamage.a; sourceTree = BUILT_PRODUCTS_DIR; }; 19104DB22909C06C00C49C7B /* libEmotionalDamage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libEmotionalDamage.a; sourceTree = BUILT_PRODUCTS_DIR; };
19104DB42909C06D00C49C7B /* EmotionalDamage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmotionalDamage.swift; sourceTree = "<group>"; }; 19104DB42909C06D00C49C7B /* EmotionalDamage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmotionalDamage.swift; sourceTree = "<group>"; };
191E5FAB290A5D92001A3B7C /* libminimuxer.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libminimuxer.a; sourceTree = BUILT_PRODUCTS_DIR; }; 191E5FAB290A5D92001A3B7C /* libminimuxer.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libminimuxer.a; sourceTree = BUILT_PRODUCTS_DIR; };
191E5FAD290A5D92001A3B7C /* minimuxer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = minimuxer.swift; sourceTree = "<group>"; };
191E5FB5290A5E1F001A3B7C /* libminimuxer.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libminimuxer.a; path = "Dependencies/minimuxer/target/aarch64-apple-ios/debug/libminimuxer.a"; sourceTree = "<group>"; };
191E5FCF290A651D001A3B7C /* jplist.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = jplist.c; path = Dependencies/libplist/src/jplist.c; sourceTree = SOURCE_ROOT; };
191E5FD0290A651D001A3B7C /* jsmn.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = jsmn.c; path = Dependencies/libplist/src/jsmn.c; sourceTree = SOURCE_ROOT; };
191E5FD1290A651D001A3B7C /* jsmn.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jsmn.h; path = Dependencies/libplist/src/jsmn.h; sourceTree = SOURCE_ROOT; };
1920B04E2924AC8300744F60 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; }; 1920B04E2924AC8300744F60 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; };
19B9B7442845E6DF0076EF69 /* SelectTeamViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectTeamViewController.swift; sourceTree = "<group>"; }; 19B9B7442845E6DF0076EF69 /* SelectTeamViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectTeamViewController.swift; sourceTree = "<group>"; };
9961EC2D29BE9F2E00AF2C6F /* minimuxer-helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "minimuxer-helpers.swift"; path = "Dependencies/minimuxer/minimuxer-helpers.swift"; sourceTree = SOURCE_ROOT; };
99F87D1629D8E4C900B40039 /* SwiftBridgeCore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SwiftBridgeCore.swift; path = Dependencies/minimuxer/SwiftBridgeCore.swift; sourceTree = SOURCE_ROOT; };
99F87D1729D8E4C900B40039 /* minimuxer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = minimuxer.swift; path = Dependencies/minimuxer/minimuxer.swift; sourceTree = SOURCE_ROOT; };
B3146EC6284F580500BBC3FD /* Roxas.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Roxas.xcodeproj; path = Dependencies/Roxas/Roxas.xcodeproj; sourceTree = "<group>"; }; B3146EC6284F580500BBC3FD /* Roxas.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Roxas.xcodeproj; path = Dependencies/Roxas/Roxas.xcodeproj; sourceTree = "<group>"; };
B33FFBA9295F8F78002259E6 /* preboard.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = preboard.c; path = src/preboard.c; sourceTree = "<group>"; }; B33FFBA9295F8F78002259E6 /* preboard.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = preboard.c; path = src/preboard.c; sourceTree = "<group>"; };
B33FFBAB295F8F98002259E6 /* companion_proxy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = companion_proxy.c; path = src/companion_proxy.c; sourceTree = "<group>"; }; B33FFBAB295F8F98002259E6 /* companion_proxy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = companion_proxy.c; path = src/companion_proxy.c; sourceTree = "<group>"; };
@@ -602,6 +570,7 @@
BF41B807233433C100C593A3 /* LoadingState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingState.swift; sourceTree = "<group>"; }; BF41B807233433C100C593A3 /* LoadingState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingState.swift; sourceTree = "<group>"; };
BF42345825101C1D006D1EB2 /* WidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WidgetView.swift; sourceTree = "<group>"; }; BF42345825101C1D006D1EB2 /* WidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WidgetView.swift; sourceTree = "<group>"; };
BF44EEEF246B08BA002A52F2 /* BackupController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupController.swift; sourceTree = "<group>"; }; BF44EEEF246B08BA002A52F2 /* BackupController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupController.swift; sourceTree = "<group>"; };
BF44EEF2246B3A17002A52F2 /* AltBackup.ipa */ = {isa = PBXFileReference; lastKnownFileType = file; path = AltBackup.ipa; sourceTree = "<group>"; };
BF44EEFB246B4550002A52F2 /* RemoveAppOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveAppOperation.swift; sourceTree = "<group>"; }; BF44EEFB246B4550002A52F2 /* RemoveAppOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveAppOperation.swift; sourceTree = "<group>"; };
BF45872B2298D31600BD7491 /* libimobiledevice.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libimobiledevice.a; sourceTree = BUILT_PRODUCTS_DIR; }; BF45872B2298D31600BD7491 /* libimobiledevice.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libimobiledevice.a; sourceTree = BUILT_PRODUCTS_DIR; };
BF4587C82298D3A800BD7491 /* service.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = service.h; path = Dependencies/libimobiledevice/src/service.h; sourceTree = SOURCE_ROOT; }; BF4587C82298D3A800BD7491 /* service.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = service.h; path = Dependencies/libimobiledevice/src/service.h; sourceTree = SOURCE_ROOT; };
@@ -758,6 +727,7 @@
BF9ABA4A22DD137F008935CF /* NavigationBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationBar.swift; sourceTree = "<group>"; }; BF9ABA4A22DD137F008935CF /* NavigationBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationBar.swift; sourceTree = "<group>"; };
BF9ABA4C22DD16DE008935CF /* PillButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillButton.swift; sourceTree = "<group>"; }; BF9ABA4C22DD16DE008935CF /* PillButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillButton.swift; sourceTree = "<group>"; };
BFA8172A23C5633D001B5953 /* FetchAnisetteDataOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchAnisetteDataOperation.swift; sourceTree = "<group>"; }; BFA8172A23C5633D001B5953 /* FetchAnisetteDataOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchAnisetteDataOperation.swift; sourceTree = "<group>"; };
BFB1169C22932DB100BB457C /* apps.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = apps.json; sourceTree = "<group>"; };
BFB39B5B252BC10E00D1BE50 /* Managed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Managed.swift; sourceTree = "<group>"; }; BFB39B5B252BC10E00D1BE50 /* Managed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Managed.swift; sourceTree = "<group>"; };
BFB4323E22DE852000B7F8BC /* UpdateCollectionViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = UpdateCollectionViewCell.xib; sourceTree = "<group>"; }; BFB4323E22DE852000B7F8BC /* UpdateCollectionViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = UpdateCollectionViewCell.xib; sourceTree = "<group>"; };
BFB6B21D231870160022A802 /* NewsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewsViewController.swift; sourceTree = "<group>"; }; BFB6B21D231870160022A802 /* NewsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewsViewController.swift; sourceTree = "<group>"; };
@@ -787,6 +757,34 @@
BFD2479E2284FBD000981D42 /* UIColor+AltStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+AltStore.swift"; sourceTree = "<group>"; }; BFD2479E2284FBD000981D42 /* UIColor+AltStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+AltStore.swift"; sourceTree = "<group>"; };
BFD44605241188C300EAB90A /* CodableServerError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodableServerError.swift; sourceTree = "<group>"; }; BFD44605241188C300EAB90A /* CodableServerError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodableServerError.swift; sourceTree = "<group>"; };
BFD52BD222A06EFB000B7ED1 /* ALTConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ALTConstants.h; sourceTree = "<group>"; }; BFD52BD222A06EFB000B7ED1 /* ALTConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ALTConstants.h; sourceTree = "<group>"; };
BFD52BE522A1A9CA000B7ED1 /* ptrarray.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ptrarray.c; path = Dependencies/libplist/src/ptrarray.c; sourceTree = SOURCE_ROOT; };
BFD52BE622A1A9CA000B7ED1 /* base64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = base64.c; path = Dependencies/libplist/src/base64.c; sourceTree = SOURCE_ROOT; };
BFD52BE722A1A9CA000B7ED1 /* hashtable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hashtable.c; path = Dependencies/libplist/src/hashtable.c; sourceTree = SOURCE_ROOT; };
BFD52BE822A1A9CA000B7ED1 /* Dictionary.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Dictionary.cpp; path = Dependencies/libplist/src/Dictionary.cpp; sourceTree = SOURCE_ROOT; };
BFD52BE922A1A9CA000B7ED1 /* ptrarray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ptrarray.h; path = Dependencies/libplist/src/ptrarray.h; sourceTree = SOURCE_ROOT; };
BFD52BEA22A1A9CA000B7ED1 /* bplist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = bplist.c; path = Dependencies/libplist/src/bplist.c; sourceTree = SOURCE_ROOT; };
BFD52BEB22A1A9CA000B7ED1 /* String.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = String.cpp; path = Dependencies/libplist/src/String.cpp; sourceTree = SOURCE_ROOT; };
BFD52BEC22A1A9CA000B7ED1 /* time64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = time64.c; path = Dependencies/libplist/src/time64.c; sourceTree = SOURCE_ROOT; };
BFD52BED22A1A9CA000B7ED1 /* plist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = plist.h; path = Dependencies/libplist/src/plist.h; sourceTree = SOURCE_ROOT; };
BFD52BEE22A1A9CA000B7ED1 /* plist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = plist.c; path = Dependencies/libplist/src/plist.c; sourceTree = SOURCE_ROOT; };
BFD52BEF22A1A9CA000B7ED1 /* hashtable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = hashtable.h; path = Dependencies/libplist/src/hashtable.h; sourceTree = SOURCE_ROOT; };
BFD52BF022A1A9CA000B7ED1 /* Date.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Date.cpp; path = Dependencies/libplist/src/Date.cpp; sourceTree = SOURCE_ROOT; };
BFD52BF122A1A9CA000B7ED1 /* Uid.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Uid.cpp; path = Dependencies/libplist/src/Uid.cpp; sourceTree = SOURCE_ROOT; };
BFD52BF222A1A9CA000B7ED1 /* Boolean.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Boolean.cpp; path = Dependencies/libplist/src/Boolean.cpp; sourceTree = SOURCE_ROOT; };
BFD52BF322A1A9CA000B7ED1 /* Real.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Real.cpp; path = Dependencies/libplist/src/Real.cpp; sourceTree = SOURCE_ROOT; };
BFD52BF422A1A9CA000B7ED1 /* strbuf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = strbuf.h; path = Dependencies/libplist/src/strbuf.h; sourceTree = SOURCE_ROOT; };
BFD52BF522A1A9CA000B7ED1 /* bytearray.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = bytearray.c; path = Dependencies/libplist/src/bytearray.c; sourceTree = SOURCE_ROOT; };
BFD52BF622A1A9CA000B7ED1 /* base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = base64.h; path = Dependencies/libplist/src/base64.h; sourceTree = SOURCE_ROOT; };
BFD52BF722A1A9CA000B7ED1 /* Data.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Data.cpp; path = Dependencies/libplist/src/Data.cpp; sourceTree = SOURCE_ROOT; };
BFD52BF822A1A9CB000B7ED1 /* Array.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Array.cpp; path = Dependencies/libplist/src/Array.cpp; sourceTree = SOURCE_ROOT; };
BFD52BF922A1A9CB000B7ED1 /* Node.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Node.cpp; path = Dependencies/libplist/src/Node.cpp; sourceTree = SOURCE_ROOT; };
BFD52BFA22A1A9CB000B7ED1 /* bytearray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bytearray.h; path = Dependencies/libplist/src/bytearray.h; sourceTree = SOURCE_ROOT; };
BFD52BFB22A1A9CB000B7ED1 /* Key.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Key.cpp; path = Dependencies/libplist/src/Key.cpp; sourceTree = SOURCE_ROOT; };
BFD52BFC22A1A9CB000B7ED1 /* Integer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Integer.cpp; path = Dependencies/libplist/src/Integer.cpp; sourceTree = SOURCE_ROOT; };
BFD52BFD22A1A9CB000B7ED1 /* Structure.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Structure.cpp; path = Dependencies/libplist/src/Structure.cpp; sourceTree = SOURCE_ROOT; };
BFD52BFE22A1A9CB000B7ED1 /* time64_limits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = time64_limits.h; path = Dependencies/libplist/src/time64_limits.h; sourceTree = SOURCE_ROOT; };
BFD52BFF22A1A9CB000B7ED1 /* time64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = time64.h; path = Dependencies/libplist/src/time64.h; sourceTree = SOURCE_ROOT; };
BFD52C0022A1A9CB000B7ED1 /* xplist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = xplist.c; path = Dependencies/libplist/src/xplist.c; sourceTree = SOURCE_ROOT; };
BFD52C1D22A1A9EC000B7ED1 /* node.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = node.c; path = Dependencies/libplist/libcnary/node.c; sourceTree = SOURCE_ROOT; }; BFD52C1D22A1A9EC000B7ED1 /* node.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = node.c; path = Dependencies/libplist/libcnary/node.c; sourceTree = SOURCE_ROOT; };
BFD52C1E22A1A9EC000B7ED1 /* node_list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = node_list.c; path = Dependencies/libplist/libcnary/node_list.c; sourceTree = SOURCE_ROOT; }; BFD52C1E22A1A9EC000B7ED1 /* node_list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = node_list.c; path = Dependencies/libplist/libcnary/node_list.c; sourceTree = SOURCE_ROOT; };
BFD52C1F22A1A9EC000B7ED1 /* cnary.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cnary.c; path = Dependencies/libplist/libcnary/cnary.c; sourceTree = SOURCE_ROOT; }; BFD52C1F22A1A9EC000B7ED1 /* cnary.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cnary.c; path = Dependencies/libplist/libcnary/cnary.c; sourceTree = SOURCE_ROOT; };
@@ -840,7 +838,6 @@
D57FE84328C7DB7100216002 /* ErrorLogViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorLogViewController.swift; sourceTree = "<group>"; }; D57FE84328C7DB7100216002 /* ErrorLogViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorLogViewController.swift; sourceTree = "<group>"; };
D58916FD28C7C55C00E39C8B /* LoggedError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggedError.swift; sourceTree = "<group>"; }; D58916FD28C7C55C00E39C8B /* LoggedError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggedError.swift; sourceTree = "<group>"; };
D593F1932717749A006E82DE /* PatchAppOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PatchAppOperation.swift; sourceTree = "<group>"; }; D593F1932717749A006E82DE /* PatchAppOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PatchAppOperation.swift; sourceTree = "<group>"; };
D5ACE84428E3B8450021CAB9 /* ClearAppCacheOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClearAppCacheOperation.swift; sourceTree = "<group>"; };
D5CA0C4A280E141900469595 /* ManagedPatron.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManagedPatron.swift; sourceTree = "<group>"; }; D5CA0C4A280E141900469595 /* ManagedPatron.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManagedPatron.swift; sourceTree = "<group>"; };
D5CA0C4C280E242500469595 /* AltStore 10.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "AltStore 10.xcdatamodel"; sourceTree = "<group>"; }; D5CA0C4C280E242500469595 /* AltStore 10.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "AltStore 10.xcdatamodel"; sourceTree = "<group>"; };
D5CA0C4D280E249E00469595 /* AltStore9ToAltStore10.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = AltStore9ToAltStore10.xcmappingmodel; sourceTree = "<group>"; }; D5CA0C4D280E249E00469595 /* AltStore9ToAltStore10.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = AltStore9ToAltStore10.xcmappingmodel; sourceTree = "<group>"; };
@@ -917,13 +914,13 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
B33FFBA8295F8E98002259E6 /* libfragmentzip.a in Frameworks */, B33FFBA8295F8E98002259E6 /* libfragmentzip.a in Frameworks */,
191E6087290C7B50001A3B7C /* libminimuxer.a in Frameworks */,
191E5FB4290A5DA0001A3B7C /* libminimuxer.a in Frameworks */, 191E5FB4290A5DA0001A3B7C /* libminimuxer.a in Frameworks */,
19104DBC2909C4E500C49C7B /* libEmotionalDamage.a in Frameworks */, 19104DBC2909C4E500C49C7B /* libEmotionalDamage.a in Frameworks */,
19104D952909BAEA00C49C7B /* libimobiledevice.a in Frameworks */, 19104D952909BAEA00C49C7B /* libimobiledevice.a in Frameworks */,
B3146ED2284F581E00BBC3FD /* Roxas.framework in Frameworks */, B3146ED2284F581E00BBC3FD /* Roxas.framework in Frameworks */,
D533E8B72727841800A9B5DD /* libAppleArchive.tbd in Frameworks */, D533E8B72727841800A9B5DD /* libAppleArchive.tbd in Frameworks */,
B3C395F9284F362400DA9E2F /* AppCenterCrashes in Frameworks */, B3C395F9284F362400DA9E2F /* AppCenterCrashes in Frameworks */,
9922FFEC29B501C50020F868 /* Starscream in Frameworks */,
D533E8BE2727BBF800A9B5DD /* libcurl.a in Frameworks */, D533E8BE2727BBF800A9B5DD /* libcurl.a in Frameworks */,
4879A9622861049C00FC1BBD /* OpenSSL in Frameworks */, 4879A9622861049C00FC1BBD /* OpenSSL in Frameworks */,
B3C395F4284F35DD00DA9E2F /* Nuke in Frameworks */, B3C395F4284F35DD00DA9E2F /* Nuke in Frameworks */,
@@ -948,9 +945,8 @@
191E5FAC290A5D92001A3B7C /* minimuxer */ = { 191E5FAC290A5D92001A3B7C /* minimuxer */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
9961EC2D29BE9F2E00AF2C6F /* minimuxer-helpers.swift */,
99F87D1429D8E3F100B40039 /* Generated */,
B343F847295F6321002B1159 /* minimuxer.xcodeproj */, B343F847295F6321002B1159 /* minimuxer.xcodeproj */,
191E5FAD290A5D92001A3B7C /* minimuxer.swift */,
); );
path = minimuxer; path = minimuxer;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -972,15 +968,6 @@
path = "libimobiledevice-glue/src"; path = "libimobiledevice-glue/src";
sourceTree = "<group>"; sourceTree = "<group>";
}; };
99F87D1429D8E3F100B40039 /* Generated */ = {
isa = PBXGroup;
children = (
99F87D1629D8E4C900B40039 /* SwiftBridgeCore.swift */,
99F87D1729D8E4C900B40039 /* minimuxer.swift */,
);
name = Generated;
sourceTree = "<group>";
};
B3146EC7284F580500BBC3FD /* Products */ = { B3146EC7284F580500BBC3FD /* Products */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -1193,41 +1180,37 @@
BF4588562298DC6D00BD7491 /* libplist */ = { BF4588562298DC6D00BD7491 /* libplist */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
0EA166462ADFE0D1003015C1 /* Dictionary.cpp */, BFD52BE622A1A9CA000B7ED1 /* base64.c */,
0E1A1F902AE36A9600364CAD /* bytearray.c */, BFD52BEA22A1A9CA000B7ED1 /* bplist.c */,
0EA166442ADFE0D1003015C1 /* bplist.c */, BFD52BF522A1A9CA000B7ED1 /* bytearray.c */,
0EA166432ADFE0D1003015C1 /* Data.cpp */, BFD52BE722A1A9CA000B7ED1 /* hashtable.c */,
0EA166422ADFE0D1003015C1 /* Date.cpp */, 191E5FCF290A651D001A3B7C /* jplist.c */,
0EA1664F2ADFE0D1003015C1 /* hashtable.c */, 191E5FD0290A651D001A3B7C /* jsmn.c */,
0EA166532ADFE0D2003015C1 /* Integer.cpp */, BFD52BEE22A1A9CA000B7ED1 /* plist.c */,
0EA166562ADFE0D2003015C1 /* oplist.c */, BFD52BE522A1A9CA000B7ED1 /* ptrarray.c */,
0EA166522ADFE0D2003015C1 /* out-default.c */, BFD52BEC22A1A9CA000B7ED1 /* time64.c */,
0EA166472ADFE0D1003015C1 /* out-limd.c */, BFD52C0022A1A9CB000B7ED1 /* xplist.c */,
0EA166552ADFE0D2003015C1 /* out-plutil.c */, BFD52BF822A1A9CB000B7ED1 /* Array.cpp */,
0EA166492ADFE0D1003015C1 /* String.cpp */, BFD52BF222A1A9CA000B7ED1 /* Boolean.cpp */,
0EA1665A2ADFE0D2003015C1 /* Structure.cpp */, BFD52BF722A1A9CA000B7ED1 /* Data.cpp */,
0EA166452ADFE0D1003015C1 /* Array.cpp */, BFD52BF022A1A9CA000B7ED1 /* Date.cpp */,
0EA1664A2ADFE0D1003015C1 /* base64.c */, BFD52BE822A1A9CA000B7ED1 /* Dictionary.cpp */,
0EA166572ADFE0D2003015C1 /* jsmn.c */, BFD52BFC22A1A9CB000B7ED1 /* Integer.cpp */,
0EA1664E2ADFE0D1003015C1 /* Boolean.cpp */, BFD52BFB22A1A9CB000B7ED1 /* Key.cpp */,
0EA4B9BB2AE4A3F6009209CE /* plist.c */, BFD52BF922A1A9CB000B7ED1 /* Node.cpp */,
0EA166412ADFE0D1003015C1 /* jplist.c */, BFD52BF322A1A9CA000B7ED1 /* Real.cpp */,
0EA166582ADFE0D2003015C1 /* Key.cpp */, BFD52BEB22A1A9CA000B7ED1 /* String.cpp */,
0EA166512ADFE0D2003015C1 /* ptrarray.c */, BFD52BFD22A1A9CB000B7ED1 /* Structure.cpp */,
0EA1664C2ADFE0D1003015C1 /* time64.c */, BFD52BF122A1A9CA000B7ED1 /* Uid.cpp */,
0EA166502ADFE0D2003015C1 /* Node.cpp */, BFD52BF622A1A9CA000B7ED1 /* base64.h */,
0EA166542ADFE0D2003015C1 /* Real.cpp */, BFD52BFA22A1A9CB000B7ED1 /* bytearray.h */,
0EA1664B2ADFE0D1003015C1 /* Uid.cpp */, BFD52BEF22A1A9CA000B7ED1 /* hashtable.h */,
0EA166592ADFE0D2003015C1 /* xplist.c */, 191E5FD1290A651D001A3B7C /* jsmn.h */,
0EA166662ADFE122003015C1 /* base64.h */, BFD52BED22A1A9CA000B7ED1 /* plist.h */,
0EA166652ADFE122003015C1 /* hashtable.h */, BFD52BE922A1A9CA000B7ED1 /* ptrarray.h */,
0EA166632ADFE122003015C1 /* jsmn.h */, BFD52BF422A1A9CA000B7ED1 /* strbuf.h */,
0EA166642ADFE122003015C1 /* plist.h */, BFD52BFE22A1A9CB000B7ED1 /* time64_limits.h */,
0EA166612ADFE122003015C1 /* bytearray.h */, BFD52BFF22A1A9CB000B7ED1 /* time64.h */,
0EA166622ADFE122003015C1 /* ptrarray.h */,
0EA166672ADFE122003015C1 /* strbuf.h */,
0EA1665F2ADFE122003015C1 /* time64_limits.h */,
0EA166602ADFE122003015C1 /* time64.h */,
BF4588892298DDEA00BD7491 /* libcnary */, BF4588892298DDEA00BD7491 /* libcnary */,
); );
path = libplist; path = libplist;
@@ -1584,6 +1567,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
B343F86C295F759E002B1159 /* libresolv.tbd */, B343F86C295F759E002B1159 /* libresolv.tbd */,
191E5FB5290A5E1F001A3B7C /* libminimuxer.a */,
B39575F4284F29E20080B4FF /* Roxas.framework */, B39575F4284F29E20080B4FF /* Roxas.framework */,
D533E8B62727841800A9B5DD /* libAppleArchive.tbd */, D533E8B62727841800A9B5DD /* libAppleArchive.tbd */,
BF580497246A3D19008AE704 /* UIKit.framework */, BF580497246A3D19008AE704 /* UIKit.framework */,
@@ -1624,7 +1608,8 @@
BFD247962284D7C100981D42 /* Resources */ = { BFD247962284D7C100981D42 /* Resources */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
0E764E162ADFF5740043DD4E /* AltBackup.ipa */, BF44EEF2246B3A17002A52F2 /* AltBackup.ipa */,
BFB1169C22932DB100BB457C /* apps.json */,
BFD247762284B9A700981D42 /* Assets.xcassets */, BFD247762284B9A700981D42 /* Assets.xcassets */,
BF770E6822BD57DD002A40FE /* Silence.m4a */, BF770E6822BD57DD002A40FE /* Silence.m4a */,
); );
@@ -1699,7 +1684,6 @@
D57F2C9026E0070200B9FA39 /* EnableJITOperation.swift */, D57F2C9026E0070200B9FA39 /* EnableJITOperation.swift */,
D5DAE0952804DF430034D8D4 /* UpdatePatronsOperation.swift */, D5DAE0952804DF430034D8D4 /* UpdatePatronsOperation.swift */,
D5E1E7C028077DE90016FC96 /* FetchTrustedSourcesOperation.swift */, D5E1E7C028077DE90016FC96 /* FetchTrustedSourcesOperation.swift */,
D5ACE84428E3B8450021CAB9 /* ClearAppCacheOperation.swift */,
BF7B44062725A4B8005288A4 /* Patch App */, BF7B44062725A4B8005288A4 /* Patch App */,
); );
path = Operations; path = Operations;
@@ -1782,30 +1766,43 @@
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */ /* Begin PBXHeadersBuildPhase section */
191E5FD4290A6EE0001A3B7C /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
BF4587272298D31600BD7491 /* Headers */ = { BF4587272298D31600BD7491 /* Headers */ = {
isa = PBXHeadersBuildPhase; isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
0EA166682ADFE122003015C1 /* jsmn.h in Headers */,
BF4588112298D3AB00BD7491 /* misagent.h in Headers */, BF4588112298D3AB00BD7491 /* misagent.h in Headers */,
BF4588042298D3AB00BD7491 /* lockdown.h in Headers */, BF4588042298D3AB00BD7491 /* lockdown.h in Headers */,
BF45880B2298D3AB00BD7491 /* mobilesync.h in Headers */, BF45880B2298D3AB00BD7491 /* mobilesync.h in Headers */,
BF4588002298D3AB00BD7491 /* restore.h in Headers */, BF4588002298D3AB00BD7491 /* restore.h in Headers */,
BF4588152298D3AB00BD7491 /* mobilebackup.h in Headers */, BF4588152298D3AB00BD7491 /* mobilebackup.h in Headers */,
BF4588182298D3AB00BD7491 /* syslog_relay.h in Headers */, BF4588182298D3AB00BD7491 /* syslog_relay.h in Headers */,
BFD52C1022A1A9CB000B7ED1 /* strbuf.h in Headers */,
BF45881D2298D3AB00BD7491 /* file_relay.h in Headers */, BF45881D2298D3AB00BD7491 /* file_relay.h in Headers */,
BFD52C0922A1A9CB000B7ED1 /* plist.h in Headers */,
BF4587FD2298D3AB00BD7491 /* sbservices.h in Headers */, BF4587FD2298D3AB00BD7491 /* sbservices.h in Headers */,
BF4588362298D3C100BD7491 /* debug.h in Headers */, BF4588362298D3C100BD7491 /* debug.h in Headers */,
BF4588202298D3AB00BD7491 /* mobile_image_mounter.h in Headers */, BF4588202298D3AB00BD7491 /* mobile_image_mounter.h in Headers */,
BF4588122298D3AB00BD7491 /* house_arrest.h in Headers */, BF4588122298D3AB00BD7491 /* house_arrest.h in Headers */,
BF45881F2298D3AB00BD7491 /* device_link_service.h in Headers */, BF45881F2298D3AB00BD7491 /* device_link_service.h in Headers */,
BFD52C1A22A1A9CB000B7ED1 /* time64_limits.h in Headers */,
BF45880E2298D3AB00BD7491 /* debugserver.h in Headers */, BF45880E2298D3AB00BD7491 /* debugserver.h in Headers */,
BF4588102298D3AB00BD7491 /* heartbeat.h in Headers */, BF4588102298D3AB00BD7491 /* heartbeat.h in Headers */,
BF4587FA2298D3AB00BD7491 /* diagnostics_relay.h in Headers */, BF4587FA2298D3AB00BD7491 /* diagnostics_relay.h in Headers */,
BFD52C1622A1A9CB000B7ED1 /* bytearray.h in Headers */,
BFD52C1222A1A9CB000B7ED1 /* base64.h in Headers */,
BF4588192298D3AB00BD7491 /* webinspector.h in Headers */, BF4588192298D3AB00BD7491 /* webinspector.h in Headers */,
BF4588342298D3C100BD7491 /* userpref.h in Headers */, BF4588342298D3C100BD7491 /* userpref.h in Headers */,
BF45880A2298D3AB00BD7491 /* screenshotr.h in Headers */, BF45880A2298D3AB00BD7491 /* screenshotr.h in Headers */,
BFD52C0B22A1A9CB000B7ED1 /* hashtable.h in Headers */,
BF4587FE2298D3AB00BD7491 /* mobilebackup2.h in Headers */, BF4587FE2298D3AB00BD7491 /* mobilebackup2.h in Headers */,
BFD52C0522A1A9CB000B7ED1 /* ptrarray.h in Headers */,
BF45881C2298D3AB00BD7491 /* afc.h in Headers */, BF45881C2298D3AB00BD7491 /* afc.h in Headers */,
BF45881A2298D3AB00BD7491 /* mobileactivation.h in Headers */, BF45881A2298D3AB00BD7491 /* mobileactivation.h in Headers */,
BF4588052298D3AB00BD7491 /* idevice.h in Headers */, BF4588052298D3AB00BD7491 /* idevice.h in Headers */,
@@ -1813,6 +1810,7 @@
BF4587F82298D3AB00BD7491 /* service.h in Headers */, BF4587F82298D3AB00BD7491 /* service.h in Headers */,
BF4588252298D3AB00BD7491 /* property_list_service.h in Headers */, BF4588252298D3AB00BD7491 /* property_list_service.h in Headers */,
BF4588132298D3AB00BD7491 /* notification_proxy.h in Headers */, BF4588132298D3AB00BD7491 /* notification_proxy.h in Headers */,
BFD52C1B22A1A9CB000B7ED1 /* time64.h in Headers */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -1855,6 +1853,7 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 191E5FAF290A5D92001A3B7C /* Build configuration list for PBXNativeTarget "minimuxer" */; buildConfigurationList = 191E5FAF290A5D92001A3B7C /* Build configuration list for PBXNativeTarget "minimuxer" */;
buildPhases = ( buildPhases = (
191E5FD4290A6EE0001A3B7C /* Headers */,
191E5FA7290A5D92001A3B7C /* Sources */, 191E5FA7290A5D92001A3B7C /* Sources */,
191E5FA8290A5D92001A3B7C /* Frameworks */, 191E5FA8290A5D92001A3B7C /* Frameworks */,
); );
@@ -1970,7 +1969,6 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = BFD2477E2284B9A700981D42 /* Build configuration list for PBXNativeTarget "SideStore" */; buildConfigurationList = BFD2477E2284B9A700981D42 /* Build configuration list for PBXNativeTarget "SideStore" */;
buildPhases = ( buildPhases = (
99F87D0629D8B51400B40039 /* ShellScript */,
BFD247662284B9A500981D42 /* Sources */, BFD247662284B9A500981D42 /* Sources */,
BFD247672284B9A500981D42 /* Frameworks */, BFD247672284B9A500981D42 /* Frameworks */,
BFD247682284B9A500981D42 /* Resources */, BFD247682284B9A500981D42 /* Resources */,
@@ -1992,7 +1990,6 @@
B3C395F6284F362400DA9E2F /* AppCenterAnalytics */, B3C395F6284F362400DA9E2F /* AppCenterAnalytics */,
B3C395F8284F362400DA9E2F /* AppCenterCrashes */, B3C395F8284F362400DA9E2F /* AppCenterCrashes */,
4879A9612861049C00FC1BBD /* OpenSSL */, 4879A9612861049C00FC1BBD /* OpenSSL */,
9922FFEB29B501C50020F868 /* Starscream */,
); );
productName = AltStore; productName = AltStore;
productReference = BFD2476A2284B9A500981D42 /* SideStore.app */; productReference = BFD2476A2284B9A500981D42 /* SideStore.app */;
@@ -2064,7 +2061,6 @@
4879A95D2861046500FC1BBD /* XCRemoteSwiftPackageReference "AltSign" */, 4879A95D2861046500FC1BBD /* XCRemoteSwiftPackageReference "AltSign" */,
4879A9602861049C00FC1BBD /* XCRemoteSwiftPackageReference "OpenSSL" */, 4879A9602861049C00FC1BBD /* XCRemoteSwiftPackageReference "OpenSSL" */,
99C4EF472978D52400CB538D /* XCRemoteSwiftPackageReference "SemanticVersion" */, 99C4EF472978D52400CB538D /* XCRemoteSwiftPackageReference "SemanticVersion" */,
9922FFEA29B501C50020F868 /* XCRemoteSwiftPackageReference "Starscream" */,
); );
productRefGroup = BFD2476B2284B9A500981D42 /* Products */; productRefGroup = BFD2476B2284B9A500981D42 /* Products */;
projectDirPath = ""; projectDirPath = "";
@@ -2208,6 +2204,7 @@
BFE60738231ADF49002B0E8E /* Settings.storyboard in Resources */, BFE60738231ADF49002B0E8E /* Settings.storyboard in Resources */,
D57DF638271E32F000677701 /* PatchApp.storyboard in Resources */, D57DF638271E32F000677701 /* PatchApp.storyboard in Resources */,
BFD2477A2284B9A700981D42 /* LaunchScreen.storyboard in Resources */, BFD2477A2284B9A700981D42 /* LaunchScreen.storyboard in Resources */,
BF44EEF3246B3A17002A52F2 /* AltBackup.ipa in Resources */,
BF770E6922BD57DD002A40FE /* Silence.m4a in Resources */, BF770E6922BD57DD002A40FE /* Silence.m4a in Resources */,
BFD247772284B9A700981D42 /* Assets.xcassets in Resources */, BFD247772284B9A700981D42 /* Assets.xcassets in Resources */,
1920B04F2924AC8300744F60 /* Settings.bundle in Resources */, 1920B04F2924AC8300744F60 /* Settings.bundle in Resources */,
@@ -2215,7 +2212,6 @@
BFB6B22423187A3D0022A802 /* NewsCollectionViewCell.xib in Resources */, BFB6B22423187A3D0022A802 /* NewsCollectionViewCell.xib in Resources */,
BFD247752284B9A500981D42 /* Main.storyboard in Resources */, BFD247752284B9A500981D42 /* Main.storyboard in Resources */,
BFDB5B2622EFBBEA00F74113 /* BrowseCollectionViewCell.xib in Resources */, BFDB5B2622EFBBEA00F74113 /* BrowseCollectionViewCell.xib in Resources */,
0E764E172ADFF5740043DD4E /* AltBackup.ipa in Resources */,
BFE6073C231AE1E7002B0E8E /* SettingsHeaderFooterView.xib in Resources */, BFE6073C231AE1E7002B0E8E /* SettingsHeaderFooterView.xib in Resources */,
BF29012F2318F6B100D88A45 /* AppBannerView.xib in Resources */, BF29012F2318F6B100D88A45 /* AppBannerView.xib in Resources */,
BFE6325A22A83BEB00F30809 /* Authentication.storyboard in Resources */, BFE6325A22A83BEB00F30809 /* Authentication.storyboard in Resources */,
@@ -2224,27 +2220,6 @@
}; };
/* End PBXResourcesBuildPhase section */ /* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
99F87D0629D8B51400B40039 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
outputFileListPaths = (
);
outputPaths = (
"./Dependencies/minimuxer/minimuxer-helpers.swift",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "bash ./Dependencies/fetch-prebuilt.sh minimuxer\n";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */
19104DAE2909C06C00C49C7B /* Sources */ = { 19104DAE2909C06C00C49C7B /* Sources */ = {
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
@@ -2258,8 +2233,7 @@
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
99F87D1929D8E4C900B40039 /* minimuxer.swift in Sources */, 191E5FAE290A5D92001A3B7C /* minimuxer.swift in Sources */,
99F87D1829D8E4C900B40039 /* SwiftBridgeCore.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -2291,73 +2265,69 @@
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
0E1A1F912AE36A9700364CAD /* bytearray.c in Sources */,
0EA1666E2ADFE140003015C1 /* ptrarray.c in Sources */,
0EA1665B2ADFE0D2003015C1 /* out-limd.c in Sources */,
0EA166742ADFE140003015C1 /* Date.cpp in Sources */,
0EA166712ADFE140003015C1 /* Key.cpp in Sources */,
0EA1665C2ADFE0D2003015C1 /* out-default.c in Sources */,
0EA1666A2ADFE140003015C1 /* String.cpp in Sources */,
0EA166732ADFE140003015C1 /* Dictionary.cpp in Sources */,
0EA1665D2ADFE0D2003015C1 /* out-plutil.c in Sources */,
0EA1665E2ADFE0D2003015C1 /* oplist.c in Sources */,
0EA166702ADFE140003015C1 /* Node.cpp in Sources */,
0EA166752ADFE140003015C1 /* Real.cpp in Sources */,
0EA166762ADFE140003015C1 /* base64.c in Sources */,
0EA1666D2ADFE140003015C1 /* Data.cpp in Sources */,
BF45881B2298D3AB00BD7491 /* house_arrest.c in Sources */, BF45881B2298D3AB00BD7491 /* house_arrest.c in Sources */,
0EA1666F2ADFE140003015C1 /* hashtable.c in Sources */, BFD52C0622A1A9CB000B7ED1 /* bplist.c in Sources */,
BF4588232298D3AB00BD7491 /* mobilesync.c in Sources */, BF4588232298D3AB00BD7491 /* mobilesync.c in Sources */,
BF4588072298D3AB00BD7491 /* afc.c in Sources */, BF4588072298D3AB00BD7491 /* afc.c in Sources */,
191E607D290B2EA5001A3B7C /* jsmn.c in Sources */,
191E607E290B2EA7001A3B7C /* jplist.c in Sources */,
BF4588082298D3AB00BD7491 /* mobile_image_mounter.c in Sources */, BF4588082298D3AB00BD7491 /* mobile_image_mounter.c in Sources */,
BFD52C1122A1A9CB000B7ED1 /* bytearray.c in Sources */,
BF4588022298D3AB00BD7491 /* file_relay.c in Sources */, BF4588022298D3AB00BD7491 /* file_relay.c in Sources */,
BF45880F2298D3AB00BD7491 /* debugserver.c in Sources */, BF45880F2298D3AB00BD7491 /* debugserver.c in Sources */,
0EA166792ADFE140003015C1 /* bplist.c in Sources */,
0EA166772ADFE140003015C1 /* jplist.c in Sources */,
BF4588162298D3AB00BD7491 /* restore.c in Sources */, BF4588162298D3AB00BD7491 /* restore.c in Sources */,
BFD52C0422A1A9CB000B7ED1 /* Dictionary.cpp in Sources */,
BFD52C0222A1A9CB000B7ED1 /* base64.c in Sources */,
BFD52C2022A1A9EC000B7ED1 /* node.c in Sources */, BFD52C2022A1A9EC000B7ED1 /* node.c in Sources */,
BF4588092298D3AB00BD7491 /* installation_proxy.c in Sources */, BF4588092298D3AB00BD7491 /* installation_proxy.c in Sources */,
0EA1666B2ADFE140003015C1 /* Boolean.cpp in Sources */,
0EA1667E2ADFE140003015C1 /* time64.c in Sources */,
BF4587FF2298D3AB00BD7491 /* heartbeat.c in Sources */, BF4587FF2298D3AB00BD7491 /* heartbeat.c in Sources */,
BF4588222298D3AB00BD7491 /* mobileactivation.c in Sources */, BF4588222298D3AB00BD7491 /* mobileactivation.c in Sources */,
BFD52C1822A1A9CB000B7ED1 /* Integer.cpp in Sources */,
BF4588212298D3AB00BD7491 /* idevice.c in Sources */, BF4588212298D3AB00BD7491 /* idevice.c in Sources */,
B343F885295F7C5D002B1159 /* tlv.c in Sources */, B343F885295F7C5D002B1159 /* tlv.c in Sources */,
BFD52C1C22A1A9CB000B7ED1 /* xplist.c in Sources */,
BF4587F92298D3AB00BD7491 /* diagnostics_relay.c in Sources */, BF4587F92298D3AB00BD7491 /* diagnostics_relay.c in Sources */,
B343F87D295F7C5D002B1159 /* cbuf.c in Sources */, B343F87D295F7C5D002B1159 /* cbuf.c in Sources */,
BF4588062298D3AB00BD7491 /* webinspector.c in Sources */, BF4588062298D3AB00BD7491 /* webinspector.c in Sources */,
BFD52C1722A1A9CB000B7ED1 /* Key.cpp in Sources */,
B343F883295F7C5D002B1159 /* thread.c in Sources */, B343F883295F7C5D002B1159 /* thread.c in Sources */,
BF45880D2298D3AB00BD7491 /* mobilebackup.c in Sources */, BF45880D2298D3AB00BD7491 /* mobilebackup.c in Sources */,
BFD52C0C22A1A9CB000B7ED1 /* Date.cpp in Sources */,
BFD52C0A22A1A9CB000B7ED1 /* plist.c in Sources */,
BFD52C1322A1A9CB000B7ED1 /* Data.cpp in Sources */,
BF45883A2298D3C100BD7491 /* debug.c in Sources */, BF45883A2298D3C100BD7491 /* debug.c in Sources */,
B343F881295F7C5D002B1159 /* termcolors.c in Sources */, B343F881295F7C5D002B1159 /* termcolors.c in Sources */,
0EA1667D2ADFE140003015C1 /* xplist.c in Sources */,
B343F87E295F7C5D002B1159 /* collection.c in Sources */, B343F87E295F7C5D002B1159 /* collection.c in Sources */,
BFD52C0F22A1A9CB000B7ED1 /* Real.cpp in Sources */,
B33FFBAA295F8F78002259E6 /* preboard.c in Sources */, B33FFBAA295F8F78002259E6 /* preboard.c in Sources */,
B33FFBAC295F8F98002259E6 /* companion_proxy.c in Sources */, B33FFBAC295F8F98002259E6 /* companion_proxy.c in Sources */,
BF4587FB2298D3AB00BD7491 /* notification_proxy.c in Sources */, BF4587FB2298D3AB00BD7491 /* notification_proxy.c in Sources */,
BF4588352298D3C100BD7491 /* userpref.c in Sources */, BF4588352298D3C100BD7491 /* userpref.c in Sources */,
0EA1667A2ADFE140003015C1 /* Uid.cpp in Sources */, BFD52C0122A1A9CB000B7ED1 /* ptrarray.c in Sources */,
B343F87C295F7C5D002B1159 /* opack.c in Sources */, B343F87C295F7C5D002B1159 /* opack.c in Sources */,
BFD52C0E22A1A9CB000B7ED1 /* Boolean.cpp in Sources */,
BFD52C0822A1A9CB000B7ED1 /* time64.c in Sources */,
B343F884295F7C5D002B1159 /* utils.c in Sources */, B343F884295F7C5D002B1159 /* utils.c in Sources */,
BFD52C2122A1A9EC000B7ED1 /* node_list.c in Sources */, BFD52C2122A1A9EC000B7ED1 /* node_list.c in Sources */,
B343F87F295F7C5D002B1159 /* glue.c in Sources */, B343F87F295F7C5D002B1159 /* glue.c in Sources */,
BFD52C1422A1A9CB000B7ED1 /* Array.cpp in Sources */,
BF4588242298D3AB00BD7491 /* property_list_service.c in Sources */, BF4588242298D3AB00BD7491 /* property_list_service.c in Sources */,
BF45881E2298D3AB00BD7491 /* misagent.c in Sources */, BF45881E2298D3AB00BD7491 /* misagent.c in Sources */,
0EA166692ADFE140003015C1 /* Array.cpp in Sources */,
B343F880295F7C5D002B1159 /* socket.c in Sources */, B343F880295F7C5D002B1159 /* socket.c in Sources */,
BF4587FC2298D3AB00BD7491 /* sbservices.c in Sources */, BF4587FC2298D3AB00BD7491 /* sbservices.c in Sources */,
0EA166782ADFE140003015C1 /* jsmn.c in Sources */, BFD52C1522A1A9CB000B7ED1 /* Node.cpp in Sources */,
BF4588142298D3AB00BD7491 /* device_link_service.c in Sources */, BF4588142298D3AB00BD7491 /* device_link_service.c in Sources */,
BF4588172298D3AB00BD7491 /* screenshotr.c in Sources */, BF4588172298D3AB00BD7491 /* screenshotr.c in Sources */,
BFD52C0D22A1A9CB000B7ED1 /* Uid.cpp in Sources */,
BFD52C0322A1A9CB000B7ED1 /* hashtable.c in Sources */,
BF4588432298D40000BD7491 /* libusbmuxd.c in Sources */, BF4588432298D40000BD7491 /* libusbmuxd.c in Sources */,
0EA1667B2ADFE140003015C1 /* Structure.cpp in Sources */,
0EA1666C2ADFE140003015C1 /* Integer.cpp in Sources */,
BF4588032298D3AB00BD7491 /* syslog_relay.c in Sources */, BF4588032298D3AB00BD7491 /* syslog_relay.c in Sources */,
BF4588272298D3AB00BD7491 /* service.c in Sources */, BF4588272298D3AB00BD7491 /* service.c in Sources */,
BFD52C0722A1A9CB000B7ED1 /* String.cpp in Sources */,
BF4588262298D3AB00BD7491 /* lockdown.c in Sources */, BF4588262298D3AB00BD7491 /* lockdown.c in Sources */,
BFD52C2222A1A9EC000B7ED1 /* cnary.c in Sources */, BFD52C2222A1A9EC000B7ED1 /* cnary.c in Sources */,
BF45880C2298D3AB00BD7491 /* mobilebackup2.c in Sources */, BF45880C2298D3AB00BD7491 /* mobilebackup2.c in Sources */,
0EA4B9BC2AE4A414009209CE /* plist.c in Sources */, BFD52C1922A1A9CB000B7ED1 /* Structure.cpp in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -2507,7 +2477,6 @@
BFD6B03322DFF20800B86064 /* MyAppsComponents.swift in Sources */, BFD6B03322DFF20800B86064 /* MyAppsComponents.swift in Sources */,
BF41B808233433C100C593A3 /* LoadingState.swift in Sources */, BF41B808233433C100C593A3 /* LoadingState.swift in Sources */,
BFF0B69A2322D7D0007A79E1 /* UIScreen+CompactHeight.swift in Sources */, BFF0B69A2322D7D0007A79E1 /* UIScreen+CompactHeight.swift in Sources */,
D5ACE84528E3B8450021CAB9 /* ClearAppCacheOperation.swift in Sources */,
D5F2F6A92720B7C20081CCF5 /* PatchViewController.swift in Sources */, D5F2F6A92720B7C20081CCF5 /* PatchViewController.swift in Sources */,
B39F16132918D7C5002E9404 /* Consts.swift in Sources */, B39F16132918D7C5002E9404 /* Consts.swift in Sources */,
BF8F69C222E659F700049BA1 /* AppContentViewController.swift in Sources */, BF8F69C222E659F700049BA1 /* AppContentViewController.swift in Sources */,
@@ -2515,7 +2484,6 @@
BFB39B5C252BC10E00D1BE50 /* Managed.swift in Sources */, BFB39B5C252BC10E00D1BE50 /* Managed.swift in Sources */,
BF770E5822BC3D0F002A40FE /* RefreshGroup.swift in Sources */, BF770E5822BC3D0F002A40FE /* RefreshGroup.swift in Sources */,
19B9B7452845E6DF0076EF69 /* SelectTeamViewController.swift in Sources */, 19B9B7452845E6DF0076EF69 /* SelectTeamViewController.swift in Sources */,
99F87D0529D8B4E200B40039 /* minimuxer-helpers.swift in Sources */,
BF18B0F122E25DF9005C4CF5 /* ToastView.swift in Sources */, BF18B0F122E25DF9005C4CF5 /* ToastView.swift in Sources */,
BF3D649F22E7B24C00E9056B /* CollapsingTextView.swift in Sources */, BF3D649F22E7B24C00E9056B /* CollapsingTextView.swift in Sources */,
BF02419622F2199300129732 /* RefreshAttemptsViewController.swift in Sources */, BF02419622F2199300129732 /* RefreshAttemptsViewController.swift in Sources */,
@@ -2705,7 +2673,7 @@
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OBJC_BRIDGING_HEADER = "Dependencies/minimuxer/minimuxer-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = Dependencies/minimuxer/minimuxer.h;
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
}; };
@@ -2727,7 +2695,7 @@
OTHER_LDFLAGS = "-ObjC"; OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SWIFT_OBJC_BRIDGING_HEADER = "Dependencies/minimuxer/minimuxer-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = Dependencies/minimuxer/minimuxer.h;
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
}; };
@@ -3225,10 +3193,9 @@
); );
LIBRARY_SEARCH_PATHS = ( LIBRARY_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)/Dependencies/libfragmentzip", "$(PROJECT_DIR)/Dependencies/fragmentzip",
"$(PROJECT_DIR)/Dependencies/libcurl", "$(PROJECT_DIR)/Dependencies/libcurl",
); );
OTHER_LDFLAGS = "";
PRODUCT_BUNDLE_IDENTIFIER = "$(PRODUCT_BUNDLE_IDENTIFIER)"; PRODUCT_BUNDLE_IDENTIFIER = "$(PRODUCT_BUNDLE_IDENTIFIER)";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@@ -3260,10 +3227,9 @@
); );
LIBRARY_SEARCH_PATHS = ( LIBRARY_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)/Dependencies/libfragmentzip", "$(PROJECT_DIR)/Dependencies/fragmentzip",
"$(PROJECT_DIR)/Dependencies/libcurl", "$(PROJECT_DIR)/Dependencies/libcurl",
); );
OTHER_LDFLAGS = "";
PRODUCT_BUNDLE_IDENTIFIER = "$(PRODUCT_BUNDLE_IDENTIFIER)"; PRODUCT_BUNDLE_IDENTIFIER = "$(PRODUCT_BUNDLE_IDENTIFIER)";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@@ -3377,14 +3343,6 @@
minimumVersion = 1.1.180; minimumVersion = 1.1.180;
}; };
}; };
9922FFEA29B501C50020F868 /* XCRemoteSwiftPackageReference "Starscream" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/daltoniam/Starscream.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 4.0.0;
};
};
99C4EF472978D52400CB538D /* XCRemoteSwiftPackageReference "SemanticVersion" */ = { 99C4EF472978D52400CB538D /* XCRemoteSwiftPackageReference "SemanticVersion" */ = {
isa = XCRemoteSwiftPackageReference; isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/SwiftPackageIndex/SemanticVersion.git"; repositoryURL = "https://github.com/SwiftPackageIndex/SemanticVersion.git";
@@ -3464,11 +3422,6 @@
package = 4879A9602861049C00FC1BBD /* XCRemoteSwiftPackageReference "OpenSSL" */; package = 4879A9602861049C00FC1BBD /* XCRemoteSwiftPackageReference "OpenSSL" */;
productName = OpenSSL; productName = OpenSSL;
}; };
9922FFEB29B501C50020F868 /* Starscream */ = {
isa = XCSwiftPackageProductDependency;
package = 9922FFEA29B501C50020F868 /* XCRemoteSwiftPackageReference "Starscream" */;
productName = Starscream;
};
99C4EF4C2979132100CB538D /* SemanticVersion */ = { 99C4EF4C2979132100CB538D /* SemanticVersion */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
package = 99C4EF472978D52400CB538D /* XCRemoteSwiftPackageReference "SemanticVersion" */; package = 99C4EF472978D52400CB538D /* XCRemoteSwiftPackageReference "SemanticVersion" */;

View File

@@ -6,7 +6,7 @@
"location" : "https://github.com/SideStore/AltSign", "location" : "https://github.com/SideStore/AltSign",
"state" : { "state" : {
"branch" : "master", "branch" : "master",
"revision" : "cc6189f0f7cd8e5bd24943af9322e0ff9420e9f4" "revision" : "7e0e7edcf8fbc44ac1e35da3e9030a297aa18b84"
} }
}, },
{ {
@@ -14,17 +14,8 @@
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",
"location" : "https://github.com/microsoft/appcenter-sdk-apple.git", "location" : "https://github.com/microsoft/appcenter-sdk-apple.git",
"state" : { "state" : {
"revision" : "b2dc99cfedead0bad4e6573d86c5228c89cff332", "revision" : "8354a50fe01a7e54e196d3b5493b5ab53dd5866a",
"version" : "4.4.3" "version" : "4.4.2"
}
},
{
"identity" : "imobiledevice.swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/SideStore/iMobileDevice.swift",
"state" : {
"revision" : "74e481106dd155c0cd21bca6795fd9fe5f751654",
"version" : "1.0.5"
} }
}, },
{ {
@@ -59,8 +50,8 @@
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",
"location" : "https://github.com/krzyzanowskim/OpenSSL", "location" : "https://github.com/krzyzanowskim/OpenSSL",
"state" : { "state" : {
"revision" : "0faf71a188bcfdf0245cab42886b9b240ca71c52", "revision" : "033fcb41dac96b1b6effa945ca1f9ade002370b2",
"version" : "1.1.2200" "version" : "1.1.1501"
} }
}, },
{ {
@@ -68,8 +59,8 @@
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",
"location" : "https://github.com/microsoft/PLCrashReporter.git", "location" : "https://github.com/microsoft/PLCrashReporter.git",
"state" : { "state" : {
"revision" : "81cdec2b3827feb03286cb297f4c501a8eb98df1", "revision" : "6b27393cad517c067dceea85fadf050e70c4ceaa",
"version" : "1.10.2" "version" : "1.10.1"
} }
}, },
{ {
@@ -77,8 +68,8 @@
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",
"location" : "https://github.com/SwiftPackageIndex/SemanticVersion.git", "location" : "https://github.com/SwiftPackageIndex/SemanticVersion.git",
"state" : { "state" : {
"revision" : "a70840d5fca686ae3bd2fcf8aecc5ded0bd4f125", "revision" : "fc670910dc0903cc269b3d0b776cda5703979c4e",
"version" : "0.3.6" "version" : "0.3.5"
} }
}, },
{ {
@@ -86,17 +77,8 @@
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",
"location" : "https://github.com/sparkle-project/Sparkle.git", "location" : "https://github.com/sparkle-project/Sparkle.git",
"state" : { "state" : {
"revision" : "f0ceaf5cc9f3f23daa0ccb6dcebd79fc96ccc7d9", "revision" : "286edd1fa22505a9e54d170e9fd07d775ea233f2",
"version" : "2.5.0" "version" : "2.1.0"
}
},
{
"identity" : "starscream",
"kind" : "remoteSourceControl",
"location" : "https://github.com/daltoniam/Starscream.git",
"state" : {
"revision" : "ac6c0fc9da221873e01bd1a0d4818498a71eef33",
"version" : "4.0.6"
} }
}, },
{ {

View File

@@ -218,7 +218,7 @@ final class AppViewController: UIViewController
self._shouldResetLayout = false self._shouldResetLayout = false
} }
let statusBarHeight = self.view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0 let statusBarHeight = UIApplication.shared.statusBarFrame.height
let cornerRadius = self.contentViewControllerShadowView.layer.cornerRadius let cornerRadius = self.contentViewControllerShadowView.layer.cornerRadius
let inset = 12 as CGFloat let inset = 12 as CGFloat
@@ -323,7 +323,7 @@ final class AppViewController: UIViewController
self.backButtonContainerView.layer.cornerRadius = self.backButtonContainerView.bounds.midY self.backButtonContainerView.layer.cornerRadius = self.backButtonContainerView.bounds.midY
self.scrollView.verticalScrollIndicatorInsets.top = statusBarHeight self.scrollView.scrollIndicatorInsets.top = statusBarHeight
// Adjust content offset + size. // Adjust content offset + size.
let contentOffset = self.scrollView.contentOffset let contentOffset = self.scrollView.contentOffset

View File

@@ -93,18 +93,11 @@ private extension AppIDsViewController
let currentDate = Date() let currentDate = Date()
let formatter = DateComponentsFormatter() let numberOfDays = expirationDate.numberOfCalendarDays(since: currentDate)
formatter.unitsStyle = .full let numberOfDaysText = (numberOfDays == 1) ? NSLocalizedString("1 day", comment: "") : String(format: NSLocalizedString("%@ days", comment: ""), NSNumber(value: numberOfDays))
formatter.includesApproximationPhrase = false cell.bannerView.button.setTitle(numberOfDaysText.uppercased(), for: .normal)
formatter.includesTimeRemainingPhrase = false
formatter.allowedUnits = [.minute, .hour, .day]
formatter.maximumUnitCount = 1
cell.bannerView.button.setTitle((formatter.string(from: currentDate, to: expirationDate) ?? NSLocalizedString("Unknown", comment: "")).uppercased(), for: .normal) attributedAccessibilityLabel.mutableString.append(String(format: NSLocalizedString("Expires in %@.", comment: ""), numberOfDaysText) + " ")
// formatter.includesTimeRemainingPhrase = true
// attributedAccessibilityLabel.mutableString.append((formatter.string(from: currentDate, to: expirationDate) ?? NSLocalizedString("Unknown", comment: "")) + " ")
} }
else else
{ {

View File

@@ -8,7 +8,6 @@
import UIKit import UIKit
import minimuxer
import AltStoreCore import AltStoreCore
import Roxas import Roxas
@@ -266,12 +265,6 @@ private extension BrowseViewController
return return
} }
if !minimuxer.ready() {
let toastView = ToastView(error: MinimuxerError.NoConnection)
toastView.show(in: self)
return
}
_ = AppManager.shared.install(app, presentingViewController: self) { (result) in _ = AppManager.shared.install(app, presentingViewController: self) { (result) in
DispatchQueue.main.async { DispatchQueue.main.async {
switch result switch result

View File

@@ -22,7 +22,7 @@ final class CollapsingTextView: UITextView
} }
} }
var lineSpacing: Double = 2 { var lineSpacing: CGFloat = 2 {
didSet { didSet {
self.setNeedsLayout() self.setNeedsLayout()
} }
@@ -34,19 +34,7 @@ final class CollapsingTextView: UITextView
{ {
super.awakeFromNib() super.awakeFromNib()
self.initialize()
}
private func initialize()
{
if #available(iOS 16, *)
{
self.updateText()
}
else
{
self.layoutManager.delegate = self self.layoutManager.delegate = self
}
self.textContainerInset = .zero self.textContainerInset = .zero
self.textContainer.lineFragmentPadding = 0 self.textContainer.lineFragmentPadding = 0
@@ -120,25 +108,6 @@ private extension CollapsingTextView
{ {
self.isCollapsed.toggle() self.isCollapsed.toggle()
} }
@available(iOS 16, *)
func updateText()
{
do
{
let style = NSMutableParagraphStyle()
style.lineSpacing = self.lineSpacing
var attributedText = try AttributedString(self.attributedText, including: \.uiKit)
attributedText[AttributeScopes.UIKitAttributes.ParagraphStyleAttribute.self] = style
self.attributedText = NSAttributedString(attributedText)
}
catch
{
print("[ALTLog] Failed to update CollapsingTextView line spacing:", error)
}
}
} }
extension CollapsingTextView: NSLayoutManagerDelegate extension CollapsingTextView: NSLayoutManagerDelegate

View File

@@ -8,12 +8,6 @@
import UIKit import UIKit
extension PillButton
{
static let minimumSize = CGSize(width: 77, height: 31)
static let contentInsets = NSDirectionalEdgeInsets(top: 7, leading: 13, bottom: 7, trailing: 13)
}
final class PillButton: UIButton final class PillButton: UIButton
{ {
override var accessibilityValue: String? { override var accessibilityValue: String? {
@@ -76,7 +70,9 @@ final class PillButton: UIButton
}() }()
override var intrinsicContentSize: CGSize { override var intrinsicContentSize: CGSize {
let size = self.sizeThatFits(CGSize(width: Double.infinity, height: .infinity)) var size = super.intrinsicContentSize
size.width += 26
size.height += 3
return size return size
} }
@@ -92,8 +88,6 @@ final class PillButton: UIButton
self.layer.masksToBounds = true self.layer.masksToBounds = true
self.accessibilityTraits.formUnion([.updatesFrequently, .button]) self.accessibilityTraits.formUnion([.updatesFrequently, .button])
self.contentEdgeInsets = UIEdgeInsets(top: Self.contentInsets.top, left: Self.contentInsets.leading, bottom: Self.contentInsets.bottom, right: Self.contentInsets.trailing)
self.activityIndicatorView.style = .medium self.activityIndicatorView.style = .medium
self.activityIndicatorView.isUserInteractionEnabled = false self.activityIndicatorView.isUserInteractionEnabled = false
@@ -125,15 +119,6 @@ final class PillButton: UIButton
self.update() self.update()
} }
override func sizeThatFits(_ size: CGSize) -> CGSize
{
var size = super.sizeThatFits(size)
size.width = max(size.width, PillButton.minimumSize.width)
size.height = max(size.height, PillButton.minimumSize.height)
return size
}
} }
private extension PillButton private extension PillButton

View File

@@ -14,7 +14,7 @@
<key>ALTPairingFile</key> <key>ALTPairingFile</key>
<string>&lt;insert pairing file here&gt;</string> <string>&lt;insert pairing file here&gt;</string>
<key>ALTAnisetteURL</key> <key>ALTAnisetteURL</key>
<string>https://ani.sidestore.io</string> <string>https://sideloadly.io/anisette/irGb3Quww8zrhgqnzmrx</string>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string> <string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDocumentTypes</key> <key>CFBundleDocumentTypes</key>

View File

@@ -14,8 +14,6 @@ import minimuxer
import AltStoreCore import AltStoreCore
import UniformTypeIdentifiers import UniformTypeIdentifiers
let pairingFileName = "ALTPairingFile.mobiledevicepairing"
final class LaunchViewController: RSTLaunchViewController, UIDocumentPickerDelegate final class LaunchViewController: RSTLaunchViewController, UIDocumentPickerDelegate
{ {
private var didFinishLaunching = false private var didFinishLaunching = false
@@ -81,7 +79,7 @@ final class LaunchViewController: RSTLaunchViewController, UIDocumentPickerDeleg
} else { } else {
// Show an alert explaining the pairing file // Show an alert explaining the pairing file
// Create new Alert // Create new Alert
let dialogMessage = UIAlertController(title: "Pairing File", message: "Select the pairing file for your device. For more information, go to https://wiki.sidestore.io/guides/getting-started/#pairing-file", preferredStyle: .alert) let dialogMessage = UIAlertController(title: "Pairing File", message: "Select the pairing file for your device. For more information, go to https://wiki.sidestore.io/guides/install#pairing-process", preferredStyle: .alert)
// Create OK button with action handler // Create OK button with action handler
let ok = UIAlertAction(title: "OK", style: .default, handler: { (action) -> Void in let ok = UIAlertAction(title: "OK", style: .default, handler: { (action) -> Void in
@@ -127,11 +125,14 @@ final class LaunchViewController: RSTLaunchViewController, UIDocumentPickerDeleg
} }
// Save to a file for next launch // Save to a file for next launch
let pairingFile = FileManager.default.documentsDirectory.appendingPathComponent("\(pairingFileName)") let filename = "ALTPairingFile.mobiledevicepairing"
try pairing_string?.write(to: pairingFile, atomically: true, encoding: String.Encoding.utf8) let fm = FileManager.default
let documentsPath = fm.documentsDirectory.appendingPathComponent("/\(filename)")
try pairing_string?.write(to: documentsPath, atomically: true, encoding: String.Encoding.utf8)
// Start minimuxer now that we have a file // Start minimuxer now that we have a file
start_minimuxer_threads(pairing_string!) start_minimuxer_threads(pairing_string!)
} catch { } catch {
displayError("Unable to read pairing file") displayError("Unable to read pairing file")
} }
@@ -147,20 +148,22 @@ final class LaunchViewController: RSTLaunchViewController, UIDocumentPickerDeleg
} }
func start_minimuxer_threads(_ pairing_file: String) { func start_minimuxer_threads(_ pairing_file: String) {
target_minimuxer_address() set_usbmuxd_socket()
let documentsDirectory = FileManager.default.documentsDirectory.absoluteString #if false // Retries
do { var res = start_minimuxer(pairing_file: pairing_file)
try start(pairing_file, documentsDirectory) var attempts = 10
} catch { while (attempts != 0 && res != 0) {
try! FileManager.default.removeItem(at: FileManager.default.documentsDirectory.appendingPathComponent("\(pairingFileName)")) print("start_minimuxer `res` != 0, retry #\(attempts)")
displayError("minimuxer failed to start, please restart SideStore. \((error as? LocalizedError)?.failureReason ?? "UNKNOWN ERROR!!!!!! REPORT TO GITHUB ISSUES!")") res = start_minimuxer(pairing_file: pairing_file)
attempts -= 1
} }
if #available(iOS 17, *) { #else
// TODO: iOS 17 and above have a new JIT implementation that is completely broken in SideStore :( let res = start_minimuxer(pairing_file: pairing_file)
} #endif
else { if res != 0 {
start_auto_mounter(documentsDirectory) displayError("minimuxer failed to start. Incorrect arguments were passed.")
} }
auto_mount_dev_image()
} }
} }

View File

@@ -307,16 +307,6 @@ extension AppManager
presentingViewController.present(alertController, animated: true, completion: nil) presentingViewController.present(alertController, animated: true, completion: nil)
} }
} }
func clearAppCache(completion: @escaping (Result<Void, Error>) -> Void)
{
let clearAppCacheOperation = ClearAppCacheOperation()
clearAppCacheOperation.resultHandler = { result in
completion(result)
}
self.run([clearAppCacheOperation], context: nil)
}
} }
extension AppManager extension AppManager
@@ -764,12 +754,6 @@ extension AppManager
let progress = self.refreshProgress[app.bundleIdentifier] let progress = self.refreshProgress[app.bundleIdentifier]
return progress return progress
} }
func isActivelyManagingApp(withBundleID bundleID: String) -> Bool
{
let isActivelyManaging = self.installationProgress.keys.contains(bundleID) || self.refreshProgress.keys.contains(bundleID)
return isActivelyManaging
}
} }
extension AppManager extension AppManager
@@ -824,6 +808,12 @@ private extension AppManager
} }
} }
func isActivelyManagingApp(withBundleID bundleID: String) -> Bool
{
let isActivelyManaging = self.installationProgress.keys.contains(bundleID) || self.refreshProgress.keys.contains(bundleID)
return isActivelyManaging
}
@discardableResult @discardableResult
private func perform(_ operations: [AppOperation], presentingViewController: UIViewController?, group: RefreshGroup) -> RefreshGroup private func perform(_ operations: [AppOperation], presentingViewController: UIViewController?, group: RefreshGroup) -> RefreshGroup
{ {
@@ -886,9 +876,7 @@ private extension AppManager
if app.certificateSerialNumber != group.context.certificate?.serialNumber || if app.certificateSerialNumber != group.context.certificate?.serialNumber ||
uti != nil || uti != nil ||
app.needsResign || app.needsResign
// We need to reinstall ourselves on refresh to ensure the new provisioning profile is used
app.bundleIdentifier == StoreApp.altstoreAppID
{ {
// Resign app instead of just refreshing profiles because either: // Resign app instead of just refreshing profiles because either:
// * Refreshing using different certificate // * Refreshing using different certificate
@@ -958,13 +946,7 @@ private extension AppManager
} }
else else
{ {
DispatchQueue.main.schedule {
UIApplication.shared.isIdleTimerDisabled = UserDefaults.standard.isIdleTimeoutDisableEnabled
}
performAppOperations() performAppOperations()
DispatchQueue.main.schedule {
UIApplication.shared.isIdleTimerDisabled = false
}
} }
return group return group
@@ -1043,32 +1025,6 @@ private extension AppManager
verifyOperation.addDependency(downloadOperation) verifyOperation.addDependency(downloadOperation)
/* Refresh Anisette Data */
let refreshAnisetteDataOperation = FetchAnisetteDataOperation(context: group.context)
refreshAnisetteDataOperation.resultHandler = { (result) in
switch result
{
case .failure(let error): context.error = error
case .success(let anisetteData): group.context.session?.anisetteData = anisetteData
}
}
refreshAnisetteDataOperation.addDependency(verifyOperation)
/* Fetch Provisioning Profiles */
let fetchProvisioningProfilesOperation = FetchProvisioningProfilesOperation(context: context)
fetchProvisioningProfilesOperation.additionalEntitlements = additionalEntitlements
fetchProvisioningProfilesOperation.resultHandler = { (result) in
switch result
{
case .failure(let error): context.error = error
case .success(let provisioningProfiles): context.provisioningProfiles = provisioningProfiles
}
}
fetchProvisioningProfilesOperation.addDependency(refreshAnisetteDataOperation)
progress.addChild(fetchProvisioningProfilesOperation.progress, withPendingUnitCount: 5)
/* Deactivate Apps (if necessary) */ /* Deactivate Apps (if necessary) */
let deactivateAppsOperation = RSTAsyncBlockOperation { [weak self] (operation) in let deactivateAppsOperation = RSTAsyncBlockOperation { [weak self] (operation) in
do do
@@ -1085,12 +1041,6 @@ private extension AppManager
throw error throw error
} }
guard let profiles = context.provisioningProfiles else { throw OperationError.invalidParameters }
if !profiles.contains(where: { $1.isFreeProvisioningProfile == true }) {
operation.finish()
return
}
guard let app = context.app, let presentingViewController = context.authenticatedContext.presentingViewController else { throw OperationError.invalidParameters } guard let app = context.app, let presentingViewController = context.authenticatedContext.presentingViewController else { throw OperationError.invalidParameters }
self?.deactivateApps(for: app, presentingViewController: presentingViewController) { result in self?.deactivateApps(for: app, presentingViewController: presentingViewController) { result in
@@ -1109,7 +1059,7 @@ private extension AppManager
operation.finish() operation.finish()
} }
} }
deactivateAppsOperation.addDependency(fetchProvisioningProfilesOperation) deactivateAppsOperation.addDependency(verifyOperation)
/* Patch App */ /* Patch App */
@@ -1184,6 +1134,32 @@ private extension AppManager
patchAppOperation.addDependency(deactivateAppsOperation) patchAppOperation.addDependency(deactivateAppsOperation)
/* Refresh Anisette Data */
let refreshAnisetteDataOperation = FetchAnisetteDataOperation(context: group.context)
refreshAnisetteDataOperation.resultHandler = { (result) in
switch result
{
case .failure(let error): context.error = error
case .success(let anisetteData): group.context.session?.anisetteData = anisetteData
}
}
refreshAnisetteDataOperation.addDependency(patchAppOperation)
/* Fetch Provisioning Profiles */
let fetchProvisioningProfilesOperation = FetchProvisioningProfilesOperation(context: context)
fetchProvisioningProfilesOperation.additionalEntitlements = additionalEntitlements
fetchProvisioningProfilesOperation.resultHandler = { (result) in
switch result
{
case .failure(let error): context.error = error
case .success(let provisioningProfiles): context.provisioningProfiles = provisioningProfiles
}
}
fetchProvisioningProfilesOperation.addDependency(refreshAnisetteDataOperation)
progress.addChild(fetchProvisioningProfilesOperation.progress, withPendingUnitCount: 5)
/* Resign */ /* Resign */
let resignAppOperation = ResignAppOperation(context: context) let resignAppOperation = ResignAppOperation(context: context)
resignAppOperation.resultHandler = { (result) in resignAppOperation.resultHandler = { (result) in
@@ -1193,7 +1169,7 @@ private extension AppManager
case .success(let resignedApp): context.resignedApp = resignedApp case .success(let resignedApp): context.resignedApp = resignedApp
} }
} }
resignAppOperation.addDependency(patchAppOperation) resignAppOperation.addDependency(fetchProvisioningProfilesOperation)
progress.addChild(resignAppOperation.progress, withPendingUnitCount: 20) progress.addChild(resignAppOperation.progress, withPendingUnitCount: 20)
@@ -1236,7 +1212,7 @@ private extension AppManager
progress.addChild(installOperation.progress, withPendingUnitCount: 30) progress.addChild(installOperation.progress, withPendingUnitCount: 30)
installOperation.addDependency(sendAppOperation) installOperation.addDependency(sendAppOperation)
let operations = [downloadOperation, verifyOperation, refreshAnisetteDataOperation, fetchProvisioningProfilesOperation, deactivateAppsOperation, patchAppOperation, resignAppOperation, sendAppOperation, installOperation] let operations = [downloadOperation, verifyOperation, deactivateAppsOperation, patchAppOperation, refreshAnisetteDataOperation, fetchProvisioningProfilesOperation, resignAppOperation, sendAppOperation, installOperation]
group.add(operations) group.add(operations)
self.run(operations, context: group.context) self.run(operations, context: group.context)

View File

@@ -10,12 +10,10 @@ import UIKit
import MobileCoreServices import MobileCoreServices
import Intents import Intents
import Combine import Combine
import UniformTypeIdentifiers
import AltStoreCore import AltStoreCore
import AltSign import AltSign
import Roxas import Roxas
import minimuxer
import Nuke import Nuke
@@ -329,25 +327,21 @@ private extension MyAppsViewController
let currentDate = Date() let currentDate = Date()
let numberOfDays = installedApp.expirationDate.numberOfCalendarDays(since: currentDate) let numberOfDays = installedApp.expirationDate.numberOfCalendarDays(since: currentDate)
let numberOfDaysText: String
let formatter = DateComponentsFormatter() if numberOfDays == 1
formatter.unitsStyle = .full {
formatter.includesApproximationPhrase = false numberOfDaysText = NSLocalizedString("1 day", comment: "")
formatter.includesTimeRemainingPhrase = false }
else
formatter.allowedUnits = [.day, .hour, .minute] {
numberOfDaysText = String(format: NSLocalizedString("%@ days", comment: ""), NSNumber(value: numberOfDays))
formatter.maximumUnitCount = 1 }
cell.bannerView.button.setTitle(formatter.string(from: currentDate, to: installedApp.expirationDate)?.uppercased(), for: .normal)
cell.bannerView.button.setTitle(numberOfDaysText.uppercased(), for: .normal)
cell.bannerView.button.accessibilityLabel = String(format: NSLocalizedString("Refresh %@", comment: ""), installedApp.name) cell.bannerView.button.accessibilityLabel = String(format: NSLocalizedString("Refresh %@", comment: ""), installedApp.name)
formatter.includesTimeRemainingPhrase = true cell.bannerView.accessibilityLabel? += ". " + String(format: NSLocalizedString("Expires in %@", comment: ""), numberOfDaysText)
cell.bannerView.accessibilityLabel? += ". " + (formatter.string(from: currentDate, to: installedApp.expirationDate) ?? NSLocalizedString("Unknown", comment: "")) + " "
// Make sure refresh button is correct size. // Make sure refresh button is correct size.
cell.layoutIfNeeded() cell.layoutIfNeeded()
@@ -645,12 +639,6 @@ private extension MyAppsViewController
@IBAction func refreshAllApps(_ sender: UIBarButtonItem) @IBAction func refreshAllApps(_ sender: UIBarButtonItem)
{ {
if !minimuxer.ready() {
let toastView = ToastView(error: MinimuxerError.NoConnection)
toastView.show(in: self)
return
}
self.isRefreshingAllApps = true self.isRefreshingAllApps = true
self.collectionView.collectionViewLayout.invalidateLayout() self.collectionView.collectionViewLayout.invalidateLayout()
@@ -713,15 +701,18 @@ private extension MyAppsViewController
@IBAction func sideloadApp(_ sender: UIBarButtonItem) @IBAction func sideloadApp(_ sender: UIBarButtonItem)
{ {
if !minimuxer.ready() { let supportedTypes: [String]
let toastView = ToastView(error: MinimuxerError.NoConnection)
toastView.show(in: self) if let types = UTTypeCreateAllIdentifiersForTag(kUTTagClassFilenameExtension, "ipa" as CFString, nil)?.takeRetainedValue()
return {
supportedTypes = (types as NSArray).map { $0 as! String }
}
else
{
supportedTypes = ["com.apple.itunes.ipa"] // Declared by the system.
} }
let supportedTypes = UTType.types(tag: "ipa", tagClass: .filenameExtension, conformingTo: nil) let documentPickerViewController = UIDocumentPickerViewController(documentTypes: supportedTypes, in: .import)
let documentPickerViewController = UIDocumentPickerViewController(forOpeningContentTypes: supportedTypes, asCopy: true)
documentPickerViewController.delegate = self documentPickerViewController.delegate = self
self.present(documentPickerViewController, animated: true, completion: nil) self.present(documentPickerViewController, animated: true, completion: nil)
} }
@@ -1023,12 +1014,6 @@ private extension MyAppsViewController
func refresh(_ installedApp: InstalledApp) func refresh(_ installedApp: InstalledApp)
{ {
if !minimuxer.ready() {
let toastView = ToastView(error: MinimuxerError.NoConnection)
toastView.show(in: self)
return
}
let previousProgress = AppManager.shared.refreshProgress(for: installedApp) let previousProgress = AppManager.shared.refreshProgress(for: installedApp)
guard previousProgress == nil else { guard previousProgress == nil else {
previousProgress?.cancel() previousProgress?.cancel()
@@ -1050,12 +1035,6 @@ private extension MyAppsViewController
func activate(_ installedApp: InstalledApp) func activate(_ installedApp: InstalledApp)
{ {
if !minimuxer.ready() {
let toastView = ToastView(error: MinimuxerError.NoConnection)
toastView.show(in: self)
return
}
func finish(_ result: Result<InstalledApp, Error>) func finish(_ result: Result<InstalledApp, Error>)
{ {
do do
@@ -1132,11 +1111,6 @@ private extension MyAppsViewController
func deactivate(_ installedApp: InstalledApp, completionHandler: ((Result<InstalledApp, Error>) -> Void)? = nil) func deactivate(_ installedApp: InstalledApp, completionHandler: ((Result<InstalledApp, Error>) -> Void)? = nil)
{ {
guard installedApp.isActive else { return } guard installedApp.isActive else { return }
if !minimuxer.ready() {
let toastView = ToastView(error: MinimuxerError.NoConnection)
toastView.show(in: self)
return
}
installedApp.isActive = false installedApp.isActive = false
AppManager.shared.deactivate(installedApp, presentingViewController: self) { (result) in AppManager.shared.deactivate(installedApp, presentingViewController: self) { (result) in
@@ -1198,11 +1172,6 @@ private extension MyAppsViewController
func backup(_ installedApp: InstalledApp) func backup(_ installedApp: InstalledApp)
{ {
if !minimuxer.ready() {
let toastView = ToastView(error: MinimuxerError.NoConnection)
toastView.show(in: self)
return
}
let title = NSLocalizedString("Start Backup?", comment: "") let title = NSLocalizedString("Start Backup?", comment: "")
let message = NSLocalizedString("This will replace any previous backups. Please leave SideStore open until the backup is complete.", comment: "") let message = NSLocalizedString("This will replace any previous backups. Please leave SideStore open until the backup is complete.", comment: "")
@@ -1242,11 +1211,6 @@ private extension MyAppsViewController
func restore(_ installedApp: InstalledApp) func restore(_ installedApp: InstalledApp)
{ {
if !minimuxer.ready() {
let toastView = ToastView(error: MinimuxerError.NoConnection)
toastView.show(in: self)
return
}
let message = String(format: NSLocalizedString("This will replace all data you currently have in %@.", comment: ""), installedApp.name) let message = String(format: NSLocalizedString("This will replace all data you currently have in %@.", comment: ""), installedApp.name)
let alertController = UIAlertController(title: NSLocalizedString("Are you sure you want to restore this backup?", comment: ""), message: message, preferredStyle: .actionSheet) let alertController = UIAlertController(title: NSLocalizedString("Are you sure you want to restore this backup?", comment: ""), message: message, preferredStyle: .actionSheet)
alertController.addAction(.cancel) alertController.addAction(.cancel)
@@ -1282,11 +1246,8 @@ private extension MyAppsViewController
{ {
guard let backupURL = FileManager.default.backupDirectoryURL(for: installedApp) else { return } guard let backupURL = FileManager.default.backupDirectoryURL(for: installedApp) else { return }
let documentPicker = UIDocumentPickerViewController(forExporting: [backupURL], asCopy: true) let documentPicker = UIDocumentPickerViewController(url: backupURL, in: .exportToService)
documentPicker.delegate = self
// Don't set delegate to avoid conflicting with import callbacks.
// documentPicker.delegate = self
self.present(documentPicker, animated: true, completion: nil) self.present(documentPicker, animated: true, completion: nil)
} }
@@ -1350,16 +1311,6 @@ private extension MyAppsViewController
@available(iOS 14, *) @available(iOS 14, *)
func enableJIT(for installedApp: InstalledApp) func enableJIT(for installedApp: InstalledApp)
{ {
if #available(iOS 17, *) {
let toastView = ToastView(error: OperationError.tooNewError)
toastView.show(in: self)
return
}
if !minimuxer.ready() {
let toastView = ToastView(error: MinimuxerError.NoConnection)
toastView.show(in: self)
return
}
AppManager.shared.enableJIT(for: installedApp) { result in AppManager.shared.enableJIT(for: installedApp) { result in
DispatchQueue.main.async { DispatchQueue.main.async {
switch result switch result
@@ -1367,7 +1318,7 @@ private extension MyAppsViewController
case .success: break case .success: break
case .failure(let error): case .failure(let error):
let toastView = ToastView(error: error) let toastView = ToastView(error: error)
toastView.show(in: self.navigationController?.view ?? self.view, duration: 5) toastView.show(in: self)
} }
} }
} }
@@ -1514,7 +1465,7 @@ extension MyAppsViewController
let registeredAppIDs = team.appIDs.count let registeredAppIDs = team.appIDs.count
let maximumAppIDCount = 10 let maximumAppIDCount = 10
let remainingAppIDs = maximumAppIDCount - registeredAppIDs let remainingAppIDs = max(maximumAppIDCount - registeredAppIDs, 0)
if remainingAppIDs == 1 if remainingAppIDs == 1
{ {
@@ -1525,7 +1476,7 @@ extension MyAppsViewController
footerView.textLabel.text = String(format: NSLocalizedString("%@ App IDs Remaining", comment: ""), NSNumber(value: remainingAppIDs)) footerView.textLabel.text = String(format: NSLocalizedString("%@ App IDs Remaining", comment: ""), NSNumber(value: remainingAppIDs))
} }
footerView.textLabel.isHidden = remainingAppIDs < 0 footerView.textLabel.isHidden = false
case .individual, .organization, .unknown: footerView.textLabel.isHidden = true case .individual, .organization, .unknown: footerView.textLabel.isHidden = true
@unknown default: break @unknown default: break
@@ -2099,9 +2050,16 @@ extension MyAppsViewController: UIDocumentPickerDelegate
{ {
guard let fileURL = urls.first else { return } guard let fileURL = urls.first else { return }
switch controller.documentPickerMode
{
case .import, .open:
self.sideloadApp(at: fileURL) { (result) in self.sideloadApp(at: fileURL) { (result) in
print("Sideloaded app at \(fileURL) with result:", result) print("Sideloaded app at \(fileURL) with result:", result)
} }
case .exportToService, .moveToService: break
@unknown default: break
}
} }
} }

View File

@@ -426,10 +426,6 @@ extension NewsViewController: UICollectionViewDelegateFlowLayout
return previousSize return previousSize
} }
// Take layout margins into account.
self.prototypeCell.layoutMargins.left = self.view.layoutMargins.left
self.prototypeCell.layoutMargins.right = self.view.layoutMargins.right
let widthConstraint = self.prototypeCell.contentView.widthAnchor.constraint(equalToConstant: collectionView.bounds.width) let widthConstraint = self.prototypeCell.contentView.widthAnchor.constraint(equalToConstant: collectionView.bounds.width)
NSLayoutConstraint.activate([widthConstraint]) NSLayoutConstraint.activate([widthConstraint])
defer { NSLayoutConstraint.deactivate([widthConstraint]) } defer { NSLayoutConstraint.deactivate([widthConstraint]) }

View File

@@ -12,7 +12,6 @@ import Network
import AltStoreCore import AltStoreCore
import AltSign import AltSign
import minimuxer
enum AuthenticationError: LocalizedError enum AuthenticationError: LocalizedError
{ {
@@ -594,7 +593,7 @@ private extension AuthenticationOperation
func registerCurrentDevice(for team: ALTTeam, session: ALTAppleAPISession, completionHandler: @escaping (Result<ALTDevice, Error>) -> Void) func registerCurrentDevice(for team: ALTTeam, session: ALTAppleAPISession, completionHandler: @escaping (Result<ALTDevice, Error>) -> Void)
{ {
guard let udid = fetch_udid()?.toString() else { guard let udid = Bundle.main.object(forInfoDictionaryKey: Bundle.Info.deviceID) as? String else {
return completionHandler(.failure(OperationError.unknownUDID)) return completionHandler(.failure(OperationError.unknownUDID))
} }

View File

@@ -11,7 +11,6 @@ import CoreData
import AltStoreCore import AltStoreCore
import EmotionalDamage import EmotionalDamage
import minimuxer
enum RefreshError: LocalizedError enum RefreshError: LocalizedError
{ {
@@ -98,19 +97,6 @@ final class BackgroundRefreshAppsOperation: ResultOperation<[String: Result<Inst
return return
} }
start_em_proxy(bind_addr: Consts.Proxy.serverURL) start_em_proxy(bind_addr: Consts.Proxy.serverURL)
target_minimuxer_address()
let documentsDirectory = FileManager.default.documentsDirectory.absoluteString
do {
try minimuxer.start(try String(contentsOf: FileManager.default.documentsDirectory.appendingPathComponent("\(pairingFileName)")), documentsDirectory)
} catch {
self.finish(.failure(error))
}
if #available(iOS 17, *) {
// TODO: iOS 17 and above have a new JIT implementation that is completely broken in SideStore :(
}
else {
start_auto_mounter(documentsDirectory)
}
self.managedObjectContext.perform { self.managedObjectContext.perform {
print("Apps to refresh:", self.installedApps.map(\.bundleIdentifier)) print("Apps to refresh:", self.installedApps.map(\.bundleIdentifier))

View File

@@ -29,9 +29,6 @@ class BackupAppOperation: ResultOperation<Void>
private var appName: String? private var appName: String?
private var timeoutTimer: Timer? private var timeoutTimer: Timer?
private weak var applicationWillReturnObserver: NSObjectProtocol?
private weak var backupResponseObserver: NSObjectProtocol?
init(action: Action, context: InstallAppOperationContext) init(action: Action, context: InstallAppOperationContext)
{ {
self.action = action self.action = action
@@ -46,7 +43,10 @@ class BackupAppOperation: ResultOperation<Void>
do do
{ {
if let error = self.context.error { throw error } if let error = self.context.error
{
throw error
}
guard let installedApp = self.context.installedApp, let context = installedApp.managedObjectContext else { throw OperationError.invalidParameters } guard let installedApp = self.context.installedApp, let context = installedApp.managedObjectContext else { throw OperationError.invalidParameters }
context.perform { context.perform {
@@ -55,7 +55,8 @@ class BackupAppOperation: ResultOperation<Void>
let appName = installedApp.name let appName = installedApp.name
self.appName = appName self.appName = appName
let altstoreOpenURL = URL(string: "sidestore://")! guard let altstoreApp = InstalledApp.fetchAltStore(in: context) else { throw OperationError.appNotFound }
let altstoreOpenURL = altstoreApp.openAppURL
var returnURLComponents = URLComponents(url: altstoreOpenURL, resolvingAgainstBaseURL: false) var returnURLComponents = URLComponents(url: altstoreOpenURL, resolvingAgainstBaseURL: false)
returnURLComponents?.host = "appBackupResponse" returnURLComponents?.host = "appBackupResponse"
@@ -152,11 +153,8 @@ private extension BackupAppOperation
{ {
func registerObservers() func registerObservers()
{ {
self.applicationWillReturnObserver = NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification, object: nil, queue: .main) { [weak self] (notification) in var applicationWillReturnObserver: NSObjectProtocol!
defer { applicationWillReturnObserver = NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification, object: nil, queue: .main) { [weak self] (notification) in
self?.applicationWillReturnObserver.map { NotificationCenter.default.removeObserver($0) }
}
guard let self = self, !self.isFinished else { return } guard let self = self, !self.isFinished else { return }
self.timeoutTimer = Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { [weak self] (timer) in self.timeoutTimer = Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { [weak self] (timer) in
@@ -168,17 +166,18 @@ private extension BackupAppOperation
self.finish(.failure(OperationError.timedOut)) self.finish(.failure(OperationError.timedOut))
} }
} }
NotificationCenter.default.removeObserver(applicationWillReturnObserver!)
} }
self.backupResponseObserver = NotificationCenter.default.addObserver(forName: AppDelegate.appBackupDidFinish, object: nil, queue: nil) { [weak self] (notification) in var backupResponseObserver: NSObjectProtocol!
defer { backupResponseObserver = NotificationCenter.default.addObserver(forName: AppDelegate.appBackupDidFinish, object: nil, queue: nil) { [weak self] (notification) in
self?.backupResponseObserver.map { NotificationCenter.default.removeObserver($0) }
}
self?.timeoutTimer?.invalidate() self?.timeoutTimer?.invalidate()
let result = notification.userInfo?[AppDelegate.appBackupResultKey] as? Result<Void, Error> ?? .failure(OperationError.unknownResult) let result = notification.userInfo?[AppDelegate.appBackupResultKey] as? Result<Void, Error> ?? .failure(OperationError.unknownResult)
self?.finish(result) self?.finish(result)
NotificationCenter.default.removeObserver(backupResponseObserver!)
} }
} }
} }

View File

@@ -1,208 +0,0 @@
//
// ClearAppCacheOperation.swift
// AltStore
//
// Created by Riley Testut on 9/27/22.
// Copyright © 2022 Riley Testut. All rights reserved.
//
import Foundation
import AltStoreCore
/*
struct BatchError: ALTLocalizedError
{
enum Code: Int, ALTErrorCode
{
typealias Error = BatchError
case batchError
}
var code: Code = .batchError
var underlyingErrors: [Error]
var errorTitle: String?
var errorFailure: String?
init(errors: [Error])
{
self.underlyingErrors = errors
}
var errorFailureReason: String {
guard !self.underlyingErrors.isEmpty else { return NSLocalizedString("An unknown error occured.", comment: "") }
let errorMessages = self.underlyingErrors.map { $0.localizedDescription }
let message = errorMessages.joined(separator: "\n\n")
return message
}
}
*/
@objc(ClearAppCacheOperation)
class ClearAppCacheOperation: ResultOperation<Void>
{
private let coordinator = NSFileCoordinator()
private let coordinatorQueue = OperationQueue()
override init()
{
self.coordinatorQueue.name = "AltStore - ClearAppCacheOperation Queue"
}
override func main()
{
super.main()
var allErrors = [Error]()
self.clearTemporaryDirectory { result in
switch result
{
//case .failure(let batchError as BatchError): allErrors.append(contentsOf: batchError.underlyingErrors)
case .failure(let error): allErrors.append(error)
case .success: break
}
self.removeUninstalledAppBackupDirectories { result in
switch result
{
//case .failure(let batchError as BatchError): allErrors.append(contentsOf: batchError.underlyingErrors)
case .failure(let error): allErrors.append(error)
case .success: break
}
if allErrors.isEmpty
{
self.finish(.success(()))
}
else
{
self.finish(.failure(OperationError.cacheClearError(errors: allErrors.map({ error in
return error.localizedDescription
}))))
}
}
}
}
}
private extension ClearAppCacheOperation
{
func clearTemporaryDirectory(completion: @escaping (Result<Void, Error>) -> Void)
{
let intent = NSFileAccessIntent.writingIntent(with: FileManager.default.temporaryDirectory, options: [.forDeleting])
self.coordinator.coordinate(with: [intent], queue: self.coordinatorQueue) { (error) in
do
{
if let error
{
throw error
}
let fileURLs = try FileManager.default.contentsOfDirectory(at: intent.url,
includingPropertiesForKeys: [],
options: [.skipsSubdirectoryDescendants, .skipsHiddenFiles])
var errors = [Error]()
for fileURL in fileURLs
{
do
{
print("[ALTLog] Removing item from temporary directory:", fileURL.lastPathComponent)
try FileManager.default.removeItem(at: fileURL)
}
catch
{
print("[ALTLog] Failed to remove \(fileURL.lastPathComponent) from temporary directory.", error)
errors.append(error)
}
}
if !errors.isEmpty
{
completion(.failure(OperationError.cacheClearError(errors: errors.map({ error in
return error.localizedDescription
}))))
}
else
{
completion(.success(()))
}
}
catch
{
completion(.failure(error))
}
}
}
func removeUninstalledAppBackupDirectories(completion: @escaping (Result<Void, Error>) -> Void)
{
guard let backupsDirectory = FileManager.default.appBackupsDirectory else { return completion(.failure(OperationError.missingAppGroup)) }
DatabaseManager.shared.persistentContainer.performBackgroundTask { context in
let installedAppBundleIDs = Set(InstalledApp.all(in: context).map { $0.bundleIdentifier })
let intent = NSFileAccessIntent.writingIntent(with: backupsDirectory, options: [.forDeleting])
self.coordinator.coordinate(with: [intent], queue: self.coordinatorQueue) { (error) in
do
{
if let error
{
throw error
}
var isDirectory: ObjCBool = false
guard FileManager.default.fileExists(atPath: intent.url.path, isDirectory: &isDirectory), isDirectory.boolValue else {
completion(.success(()))
return
}
let fileURLs = try FileManager.default.contentsOfDirectory(at: intent.url,
includingPropertiesForKeys: [.isDirectoryKey, .nameKey],
options: [.skipsSubdirectoryDescendants, .skipsHiddenFiles])
var errors = [Error]()
for backupDirectory in fileURLs
{
do
{
let resourceValues = try backupDirectory.resourceValues(forKeys: [.isDirectoryKey, .nameKey])
guard let isDirectory = resourceValues.isDirectory, let bundleID = resourceValues.name else { continue }
if isDirectory && !installedAppBundleIDs.contains(bundleID) && !AppManager.shared.isActivelyManagingApp(withBundleID: bundleID)
{
print("[ALTLog] Removing backup directory for uninstalled app:", bundleID)
try FileManager.default.removeItem(at: backupDirectory)
}
}
catch
{
print("[ALTLog] Failed to remove app backup directory:", error)
errors.append(error)
}
}
if !errors.isEmpty
{
completion(.failure(OperationError.cacheClearError(errors: errors.map({ error in
return error.localizedDescription
}))))
}
else
{
completion(.success(()))
}
}
catch
{
print("[ALTLog] Failed to remove app backup directory:", error)
completion(.failure(error))
}
}
}
}
}

View File

@@ -31,7 +31,11 @@ final class DeactivateAppOperation: ResultOperation<InstalledApp>
{ {
super.main() super.main()
if let error = self.context.error { return self.finish(.failure(error)) } if let error = self.context.error
{
self.finish(.failure(error))
return
}
DatabaseManager.shared.persistentContainer.performBackgroundTask { (context) in DatabaseManager.shared.persistentContainer.performBackgroundTask { (context) in
let installedApp = context.object(with: self.app.objectID) as! InstalledApp let installedApp = context.object(with: self.app.objectID) as! InstalledApp
@@ -40,15 +44,20 @@ final class DeactivateAppOperation: ResultOperation<InstalledApp>
for profile in allIdentifiers { for profile in allIdentifiers {
do { do {
try remove_provisioning_profile(profile) let res = try remove_provisioning_profile(id: profile)
if case Uhoh.Bad(let code) = res {
self.finish(.failure(minimuxer_to_operation(code: code)))
}
} catch Uhoh.Bad(let code) {
self.finish(.failure(minimuxer_to_operation(code: code)))
} catch {
self.finish(.failure(ALTServerError(.unknownResponse)))
}
}
self.progress.completedUnitCount += 1 self.progress.completedUnitCount += 1
installedApp.isActive = false installedApp.isActive = false
self.finish(.success(installedApp)) self.finish(.success(installedApp))
break
} catch {
self.finish(.failure(error))
}
}
} }
} }
} }

View File

@@ -45,19 +45,23 @@ final class EnableJITOperation<Context: EnableJITContext>: ResultOperation<Void>
guard let installedApp = self.context.installedApp else { return self.finish(.failure(OperationError.invalidParameters)) } guard let installedApp = self.context.installedApp else { return self.finish(.failure(OperationError.invalidParameters)) }
installedApp.managedObjectContext?.perform { installedApp.managedObjectContext?.perform {
var retries = 3 let v = minimuxer_to_operation(code: 1)
while (retries > 0){
do { do {
try debug_app(installedApp.resignedBundleIdentifier) var x = try debug_app(app_id: installedApp.resignedBundleIdentifier)
switch x {
case .Good:
self.finish(.success(())) self.finish(.success(()))
retries = 0 case .Bad(let code):
self.finish(.failure(minimuxer_to_operation(code: code)))
}
} catch Uhoh.Bad(let code) {
self.finish(.failure(minimuxer_to_operation(code: code)))
} catch { } catch {
retries -= 1 self.finish(.failure(OperationError.unknown))
if (retries <= 0){ }
self.finish(.failure(error))
}
}
}
} }
} }
} }

View File

@@ -7,28 +7,15 @@
// //
import Foundation import Foundation
import CommonCrypto
import Starscream
import AltStoreCore import AltStoreCore
import AltSign import AltSign
import Roxas import Roxas
@objc(FetchAnisetteDataOperation) @objc(FetchAnisetteDataOperation)
final class FetchAnisetteDataOperation: ResultOperation<ALTAnisetteData>, WebSocketDelegate final class FetchAnisetteDataOperation: ResultOperation<ALTAnisetteData>
{ {
let context: OperationContext let context: OperationContext
var socket: WebSocket!
var url: URL?
var startProvisioningURL: URL?
var endProvisioningURL: URL?
var clientInfo: String?
var userAgent: String?
var mdLu: String?
var deviceId: String?
init(context: OperationContext) init(context: OperationContext)
{ {
@@ -45,412 +32,32 @@ final class FetchAnisetteDataOperation: ResultOperation<ALTAnisetteData>, WebSoc
return return
} }
self.url = AnisetteManager.currentURL let url = AnisetteManager.currentURL
print("Anisette URL: \(self.url!.absoluteString)") DLOG("Anisette URL: %@", url.absoluteString)
if let identifier = Keychain.shared.identifier, let task = URLSession.shared.dataTask(with: url) { data, response, error in
let adiPb = Keychain.shared.adiPb { guard let data = data, error == nil else { return }
fetchAnisetteV3(identifier, adiPb)
} else {
provision()
}
}
// MARK: - COMMON do {
func extractAnisetteData(_ data: Data, _ response: HTTPURLResponse?, v3: Bool) throws {
// make sure this JSON is in the format we expect // make sure this JSON is in the format we expect
// convert data to json // convert data to json
if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: String] { if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: String] {
if v3 {
if json["result"] == "GetHeadersError" {
let message = json["message"]
print("Error getting V3 headers: \(message ?? "no message")")
if let message = message,
message.contains("-45061") {
print("Error message contains -45061 (not provisioned), resetting adi.pb and retrying")
Keychain.shared.adiPb = nil
return provision()
} else { throw OperationError.anisetteV3Error(message: message ?? "Unknown error") }
}
}
// try to read out a dictionary // try to read out a dictionary
//for some reason serial number isn't needed but it doesn't work unless it has a value //for some reason serial number isn't needed but it doesn't work unless it has a value
var formattedJSON: [String: String] = ["deviceSerialNumber": "0"] let formattedJSON: [String: String] = ["machineID": json["X-Apple-I-MD-M"]!, "oneTimePassword": json["X-Apple-I-MD"]!, "localUserID": json["X-Apple-I-MD-LU"]!, "routingInfo": json["X-Apple-I-MD-RINFO"]!, "deviceUniqueIdentifier": json["X-Mme-Device-Id"]!, "deviceDescription": json["X-MMe-Client-Info"]!, "date": json["X-Apple-I-Client-Time"]!, "locale": json["X-Apple-Locale"]!, "timeZone": json["X-Apple-I-TimeZone"]!, "deviceSerialNumber": "1"]
if let machineID = json["X-Apple-I-MD-M"] { formattedJSON["machineID"] = machineID }
if let oneTimePassword = json["X-Apple-I-MD"] { formattedJSON["oneTimePassword"] = oneTimePassword }
if let routingInfo = json["X-Apple-I-MD-RINFO"] { formattedJSON["routingInfo"] = routingInfo }
if v3 {
formattedJSON["deviceDescription"] = self.clientInfo!
formattedJSON["localUserID"] = self.mdLu!
formattedJSON["deviceUniqueIdentifier"] = self.deviceId!
// Generate date stuff on client
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.calendar = Calendar(identifier: .gregorian)
formatter.timeZone = TimeZone.current
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"
let dateString = formatter.string(from: Date())
formattedJSON["date"] = dateString
formattedJSON["locale"] = Locale.current.identifier
formattedJSON["timeZone"] = TimeZone.current.abbreviation()
} else {
if let deviceDescription = json["X-MMe-Client-Info"] { formattedJSON["deviceDescription"] = deviceDescription }
if let localUserID = json["X-Apple-I-MD-LU"] { formattedJSON["localUserID"] = localUserID }
if let deviceUniqueIdentifier = json["X-Mme-Device-Id"] { formattedJSON["deviceUniqueIdentifier"] = deviceUniqueIdentifier }
if let date = json["X-Apple-I-Client-Time"] { formattedJSON["date"] = date }
if let locale = json["X-Apple-Locale"] { formattedJSON["locale"] = locale }
if let timeZone = json["X-Apple-I-TimeZone"] { formattedJSON["timeZone"] = timeZone }
}
if let response = response,
let version = response.value(forHTTPHeaderField: "Implementation-Version") {
print("Implementation-Version: \(version)")
} else { print("No Implementation-Version header") }
print("Anisette used: \(formattedJSON)")
print("Original JSON: \(json)")
if let anisette = ALTAnisetteData(json: formattedJSON) { if let anisette = ALTAnisetteData(json: formattedJSON) {
print("Anisette is valid!") DLOG("Anisette used: %@", formattedJSON)
self.finish(.success(anisette)) self.finish(.success(anisette))
} else {
print("Anisette is invalid!!!!")
if v3 {
throw OperationError.anisetteV3Error(message: "Invalid anisette (the returned data may not have all the required fields)")
} else {
throw OperationError.anisetteV1Error(message: "Invalid anisette (the returned data may not have all the required fields)")
} }
} }
} else {
if v3 {
throw OperationError.anisetteV3Error(message: "Invalid anisette (the returned data may not be in JSON)")
} else {
throw OperationError.anisetteV1Error(message: "Invalid anisette (the returned data may not be in JSON)")
}
}
}
// MARK: - V1
func handleV1() {
print("Server is V1")
if UserDefaults.shared.trustedServerURL == AnisetteManager.currentURLString {
print("Server has already been trusted, fetching anisette")
return self.fetchAnisetteV1()
}
print("Alerting user about outdated server")
let alert = UIAlertController(title: "WARNING: Outdated anisette server", message: "We've detected you are using an older anisette server. Using this server has a higher likelihood of locking your account and causing other issues. Are you sure you want to continue?", preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: "Continue", style: UIAlertAction.Style.destructive, handler: { action in
print("Fetching anisette via V1")
UserDefaults.shared.trustedServerURL = AnisetteManager.currentURLString
self.fetchAnisetteV1()
}))
alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertAction.Style.cancel, handler: { action in
print("Cancelled anisette operation")
self.finish(.failure(OperationError.cancelled))
}))
let keyWindow = UIApplication.shared.windows.filter { $0.isKeyWindow }.first
DispatchQueue.main.async {
if let presentingController = keyWindow?.rootViewController?.presentedViewController {
presentingController.present(alert, animated: true)
} else {
keyWindow?.rootViewController?.present(alert, animated: true)
}
}
}
func fetchAnisetteV1() {
print("Fetching anisette V1")
URLSession.shared.dataTask(with: self.url!) { data, response, error in
do {
guard let data = data, error == nil else { throw OperationError.anisetteV1Error(message: "Unable to fetch data\(error != nil ? " (\(error!.localizedDescription))" : "")") }
try self.extractAnisetteData(data, response as? HTTPURLResponse, v3: false)
} catch let error as NSError { } catch let error as NSError {
print("Failed to load: \(error.localizedDescription)") print("Failed to load: \(error.localizedDescription)")
self.finish(.failure(error)) self.finish(.failure(error))
} }
}.resume()
} }
// MARK: - V3: PROVISIONING task.resume()
func provision() {
fetchClientInfo {
print("Getting provisioning URLs")
var request = self.buildAppleRequest(url: URL(string: "https://gsa.apple.com/grandslam/GsService2/lookup")!)
request.httpMethod = "GET"
URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data,
let plist = try? PropertyListSerialization.propertyList(from: data, format: nil) as? Dictionary<String, Dictionary<String, Any>>,
let startProvisioningString = plist["urls"]?["midStartProvisioning"] as? String,
let startProvisioningURL = URL(string: startProvisioningString),
let endProvisioningString = plist["urls"]?["midFinishProvisioning"] as? String,
let endProvisioningURL = URL(string: endProvisioningString) {
self.startProvisioningURL = startProvisioningURL
self.endProvisioningURL = endProvisioningURL
print("startProvisioningURL: \(self.startProvisioningURL!.absoluteString)")
print("endProvisioningURL: \(self.endProvisioningURL!.absoluteString)")
print("Starting a provisioning session")
self.startProvisioningSession()
} else {
print("Apple didn't give valid URLs! Got response: \(String(data: data ?? Data("nothing".utf8), encoding: .utf8) ?? "not utf8")")
self.finish(.failure(OperationError.provisioningError(result: "Apple didn't give valid URLs. Please try again later", message: nil)))
}
}.resume()
} }
} }
func startProvisioningSession() {
let provisioningSessionURL = self.url!.appendingPathComponent("v3").appendingPathComponent("provisioning_session")
var wsRequest = URLRequest(url: provisioningSessionURL)
wsRequest.timeoutInterval = 5
self.socket = WebSocket(request: wsRequest)
self.socket.delegate = self
self.socket.connect()
}
func didReceive(event: WebSocketEvent, client: WebSocketClient) {
switch event {
case .text(let string):
do {
if let json = try JSONSerialization.jsonObject(with: string.data(using: .utf8)!, options: []) as? [String: Any] {
guard let result = json["result"] as? String else {
print("The server didn't give us a result")
client.disconnect(closeCode: 0)
self.finish(.failure(OperationError.provisioningError(result: "The server didn't give us a result", message: nil)))
return
}
print("Received result: \(result)")
switch result {
case "GiveIdentifier":
print("Giving identifier")
client.json(["identifier": Keychain.shared.identifier!])
case "GiveStartProvisioningData":
print("Getting start provisioning data")
let body = [
"Header": [String: Any](),
"Request": [String: Any](),
]
var request = self.buildAppleRequest(url: self.startProvisioningURL!)
request.httpMethod = "POST"
request.httpBody = try! PropertyListSerialization.data(fromPropertyList: body, format: .xml, options: 0)
URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data,
let plist = try? PropertyListSerialization.propertyList(from: data, format: nil) as? Dictionary<String, Dictionary<String, Any>>,
let spim = plist["Response"]?["spim"] as? String {
print("Giving start provisioning data")
client.json(["spim": spim])
} else {
print("Apple didn't give valid start provisioning data! Got response: \(String(data: data ?? Data("nothing".utf8), encoding: .utf8) ?? "not utf8")")
client.disconnect(closeCode: 0)
self.finish(.failure(OperationError.provisioningError(result: "Apple didn't give valid start provisioning data. Please try again later", message: nil)))
}
}.resume()
case "GiveEndProvisioningData":
print("Getting end provisioning data")
guard let cpim = json["cpim"] as? String else {
print("The server didn't give us a cpim")
client.disconnect(closeCode: 0)
self.finish(.failure(OperationError.provisioningError(result: "The server didn't give us a cpim", message: nil)))
return
}
let body = [
"Header": [String: Any](),
"Request": [
"cpim": cpim,
],
]
var request = self.buildAppleRequest(url: self.endProvisioningURL!)
request.httpMethod = "POST"
request.httpBody = try! PropertyListSerialization.data(fromPropertyList: body, format: .xml, options: 0)
URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data,
let plist = try? PropertyListSerialization.propertyList(from: data, format: nil) as? Dictionary<String, Dictionary<String, Any>>,
let ptm = plist["Response"]?["ptm"] as? String,
let tk = plist["Response"]?["tk"] as? String {
print("Giving end provisioning data")
client.json(["ptm": ptm, "tk": tk])
} else {
print("Apple didn't give valid end provisioning data! Got response: \(String(data: data ?? Data("nothing".utf8), encoding: .utf8) ?? "not utf8")")
client.disconnect(closeCode: 0)
self.finish(.failure(OperationError.provisioningError(result: "Apple didn't give valid end provisioning data. Please try again later", message: nil)))
}
}.resume()
case "ProvisioningSuccess":
print("Provisioning succeeded!")
client.disconnect(closeCode: 0)
guard let adiPb = json["adi_pb"] as? String else {
print("The server didn't give us an adi.pb file")
self.finish(.failure(OperationError.provisioningError(result: "The server didn't give us an adi.pb file", message: nil)))
return
}
Keychain.shared.adiPb = adiPb
self.fetchAnisetteV3(Keychain.shared.identifier!, Keychain.shared.adiPb!)
default:
if result.contains("Error") || result.contains("Invalid") || result == "ClosingPerRequest" || result == "Timeout" || result == "TextOnly" {
print("Failing because of \(result)")
self.finish(.failure(OperationError.provisioningError(result: result, message: json["message"] as? String)))
}
}
}
} catch let error as NSError {
print("Failed to handle text: \(error.localizedDescription)")
self.finish(.failure(OperationError.provisioningError(result: error.localizedDescription, message: nil)))
}
case .connected:
print("Connected")
case .disconnected(let string, let code):
print("Disconnected: \(code); \(string)")
case .error(let error):
print("Got error: \(String(describing: error))")
default:
print("Unknown event: \(event)")
}
}
func buildAppleRequest(url: URL) -> URLRequest {
var request = URLRequest(url: url)
request.setValue(self.clientInfo!, forHTTPHeaderField: "X-Mme-Client-Info")
request.setValue(self.userAgent!, forHTTPHeaderField: "User-Agent")
request.setValue("text/x-xml-plist", forHTTPHeaderField: "Content-Type")
request.setValue("*/*", forHTTPHeaderField: "Accept")
request.setValue(self.mdLu!, forHTTPHeaderField: "X-Apple-I-MD-LU")
request.setValue(self.deviceId!, forHTTPHeaderField: "X-Mme-Device-Id")
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.calendar = Calendar(identifier: .gregorian)
formatter.timeZone = TimeZone(identifier: "UTC")
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"
let dateString = formatter.string(from: Date())
request.setValue(dateString, forHTTPHeaderField: "X-Apple-I-Client-Time")
request.setValue(Locale.current.identifier, forHTTPHeaderField: "X-Apple-Locale")
request.setValue(TimeZone.current.abbreviation(), forHTTPHeaderField: "X-Apple-I-TimeZone")
return request
}
// MARK: - V3: FETCHING
func fetchClientInfo(_ callback: @escaping () -> Void) {
if self.clientInfo != nil &&
self.userAgent != nil &&
self.mdLu != nil &&
self.deviceId != nil &&
Keychain.shared.identifier != nil {
print("Skipping client_info fetch since all the properties we need aren't nil")
return callback()
}
print("Trying to get client_info")
let clientInfoURL = self.url!.appendingPathComponent("v3").appendingPathComponent("client_info")
URLSession.shared.dataTask(with: clientInfoURL) { data, response, error in
do {
guard let data = data, error == nil else {
return self.finish(.failure(OperationError.anisetteV3Error(message: "Couldn't fetch client info. The server may be down\(error != nil ? " (\(error!.localizedDescription))" : "")")))
}
if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: String] {
if let clientInfo = json["client_info"] {
print("Server is V3")
self.clientInfo = clientInfo
self.userAgent = json["user_agent"]!
print("Client-Info: \(self.clientInfo!)")
print("User-Agent: \(self.userAgent!)")
if Keychain.shared.identifier == nil {
print("Generating identifier")
var bytes = [Int8](repeating: 0, count: 16)
let status = SecRandomCopyBytes(kSecRandomDefault, bytes.count, &bytes)
if status != errSecSuccess {
print("ERROR GENERATING IDENTIFIER!!! \(status)")
return self.finish(.failure(OperationError.provisioningError(result: "Couldn't generate identifier", message: nil)))
}
Keychain.shared.identifier = Data(bytes: &bytes, count: bytes.count).base64EncodedString()
}
let decoded = Data(base64Encoded: Keychain.shared.identifier!)!
self.mdLu = decoded.sha256().hexEncodedString()
print("X-Apple-I-MD-LU: \(self.mdLu!)")
let uuid: UUID = decoded.object()
self.deviceId = uuid.uuidString.uppercased()
print("X-Mme-Device-Id: \(self.deviceId!)")
callback()
} else { self.handleV1() }
} else { self.finish(.failure(OperationError.anisetteV3Error(message: "Couldn't fetch client info. The returned data may not be in JSON"))) }
} catch let error as NSError {
print("Failed to load: \(error.localizedDescription)")
self.handleV1()
}
}.resume()
}
func fetchAnisetteV3(_ identifier: String, _ adiPb: String) {
fetchClientInfo {
print("Fetching anisette V3")
var request = URLRequest(url: self.url!.appendingPathComponent("v3").appendingPathComponent("get_headers"))
request.httpMethod = "POST"
request.httpBody = try! JSONSerialization.data(withJSONObject: [
"identifier": identifier,
"adi_pb": adiPb
], options: [])
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
URLSession.shared.dataTask(with: request) { data, response, error in
do {
guard let data = data, error == nil else { throw OperationError.anisetteV3Error(message: "Couldn't fetch anisette") }
try self.extractAnisetteData(data, response as? HTTPURLResponse, v3: true)
} catch let error as NSError {
print("Failed to load: \(error.localizedDescription)")
self.finish(.failure(error))
}
}.resume()
}
}
}
extension WebSocketClient {
func json(_ dictionary: [String: String]) {
let data = try! JSONSerialization.data(withJSONObject: dictionary, options: [])
self.write(string: String(data: data, encoding: .utf8)!)
}
}
extension Data {
// https://stackoverflow.com/a/25391020
func sha256() -> Data {
var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
self.withUnsafeBytes {
_ = CC_SHA256($0.baseAddress, CC_LONG(self.count), &hash)
}
return Data(hash)
}
// https://stackoverflow.com/a/40089462
func hexEncodedString() -> String {
return self.map { String(format: "%02hhX", $0) }.joined()
}
// https://stackoverflow.com/a/59127761
func object<T>() -> T { self.withUnsafeBytes { $0.load(as: T.self) } }
}

View File

@@ -262,19 +262,14 @@ extension FetchProvisioningProfilesOperation
{ {
throw OperationError.maximumAppIDLimitReached(application: application, requiredAppIDs: requiredAppIDs, availableAppIDs: availableAppIDs, nextExpirationDate: expirationDate) throw OperationError.maximumAppIDLimitReached(application: application, requiredAppIDs: requiredAppIDs, availableAppIDs: availableAppIDs, nextExpirationDate: expirationDate)
} }
else
{
throw ALTAppleAPIError(.maximumAppIDLimitReached)
} }
} }
//App ID name must be ascii. If the name is not ascii, using bundleID instead
let appIDName: String
if !name.allSatisfy({ $0.isASCII }) {
//Contains non ASCII (Such as Chinese/Japanese...), using bundleID
appIDName = bundleIdentifier
}else {
//ASCII text, keep going as usual
appIDName = name
} }
ALTAppleAPI.shared.addAppID(withName: appIDName, bundleIdentifier: bundleIdentifier, team: team, session: session) { (appID, error) in ALTAppleAPI.shared.addAppID(withName: name, bundleIdentifier: bundleIdentifier, team: team, session: session) { (appID, error) in
do do
{ {
do do
@@ -389,39 +384,19 @@ extension FetchProvisioningProfilesOperation
if app.isAltStoreApp if app.isAltStoreApp
{ {
print("Application groups before modifying for SideStore: \(applicationGroups)")
// Remove app groups that contain AltStore since they can be problematic (cause SideStore to expire early)
for (index, group) in applicationGroups.enumerated() {
if group.contains("AltStore") {
print("Removing application group: \(group)")
applicationGroups.remove(at: index)
}
}
// Make sure we add .AltWidget for the widget
var altStoreAppGroupID = Bundle.baseAltStoreAppGroupID
for (_, group) in applicationGroups.enumerated() {
if group.contains("AltWidget") {
altStoreAppGroupID += ".AltWidget"
break
}
}
// Potentially updating app groups for this specific AltStore. // Potentially updating app groups for this specific AltStore.
// Find the (unique) AltStore app group, then replace it // Find the (unique) AltStore app group, then replace it
// with the correct "base" app group ID. // with the correct "base" app group ID.
// Otherwise, we may append a duplicate team identifier to the end. // Otherwise, we may append a duplicate team identifier to the end.
if let index = applicationGroups.firstIndex(where: { $0.contains(Bundle.baseAltStoreAppGroupID) }) if let index = applicationGroups.firstIndex(where: { $0.contains(Bundle.baseAltStoreAppGroupID) })
{ {
applicationGroups[index] = altStoreAppGroupID applicationGroups[index] = Bundle.baseAltStoreAppGroupID
} }
else else
{ {
applicationGroups.append(altStoreAppGroupID) applicationGroups.append(Bundle.baseAltStoreAppGroupID)
} }
} }
print("Application groups: \(applicationGroups)")
// Dispatch onto global queue to prevent appGroupsLock deadlock. // Dispatch onto global queue to prevent appGroupsLock deadlock.
DispatchQueue.global().async { DispatchQueue.global().async {
@@ -503,13 +478,10 @@ extension FetchProvisioningProfilesOperation
ALTAppleAPI.shared.delete(profile, for: team, session: session) { (success, error) in ALTAppleAPI.shared.delete(profile, for: team, session: session) { (success, error) in
switch Result(success, error) switch Result(success, error)
{ {
case .failure: case .failure(let error): completionHandler(.failure(error))
// As of March 20, 2023, the free provisioning profile is re-generated each fetch, and you can no longer delete it.
// So instead, we just return the fetched profile from above.
completionHandler(.success(profile))
case .success: case .success:
// Fetch new provisioning profile
// Fetch new provisiong profile
ALTAppleAPI.shared.fetchProvisioningProfile(for: appID, deviceType: .iphone, team: team, session: session) { (profile, error) in ALTAppleAPI.shared.fetchProvisioningProfile(for: appID, deviceType: .iphone, team: team, session: session) { (profile, error) in
completionHandler(Result(profile, error)) completionHandler(Result(profile, error))
} }

View File

@@ -11,7 +11,6 @@ import Network
import AltStoreCore import AltStoreCore
import AltSign import AltSign
import Roxas import Roxas
import minimuxer
@objc(InstallAppOperation) @objc(InstallAppOperation)
final class InstallAppOperation: ResultOperation<InstalledApp> final class InstallAppOperation: ResultOperation<InstalledApp>
@@ -41,14 +40,12 @@ final class InstallAppOperation: ResultOperation<InstalledApp>
guard guard
let certificate = self.context.certificate, let certificate = self.context.certificate,
let resignedApp = self.context.resignedApp, let resignedApp = self.context.resignedApp
let provisioningProfiles = self.context.provisioningProfiles
else { return self.finish(.failure(OperationError.invalidParameters)) } else { return self.finish(.failure(OperationError.invalidParameters)) }
let backgroundContext = DatabaseManager.shared.persistentContainer.newBackgroundContext() let backgroundContext = DatabaseManager.shared.persistentContainer.newBackgroundContext()
backgroundContext.perform { backgroundContext.perform {
/* App */ /* App */
let installedApp: InstalledApp let installedApp: InstalledApp
@@ -118,7 +115,8 @@ final class InstallAppOperation: ResultOperation<InstalledApp>
// Temporary directory and resigned .ipa no longer needed, so delete them now to ensure AltStore doesn't quit before we get the chance to. // Temporary directory and resigned .ipa no longer needed, so delete them now to ensure AltStore doesn't quit before we get the chance to.
self.cleanUp() self.cleanUp()
if let sideloadedAppsLimit = UserDefaults.standard.activeAppsLimit, provisioningProfiles.contains(where: { $1.isFreeProvisioningProfile == true }) var activeProfiles: Set<String>?
if let sideloadedAppsLimit = UserDefaults.standard.activeAppsLimit
{ {
// When installing these new profiles, AltServer will remove all non-active profiles to ensure we remain under limit. // When installing these new profiles, AltServer will remove all non-active profiles to ensure we remain under limit.
@@ -143,70 +141,23 @@ final class InstallAppOperation: ResultOperation<InstalledApp>
installedApp.isActive = false installedApp.isActive = false
} }
} }
}
else activeProfiles = Set(activeApps.flatMap { (installedApp) -> [String] in
{ let appExtensionProfiles = installedApp.appExtensions.map { $0.resignedBundleIdentifier }
installedApp.isActive = true return [installedApp.resignedBundleIdentifier] + appExtensionProfiles
})
} }
var installing = true let ns_bundle = NSString(string: installedApp.bundleIdentifier)
if installedApp.storeApp?.bundleIdentifier.range(of: Bundle.Info.appbundleIdentifier) != nil { let ns_bundle_ptr = UnsafeMutablePointer<CChar>(mutating: ns_bundle.utf8String)
// Reinstalling ourself will hang until we leave the app, so we need to exit it without force closing
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
if UIApplication.shared.applicationState != .active {
print("We are not in the foreground, let's not do anything")
return
}
if !installing {
print("Installing finished")
return
}
print("We are still installing after 3 seconds")
UNUserNotificationCenter.current().getNotificationSettings { settings in
switch (settings.authorizationStatus) {
case .authorized, .ephemeral, .provisional:
print("Notifications are enabled")
let content = UNMutableNotificationContent() let res = minimuxer_install_ipa(ns_bundle_ptr)
content.title = "Refreshing..." if res == 0 {
content.body = "SideStore will automatically move to the homescreen to finish refreshing!"
let notification = UNNotificationRequest(identifier: Bundle.Info.appbundleIdentifier + ".FinishRefreshNotification", content: content, trigger: UNTimeIntervalNotificationTrigger(timeInterval: 2, repeats: false))
UNUserNotificationCenter.current().add(notification)
break
default:
print("Notifications are not enabled")
let alert = UIAlertController(title: "Finish Refresh", message: "Please reopen SideStore after the process is finished.To finish refreshing, SideStore must be moved to the background. To do this, you can either go to the Home Screen manually or by hitting Continue. Please reopen SideStore after doing this.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("Continue", comment: ""), style: .default, handler: { _ in
print("Going home")
UIApplication.shared.perform(#selector(NSXPCConnection.suspend))
}))
DispatchQueue.main.async {
let keyWindow = UIApplication.shared.windows.filter { $0.isKeyWindow }.first
if var topController = keyWindow?.rootViewController {
while let presentedViewController = topController.presentedViewController {
topController = presentedViewController
}
topController.present(alert, animated: true)
} else {
print("No key window? Let's just go home")
}
}
}
}
UIApplication.shared.perform(#selector(NSXPCConnection.suspend))
}
}
do {
try install_ipa(installedApp.bundleIdentifier)
installing = false
installedApp.refreshedDate = Date() installedApp.refreshedDate = Date()
self.finish(.success(installedApp)) self.finish(.success(installedApp))
} catch let error {
installing = false } else {
self.finish(.failure(error)) self.finish(.failure(minimuxer_to_operation(code: res)))
} }
} }
} }
@@ -223,11 +174,10 @@ final class InstallAppOperation: ResultOperation<InstalledApp>
do do
{ {
try FileManager.default.removeItem(at: fileURL) try FileManager.default.removeItem(at: fileURL)
print("Removed refreshed IPA")
} }
catch catch
{ {
print("Failed to remove refreshed .ipa: \(error)") print("Failed to remove refreshed .ipa:", error)
} }
} }

View File

@@ -8,7 +8,6 @@
import Foundation import Foundation
import AltSign import AltSign
import minimuxer
enum OperationError: LocalizedError enum OperationError: LocalizedError
{ {
@@ -34,13 +33,18 @@ enum OperationError: LocalizedError
case openAppFailed(name: String) case openAppFailed(name: String)
case missingAppGroup case missingAppGroup
case noWiFi case noDevice
case tooNewError case createService(name: String)
case anisetteV1Error(message: String) case getFromDevice(name: String)
case provisioningError(result: String, message: String?) case setArgument(name: String)
case anisetteV3Error(message: String) case afc
case install
case cacheClearError(errors: [String]) case uninstall
case lookupApps
case detach
case functionArguments
case profileInstall
case noConnection
var failureReason: String? { var failureReason: String? {
switch self { switch self {
@@ -57,12 +61,18 @@ enum OperationError: LocalizedError
case .openAppFailed(let name): return String(format: NSLocalizedString("SideStore was denied permission to launch %@.", comment: ""), name) case .openAppFailed(let name): return String(format: NSLocalizedString("SideStore was denied permission to launch %@.", comment: ""), name)
case .missingAppGroup: return NSLocalizedString("SideStore's shared app group could not be found.", comment: "") case .missingAppGroup: return NSLocalizedString("SideStore's shared app group could not be found.", comment: "")
case .maximumAppIDLimitReached: return NSLocalizedString("Cannot register more than 10 App IDs.", comment: "") case .maximumAppIDLimitReached: return NSLocalizedString("Cannot register more than 10 App IDs.", comment: "")
case .noWiFi: return NSLocalizedString("You do not appear to be connected to WiFi!\nSideStore will never be able to install or refresh applications without WiFi.", comment: "") case .noDevice: return NSLocalizedString("Cannot fetch the device from the muxer", comment: "")
case .tooNewError: return NSLocalizedString("iOS 17 has changed how JIT is enabled therefore SideStore cannot enable it at this time, sorry for any inconvenience.\nWe will let everyone know once we have a solution!", comment: "") case .createService(let name): return String(format: NSLocalizedString("Cannot start a %@ server on the device.", comment: ""), name)
case .anisetteV1Error(let message): return String(format: NSLocalizedString("An error occurred when getting anisette data from a V1 server: %@. Try using another anisette server.", comment: ""), message) case .getFromDevice(let name): return String(format: NSLocalizedString("Cannot fetch %@ from the device.", comment: ""), name)
case .provisioningError(let result, let message): return String(format: NSLocalizedString("An error occurred when provisioning: %@%@. Please try again. If the issue persists, report it on GitHub Issues!", comment: ""), result, message != nil ? (" (" + message! + ")") : "") case .setArgument(let name): return String(format: NSLocalizedString("Cannot set %@ on the device.", comment: ""), name)
case .anisetteV3Error(let message): return String(format: NSLocalizedString("An error occurred when getting anisette data from a V3 server: %@. Please try again. If the issue persists, report it on GitHub Issues!", comment: ""), message) case .afc: return NSLocalizedString("AFC was unable to manage files on the device", comment: "")
case .cacheClearError(let errors): return String(format: NSLocalizedString("An error occurred while clearing cache: %@", comment: ""), errors.joined(separator: "\n")) case .install: return NSLocalizedString("Unable to install the app from the staging directory", comment: "")
case .uninstall: return NSLocalizedString("Unable to uninstall the app", comment: "")
case .lookupApps: return NSLocalizedString("Unable to fetch apps from the device", comment: "")
case .detach: return NSLocalizedString("Unable to detach from the app's process", comment: "")
case .functionArguments: return NSLocalizedString("A function was passed invalid arguments", comment: "")
case .profileInstall: return NSLocalizedString("Unable to manage profiles on the device", comment: "")
case .noConnection: return NSLocalizedString("Unable to connect to the device, make sure Wireguard is enabled and you're connected to WiFi", comment: "")
} }
} }
@@ -108,66 +118,49 @@ enum OperationError: LocalizedError
} }
} }
extension MinimuxerError: LocalizedError { func minimuxer_to_operation(code: Int32) -> OperationError {
public var failureReason: String? { switch code {
switch self { case -1:
case .NoDevice: return OperationError.noDevice
return NSLocalizedString("Cannot fetch the device from the muxer", comment: "") case -2:
case .NoConnection: return OperationError.createService(name: "debug")
return NSLocalizedString("Unable to connect to the device, make sure Wireguard is enabled and you're connected to WiFi", comment: "") case -3:
case .PairingFile: return OperationError.createService(name: "instproxy")
return NSLocalizedString("Invalid pairing file. Your pairing file either didn't have a UDID, or it wasn't a valid plist. Please use jitterbugpair to generate it", comment: "") case -4:
return OperationError.getFromDevice(name: "installed apps")
case .CreateDebug: case -5:
return self.createService(name: "debug") return OperationError.getFromDevice(name: "path to the app")
case .LookupApps: case -6:
return self.getFromDevice(name: "installed apps") return OperationError.getFromDevice(name: "bundle path")
case .FindApp: case -7:
return self.getFromDevice(name: "path to the app") return OperationError.setArgument(name: "max packet")
case .BundlePath: case -8:
return self.getFromDevice(name: "bundle path") return OperationError.setArgument(name: "working directory")
case .MaxPacket: case -9:
return self.setArgument(name: "max packet") return OperationError.setArgument(name: "argv")
case .WorkingDirectory: case -10:
return self.setArgument(name: "working directory") return OperationError.getFromDevice(name: "launch success")
case .Argv: case -11:
return self.setArgument(name: "argv") return OperationError.detach
case .LaunchSuccess: case -12:
return self.getFromDevice(name: "launch success") return OperationError.functionArguments
case .Detach: case -13:
return NSLocalizedString("Unable to detach from the app's process", comment: "") return OperationError.createService(name: "AFC")
case .Attach: case -14:
return NSLocalizedString("Unable to attach to the app's process", comment: "") return OperationError.afc
case -15:
case .CreateInstproxy: return OperationError.install
return self.createService(name: "instproxy") case -16:
case .CreateAfc: return OperationError.uninstall
return self.createService(name: "AFC") case -17:
case .RwAfc: return OperationError.createService(name: "misagent")
return NSLocalizedString("AFC was unable to manage files on the device", comment: "") case -18:
case .InstallApp(let message): return OperationError.profileInstall
return NSLocalizedString("Unable to install the app: \(message.toString())", comment: "") case -19:
case .UninstallApp: return OperationError.profileInstall
return NSLocalizedString("Unable to uninstall the app", comment: "") case -20:
return OperationError.noConnection
case .CreateMisagent: default:
return self.createService(name: "misagent") return OperationError.unknown
case .ProfileInstall:
return NSLocalizedString("Unable to manage profiles on the device", comment: "")
case .ProfileRemove:
return NSLocalizedString("Unable to manage profiles on the device", comment: "")
}
}
fileprivate func createService(name: String) -> String {
return String(format: NSLocalizedString("Cannot start a %@ server on the device.", comment: ""), name)
}
fileprivate func getFromDevice(name: String) -> String {
return String(format: NSLocalizedString("Cannot fetch %@ from the device.", comment: ""), name)
}
fileprivate func setArgument(name: String) -> String {
return String(format: NSLocalizedString("Cannot set %@ on the device.", comment: ""), name)
} }
} }

View File

@@ -35,28 +35,34 @@ final class RefreshAppOperation: ResultOperation<InstalledApp>
do do
{ {
if let error = self.context.error { return self.finish(.failure(error)) } if let error = self.context.error
{
guard let profiles = self.context.provisioningProfiles else { return self.finish(.failure(OperationError.invalidParameters)) } throw error
guard let app = self.context.app else { return self.finish(.failure(OperationError.appNotFound)) }
for p in profiles {
do {
let bytes = p.value.data.toRustByteSlice()
try install_provisioning_profile(bytes.forRust())
} catch {
self.finish(.failure(MinimuxerError.ProfileInstall))
} }
guard let profiles = self.context.provisioningProfiles else { throw OperationError.invalidParameters }
guard let app = self.context.app else { throw OperationError.appNotFound }
DatabaseManager.shared.persistentContainer.performBackgroundTask { (context) in DatabaseManager.shared.persistentContainer.performBackgroundTask { (context) in
print("Sending refresh app request...") print("Sending refresh app request...")
for p in profiles {
do {
let x = try install_provisioning_profile(plist: p.value.data)
if case .Bad(let code) = x {
self.finish(.failure(minimuxer_to_operation(code: code)))
}
} catch Uhoh.Bad(let code) {
self.finish(.failure(minimuxer_to_operation(code: code)))
} catch {
self.finish(.failure(OperationError.unknown))
}
self.progress.completedUnitCount += 1 self.progress.completedUnitCount += 1
let predicate = NSPredicate(format: "%K == %@", #keyPath(InstalledApp.bundleIdentifier), app.bundleIdentifier) let predicate = NSPredicate(format: "%K == %@", #keyPath(InstalledApp.bundleIdentifier), app.bundleIdentifier)
self.managedObjectContext.perform { self.managedObjectContext.perform {
guard let installedApp = InstalledApp.first(satisfying: predicate, in: self.managedObjectContext) else { guard let installedApp = InstalledApp.first(satisfying: predicate, in: self.managedObjectContext) else {
self.finish(.failure(OperationError.appNotFound))
return return
} }
installedApp.update(provisioningProfile: p.value) installedApp.update(provisioningProfile: p.value)
@@ -69,5 +75,9 @@ final class RefreshAppOperation: ResultOperation<InstalledApp>
} }
} }
} }
catch
{
self.finish(.failure(error))
}
} }
} }

View File

@@ -39,11 +39,15 @@ final class RemoveAppOperation: ResultOperation<InstalledApp>
let resignedBundleIdentifier = installedApp.resignedBundleIdentifier let resignedBundleIdentifier = installedApp.resignedBundleIdentifier
do { do {
try remove_app(resignedBundleIdentifier) let res = try remove_app(app_id: resignedBundleIdentifier)
} catch { if case Uhoh.Bad(let code) = res {
return self.finish(.failure(error)) self.finish(.failure(minimuxer_to_operation(code: code)))
}
} catch Uhoh.Bad(let code) {
self.finish(.failure(minimuxer_to_operation(code: code)))
} catch {
self.finish(.failure(ALTServerError(.appDeletionFailed)))
} }
DatabaseManager.shared.persistentContainer.performBackgroundTask { (context) in DatabaseManager.shared.persistentContainer.performBackgroundTask { (context) in
self.progress.completedUnitCount += 1 self.progress.completedUnitCount += 1

View File

@@ -11,7 +11,6 @@ import Roxas
import AltStoreCore import AltStoreCore
import AltSign import AltSign
import minimuxer
@objc(ResignAppOperation) @objc(ResignAppOperation)
final class ResignAppOperation: ResultOperation<ALTApplication> final class ResignAppOperation: ResultOperation<ALTApplication>
@@ -62,7 +61,6 @@ final class ResignAppOperation: ResultOperation<ALTApplication>
{ {
let destinationURL = InstalledApp.refreshedIPAURL(for: app) let destinationURL = InstalledApp.refreshedIPAURL(for: app)
try FileManager.default.copyItem(at: resignedURL, to: destinationURL, shouldReplace: true) try FileManager.default.copyItem(at: resignedURL, to: destinationURL, shouldReplace: true)
print("Successfully resigned app to \(destinationURL.absoluteString)")
// Use appBundleURL since we need an app bundle, not .ipa. // Use appBundleURL since we need an app bundle, not .ipa.
guard let resignedApplication = ALTApplication(fileURL: appBundleURL) else { throw OperationError.invalidApp } guard let resignedApplication = ALTApplication(fileURL: appBundleURL) else { throw OperationError.invalidApp }
@@ -149,14 +147,6 @@ private extension ResignAppOperation
infoDictionary[Bundle.Info.exportedUTIs] = exportedUTIs infoDictionary[Bundle.Info.exportedUTIs] = exportedUTIs
try (infoDictionary as NSDictionary).write(to: bundle.infoPlistURL) try (infoDictionary as NSDictionary).write(to: bundle.infoPlistURL)
// Remove _CodeSignature folder (if it exists) because it will be added when resigning and it may have files that aren't overwritten when resigning
// These files might be the cause of some ApplicationVerificationFailed errors
let codeSignaturePath = bundle.bundleURL.appendingPathComponent("_CodeSignature").absoluteString.replacingOccurrences(of: "file://", with: "")
if FileManager.default.fileExists(atPath: codeSignaturePath) {
try FileManager.default.removeItem(atPath: codeSignaturePath)
print("Removed _CodeSignature folder at \(codeSignaturePath)")
}
} }
DispatchQueue.global().async { DispatchQueue.global().async {
@@ -182,7 +172,7 @@ private extension ResignAppOperation
if app.isAltStoreApp if app.isAltStoreApp
{ {
guard let udid = fetch_udid()?.toString() as? String else { throw OperationError.unknownUDID } guard let udid = Bundle.main.object(forInfoDictionaryKey: Bundle.Info.deviceID) as? String else { throw OperationError.unknownUDID }
guard let pairingFileString = Bundle.main.object(forInfoDictionaryKey: Bundle.Info.devicePairingString) as? String else { throw OperationError.unknownUDID } guard let pairingFileString = Bundle.main.object(forInfoDictionaryKey: Bundle.Info.devicePairingString) as? String else { throw OperationError.unknownUDID }
additionalValues[Bundle.Info.devicePairingString] = pairingFileString additionalValues[Bundle.Info.devicePairingString] = pairingFileString
additionalValues[Bundle.Info.deviceID] = udid additionalValues[Bundle.Info.deviceID] = udid
@@ -203,7 +193,7 @@ private extension ResignAppOperation
// The embedded certificate + certificate identifier are already in app bundle, no need to update them. // The embedded certificate + certificate identifier are already in app bundle, no need to update them.
} }
} }
else if infoDictionary.keys.contains(Bundle.Info.deviceID), let udid = fetch_udid()?.toString() as? String else if infoDictionary.keys.contains(Bundle.Info.deviceID), let udid = Bundle.main.object(forInfoDictionaryKey: Bundle.Info.deviceID) as? String
{ {
// There is an ALTDeviceID entry, so assume the app is using AltKit and replace it with the device's UDID. // There is an ALTDeviceID entry, so assume the app is using AltKit and replace it with the device's UDID.
additionalValues[Bundle.Info.deviceID] = udid additionalValues[Bundle.Info.deviceID] = udid
@@ -228,7 +218,6 @@ private extension ResignAppOperation
// Prepare app // Prepare app
try prepare(appBundle, additionalInfoDictionaryValues: additionalValues) try prepare(appBundle, additionalInfoDictionaryValues: additionalValues)
try self.removeMissingAppExtensionReferences(from: appBundle)
if let directory = appBundle.builtInPlugInsURL, let enumerator = FileManager.default.enumerator(at: directory, includingPropertiesForKeys: nil, options: [.skipsSubdirectoryDescendants]) if let directory = appBundle.builtInPlugInsURL, let enumerator = FileManager.default.enumerator(at: directory, includingPropertiesForKeys: nil, options: [.skipsSubdirectoryDescendants])
{ {
@@ -269,28 +258,4 @@ private extension ResignAppOperation
return progress return progress
} }
func removeMissingAppExtensionReferences(from bundle: Bundle) throws
{
// If app extensions have been removed from an app (either by AltStore or the developer),
// we must remove all references to them from SC_Info/Manifest.plist (if it exists).
let scInfoURL = bundle.bundleURL.appendingPathComponent("SC_Info")
let manifestPlistURL = scInfoURL.appendingPathComponent("Manifest.plist")
guard let manifestPlist = NSMutableDictionary(contentsOf: manifestPlistURL), let sinfReplicationPaths = manifestPlist["SinfReplicationPaths"] as? [String] else { return }
// Remove references to missing files.
let filteredReplicationPaths = sinfReplicationPaths.filter { path in
guard let fileURL = URL(string: path, relativeTo: bundle.bundleURL) else { return false }
let fileExists = FileManager.default.fileExists(atPath: fileURL.path)
return fileExists
}
manifestPlist["SinfReplicationPaths"] = filteredReplicationPaths
// Save updated Manifest.plist to disk.
try manifestPlist.write(to: manifestPlistURL)
}
} }

View File

@@ -9,7 +9,6 @@ import Foundation
import Network import Network
import AltStoreCore import AltStoreCore
import minimuxer
@objc(SendAppOperation) @objc(SendAppOperation)
final class SendAppOperation: ResultOperation<()> final class SendAppOperation: ResultOperation<()>
@@ -33,7 +32,8 @@ final class SendAppOperation: ResultOperation<()>
if let error = self.context.error if let error = self.context.error
{ {
return self.finish(.failure(error)) self.finish(.failure(error))
return
} }
guard let resignedApp = self.context.resignedApp else { return self.finish(.failure(OperationError.invalidParameters)) } guard let resignedApp = self.context.resignedApp else { return self.finish(.failure(OperationError.invalidParameters)) }
@@ -44,20 +44,25 @@ final class SendAppOperation: ResultOperation<()>
print("AFC App `fileURL`: \(fileURL.absoluteString)") print("AFC App `fileURL`: \(fileURL.absoluteString)")
let ns_bundle = NSString(string: app.bundleIdentifier)
let ns_bundle_ptr = UnsafeMutablePointer<CChar>(mutating: ns_bundle.utf8String)
if let data = NSData(contentsOf: fileURL) { if let data = NSData(contentsOf: fileURL) {
do { let pls = UnsafeMutablePointer<UInt8>.allocate(capacity: data.length)
let bytes = Data(data).toRustByteSlice() for (index, data) in data.enumerated() {
try yeet_app_afc(app.bundleIdentifier, bytes.forRust()) pls[index] = data
self.progress.completedUnitCount += 1
self.finish(.success(()))
} catch {
self.finish(.failure(MinimuxerError.RwAfc))
self.progress.completedUnitCount += 1
self.finish(.success(()))
} }
let res = minimuxer_yeet_app_afc(ns_bundle_ptr, pls, UInt(data.length))
if res == 0 {
print("minimuxer_yeet_app_afc `res` == \(res)")
self.progress.completedUnitCount += 1
self.finish(.success(()))
} else { } else {
print("IPA doesn't exist????") self.finish(.failure(minimuxer_to_operation(code: res)))
self.finish(.failure(OperationError.appNotFound)) }
} else {
self.finish(.failure(ALTServerError(.underlyingError)))
} }
} }
} }

Binary file not shown.

View File

@@ -1,158 +1 @@
{ {"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"72x72","expected-size":"72","filename":"72.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"76x76","expected-size":"152","filename":"152.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"50x50","expected-size":"100","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"76x76","expected-size":"76","filename":"76.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"50x50","expected-size":"50","filename":"50.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"72x72","expected-size":"144","filename":"144.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"40x40","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"83.5x83.5","expected-size":"167","filename":"167.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"20x20","expected-size":"20","filename":"20.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"}]}
"images" : [
{
"filename" : "40.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"filename" : "60.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"filename" : "29.png",
"idiom" : "iphone",
"scale" : "1x",
"size" : "29x29"
},
{
"filename" : "58.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"filename" : "87.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"filename" : "80.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"filename" : "120.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"filename" : "57.png",
"idiom" : "iphone",
"scale" : "1x",
"size" : "57x57"
},
{
"filename" : "114.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "57x57"
},
{
"filename" : "120.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"filename" : "180.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"filename" : "20.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "20x20"
},
{
"filename" : "40.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "20x20"
},
{
"filename" : "29.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "29x29"
},
{
"filename" : "58.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "29x29"
},
{
"filename" : "40.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "40x40"
},
{
"filename" : "80.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"filename" : "50.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "50x50"
},
{
"filename" : "100.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "50x50"
},
{
"filename" : "72.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "72x72"
},
{
"filename" : "144.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "72x72"
},
{
"filename" : "76.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "76x76"
},
{
"filename" : "152.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "76x76"
},
{
"filename" : "167.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"filename" : "1024.png",
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "riley.jpg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "shane.jpeg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 846 KiB

View File

@@ -1,21 +0,0 @@
{
"images" : [
{
"filename" : "1024.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,269 @@
{
"name": "AltStore",
"identifier": "com.rileytestut.AltStore",
"sourceURL": "https://cdn.altstore.io/file/altstore/apps.json",
"apps": [
{
"name": "AltStore",
"bundleIdentifier": "com.rileytestut.AltStore",
"developerName": "Riley Testut",
"version": "1.5.1",
"versionDate": "2022-07-14T12:00:00-05:00",
"versionDescription": "This update fixes the following issues:\n\n• Using Apple IDs that contain capital letters\n• Using Apple IDs with 2FA enabled without any trusted devices\n• Repeatedly asking some users to sign in every refresh\n• \"Incorrect Apple ID or password\" error after changing Apple ID email address\n• “Application is missing application-identifier” error when sideloading or (de-)activating certain apps\n• Potential crash when receiving unknown error codes from AltServer",
"downloadURL": "https://cdn.altstore.io/file/altstore/apps/altstore/1_5_1.ipa",
"localizedDescription": "AltStore is an alternative app store for non-jailbroken devices. \n\nThis version of AltStore allows you to install Delta, an all-in-one emulator for iOS, as well as sideload other .ipa files from the Files app.",
"iconURL": "https://user-images.githubusercontent.com/705880/65270980-1eb96f80-dad1-11e9-9367-78ccd25ceb02.png",
"tintColor": "018084",
"size": 5465976,
"screenshotURLs": [
"https://user-images.githubusercontent.com/705880/78942028-acf54300-7a6d-11ea-821c-5bb7a9b3e73a.PNG",
"https://user-images.githubusercontent.com/705880/78942222-0fe6da00-7a6e-11ea-9f2a-dda16157583c.PNG",
"https://user-images.githubusercontent.com/705880/65605577-332cba80-df5e-11e9-9f00-b369ce974f71.PNG"
],
"permissions": [
{
"type": "background-fetch",
"usageDescription": "AltStore periodically refreshes apps in the background to prevent them from expiring."
},
{
"type": "background-audio",
"usageDescription": "Allows AltStore to run longer than 30 seconds when refreshing apps in background."
}
]
},
{
"name": "AltStore",
"bundleIdentifier": "com.rileytestut.AltStore.Beta",
"developerName": "Riley Testut",
"subtitle": "An alternative App Store for iOS.",
"version": "1.6b2",
"versionDate": "2022-09-21T13:00:00-05:00",
"versionDescription": "• Fixed “error migrating persistent store” issue on launch\n\nPREVIOUS VERSION\n\nLock Screen Widget (iOS 16+)\n• Counts down days until AltStore expires\n• Comes in 2 different styles: “icon” and “text”\n\nError Log\n• View past errors in more detail\n• Tap an error to copy the error message or error code\n• Search for error code directly in AltStore FAQ",
"downloadURL": "https://cdn.altstore.io/file/altstore/apps/altstore/1_6_b2.ipa",
"localizedDescription": "AltStore is an alternative app store for non-jailbroken devices. \n\nThis beta release of AltStore adds support for 3rd party sources, allowing you to download apps from other developers directly through AltStore.",
"iconURL": "https://user-images.githubusercontent.com/705880/65270980-1eb96f80-dad1-11e9-9367-78ccd25ceb02.png",
"tintColor": "018084",
"size": 5465933,
"beta": true,
"screenshotURLs": [
"https://user-images.githubusercontent.com/705880/78942028-acf54300-7a6d-11ea-821c-5bb7a9b3e73a.PNG",
"https://user-images.githubusercontent.com/705880/78942222-0fe6da00-7a6e-11ea-9f2a-dda16157583c.PNG",
"https://user-images.githubusercontent.com/705880/65605577-332cba80-df5e-11e9-9f00-b369ce974f71.PNG"
],
"permissions": [
{
"type": "background-fetch",
"usageDescription": "AltStore periodically refreshes apps in the background to prevent them from expiring."
},
{
"type": "background-audio",
"usageDescription": "Allows AltStore to run longer than 30 seconds when refreshing apps in background."
}
]
},
{
"name": "Delta",
"bundleIdentifier": "com.rileytestut.Delta",
"developerName": "Riley Testut",
"subtitle": "Classic games in your pocket.",
"version": "1.3.1",
"versionDate": "2021-12-02T13:30:00-08:00",
"versionDescription": "• Fixes game artwork not loading\n• Fixes using deprecated DeSmuME core over melonDS core for some users",
"downloadURL": "https://cdn.altstore.io/file/altstore/apps/delta/1_3_1.ipa",
"localizedDescription": "Delta is an all-in-one emulator for iOS. Delta builds upon the strengths of its predecessor, GBA4iOS, while expanding to include support for more game systems such as NES, SNES, and N64.\n\nFEATURES\n\nSupported Game Systems\n• Nintendo Entertainment System\n• Super Nintendo Entertainment System\n• Nintendo 64\n• Game Boy (Color)\n• Game Boy Advance\n• Nintendo DS\n• And plenty more to come!\n\nController Support\n• Supports PS4, PS5, Xbox One S, Xbox Series X, and MFi game controllers.\n• Supports bluetooth (and wired) keyboards, as well as the Apple Smart Keyboard.\n• Completely customize button mappings on a per-system, per-controller basis.\n• Map buttons to special “Quick Save”, “Quick Load,” and “Fast Forward” actions.\n\nSave States\n• Save and load save states for any game from the pause menu.\n• Lock save states to prevent them from being accidentally overwritten.\n• Automatically makes backup save states to ensure you never lose your progress.\n• Support for “Quick Saves,” save states that can be quickly saved/loaded with a single button press (requires external controller).\n\nCheats\n• Supports various types of cheat codes for each supported system:\n• NES: Game Genie\n• SNES: Game Genie, Pro Action Replay\n• N64: GameShark\n• GBC: Game Genie, GameShark\n• GBA: Action Replay, Code Breaker, GameShark\n• DS: Action Replay\n\nDelta Sync\n• Sync your games, game saves, save states, cheats, controller skins, and controller mappings between devices.\n• View version histories of everything you sync and optionally restore them to earlier versions.\n• Supports both Google Drive and Dropbox.\n\nCustom Controller Skins\n• Beautiful built-in controller skins for all systems.\n• Import controller skins made by others, or even make your own to share with the world!\n\nHold Button\n• Choose buttons for Delta to hold down on your behalf, freeing up your thumbs to press other buttons instead.\n• Perfect for games that typically require one button be held down constantly (ex: run button in Mario games, or the A button in Mario Kart).\n\nFast Forward\n• Speed through slower parts of games by running the game much faster than normal.\n• Easily enable or disable from the pause menu, or optionally with a mapped button on an external controller.\n\n3D/Haptic Touch\n• Use 3D or Haptic Touch to “peek” at games, save states, and cheat codes.\n• App icon shortcuts allow quick access to your most recently played games, or optionally customize the shortcuts to always include certain games.\n\nGame Artwork\n• Automatically displays appropriate box art for imported games.\n• Change a games artwork to anything you want, or select from the built-in game artwork database.\n\nMisc.\n• Gyroscope support (WarioWare: Twisted! only)\n• Microphone support (DS only)\n• Support for delta:// URL scheme to jump directly into a specific game.\n\n**Delta and AltStore LLC are in no way affiliated with Nintendo. The name \"Nintendo\" and all associated game console names are registered trademarks of Nintendo Co., Ltd.**",
"iconURL": "https://user-images.githubusercontent.com/705880/63391976-4d311700-c37a-11e9-91a8-4fb0c454413d.png",
"tintColor": "8A28F7",
"size": 19739373,
"permissions": [
{
"type": "photos",
"usageDescription": "Allows Delta to use images from your Photo Library as game artwork."
}
],
"screenshotURLs": [
"https://user-images.githubusercontent.com/705880/65600448-f7d9be00-df54-11e9-9e3e-d4c31296da94.PNG",
"https://user-images.githubusercontent.com/705880/65813009-f2ae8600-e183-11e9-9eb7-704effc11173.png",
"https://user-images.githubusercontent.com/705880/65601117-58b5c600-df56-11e9-9c19-9a5ba5da54cf.PNG",
"https://user-images.githubusercontent.com/705880/65601125-5b182000-df56-11e9-9e7e-261480e893c0.PNG"
]
},
{
"name": "Delta",
"bundleIdentifier": "com.rileytestut.Delta.Beta",
"developerName": "Riley Testut",
"subtitle": "Classic games in your pocket.",
"version": "1.4b2",
"versionDate": "2022-08-16T08:00:00-05:00",
"versionDescription": "NEW\n• Supports Split View and Stage Manager multitasking on iPad\n• Automatically pauses + resumes emulation when switching between foreground apps with Stage Manager\n• Optimized full screen-width controller skins when using Split View, Slide Over, or Stage Manager\n• Supports controller skins with new `placement` parameter\n• Supports controller skins with custom screens that dont have explicit `outputFrame`\n\nFIXED\n• Fixed not detecting keyboard presses when remapping inputs\n• Fixed potential crash rendering game screen after changing EAGLContext\n• Fixed incorrect game screen frame when software keyboard appears on iOS 16\n• Fixed software keyboard sometimes appearing when not emulating anything",
"downloadURL": "https://cdn.altstore.io/file/altstore/apps/delta/1_4_b2.ipa",
"localizedDescription": "The next consoles for Delta are coming: this beta version of Delta brings support for playing Nintendo DS and Sega Genesis games!\n\nPlease report any issues you find to support@altstore.io. Thanks!",
"iconURL": "https://user-images.githubusercontent.com/705880/63391976-4d311700-c37a-11e9-91a8-4fb0c454413d.png",
"tintColor": "8A28F7",
"size": 42968657,
"beta": true,
"permissions": [
{
"type": "photos",
"usageDescription": "Allows Delta to use images from your Photo Library as game artwork."
}
],
"screenshotURLs": [
"https://user-images.githubusercontent.com/705880/65600448-f7d9be00-df54-11e9-9e3e-d4c31296da94.PNG",
"https://user-images.githubusercontent.com/705880/65601942-e5ad4f00-df57-11e9-9255-1463e0296e46.PNG",
"https://user-images.githubusercontent.com/705880/65813009-f2ae8600-e183-11e9-9eb7-704effc11173.png",
"https://user-images.githubusercontent.com/705880/65601117-58b5c600-df56-11e9-9c19-9a5ba5da54cf.PNG"
]
},
{
"name": "Clip",
"bundleIdentifier": "com.rileytestut.Clip",
"subtitle": "Manage your clipboard history with ease.",
"developerName": "Riley Testut",
"version": "1.0",
"versionDate": "2020-06-17T12:30:00-07:00",
"versionDescription": "Initial version 🎉",
"downloadURL": "https://f000.backblazeb2.com/file/altstore/apps/clip/1_0.ipa",
"localizedDescription": "Clip is a simple clipboard manager for iOS. \n\nUnlike other clipboard managers, Clip can continue monitoring your clipboard while in the background. No longer do you need to remember to manually open or share to an app to save your clipboard; just copy and paste as you would normally do, and Clip will have your back.\n\nIn addition to background monitoring, Clip also has these features:\n\n• Save text, URLs, and images copied to the clipboard.\n• Copy, delete, or share any clippings saved to Clip.\n• Customizable history limit.\n\nDownload Clip today, and never worry about losing your clipboard again!",
"iconURL": "https://user-images.githubusercontent.com/705880/63391981-5326f800-c37a-11e9-99d8-760fd06bb601.png",
"tintColor": "EC008C",
"size": 445056,
"permissions": [
{
"type": "background-audio",
"usageDescription": "Allows Clip to continuously monitor your clipboard in the background."
}
],
"screenshotURLs": [
"https://user-images.githubusercontent.com/705880/63391950-34286600-c37a-11e9-965f-832efe3da507.png",
"https://user-images.githubusercontent.com/705880/70830209-8e738980-1da4-11ea-8b3b-6e5fbc78adff.png"
]
},
{
"name": "Clip",
"bundleIdentifier": "com.rileytestut.Clip.Beta",
"subtitle": "Manage your clipboard history with ease.",
"developerName": "Riley Testut",
"version": "1.1b1",
"versionDate": "2020-06-17T12:30:00-07:00",
"versionDescription": "This update adds a Custom Keyboard app extension for quick access to clippings when editing text.\n\nTo enable the keyboard, go to Settings > General > Keyboard > Keyboards > Add New Keyboard... and add \"ClipBoard\". Once added, make sure to then enable \"Allow Full Access\" for ClipBoard so it can access your clippings.",
"downloadURL": "https://f000.backblazeb2.com/file/altstore/apps/clip/1_1_b1.ipa",
"localizedDescription": "Clip is a simple clipboard manager for iOS. \n\nUnlike other clipboard managers, Clip can continue monitoring your clipboard while in the background. No longer do you need to remember to manually open or share to an app to save your clipboard; just copy and paste as you would normally do, and Clip will have your back.\n\nIn addition to background monitoring, Clip also has these features:\n\n• Save text, URLs, and images copied to the clipboard.\n• Copy, delete, or share any clippings saved to Clip.\n• Customizable history limit.\n\nDownload Clip today, and never worry about losing your clipboard again!",
"iconURL": "https://user-images.githubusercontent.com/705880/63391981-5326f800-c37a-11e9-99d8-760fd06bb601.png",
"tintColor": "EC008C",
"size": 462771,
"beta": true,
"permissions": [
{
"type": "background-audio",
"usageDescription": "Allows Clip to continuously monitor your clipboard in the background."
}
],
"screenshotURLs": [
"https://user-images.githubusercontent.com/705880/63391950-34286600-c37a-11e9-965f-832efe3da507.png",
"https://user-images.githubusercontent.com/705880/70830209-8e738980-1da4-11ea-8b3b-6e5fbc78adff.png",
"https://user-images.githubusercontent.com/705880/84842227-70a80b00-aff9-11ea-8b04-bedb1f49c4a7.PNG",
"https://user-images.githubusercontent.com/705880/84842231-7271ce80-aff9-11ea-9272-e128aeceb95b.PNG"
]
}
],
"news": [
{
"title": "Delta Gaining DS Support",
"identifier": "delta-ds-support",
"caption": "Available this Saturday for patrons, coming soon for everyone else.",
"tintColor": "8A28F7",
"imageURL": "https://user-images.githubusercontent.com/705880/65603159-0676a400-df5a-11e9-882e-dc5566f4d50a.png",
"date": "2019-09-25",
"notify": false
},
{
"title": "Delta Now Available",
"identifier": "delta-now-available",
"caption": "Finally, relive your favorite NES, SNES, GB(C), GBA, and N64 games.",
"tintColor": "8A28F7",
"imageURL": "https://user-images.githubusercontent.com/705880/65604130-c1ec0800-df5b-11e9-8150-7657c474e3c3.png",
"appID": "com.rileytestut.Delta",
"date": "2019-09-28",
"notify": true
},
{
"title": "Sideloading is Here!",
"identifier": "sideloading-is-here",
"caption": "Update to AltStore 1.3 to install any app directly from Files.",
"tintColor": "018084",
"imageURL": "https://user-images.githubusercontent.com/705880/79022069-02932380-7b32-11ea-8bad-49907cb97ece.png",
"date": "2020-04-10T13:00:00-07:00",
"notify": true
},
{
"title": "iOS 13.4 Fixes App Crashes",
"identifier": "ios-13-4-now-available",
"caption": "Update to iOS 13.4 to fix some sideloaded apps crashing on launch.",
"tintColor": "34C759",
"date": "2020-04-10T13:30:00-07:00",
"notify": false
},
{
"title": "Clip Now Available!",
"identifier": "clip-now-available",
"caption": "Finally, a clipboard manager that can run in the background — no jailbreak required.",
"tintColor": "EC008C",
"imageURL": "https://user-images.githubusercontent.com/705880/65606598-04afdf00-df60-11e9-8f93-af6345d39557.png",
"appID": "com.rileytestut.Clip",
"date": "2020-06-17",
"notify": true
},
{
"title": "Delta, Meet Nintendo DS",
"identifier": "delta-meet-ds",
"caption": "Update to Delta 1.3 to relive all your favorite Nintendo DS games.",
"tintColor": "8A28F7",
"imageURL": "https://user-images.githubusercontent.com/705880/115617602-6ce2b600-a2a6-11eb-984e-2197a30c71e2.png",
"appID": "com.rileytestut.Delta",
"date": "2021-04-21",
"notify": true
},
{
"title": "#StandWithUkraine",
"identifier": "support-ukraine",
"caption": "Find out how you can help support those impacted by the Russian invasion.",
"tintColor": "003e80",
"imageURL": "https://user-images.githubusercontent.com/705880/156053447-a158cac7-df5f-4497-8025-15c3c2e10b48.png",
"url": "https://linktr.ee/razomforukraine",
"date": "2022-03-01",
"notify": false
},
{
"title": "The Biggest AltServer Update Yet!",
"identifier": "altserver-1-5",
"caption": "Update to AltServer 1.5 to use AltJIT and other exciting new features.",
"tintColor": "018084",
"imageURL": "https://user-images.githubusercontent.com/705880/166509576-744be578-6868-4b7d-b4fd-b9418c084327.png",
"url": "https://faq.altstore.io/release-notes/altserver",
"date": "2022-05-03",
"notify": true
},
{
"title": "More Apps in AltStore!",
"identifier": "trusted-sources",
"caption": "Update to AltStore 1.5 to easily download some of our favorite apps.",
"tintColor": "00CAB3",
"imageURL": "https://user-images.githubusercontent.com/705880/167026375-ddcb004f-7160-405c-b3e3-87a6795d2f43.png",
"url": "https://faq.altstore.io/release-notes/altstore",
"date": "2022-05-05",
"notify": true
},
{
"title": "New to AltStore?",
"identifier": "updated-faq",
"caption": "Check out our updated guide to learn how to sideload apps!",
"tintColor": "018084",
"url": "https://faq.altstore.io",
"date": "2022-07-28",
"notify": false
}
],
"userInfo": {
"patreonAccessToken": "uqoDoTxH8dY1ImE8tK76wxrzKk67gjyjBAcK8sD3RLU"
}
}

View File

@@ -3,16 +3,16 @@
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>application-identifier</key> <key>application-identifier</key>
<string>XYZ0123456.com.SideStore.SideStore</string> <string>A72ZC8AJ5X.com.SideStore.AltStore</string>
<key>aps-environment</key> <key>aps-environment</key>
<string>development</string> <string>development</string>
<key>com.apple.developer.siri</key> <key>com.apple.developer.siri</key>
<true/> <true/>
<key>com.apple.developer.team-identifier</key> <key>com.apple.developer.team-identifier</key>
<string>XYZ0123456</string> <string>A72ZC8AJ5X</string>
<key>com.apple.security.application-groups</key> <key>com.apple.security.application-groups</key>
<array> <array>
<string>group.com.SideStore.SideStore</string> <string>group.com.SideStore.AltStore</string>
</array> </array>
<key>get-task-allow</key> <key>get-task-allow</key>
<true/> <true/>

View File

@@ -16,13 +16,15 @@
<key>Key</key> <key>Key</key>
<string>customAnisetteURL</string> <string>customAnisetteURL</string>
<key>DefaultValue</key> <key>DefaultValue</key>
<string>https://ani.sidestore.io</string> <string>http://ani.sidestore.io</string>
<key>Titles</key> <key>Titles</key>
<array> <array>
<string>SideStore</string> <string>SideStore</string>
<string>Macley (US)</string> <string>Macley (US)</string>
<string>Macley (DE)</string> <string>Macley (DE)</string>
<string>DrPudding</string> <string>DrPudding</string>
<string>jkcoxson (AltServer)</string>
<string>jkcoxson (Provision)</string>
<string>Sideloadly</string> <string>Sideloadly</string>
<string>Nick</string> <string>Nick</string>
<string>Jawshoeadan</string> <string>Jawshoeadan</string>
@@ -30,10 +32,12 @@
</array> </array>
<key>Values</key> <key>Values</key>
<array> <array>
<string>https://ani.sidestore.io</string> <string>http://ani.sidestore.io</string>
<string>http://5.249.163.88:6969/</string> <string>http://us1.sternserv.tech</string>
<string>http://45.132.246.138:6969/</string> <string>http://de1.sternserv.tech</string>
<string>https://sign.rheaa.xyz</string> <string>https://sign.rheaa.xyz</string>
<string>http://jkcoxson.com:2095</string>
<string>http://jkcoxson.com:2052</string>
<string>https://sideloadly.io/anisette/irGb3Quww8zrhgqnzmrx</string> <string>https://sideloadly.io/anisette/irGb3Quww8zrhgqnzmrx</string>
<string>http://45.33.29.114</string> <string>http://45.33.29.114</string>
<string>https://anisette.jawshoeadan.me</string> <string>https://anisette.jawshoeadan.me</string>

View File

@@ -1,27 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21225" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/> <device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies> <dependencies>
<deployment identifier="iOS"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21207"/>
<capability name="Named colors" minToolsVersion="9.0"/> <capability name="Named colors" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<objects> <objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/> <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<collectionReusableView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" reuseIdentifier="AboutHeader" id="xq2-Pl-zaG" customClass="AboutPatreonHeaderView" customModule="SideStore" customModuleProvider="target"> <collectionReusableView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" reuseIdentifier="AboutHeader" id="xq2-Pl-zaG" customClass="AboutPatreonHeaderView" customModule="AltStore" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="390" height="682"/> <rect key="frame" x="0.0" y="0.0" width="375" height="445"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<stackView opaque="NO" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" axis="vertical" spacing="25" translatesAutoresizingMaskIntoConstraints="NO" id="XiA-Jf-XMp"> <stackView opaque="NO" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" axis="vertical" spacing="25" translatesAutoresizingMaskIntoConstraints="NO" id="XiA-Jf-XMp">
<rect key="frame" x="16" y="2" width="358" height="630"/> <rect key="frame" x="16" y="2" width="343" height="393"/>
<subviews> <subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="5Ol-zN-wYv"> <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="5Ol-zN-wYv">
<rect key="frame" x="0.0" y="0.0" width="358" height="426"/> <rect key="frame" x="0.0" y="0.0" width="343" height="317"/>
<subviews> <subviews>
<stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="f7H-EV-7Sx"> <stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="f7H-EV-7Sx">
<rect key="frame" x="0.0" y="0.0" width="358" height="55"/> <rect key="frame" x="0.0" y="0.0" width="343" height="55"/>
<subviews> <subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="SideStore" translatesAutoresizingMaskIntoConstraints="NO" id="pn6-Ic-MJm"> <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="SideStore" translatesAutoresizingMaskIntoConstraints="NO" id="pn6-Ic-MJm">
<rect key="frame" x="0.0" y="0.0" width="55" height="55"/> <rect key="frame" x="0.0" y="0.0" width="55" height="55"/>
@@ -31,7 +31,7 @@
</constraints> </constraints>
</imageView> </imageView>
<stackView opaque="NO" contentMode="scaleToFill" distribution="equalSpacing" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="si2-MA-3RH"> <stackView opaque="NO" contentMode="scaleToFill" distribution="equalSpacing" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="si2-MA-3RH">
<rect key="frame" x="65" y="0.0" width="293" height="55"/> <rect key="frame" x="65" y="0.0" width="278" height="55"/>
<subviews> <subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="2" translatesAutoresizingMaskIntoConstraints="NO" id="hkS-oz-wiT"> <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="2" translatesAutoresizingMaskIntoConstraints="NO" id="hkS-oz-wiT">
<rect key="frame" x="0.0" y="0.0" width="83" height="55"/> <rect key="frame" x="0.0" y="0.0" width="83" height="55"/>
@@ -51,7 +51,7 @@
</subviews> </subviews>
</stackView> </stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="2" translatesAutoresizingMaskIntoConstraints="NO" id="TFB-qo-cbh"> <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="2" translatesAutoresizingMaskIntoConstraints="NO" id="TFB-qo-cbh">
<rect key="frame" x="210" y="0.0" width="83" height="55"/> <rect key="frame" x="195" y="0.0" width="83" height="55"/>
<subviews> <subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="Zpb-k3-y7l"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="Zpb-k3-y7l">
<rect key="frame" x="0.0" y="0.0" width="83" height="50"/> <rect key="frame" x="0.0" y="0.0" width="83" height="50"/>
@@ -75,13 +75,11 @@
</constraints> </constraints>
</stackView> </stackView>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" scrollEnabled="NO" editable="NO" textAlignment="natural" selectable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FeG-e5-LJl"> <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" scrollEnabled="NO" editable="NO" textAlignment="natural" selectable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FeG-e5-LJl">
<rect key="frame" x="0.0" y="65" width="358" height="361"/> <rect key="frame" x="0.0" y="65" width="343" height="252"/>
<color key="backgroundColor" white="1" alpha="0.13" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="backgroundColor" white="1" alpha="0.13" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<string key="text">Thank you for using SideStore! <string key="text">Hello, thank you for using SideStore!
Subscribing to the patreon supports us and makes sure we can continue developing SideStore for you. If you would subscribe to the patreon that would support us and make sure we can continue developing SideStore for you.
Following us on social media allows us to give quick updates and spread the word about sideloading!
-SideTeam</string> -SideTeam</string>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
@@ -91,10 +89,10 @@ Following us on social media allows us to give quick updates and spread the word
</subviews> </subviews>
</stackView> </stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="13" translatesAutoresizingMaskIntoConstraints="NO" id="QS9-vO-bj8"> <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="13" translatesAutoresizingMaskIntoConstraints="NO" id="QS9-vO-bj8">
<rect key="frame" x="0.0" y="451" width="358" height="179"/> <rect key="frame" x="0.0" y="342" width="343" height="51"/>
<subviews> <subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="yEi-L6-kQ8"> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="yEi-L6-kQ8">
<rect key="frame" x="0.0" y="0.0" width="358" height="51"/> <rect key="frame" x="0.0" y="0.0" width="343" height="51"/>
<color key="backgroundColor" name="SettingsHighlighted"/> <color key="backgroundColor" name="SettingsHighlighted"/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="51" id="l4o-vb-cMy"/> <constraint firstAttribute="height" constant="51" id="l4o-vb-cMy"/>
@@ -104,28 +102,6 @@ Following us on social media allows us to give quick updates and spread the word
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state> </state>
</button> </button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="hov-Ce-LaM" userLabel="Twitter Button">
<rect key="frame" x="0.0" y="64" width="358" height="51"/>
<color key="backgroundColor" name="SettingsHighlighted"/>
<constraints>
<constraint firstAttribute="height" constant="51" id="m0M-GX-KKG"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="19"/>
<state key="normal" title="Follow us on Twitter!">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="VdY-7Q-amF" userLabel="Twitter Button">
<rect key="frame" x="0.0" y="128" width="358" height="51"/>
<color key="backgroundColor" name="SettingsHighlighted"/>
<constraints>
<constraint firstAttribute="height" constant="51" id="kDo-b8-6tZ"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="19"/>
<state key="normal" title="Follow us on Instagram!">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
</button>
</subviews> </subviews>
</stackView> </stackView>
</subviews> </subviews>
@@ -138,21 +114,19 @@ Following us on social media allows us to give quick updates and spread the word
<constraint firstItem="XiA-Jf-XMp" firstAttribute="top" secondItem="xq2-Pl-zaG" secondAttribute="top" constant="2" id="j8p-JX-Dcz"/> <constraint firstItem="XiA-Jf-XMp" firstAttribute="top" secondItem="xq2-Pl-zaG" secondAttribute="top" constant="2" id="j8p-JX-Dcz"/>
</constraints> </constraints>
<connections> <connections>
<outlet property="instagramButton" destination="VdY-7Q-amF" id="5kj-9x-k4F"/>
<outlet property="rileyImageView" destination="pn6-Ic-MJm" id="60i-Q0-ojz"/> <outlet property="rileyImageView" destination="pn6-Ic-MJm" id="60i-Q0-ojz"/>
<outlet property="rileyLabel" destination="DTd-Yu-HXr" id="O0y-JB-gWp"/> <outlet property="rileyLabel" destination="DTd-Yu-HXr" id="O0y-JB-gWp"/>
<outlet property="shaneLabel" destination="Zpb-k3-y7l" id="aQN-6B-s5T"/> <outlet property="shaneLabel" destination="Zpb-k3-y7l" id="aQN-6B-s5T"/>
<outlet property="supportButton" destination="yEi-L6-kQ8" id="Dzo-vd-SnD"/> <outlet property="supportButton" destination="yEi-L6-kQ8" id="Dzo-vd-SnD"/>
<outlet property="textView" destination="FeG-e5-LJl" id="K0M-lF-I6u"/> <outlet property="textView" destination="FeG-e5-LJl" id="K0M-lF-I6u"/>
<outlet property="twitterButton" destination="hov-Ce-LaM" id="gib-Lt-qtY"/>
</connections> </connections>
<point key="canvasLocation" x="147.82608695652175" y="58.258928571428569"/> <point key="canvasLocation" x="138" y="138"/>
</collectionReusableView> </collectionReusableView>
</objects> </objects>
<resources> <resources>
<image name="SideStore" width="1024" height="1024"/> <image name="SideStore" width="180" height="180"/>
<namedColor name="SettingsHighlighted"> <namedColor name="SettingsHighlighted">
<color red="0.38823529411764707" green="0.011764705882352941" blue="0.58823529411764708" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color red="0.23529411764705882" green="0.0" blue="0.40392156862745099" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor> </namedColor>
</resources> </resources>
</document> </document>

View File

@@ -56,8 +56,6 @@ final class PatronsFooterView: UICollectionReusableView
final class AboutPatreonHeaderView: UICollectionReusableView final class AboutPatreonHeaderView: UICollectionReusableView
{ {
@IBOutlet var supportButton: UIButton! @IBOutlet var supportButton: UIButton!
@IBOutlet var twitterButton: UIButton!
@IBOutlet var instagramButton: UIButton!
@IBOutlet var accountButton: UIButton! @IBOutlet var accountButton: UIButton!
@IBOutlet var textView: UITextView! @IBOutlet var textView: UITextView!
@@ -81,7 +79,7 @@ final class AboutPatreonHeaderView: UICollectionReusableView
imageView.layer.cornerRadius = imageView.bounds.midY imageView.layer.cornerRadius = imageView.bounds.midY
} }
for button in [self.supportButton, self.accountButton, self.twitterButton, self.instagramButton].compactMap({ $0 }) for button in [self.supportButton, self.accountButton].compactMap({ $0 })
{ {
button.clipsToBounds = true button.clipsToBounds = true
button.layer.cornerRadius = 16 button.layer.cornerRadius = 16

View File

@@ -111,8 +111,6 @@ private extension PatreonViewController
headerView.layoutMargins = self.view.layoutMargins headerView.layoutMargins = self.view.layoutMargins
headerView.supportButton.addTarget(self, action: #selector(PatreonViewController.openPatreonURL(_:)), for: .primaryActionTriggered) headerView.supportButton.addTarget(self, action: #selector(PatreonViewController.openPatreonURL(_:)), for: .primaryActionTriggered)
headerView.twitterButton.addTarget(self, action: #selector(PatreonViewController.openTwitterURL(_:)), for: .primaryActionTriggered)
headerView.instagramButton.addTarget(self, action: #selector(PatreonViewController.openInstagramURL(_:)), for: .primaryActionTriggered)
let defaultSupportButtonTitle = NSLocalizedString("Become a patron", comment: "") let defaultSupportButtonTitle = NSLocalizedString("Become a patron", comment: "")
let isPatronSupportButtonTitle = NSLocalizedString("View Patreon", comment: "") let isPatronSupportButtonTitle = NSLocalizedString("View Patreon", comment: "")
@@ -182,24 +180,6 @@ private extension PatreonViewController
self.present(safariViewController, animated: true, completion: nil) self.present(safariViewController, animated: true, completion: nil)
} }
@objc func openTwitterURL(_ sender: UIButton)
{
let twitterURL = URL(string: "https://twitter.com/SideStore_io")!
let safariViewController = SFSafariViewController(url: twitterURL)
safariViewController.preferredControlTintColor = self.view.tintColor
self.present(safariViewController, animated: true, completion: nil)
}
@objc func openInstagramURL(_ sender: UIButton)
{
let twitterURL = URL(string: "https://instagram.com/sidestore.io")!
let safariViewController = SFSafariViewController(url: twitterURL)
safariViewController.preferredControlTintColor = self.view.tintColor
self.present(safariViewController, animated: true, completion: nil)
}
@IBAction func authenticate(_ sender: UIBarButtonItem) @IBAction func authenticate(_ sender: UIBarButtonItem)
{ {
PatreonAPI.shared.authenticate { (result) in PatreonAPI.shared.authenticate { (result) in

View File

@@ -21,7 +21,7 @@
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="separatorColor" white="1" alpha="0.25" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="separatorColor" white="1" alpha="0.25" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<label key="tableFooterView" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="SideStore 1.0" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="bUR-rp-Nw2"> <label key="tableFooterView" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="SideStore 1.0" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="bUR-rp-Nw2">
<rect key="frame" x="0.0" y="1245" width="375" height="25"/> <rect key="frame" x="0.0" y="1082" width="375" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/> <fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="0.69999999999999996" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="textColor" white="1" alpha="0.69999999999999996" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
@@ -167,8 +167,8 @@
<rect key="frame" x="0.0" y="0.0" width="375" height="51"/> <rect key="frame" x="0.0" y="0.0" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Support the team" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3Il-5a-5Zp"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Join the beta" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3Il-5a-5Zp">
<rect key="frame" x="30" y="15.5" width="142.5" height="20.5"/> <rect key="frame" x="30" y="15.5" width="106" height="20.5"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
@@ -236,44 +236,8 @@
<userDefinedRuntimeAttribute type="boolean" keyPath="isSelectable" value="NO"/> <userDefinedRuntimeAttribute type="boolean" keyPath="isSelectable" value="NO"/>
</userDefinedRuntimeAttributes> </userDefinedRuntimeAttributes>
</tableViewCell> </tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="GYp-O0-pse" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target">
<rect key="frame" x="0.0" y="444" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="GYp-O0-pse" id="vDG-ZV-xRS">
<rect key="frame" x="0.0" y="0.0" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Disable Idle Timeout" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="PCh-Up-aJJ">
<rect key="frame" x="30" y="15.5" width="166" height="20.5"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="iQA-wm-5ag">
<rect key="frame" x="296" y="10" width="51" height="31"/>
<connections>
<action selector="toggleNoIdleTimeoutEnabled:" destination="aMk-Xp-UL8" eventType="valueChanged" id="WSl-Jc-g5J"/>
</connections>
</switch>
</subviews>
<constraints>
<constraint firstAttribute="trailingMargin" secondItem="iQA-wm-5ag" secondAttribute="trailing" id="MJ1-HF-Dln"/>
<constraint firstItem="PCh-Up-aJJ" firstAttribute="leading" secondItem="vDG-ZV-xRS" secondAttribute="leadingMargin" id="Ocu-jn-RAQ"/>
<constraint firstItem="iQA-wm-5ag" firstAttribute="centerY" secondItem="vDG-ZV-xRS" secondAttribute="centerY" id="c6W-bN-VAb"/>
<constraint firstItem="PCh-Up-aJJ" firstAttribute="centerY" secondItem="vDG-ZV-xRS" secondAttribute="centerY" id="mL6-LB-cjn"/>
</constraints>
</tableViewCellContentView>
<color key="backgroundColor" white="1" alpha="0.14999999999999999" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<edgeInsets key="layoutMargins" top="8" left="30" bottom="8" right="30"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="style">
<integer key="value" value="2"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="boolean" keyPath="isSelectable" value="YES"/>
</userDefinedRuntimeAttributes>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="amC-sE-8O0" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target"> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="amC-sE-8O0" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target">
<rect key="frame" x="0.0" y="495" width="375" height="51"/> <rect key="frame" x="0.0" y="444" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="amC-sE-8O0" id="GEO-2e-E4k"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="amC-sE-8O0" id="GEO-2e-E4k">
<rect key="frame" x="0.0" y="0.0" width="375" height="51"/> <rect key="frame" x="0.0" y="0.0" width="375" height="51"/>
@@ -305,7 +269,7 @@
<tableViewSection headerTitle="" id="eHy-qI-w5w"> <tableViewSection headerTitle="" id="eHy-qI-w5w">
<cells> <cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="30h-59-88f" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target"> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="30h-59-88f" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target">
<rect key="frame" x="0.0" y="586" width="375" height="51"/> <rect key="frame" x="0.0" y="535" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="30h-59-88f" id="7qD-DW-Jls"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="30h-59-88f" id="7qD-DW-Jls">
<rect key="frame" x="0.0" y="0.0" width="375" height="51"/> <rect key="frame" x="0.0" y="0.0" width="375" height="51"/>
@@ -345,7 +309,7 @@
<tableViewSection headerTitle="" id="J90-vn-u2O"> <tableViewSection headerTitle="" id="J90-vn-u2O">
<cells> <cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="i4T-2q-jF3" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target"> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="i4T-2q-jF3" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target">
<rect key="frame" x="0.0" y="677" width="375" height="51"/> <rect key="frame" x="0.0" y="626" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="i4T-2q-jF3" id="VTQ-H4-aCM"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="i4T-2q-jF3" id="VTQ-H4-aCM">
<rect key="frame" x="0.0" y="0.0" width="375" height="51"/> <rect key="frame" x="0.0" y="0.0" width="375" height="51"/>
@@ -389,7 +353,7 @@
</userDefinedRuntimeAttributes> </userDefinedRuntimeAttributes>
</tableViewCell> </tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="oHX-oR-nwJ" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target"> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="oHX-oR-nwJ" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target">
<rect key="frame" x="0.0" y="728" width="375" height="51"/> <rect key="frame" x="0.0" y="677" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="oHX-oR-nwJ" id="hN4-i5-igu"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="oHX-oR-nwJ" id="hN4-i5-igu">
<rect key="frame" x="0.0" y="0.0" width="375" height="51"/> <rect key="frame" x="0.0" y="0.0" width="375" height="51"/>
@@ -433,28 +397,28 @@
</userDefinedRuntimeAttributes> </userDefinedRuntimeAttributes>
</tableViewCell> </tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="0MT-ht-Sit" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target"> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="0MT-ht-Sit" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target">
<rect key="frame" x="0.0" y="779" width="375" height="51"/> <rect key="frame" x="0.0" y="728" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="0MT-ht-Sit" id="OZp-WM-5H7"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="0MT-ht-Sit" id="OZp-WM-5H7">
<rect key="frame" x="0.0" y="0.0" width="375" height="51"/> <rect key="frame" x="0.0" y="0.0" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Asset Designer" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fGU-Fp-XgM"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Asset Designer" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fGU-Fp-XgM">
<rect key="frame" x="30" y="15.5" width="115.5" height="20.5"/> <rect key="frame" x="30" y="15.5" width="115.5" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/> <fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="0.80000000000000004" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="textColor" white="1" alpha="0.80000000000000004" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<stackView opaque="NO" contentMode="scaleToFill" ambiguous="YES" spacing="14" translatesAutoresizingMaskIntoConstraints="NO" id="R8B-DW-7mY"> <stackView opaque="NO" contentMode="scaleToFill" spacing="14" translatesAutoresizingMaskIntoConstraints="NO" id="R8B-DW-7mY">
<rect key="frame" x="206" y="15.5" width="139" height="20.5"/> <rect key="frame" x="206" y="15.5" width="139" height="20.5"/>
<subviews> <subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Chris (LitRitt)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hId-3P-41T"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Chris (LitRitt)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hId-3P-41T">
<rect key="frame" x="0.0" y="0.0" width="107" height="20.5"/> <rect key="frame" x="0.0" y="0.0" width="107" height="20.5"/>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="17"/> <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" image="Next" translatesAutoresizingMaskIntoConstraints="NO" id="baq-cE-fMY"> <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Next" translatesAutoresizingMaskIntoConstraints="NO" id="baq-cE-fMY">
<rect key="frame" x="121" y="0.0" width="18" height="20.5"/> <rect key="frame" x="121" y="0.0" width="18" height="20.5"/>
</imageView> </imageView>
</subviews> </subviews>
@@ -477,19 +441,19 @@
</userDefinedRuntimeAttributes> </userDefinedRuntimeAttributes>
</tableViewCell> </tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="O5R-Al-lGj" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target"> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="O5R-Al-lGj" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target">
<rect key="frame" x="0.0" y="830" width="375" height="51"/> <rect key="frame" x="0.0" y="779" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="O5R-Al-lGj" id="CrG-Mr-xQq"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="O5R-Al-lGj" id="CrG-Mr-xQq">
<rect key="frame" x="0.0" y="0.0" width="375" height="51"/> <rect key="frame" x="0.0" y="0.0" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Licenses" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="D6b-cd-pVK"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Licenses" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="D6b-cd-pVK">
<rect key="frame" x="30" y="15.5" width="67.5" height="20.5"/> <rect key="frame" x="30" y="15.5" width="67.5" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/> <fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="0.80000000000000004" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="textColor" white="1" alpha="0.80000000000000004" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" image="Next" translatesAutoresizingMaskIntoConstraints="NO" id="s79-GQ-khr"> <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Next" translatesAutoresizingMaskIntoConstraints="NO" id="s79-GQ-khr">
<rect key="frame" x="327" y="16.5" width="18" height="18"/> <rect key="frame" x="327" y="16.5" width="18" height="18"/>
</imageView> </imageView>
</subviews> </subviews>
@@ -517,19 +481,19 @@
<tableViewSection headerTitle="" id="OMa-EK-hRI"> <tableViewSection headerTitle="" id="OMa-EK-hRI">
<cells> <cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="FMZ-as-Ljo" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target"> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="FMZ-as-Ljo" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target">
<rect key="frame" x="0.0" y="921" width="375" height="51"/> <rect key="frame" x="0.0" y="870" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="FMZ-as-Ljo" id="JzL-Of-A3T"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="FMZ-as-Ljo" id="JzL-Of-A3T">
<rect key="frame" x="0.0" y="0.0" width="375" height="51"/> <rect key="frame" x="0.0" y="0.0" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Send Feedback" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pMI-Aj-nQF"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Send Feedback" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pMI-Aj-nQF">
<rect key="frame" x="30" y="15.5" width="125.5" height="20.5"/> <rect key="frame" x="30" y="15.5" width="125.5" height="20.5"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" image="Next" translatesAutoresizingMaskIntoConstraints="NO" id="Jyy-x0-Owj"> <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Next" translatesAutoresizingMaskIntoConstraints="NO" id="Jyy-x0-Owj">
<rect key="frame" x="327" y="16.5" width="18" height="18"/> <rect key="frame" x="327" y="16.5" width="18" height="18"/>
</imageView> </imageView>
</subviews> </subviews>
@@ -550,19 +514,19 @@
</userDefinedRuntimeAttributes> </userDefinedRuntimeAttributes>
</tableViewCell> </tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="Qca-pU-sJh" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target"> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="Qca-pU-sJh" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target">
<rect key="frame" x="0.0" y="972" width="375" height="51"/> <rect key="frame" x="0.0" y="921" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Qca-pU-sJh" id="QtU-8J-VQN"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Qca-pU-sJh" id="QtU-8J-VQN">
<rect key="frame" x="0.0" y="0.0" width="375" height="51"/> <rect key="frame" x="0.0" y="0.0" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="View Refresh Attempts" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sni-07-q0M"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="View Refresh Attempts" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sni-07-q0M">
<rect key="frame" x="30" y="15.5" width="187.5" height="20.5"/> <rect key="frame" x="30" y="15.5" width="187.5" height="20.5"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" image="Next" translatesAutoresizingMaskIntoConstraints="NO" id="4d3-me-Hqc"> <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Next" translatesAutoresizingMaskIntoConstraints="NO" id="4d3-me-Hqc">
<rect key="frame" x="327" y="16.5" width="18" height="18"/> <rect key="frame" x="327" y="16.5" width="18" height="18"/>
</imageView> </imageView>
</subviews> </subviews>
@@ -586,19 +550,19 @@
</connections> </connections>
</tableViewCell> </tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="rE2-P4-OaE" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target"> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="rE2-P4-OaE" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target">
<rect key="frame" x="0.0" y="1023" width="375" height="51"/> <rect key="frame" x="0.0" y="972" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="rE2-P4-OaE" id="qIT-rz-ZUb"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="rE2-P4-OaE" id="qIT-rz-ZUb">
<rect key="frame" x="0.0" y="0.0" width="375" height="51"/> <rect key="frame" x="0.0" y="0.0" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="View Error Log" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="PWC-OG-5jx"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="View Error Log" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="PWC-OG-5jx">
<rect key="frame" x="30" y="15.5" width="119" height="20.5"/> <rect key="frame" x="30" y="15.5" width="119" height="20.5"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" image="Next" translatesAutoresizingMaskIntoConstraints="NO" id="VfB-c5-5wG"> <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Next" translatesAutoresizingMaskIntoConstraints="NO" id="VfB-c5-5wG">
<rect key="frame" x="327" y="16.5" width="18" height="18"/> <rect key="frame" x="327" y="16.5" width="18" height="18"/>
</imageView> </imageView>
</subviews> </subviews>
@@ -618,56 +582,23 @@
<userDefinedRuntimeAttribute type="boolean" keyPath="isSelectable" value="YES"/> <userDefinedRuntimeAttribute type="boolean" keyPath="isSelectable" value="YES"/>
</userDefinedRuntimeAttributes> </userDefinedRuntimeAttributes>
<connections> <connections>
<segue destination="g8a-Rf-zWa" kind="show" id="vFC-Id-Ww6"/> <segue destination="g8a-Rf-zWa" kind="show" identifier="showErrorLog" id="SSW-vL-86I"/>
</connections> </connections>
</tableViewCell> </tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="eZ3-BT-q4D" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target">
<rect key="frame" x="0.0" y="1023" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="eZ3-BT-q4D" id="17m-VV-hzf">
<rect key="frame" x="0.0" y="0.0" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Clear Cache" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="IbH-V1-ce3">
<rect key="frame" x="30" y="15.5" width="98.5" height="20.5"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" image="Next" translatesAutoresizingMaskIntoConstraints="NO" id="FZe-BJ-fOm">
<rect key="frame" x="327" y="16.5" width="18" height="18"/>
</imageView>
</subviews>
<constraints>
<constraint firstItem="FZe-BJ-fOm" firstAttribute="centerY" secondItem="17m-VV-hzf" secondAttribute="centerY" id="bGv-Np-5aO"/>
<constraint firstAttribute="trailingMargin" secondItem="FZe-BJ-fOm" secondAttribute="trailing" id="ccb-JP-Eqi"/>
<constraint firstItem="IbH-V1-ce3" firstAttribute="centerY" secondItem="17m-VV-hzf" secondAttribute="centerY" id="iQJ-gN-sRF"/>
<constraint firstItem="IbH-V1-ce3" firstAttribute="leading" secondItem="17m-VV-hzf" secondAttribute="leadingMargin" id="m1g-Y6-aT5"/>
</constraints>
</tableViewCellContentView>
<color key="backgroundColor" white="1" alpha="0.14999999999999999" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<edgeInsets key="layoutMargins" top="8" left="30" bottom="8" right="30"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="style">
<integer key="value" value="2"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="boolean" keyPath="isSelectable" value="YES"/>
</userDefinedRuntimeAttributes>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="VNn-u4-cN8" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target"> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="VNn-u4-cN8" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target">
<rect key="frame" x="0.0" y="1074" width="375" height="51"/> <rect key="frame" x="0.0" y="1023" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="VNn-u4-cN8" id="4bh-qe-l2N"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="VNn-u4-cN8" id="4bh-qe-l2N">
<rect key="frame" x="0.0" y="0.0" width="375" height="51"/> <rect key="frame" x="0.0" y="0.0" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Reset Pairing File" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ysS-9s-dXm"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Reset Pairing File" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ysS-9s-dXm">
<rect key="frame" x="30" y="15.5" width="140" height="20.5"/> <rect key="frame" x="30" y="15.5" width="140" height="20.5"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" image="Next" translatesAutoresizingMaskIntoConstraints="NO" id="r09-mH-pOD"> <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Next" translatesAutoresizingMaskIntoConstraints="NO" id="r09-mH-pOD">
<rect key="frame" x="327" y="16.5" width="18" height="18"/> <rect key="frame" x="327" y="16.5" width="18" height="18"/>
</imageView> </imageView>
</subviews> </subviews>
@@ -687,53 +618,20 @@
<userDefinedRuntimeAttribute type="boolean" keyPath="isSelectable" value="YES"/> <userDefinedRuntimeAttribute type="boolean" keyPath="isSelectable" value="YES"/>
</userDefinedRuntimeAttributes> </userDefinedRuntimeAttributes>
</tableViewCell> </tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="e7s-hL-kv9" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target">
<rect key="frame" x="0.0" y="1125" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="e7s-hL-kv9" id="yjL-Mu-HTk">
<rect key="frame" x="0.0" y="0.0" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Reset adi.pb" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="eds-Dj-36y">
<rect key="frame" x="30" y="15.5" width="102" height="20.5"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" image="Next" translatesAutoresizingMaskIntoConstraints="NO" id="0dh-yd-7i9">
<rect key="frame" x="327" y="16.5" width="18" height="18"/>
</imageView>
</subviews>
<constraints>
<constraint firstItem="0dh-yd-7i9" firstAttribute="centerY" secondItem="yjL-Mu-HTk" secondAttribute="centerY" id="8OI-PI-weT"/>
<constraint firstItem="eds-Dj-36y" firstAttribute="leading" secondItem="yjL-Mu-HTk" secondAttribute="leadingMargin" id="BqG-Ef-xQo"/>
<constraint firstAttribute="trailingMargin" secondItem="0dh-yd-7i9" secondAttribute="trailing" id="TFW-nu-jo4"/>
<constraint firstItem="eds-Dj-36y" firstAttribute="centerY" secondItem="yjL-Mu-HTk" secondAttribute="centerY" id="YiJ-OF-FXE"/>
</constraints>
</tableViewCellContentView>
<color key="backgroundColor" white="1" alpha="0.14999999999999999" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<edgeInsets key="layoutMargins" top="8" left="30" bottom="8" right="30"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="style">
<integer key="value" value="2"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="boolean" keyPath="isSelectable" value="YES"/>
</userDefinedRuntimeAttributes>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="fj2-EJ-Z98" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target"> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="fj2-EJ-Z98" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target">
<rect key="frame" x="0.0" y="1176" width="375" height="51"/> <rect key="frame" x="0.0" y="1074" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="fj2-EJ-Z98" id="BcT-Fs-KNg"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="fj2-EJ-Z98" id="BcT-Fs-KNg">
<rect key="frame" x="0.0" y="0.0" width="375" height="51"/> <rect key="frame" x="0.0" y="0.0" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Advanced Settings" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="OcM-OM-uDE"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Advanced Settings" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="OcM-OM-uDE">
<rect key="frame" x="30" y="15.5" width="154" height="20.5"/> <rect key="frame" x="30" y="15.5" width="154" height="20.5"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" image="Next" translatesAutoresizingMaskIntoConstraints="NO" id="Pcu-Sy-yfZ"> <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Next" translatesAutoresizingMaskIntoConstraints="NO" id="Pcu-Sy-yfZ">
<rect key="frame" x="327" y="16.5" width="18" height="18"/> <rect key="frame" x="327" y="16.5" width="18" height="18"/>
</imageView> </imageView>
</subviews> </subviews>
@@ -758,6 +656,7 @@
</sections> </sections>
<connections> <connections>
<outlet property="dataSource" destination="aMk-Xp-UL8" id="c6c-fR-8C4"/> <outlet property="dataSource" destination="aMk-Xp-UL8" id="c6c-fR-8C4"/>
<outlet property="delegate" destination="aMk-Xp-UL8" id="moP-1B-lRq"/>
</connections> </connections>
</tableView> </tableView>
<navigationItem key="navigationItem" title="Settings" id="Ddg-UQ-KJ8"/> <navigationItem key="navigationItem" title="Settings" id="Ddg-UQ-KJ8"/>
@@ -766,7 +665,6 @@
<outlet property="accountNameLabel" destination="CnN-M1-AYK" id="Ldc-Py-Bix"/> <outlet property="accountNameLabel" destination="CnN-M1-AYK" id="Ldc-Py-Bix"/>
<outlet property="accountTypeLabel" destination="434-MW-Den" id="mNB-QE-4Jg"/> <outlet property="accountTypeLabel" destination="434-MW-Den" id="mNB-QE-4Jg"/>
<outlet property="backgroundRefreshSwitch" destination="DPu-zD-Als" id="eiG-Hv-Vko"/> <outlet property="backgroundRefreshSwitch" destination="DPu-zD-Als" id="eiG-Hv-Vko"/>
<outlet property="noIdleTimeoutSwitch" destination="iQA-wm-5ag" id="jHC-js-q0Y"/>
<outlet property="versionLabel" destination="bUR-rp-Nw2" id="85I-5R-hqz"/> <outlet property="versionLabel" destination="bUR-rp-Nw2" id="85I-5R-hqz"/>
</connections> </connections>
</tableViewController> </tableViewController>
@@ -986,7 +884,7 @@ Settings by i cons from the Noun Project</string>
</objects> </objects>
<point key="canvasLocation" x="1697" y="313"/> <point key="canvasLocation" x="1697" y="313"/>
</scene> </scene>
<!--Support us--> <!--Patreon-->
<scene sceneID="Lnh-9P-HnL"> <scene sceneID="Lnh-9P-HnL">
<objects> <objects>
<collectionViewController id="dp8-8j-vt9" customClass="PatreonViewController" customModule="SideStore" customModuleProvider="target" sceneMemberID="viewController"> <collectionViewController id="dp8-8j-vt9" customClass="PatreonViewController" customModule="SideStore" customModuleProvider="target" sceneMemberID="viewController">
@@ -1033,7 +931,7 @@ Settings by i cons from the Noun Project</string>
<outlet property="delegate" destination="dp8-8j-vt9" id="790-Kr-6l7"/> <outlet property="delegate" destination="dp8-8j-vt9" id="790-Kr-6l7"/>
</connections> </connections>
</collectionView> </collectionView>
<navigationItem key="navigationItem" title="Support us" largeTitleDisplayMode="always" id="uUV-1f-xEq"/> <navigationItem key="navigationItem" title="Patreon" largeTitleDisplayMode="always" id="uUV-1f-xEq"/>
</collectionViewController> </collectionViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="qq3-Hj-S9f" userLabel="First Responder" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="qq3-Hj-S9f" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects> </objects>

View File

@@ -30,14 +30,13 @@ extension SettingsViewController
fileprivate enum AppRefreshRow: Int, CaseIterable fileprivate enum AppRefreshRow: Int, CaseIterable
{ {
case backgroundRefresh case backgroundRefresh
case noIdleTimeout
@available(iOS 14, *) @available(iOS 14, *)
case addToSiri case addToSiri
static var allCases: [AppRefreshRow] { static var allCases: [AppRefreshRow] {
guard #available(iOS 14, *) else { return [.backgroundRefresh, .noIdleTimeout] } guard #available(iOS 14, *) else { return [.backgroundRefresh] }
return [.backgroundRefresh, .noIdleTimeout, .addToSiri] return [.backgroundRefresh, .addToSiri]
} }
} }
@@ -54,11 +53,8 @@ extension SettingsViewController
case sendFeedback case sendFeedback
case refreshAttempts case refreshAttempts
case errorLog case errorLog
case clearCache
case resetPairingFile case resetPairingFile
case resetAdiPb
case advancedSettings case advancedSettings
} }
} }
@@ -76,7 +72,6 @@ final class SettingsViewController: UITableViewController
@IBOutlet private var accountTypeLabel: UILabel! @IBOutlet private var accountTypeLabel: UILabel!
@IBOutlet private var backgroundRefreshSwitch: UISwitch! @IBOutlet private var backgroundRefreshSwitch: UISwitch!
@IBOutlet private var noIdleTimeoutSwitch: UISwitch!
@IBOutlet private var versionLabel: UILabel! @IBOutlet private var versionLabel: UILabel!
@@ -182,11 +177,11 @@ private extension SettingsViewController
case .patreon: case .patreon:
if isHeader if isHeader
{ {
settingsHeaderFooterView.primaryLabel.text = NSLocalizedString("SUPPORT US", comment: "") settingsHeaderFooterView.primaryLabel.text = NSLocalizedString("PATREON", comment: "")
} }
else else
{ {
settingsHeaderFooterView.secondaryLabel.text = NSLocalizedString("Support the SideStore Team by following our socials or becoming a patron!", comment: "") settingsHeaderFooterView.secondaryLabel.text = NSLocalizedString("Support the SideStore Team by becoming a patron!", comment: "")
} }
case .account: case .account:
@@ -284,11 +279,6 @@ private extension SettingsViewController
UserDefaults.standard.isBackgroundRefreshEnabled = sender.isOn UserDefaults.standard.isBackgroundRefreshEnabled = sender.isOn
} }
@IBAction func toggleNoIdleTimeoutEnabled(_ sender: UISwitch)
{
UserDefaults.standard.isIdleTimeoutDisableEnabled = sender.isOn
}
@available(iOS 14, *) @available(iOS 14, *)
@IBAction func addRefreshAppsShortcut() @IBAction func addRefreshAppsShortcut()
{ {
@@ -300,39 +290,6 @@ private extension SettingsViewController
self.present(viewController, animated: true, completion: nil) self.present(viewController, animated: true, completion: nil)
} }
func clearCache()
{
let alertController = UIAlertController(title: NSLocalizedString("Are you sure you want to clear SideStore's cache?", comment: ""),
message: NSLocalizedString("This will remove all temporary files as well as backups for uninstalled apps.", comment: ""),
preferredStyle: .actionSheet)
alertController.addAction(UIAlertAction(title: UIAlertAction.cancel.title, style: UIAlertAction.cancel.style) { [weak self] _ in
self?.tableView.indexPathForSelectedRow.map { self?.tableView.deselectRow(at: $0, animated: true) }
})
alertController.addAction(UIAlertAction(title: NSLocalizedString("Clear Cache", comment: ""), style: .destructive) { [weak self] _ in
AppManager.shared.clearAppCache { result in
DispatchQueue.main.async {
self?.tableView.indexPathForSelectedRow.map { self?.tableView.deselectRow(at: $0, animated: true) }
switch result
{
case .success: break
case .failure(let error):
let alertController = UIAlertController(title: NSLocalizedString("Unable to Clear Cache", comment: ""), message: error.localizedDescription, preferredStyle: .alert)
alertController.addAction(.ok)
self?.present(alertController, animated: true)
}
}
}
})
if let popoverController = alertController.popoverPresentationController {
popoverController.sourceView = self.view
popoverController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
}
self.present(alertController, animated: true)
}
@IBAction func handleDebugModeGesture(_ gestureRecognizer: UISwipeGestureRecognizer) @IBAction func handleDebugModeGesture(_ gestureRecognizer: UISwipeGestureRecognizer)
{ {
self.debugGestureCounter += 1 self.debugGestureCounter += 1
@@ -419,25 +376,14 @@ extension SettingsViewController
{ {
let cell = super.tableView(tableView, cellForRowAt: indexPath) let cell = super.tableView(tableView, cellForRowAt: indexPath)
// if #available(iOS 14, *) {} if #available(iOS 14, *) {}
// else if let cell = cell as? InsetGroupTableViewCell, else if let cell = cell as? InsetGroupTableViewCell,
// indexPath.section == Section.appRefresh.rawValue,
// indexPath.row == AppRefreshRow.backgroundRefresh.rawValue
// {
// // Only one row is visible pre-iOS 14.
// cell.style = .single
// }
if AppRefreshRow.AllCases().count == 1
{
if let cell = cell as? InsetGroupTableViewCell,
indexPath.section == Section.appRefresh.rawValue, indexPath.section == Section.appRefresh.rawValue,
indexPath.row == AppRefreshRow.backgroundRefresh.rawValue indexPath.row == AppRefreshRow.backgroundRefresh.rawValue
{ {
// Only one row is visible pre-iOS 14.
cell.style = .single cell.style = .single
} }
}
return cell return cell
} }
@@ -518,13 +464,11 @@ extension SettingsViewController
switch row switch row
{ {
case .backgroundRefresh: break case .backgroundRefresh: break
case .noIdleTimeout: break
case .addToSiri: case .addToSiri:
guard #available(iOS 14, *) else { return } guard #available(iOS 14, *) else { return }
self.addRefreshAppsShortcut() self.addRefreshAppsShortcut()
} }
case .credits: case .credits:
let row = CreditsRow.allCases[indexPath.row] let row = CreditsRow.allCases[indexPath.row]
switch row switch row
@@ -562,9 +506,6 @@ extension SettingsViewController
let toastView = ToastView(text: NSLocalizedString("Cannot Send Mail", comment: ""), detailText: nil) let toastView = ToastView(text: NSLocalizedString("Cannot Send Mail", comment: ""), detailText: nil)
toastView.show(in: self) toastView.show(in: self)
} }
case .clearCache: self.clearCache()
case .resetPairingFile: case .resetPairingFile:
let filename = "ALTPairingFile.mobiledevicepairing" let filename = "ALTPairingFile.mobiledevicepairing"
let fm = FileManager.default let fm = FileManager.default
@@ -589,25 +530,6 @@ extension SettingsViewController
alertController.popoverPresentationController?.sourceRect = self.tableView.rectForRow(at: indexPath) alertController.popoverPresentationController?.sourceRect = self.tableView.rectForRow(at: indexPath)
self.present(alertController, animated: true) self.present(alertController, animated: true)
self.tableView.deselectRow(at: indexPath, animated: true) self.tableView.deselectRow(at: indexPath, animated: true)
case .resetAdiPb:
let alertController = UIAlertController(
title: NSLocalizedString("Are you sure you want to reset the adi.pb file?", comment: ""),
message: NSLocalizedString("The adi.pb file is used to generate anisette data, which is required to log into an Apple ID. If you are having issues with account related things, you can try this. However, you will be required to do 2FA again. This will do nothing if you are using an older anisette server.", comment: ""),
preferredStyle: UIAlertController.Style.actionSheet)
alertController.addAction(UIAlertAction(title: NSLocalizedString("Reset adi.pb", comment: ""), style: .destructive){ _ in
if Keychain.shared.adiPb != nil {
Keychain.shared.adiPb = nil
print("Cleared adi.pb from keychain")
}
self.tableView.deselectRow(at: indexPath, animated: true)
})
alertController.addAction(.cancel)
//Fix crash on iPad
alertController.popoverPresentationController?.sourceView = self.tableView
alertController.popoverPresentationController?.sourceRect = self.tableView.rectForRow(at: indexPath)
self.present(alertController, animated: true)
self.tableView.deselectRow(at: indexPath, animated: true)
case .advancedSettings: case .advancedSettings:
// Create the URL that deep links to your app's custom settings. // Create the URL that deep links to your app's custom settings.
if let url = URL(string: UIApplication.openSettingsURLString) { if let url = URL(string: UIApplication.openSettingsURLString) {
@@ -617,7 +539,6 @@ extension SettingsViewController
ELOG("UIApplication.openSettingsURLString invalid") ELOG("UIApplication.openSettingsURLString invalid")
} }
case .refreshAttempts, .errorLog: break case .refreshAttempts, .errorLog: break
} }
default: break default: break

View File

@@ -77,12 +77,6 @@ public class Keychain
@KeychainItem(key: "patreonAccountID") @KeychainItem(key: "patreonAccountID")
public var patreonAccountID: String? public var patreonAccountID: String?
@KeychainItem(key: "identifier")
public var identifier: String?
@KeychainItem(key: "adiPb")
public var adiPb: String?
private init() private init()
{ {
} }

View File

@@ -27,7 +27,6 @@ public extension UserDefaults
@NSManaged var preferredServerID: String? @NSManaged var preferredServerID: String?
@NSManaged var isBackgroundRefreshEnabled: Bool @NSManaged var isBackgroundRefreshEnabled: Bool
@NSManaged var isIdleTimeoutDisableEnabled: Bool
@NSManaged var isDebugModeEnabled: Bool @NSManaged var isDebugModeEnabled: Bool
@NSManaged var presentedLaunchReminderNotification: Bool @NSManaged var presentedLaunchReminderNotification: Bool
@@ -43,7 +42,6 @@ public extension UserDefaults
@NSManaged var patronsRefreshID: String? @NSManaged var patronsRefreshID: String?
@NSManaged var trustedSourceIDs: [String]? @NSManaged var trustedSourceIDs: [String]?
@NSManaged var trustedServerURL: String?
var activeAppsLimit: Int? { var activeAppsLimit: Int? {
get { get {
@@ -73,7 +71,6 @@ public extension UserDefaults
let defaults = [ let defaults = [
#keyPath(UserDefaults.isBackgroundRefreshEnabled): true, #keyPath(UserDefaults.isBackgroundRefreshEnabled): true,
#keyPath(UserDefaults.isIdleTimeoutDisableEnabled): true,
#keyPath(UserDefaults.isLegacyDeactivationSupported): isLegacyDeactivationSupported, #keyPath(UserDefaults.isLegacyDeactivationSupported): isLegacyDeactivationSupported,
#keyPath(UserDefaults.activeAppLimitIncludesExtensions): activeAppLimitIncludesExtensions, #keyPath(UserDefaults.activeAppLimitIncludesExtensions): activeAppLimitIncludesExtensions,
#keyPath(UserDefaults.localServerSupportsRefreshing): localServerSupportsRefreshing, #keyPath(UserDefaults.localServerSupportsRefreshing): localServerSupportsRefreshing,

View File

@@ -192,7 +192,7 @@ public extension InstalledApp
class func fetchAppsForRefreshingAll(in context: NSManagedObjectContext) -> [InstalledApp] class func fetchAppsForRefreshingAll(in context: NSManagedObjectContext) -> [InstalledApp]
{ {
let predicate = NSPredicate(format: "%K == YES AND %K != %@", #keyPath(InstalledApp.isActive), #keyPath(InstalledApp.bundleIdentifier), StoreApp.altstoreAppID) var predicate = NSPredicate(format: "%K == YES AND %K != %@", #keyPath(InstalledApp.isActive), #keyPath(InstalledApp.bundleIdentifier), StoreApp.altstoreAppID)
print("Fetch Apps for Refreshing All 'AltStore' predicate: \(String(describing: predicate))") print("Fetch Apps for Refreshing All 'AltStore' predicate: \(String(describing: predicate))")
// if let patreonAccount = DatabaseManager.shared.patreonAccount(in: context), patreonAccount.isPatron, PatreonAPI.shared.isAuthenticated // if let patreonAccount = DatabaseManager.shared.patreonAccount(in: context), patreonAccount.isPatron, PatreonAPI.shared.isAuthenticated
@@ -223,7 +223,7 @@ public extension InstalledApp
// Date 6 hours before now. // Date 6 hours before now.
let date = Date().addingTimeInterval(-1 * 6 * 60 * 60) let date = Date().addingTimeInterval(-1 * 6 * 60 * 60)
let predicate = NSPredicate(format: "(%K == YES) AND (%K < %@) AND (%K != %@)", var predicate = NSPredicate(format: "(%K == YES) AND (%K < %@) AND (%K != %@)",
#keyPath(InstalledApp.isActive), #keyPath(InstalledApp.isActive),
#keyPath(InstalledApp.refreshedDate), date as NSDate, #keyPath(InstalledApp.refreshedDate), date as NSDate,
#keyPath(InstalledApp.bundleIdentifier), StoreApp.altstoreAppID) #keyPath(InstalledApp.bundleIdentifier), StoreApp.altstoreAppID)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 846 KiB

View File

@@ -5,12 +5,12 @@
"scale" : "1x" "scale" : "1x"
}, },
{ {
"filename" : "1024.png", "filename" : "Group 23_120.png",
"idiom" : "universal", "idiom" : "universal",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"filename" : "1024.png", "filename" : "Group 23_180.png",
"idiom" : "universal", "idiom" : "universal",
"scale" : "3x" "scale" : "3x"
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -1,7 +1,7 @@
{ {
"images" : [ "images" : [
{ {
"filename" : "sidestore-logo.svg", "filename" : "group16Copy2.pdf",
"idiom" : "universal" "idiom" : "universal"
} }
], ],

Binary file not shown.

View File

@@ -1,17 +0,0 @@
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
<title>sidestore-logo-svg</title>
<style>
.s0 { fill: none }
.s1 { fill: #bebbb4 }
</style>
<g id="Layer">
<g id="Layer">
<path id="Main" class="s0" />
<g id="Main1">
<g id="Layer">
<path id="Layer" fill-rule="evenodd" class="s1" d="m86 50c0 2.3-1.9 4.2-4.2 4.2h-50.9c-2.3 0-4.2-1.9-4.2-4.2 0-2.3 1.9-4.2 4.2-4.2h50.9c2.3 0 4.2 1.9 4.2 4.2zm-31.8-23.3v2.1c0 3.4-1.3 6.6-3.7 9-2.4 2.4-5.6 3.7-9 3.7h-10.6c-2.2 0-4.4 0.9-5.9 2.5-1.6 1.6-2.5 3.8-2.5 6 0 2.2 0.9 4.4 2.5 6 1.5 1.6 3.7 2.5 5.9 2.5h10.6c3.4 0 6.6 1.3 9 3.7 2.4 2.4 3.7 5.6 3.7 9v10.8c0 1.1-0.4 2.1-1.1 2.8-0.8 0.8-1.8 1.2-2.9 1.2h-0.4c-1.1 0-2.1-0.4-2.9-1.2-0.7-0.7-1.1-1.7-1.1-2.8v-10.8c0-1.1-0.5-2.2-1.3-3-0.8-0.8-1.8-1.3-3-1.3h-10.6c-4.5 0-8.8-1.7-11.9-4.9-3.2-3.2-5-7.5-5-12 0-4.5 1.8-8.8 5-12 3.1-3.2 7.4-4.9 11.9-4.9h10.6c1.2 0 2.2-0.5 3-1.3 0.8-0.8 1.3-1.9 1.3-3v-2.1h-4.3l8.5-12.7 8.5 12.7zm12.7 55.3c0 2.2-1.8 4-4 4h-0.5c-2.2 0-4-1.8-4-4v-19.5c0-2.2 1.8-4 4-4h0.5c2.2 0 4 1.8 4 4z"/>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,7 +1,7 @@
{ {
"images" : [ "images" : [
{ {
"filename" : "cir.svg", "filename" : "altminicon.pdf",
"idiom" : "universal" "idiom" : "universal"
} }
], ],

Binary file not shown.

View File

@@ -1,3 +0,0 @@
<svg width="100" height="100" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="50" fill="#fff" stroke-width=".265"/>
</svg>

Before

Width:  |  Height:  |  Size: 175 B

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>application-identifier</key>
<string>XYZ0123456.com.SideStore.SideStore.AltWidget</string>
<key>com.apple.developer.team-identifier</key>
<string>XYZ0123456</string>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.SideStore.SideStore</string>
</array>
<key>get-task-allow</key>
<true/>
</dict>
</plist>

View File

@@ -1,8 +1,8 @@
// Configuration settings file format documentation can be found at: // Configuration settings file format documentation can be found at:
// https://help.apple.com/xcode/#/dev745c5c974 // https://help.apple.com/xcode/#/dev745c5c974
MARKETING_VERSION = 0.5.4 MARKETING_VERSION = 0.3.0
CURRENT_PROJECT_VERSION = 5040 CURRENT_PROJECT_VERSION = 3020
// Vars to be overwritten by `CodeSigning.xcconfig` if exists // Vars to be overwritten by `CodeSigning.xcconfig` if exists
DEVELOPMENT_TEAM = S32Z3HMYVQ DEVELOPMENT_TEAM = S32Z3HMYVQ
@@ -14,14 +14,11 @@ ORG_IDENTIFIER = com.SideStore
ORG_PREFIX = $(ORG_IDENTIFIER) ORG_PREFIX = $(ORG_IDENTIFIER)
PRODUCT_NAME = SideStore PRODUCT_NAME = SideStore
EXTENSION_PREFIX = $(ORG_PREFIX).SideStore
//PRODUCT_NAME[configuration=Debug] = Prov Debug //PRODUCT_NAME[configuration=Debug] = Prov Debug
PRODUCT_BUNDLE_IDENTIFIER = $(ORG_PREFIX).SideStore PRODUCT_BUNDLE_IDENTIFIER = $(ORG_PREFIX).SideStore
// add team ID to bundle ID for debug builds since these will most likely be installed via Xcode //PRODUCT_BUNDLE_IDENTIFIER[configuration=Debug] = $(ORG_PREFIX).$(PROJECT_NAME:lower)-debug
// SideStore will expect the team ID to be at the end of the bundle ID, but this doesn't happen when we install via Xcode
// we don't want to do this for release since those builds will most likely be installed via SideServer, which adds the team ID
PRODUCT_BUNDLE_IDENTIFIER[config=Debug] = $(ORG_PREFIX).SideStore.$(DEVELOPMENT_TEAM)
EXTENSION_PREFIX = $(PRODUCT_BUNDLE_IDENTIFIER) APP_GROUP_IDENTIFIER = $(ORG_PREFIX).SideStore
APP_GROUP_IDENTIFIER = $(PRODUCT_BUNDLE_IDENTIFIER)
ICLOUD_CONTAINER_IDENTIFIER = iCloud.$(ORG_PREFIX).$(PROJECT_NAME) ICLOUD_CONTAINER_IDENTIFIER = iCloud.$(ORG_PREFIX).$(PROJECT_NAME)

View File

@@ -7,7 +7,7 @@ There are many ways to contribute to SideStore, so if you aren't a developer, th
- [Writing documentation](https://github.com/SideStore/SideStore-Docs) - [Writing documentation](https://github.com/SideStore/SideStore-Docs)
- [Submitting detailed bug reports and suggesting new features](https://github.com/SideStore/SideStore/issues/new/choose) - [Submitting detailed bug reports and suggesting new features](https://github.com/SideStore/SideStore/issues/new/choose)
- Helping out with support - Helping out with support
- [Discord](https://discord.gg/sidestore-949183273383395328) - [Discord](https://discord.gg/RgpFBX3Q3k)
- [GitHub Discussions](https://github.com/SideStore/SideStore/discussions) - [GitHub Discussions](https://github.com/SideStore/SideStore/discussions)
However, this guide will focus on the development side of things. For now, we will only have setup information here, but you can [join our Discord](https://discord.gg/RgpFBX3Q3k) if you need help However, this guide will focus on the development side of things. For now, we will only have setup information here, but you can [join our Discord](https://discord.gg/RgpFBX3Q3k) if you need help

137
Dangerfile.swift Normal file
View File

@@ -0,0 +1,137 @@
import Danger
import Foundation
// import SwiftLint
let danger = Danger()
// fileImport: DangerfileExtensions/ChangelogCheck.swift
// checkChangelog()
// Add a CHANGELOG entry for app changes
let hasChangelog = danger.git.modifiedFiles.contains("Changelog.md")
let isTrivial = (danger.github.pullRequest.body + danger.github.pullRequest.title).contains("#trivial")
if (!hasChangelog && !isTrivial) {
warn("Please add a changelog entry for your changes.")
}
// PR Too large
if danger.git.createdFiles.count + danger.git.modifiedFiles.count - danger.git.deletedFiles.count > 600 {
warn("Big PR, try to keep changes smaller if you can")
}
// Check copyright
let swiftFilesWithCopyright = danger.git.createdFiles.filter {
$0.fileType == .swift
&& danger.utils.readFile($0).contains("// Created by")
}
if !swiftFilesWithCopyright.isEmpty {
let files = swiftFilesWithCopyright.joined(separator: ", ")
warn("In Danger JS we don't include copyright headers, found them in: \(files)")
}
// # This is swiftlint plugin. More info: https://github.com/ashfurrow/danger-swiftlint
// #
// # This lints all Swift files and leave comments in PR if
// # there is any issue with linting
let filesToLint = (danger.git.modifiedFiles + danger.git.createdFiles) // .filter { !$0.contains("Documentation/") }
SwiftLint.lint(.files(filesToLint), inline: true)
// Support running via `danger local`
if danger.github != nil {
// These checks only happen on a PR
if danger.github.pullRequest.title.contains("WIP") {
warn("PR is classed as Work in Progress")
}
}
if github.pr_title.contains("WIP") {
warn("PR is classed as Work in Progress")
}
if git.commits.any {
return $0.message.contains("Merge branch '\(github.branch_for_base)'")
} {
fail("Please rebase to get rid of the merge commits in this PR ")
}
if github.pr_body.length > 1000 {
warn("PR body is too long")
}
if github.pr_body.length < 5 {
fail("PR body is too short")
}
let has_app_changes = !git.modified_files.any { $0.contains("AltStore") }
let has_altstorecore_changes = !git.modified_files.any { $0.contains("AltStoreCore") }
// let has_support_test_changes = !git.modified_files.any { $0.contains("AltStoreCore
// Tests") }
// let has_library_changes = !git.modified_files.any { $0.contains("PVLibrary") }
// let has_library_test_changes = !git.modified_files.any { $0.contains("PVLibrary Tests") }
// If changes are more than 10 lines of code, tests need to be updated too
// if (has_core_changes && !has_core_test_changes) ||
// (has_coreui_changes && !has_coreui_test_changes)) &&
// git.lines_of_code > 10 {
// fail("Tests were not updated", sticky: false)
// }
// Info.plist file shouldn't change often. Leave warning if it changes.
let is_plist_change = git.modified_files.any { $0.contains("Info.plist") }
if !is_plist_change
// warn "A Plist was changed"
warn("Plist changed, don't forget to localize your plist values")
end
// gemfile_updated = !git.modified_files.grep(/Gemfile$/).empty?
// # Leave warning, if Gemfile changes
// if gemfile_updated
// warn "The `Gemfile` was updated"
// end
// import xcodebuild
// xcodebuild.json_file = "./fastlane/reports/xcpretty-json-formatter-results.json"
// xcodebuild.parse_warnings() // returns number of warnings
// xcodebuild.parse_errors() // returns number of errors
// // xcodebuild.parse_errors(errors: danger.github.pull_request.body)
// xcodebuild.parse_tests() // returns number of test failures
// xcodebuild.perfect_build() // returns a bool indicating if the build was perfect
func checkSwiftVersions() {
SwiftChecks.check(
files: [
VersionFile(
path: "./\(projectName).xcodeproj/project.pbxproj",
interpreter: .regex("SWIFT_VERSION = (.*);")
),
VersionFile(
path: "./\(projectName).podspec",
interpreter: .regex("\\.swift_version\\s*=\\s*\"(.*)\"")
),
],
versionKind: "Swift"
)
}
func checkProjectVersions() {
SwiftChecks.check(
fileProviders: [
InfoPlistFileProvider(
discoveryMethod: .searchDirectory("./Sources", fileNames: ["Info.plist"]),
plistKey: .versionNumber,
projectFilePath: "./\(projectName).xcodeproj"
),
],
files: [
VersionFile(path: "./\(projectName).podspec", interpreter: .regex("\\.version\\s*=\\s*\"(.*)\"")),
],
versionKind: "framework"
)
}
// checkProjectVersions()
// checkSwiftVersions

View File

@@ -16,8 +16,8 @@ check_for_update() {
LAST_FETCH=`cat .last-prebuilt-fetch-$1 | perl -n -e '/([0-9]*),([^ ]*)$/ && print $1'` 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'` LAST_COMMIT=`cat .last-prebuilt-fetch-$1 | perl -n -e '/([0-9]*),([^ ]*)$/ && print $2'`
# fetch if last fetch was over 1 hour ago # fetch if last fetch was over 6 hours ago
if [[ $LAST_FETCH -lt $(expr $(date +%s) - 3600) ]] || [[ "$2" == "force" ]]; then if [[ $LAST_FETCH -lt $(expr $(date +%s) - 21600) ]] || [[ "$2" == "force" ]]; then
echo "Checking $1 for update" echo "Checking $1 for update"
echo echo
LATEST_COMMIT=`curl https://api.github.com/repos/SideStore/$1/releases/latest | perl -n -e '/Commit: https:\\/\\/github\\.com\\/[^\\/]*\\/[^\\/]*\\/commit\\/([^"]*)/ && print $1'` LATEST_COMMIT=`curl https://api.github.com/repos/SideStore/$1/releases/latest | perl -n -e '/Commit: https:\\/\\/github\\.com\\/[^\\/]*\\/[^\\/]*\\/commit\\/([^"]*)/ && print $1'`
@@ -27,30 +27,16 @@ check_for_update() {
if [[ "$LAST_COMMIT" != "$LATEST_COMMIT" ]]; then if [[ "$LAST_COMMIT" != "$LATEST_COMMIT" ]]; then
echo "Found update, downloading binaries" echo "Found update, downloading binaries"
echo echo
wget -O "$1/lib$1-sim.a" "https://github.com/SideStore/$1/releases/latest/download/lib$1-sim.a"
if [[ "$1" != "minimuxer" ]]; then
wget -O "$1/lib$1.a" "https://github.com/SideStore/$1/releases/latest/download/lib$1.a" 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" wget -O "$1/$1.h" "https://github.com/SideStore/$1/releases/latest/download/$1.h"
echo echo
else
wget -O "$1/lib$1-ios.a" "https://github.com/SideStore/$1/releases/latest/download/lib$1-ios.a"
wget -O "$1/generated.zip" "https://github.com/SideStore/$1/releases/latest/download/generated.zip"
echo
echo "Unzipping generated.zip"
cd "$1"
unzip ./generated.zip
mv -v generated/* .
rm generated.zip
rmdir generated/
cd ..
echo "Done"
fi
else else
echo "Up-to-date" echo "Up-to-date"
fi fi
echo "$(date +%s),$LATEST_COMMIT" > ".last-prebuilt-fetch-$1" echo "$(date +%s),$LATEST_COMMIT" > ".last-prebuilt-fetch-$1"
else else
echo "It hasn't been 1 hour and force was not specified, skipping update check for $1" echo "It hasn't been 6 hours and force was not specified, skipping update check for $1"
fi fi
} }

View File

@@ -7,7 +7,6 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
9961EC2829BE9C2000AF2C6F /* SwiftBridgeCore.h in Sources */ = {isa = PBXBuildFile; fileRef = 9961EC2729BE9C1200AF2C6F /* SwiftBridgeCore.h */; };
9987603329A454B500818586 /* minimuxer.h in Sources */ = {isa = PBXBuildFile; fileRef = 9987603229A454B500818586 /* minimuxer.h */; }; 9987603329A454B500818586 /* minimuxer.h in Sources */ = {isa = PBXBuildFile; fileRef = 9987603229A454B500818586 /* minimuxer.h */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
@@ -29,22 +28,12 @@
/* End PBXBuildRule section */ /* End PBXBuildRule section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
9961EC2729BE9C1200AF2C6F /* SwiftBridgeCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SwiftBridgeCore.h; path = minimuxer/SwiftBridgeCore.h; sourceTree = "<group>"; };
9987603229A454B500818586 /* minimuxer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = minimuxer.h; path = minimuxer/minimuxer.h; sourceTree = "<group>"; }; 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; }; 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; }; CA609C732349C7AAD9FA67C4 /* libminimuxer_static.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libminimuxer_static.a; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
99F87D1529D8E41100B40039 /* Generated */ = {
isa = PBXGroup;
children = (
9961EC2729BE9C1200AF2C6F /* SwiftBridgeCore.h */,
9987603229A454B500818586 /* minimuxer.h */,
);
name = Generated;
sourceTree = "<group>";
};
ADDEDBA66A6E2 /* Required for static linking */ = { ADDEDBA66A6E2 /* Required for static linking */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -72,7 +61,7 @@
CA6012A875F9D65BC3C892A8 = { CA6012A875F9D65BC3C892A8 = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
99F87D1529D8E41100B40039 /* Generated */, 9987603229A454B500818586 /* minimuxer.h */,
CA6012A875F922869D176AE5 /* Products */, CA6012A875F922869D176AE5 /* Products */,
CA6012A875F998AF0B5890DB /* Frameworks */, CA6012A875F998AF0B5890DB /* Frameworks */,
); );
@@ -85,7 +74,7 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = CA600589A243A560B9642892 /* Build configuration list for PBXNativeTarget "minimuxer-staticlib" */; buildConfigurationList = CA600589A243A560B9642892 /* Build configuration list for PBXNativeTarget "minimuxer-staticlib" */;
buildPhases = ( buildPhases = (
9987603629A4611D00818586 /* Run Script */, 9987603629A4611D00818586 /* ShellScript */,
CA600F638141A560B9642892 /* Sources */, CA600F638141A560B9642892 /* Sources */,
CA6012A875F9AF6EBB7F357C /* Universal Binary lipo */, CA6012A875F9AF6EBB7F357C /* Universal Binary lipo */,
); );
@@ -132,7 +121,7 @@
/* End PBXProject section */ /* End PBXProject section */
/* Begin PBXShellScriptBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */
9987603629A4611D00818586 /* Run Script */ = { 9987603629A4611D00818586 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
@@ -141,15 +130,10 @@
); );
inputPaths = ( inputPaths = (
); );
name = "Run Script";
outputFileListPaths = ( outputFileListPaths = (
); );
outputPaths = ( outputPaths = (
./minimuxer/minimuxer.h, ./minimuxer/minimuxer.h,
./minimuxer/SwiftBridgeCore.h,
./minimuxer/minimuxer.swift,
./minimuxer/SwiftBridgeCore.swift,
"./minimuxer/minimuxer-Bridging-Header.h",
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
@@ -182,7 +166,6 @@
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
9961EC2829BE9C2000AF2C6F /* SwiftBridgeCore.h in Sources */,
9987603329A454B500818586 /* minimuxer.h in Sources */, 9987603329A454B500818586 /* minimuxer.h in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@@ -199,7 +182,7 @@
INSTALL_MODE_FLAG = ""; INSTALL_MODE_FLAG = "";
INSTALL_OWNER = ""; INSTALL_OWNER = "";
LIB_FILE_NAME = ""; LIB_FILE_NAME = "";
"LIB_FILE_NAME[sdk=iphoneos*]" = "libminimuxer-ios"; "LIB_FILE_NAME[sdk=iphoneos*]" = libminimuxer;
"LIB_FILE_NAME[sdk=iphonesimulator*]" = "libminimuxer-sim"; "LIB_FILE_NAME[sdk=iphonesimulator*]" = "libminimuxer-sim";
PRODUCT_NAME = minimuxer_static; PRODUCT_NAME = minimuxer_static;
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
@@ -216,7 +199,7 @@
INSTALL_MODE_FLAG = ""; INSTALL_MODE_FLAG = "";
INSTALL_OWNER = ""; INSTALL_OWNER = "";
LIB_FILE_NAME = ""; LIB_FILE_NAME = "";
"LIB_FILE_NAME[sdk=iphoneos*]" = "libminimuxer-ios"; "LIB_FILE_NAME[sdk=iphoneos*]" = libminimuxer;
"LIB_FILE_NAME[sdk=iphonesimulator*]" = "libminimuxer-sim"; "LIB_FILE_NAME[sdk=iphonesimulator*]" = "libminimuxer-sim";
PRODUCT_NAME = minimuxer_static; PRODUCT_NAME = minimuxer_static;
SKIP_INSTALL = YES; SKIP_INSTALL = YES;

View File

@@ -165,13 +165,11 @@ build:
AD_HOC_CODE_SIGNING_ALLOWED=YES \ AD_HOC_CODE_SIGNING_ALLOWED=YES \
CODE_SIGNING_ALLOWED=NO \ CODE_SIGNING_ALLOWED=NO \
DEVELOPMENT_TEAM=XYZ0123456 \ DEVELOPMENT_TEAM=XYZ0123456 \
ORG_IDENTIFIER=com.SideStore \ ORG_IDENTIFIER=com.SideStore
DWARF_DSYM_FOLDER_PATH="."
fakesign: fakesign:
rm -rf archive.xcarchive/Products/Applications/SideStore.app/Frameworks/AltStoreCore.framework/Frameworks/ rm -rf archive.xcarchive/Products/Applications/SideStore.app/Frameworks/AltStoreCore.framework/Frameworks/
ldid -SAltStore/Resources/ReleaseEntitlements.plist archive.xcarchive/Products/Applications/SideStore.app/SideStore ldid -SAltStore/Resources/tempEnt.plist archive.xcarchive/Products/Applications/SideStore.app/SideStore
ldid -SAltWidget/Resources/ReleaseEntitlements.plist archive.xcarchive/Products/Applications/SideStore.app/PlugIns/AltWidgetExtension.appex/AltWidgetExtension
ipa: ipa:
mkdir Payload mkdir Payload

61
Package.resolved Normal file
View File

@@ -0,0 +1,61 @@
{
"object": {
"pins": [
{
"package": "Logger",
"repositoryURL": "https://github.com/shibapm/Logger",
"state": {
"branch": null,
"revision": "53c3ecca5abe8cf46697e33901ee774236d94cce",
"version": "0.2.3"
}
},
{
"package": "OctoKit",
"repositoryURL": "https://github.com/nerdishbynature/octokit.swift",
"state": {
"branch": null,
"revision": "f762f1566f7cd0e683b9329f169c28ab6ef993cc",
"version": "0.12.0"
}
},
{
"package": "RequestKit",
"repositoryURL": "https://github.com/nerdishbynature/RequestKit.git",
"state": {
"branch": null,
"revision": "8b0258ea2a4345cbcac90509b764faacea12efb0",
"version": "3.2.1"
}
},
{
"package": "Roxas",
"repositoryURL": "https://github.com/SideStore/Roxas.git",
"state": {
"branch": "swiftpm",
"revision": "fe142efb8b3e0330802aba3f44f508f712c0679f",
"version": null
}
},
{
"package": "danger-swift",
"repositoryURL": "https://github.com/danger/swift.git",
"state": {
"branch": null,
"revision": "579323889f26e6fb1ddb2cc5d98b1ab698bd2578",
"version": "3.14.2"
}
},
{
"package": "Version",
"repositoryURL": "https://github.com/mxcl/Version",
"state": {
"branch": null,
"revision": "1fe824b80d89201652e7eca7c9252269a1d85e25",
"version": "2.0.1"
}
}
]
},
"version": 1
}

212
Package.swift Normal file
View File

@@ -0,0 +1,212 @@
// swift-tools-version:5.6
import PackageDescription
// Version number can be found in Source/Danger/Danger.swift
// switch to false when release
let isDevelop = true
let devProducts: [Product] = isDevelop
? [
.library(name: "DangerDeps", type: .dynamic, targets: ["Danger-Swift"])
] : []
let devDependencies: [Package.Dependency] = isDevelop
? [
// .package(url: "https://github.com/shibapm/Komondor", from: "1.1.4"),
.package(url: "https://github.com/nicklockwood/SwiftFormat", from: "0.50.7"),
.package(url: "https://github.com/Realm/SwiftLint", branch: "main"),
.package(url: "https://github.com/pointfreeco/swift-snapshot-testing.git", from: "1.10.0"),
// .package(url: "https://github.com/shibapm/Rocket", from: "1.2.1")
] : []
let devTargets: [Target] = isDevelop
? [
.testTarget(name: "DangerTests",
dependencies: [
"Danger",
"DangerFixtures",
.product(name: "SnapshotTesting", package: "swift-snapshot-testing")
]),
.testTarget(name: "RunnerLibTests",
dependencies: [
"RunnerLib",
.product(name: "SnapshotTesting", package: "swift-snapshot-testing")
], exclude: ["__Snapshots__"]),
.testTarget(name: "DangerDependenciesResolverTests",
dependencies: [
"DangerDependenciesResolver",
.product(name: "SnapshotTesting", package: "swift-snapshot-testing")
],
exclude: ["__Snapshots__"]),
]
: []
let package = Package(
name: "danger-swift",
products: [
// .library(name: "DangerDeps[SideStore]", type: .dynamic, targets: ["DangerDependencies"]), // dev
.library(name: "SideStore", targets: ["SideStore", "SideStore-ObjC"]),
.library(name: "AltStoreCore", targets: ["AltStoreCore"]),
.library(name: "libimobiledevice", targets: ["libimobiledevice"]),
.library(name: "EmotionalDamage", targets: ["EmotionalDamage"]),
.library(name: "minimuxer", targets: ["minimuxer"]),
],
.library(name: "Danger", targets: ["Danger"]),
.library(name: "DangerFixtures", targets: ["DangerFixtures"]),
.executable(name: "danger-swift", targets: ["Runner"]),
] + devProducts,
dependencies: [
.package(url: "https://github.com/danger/swift.git", from: "3.0.0"), // dev
.package(url: "https://github.com/SideStore/Roxas.git", branch: "swiftpm"),
// Danger Plugins
// .package(url: "https://github.com/username/DangerPlugin.git", from: "0.1.0") // dev
],
.package(url: "https://github.com/shibapm/Logger", from: "0.1.0"),
.package(url: "https://github.com/mxcl/Version", from: "2.0.1"),
.package(name: "OctoKit", url: "https://github.com/nerdishbynature/octokit.swift", from: "0.12.0"),
] + devDependencies,
targets: [
// .target(name: "DangerDependencies", dependencies: ["Danger", "DangerPlugin"], path: "Dependencies/Danger"), // dev
.target(name: "SideStore",
dependencies: ["SideStore-ObjC", "AltStoreCore", "EmotionalDamage", "libimobiledevice", "minimuxer", "em_proxy"],
path: "AltStore",
exclude: ["Operations/Patch App/ALTAppPatcher.m"]),
.target(name: "SideStore-ObjC",
dependencies: ["Roxas"],
path: "AltStore",
sources: ["Operations/Patch App/ALTAppPatcher.m"],
publicHeadersPath: "Operations/Patch App/"),
.target(name: "AltStoreCore",
dependencies: ["AltStoreCore-ObjC"],
path: "AltStoreCore",
exclude: [
"Types/ALTAppPermission.m",
"Types/ALTPatreonBenefitType.m",
"Types/ALTSourceUserInfoKey.m"
]),
.target(name: "AltStoreCore-ObjC",
dependencies: ["Roxas"],
path: "AltStoreCore",
sources: ["Types/ALTAppPermission.m", "Types/ALTPatreonBenefitType.m", "Types/ALTSourceUserInfoKey.m"],
publicHeadersPath: "Types"),
.target(name: "EmotionalDamage",
dependencies: [""],
path: "EmotionalDamage"),
.target(name: "libimobiledevice",
dependencies: [""],
path: "Dependencies/libimobiledevice/src",
publicHeadersPath: "Dependencies/libimobiledevice/include/libimobiledevice"),
.binaryTarget( name: "minimuxer",
path: "Dependencies/minimuxer/target/release/minimuxer.xcframework"),
.binaryTarget( name: "em_proxy",
path: "Dependencies/em_proxy/target/release/em_proxy.xcframework"),
// name: "SideStore",
// // dependencies: [
// // .product(name: "RxSwift", package: "RxSwift")
// // ],
// path: "AltStore",
// exclude: ["Info.plist", "*.m"],
// cSettings: cSettings,
// cxxSettings: cxxSettings),
// .target(
// name: "PVLibrary-ObjC",
// // dependencies: [
// // .product(name: "RxSwift", package: "RxSwift")
// // ],
// path: "PVLibrary",
// exclude: ["Info.plist", "*.swift"],
// cSettings: cSettings,
// cxxSettings: cxxSettings),
]
.target(name: "Danger-Swift", dependencies: ["Danger"], plugins: [.plugin(name: "SwiftLintPlugin", package: "SwiftLint")]),
.target(name: "DangerShellExecutor"),
.target(name: "DangerDependenciesResolver", dependencies: ["DangerShellExecutor", "Version", "Logger"]),
.target(name: "Danger", dependencies: ["OctoKit", "Logger", "DangerShellExecutor"]),
.target(name: "RunnerLib", dependencies: ["Logger", "DangerShellExecutor", "Version"]),
.executableTarget(name: "Runner", dependencies: ["RunnerLib", "Logger", "DangerDependenciesResolver"]),
.target(name: "DangerFixtures", dependencies: ["Danger"]),
] + devTargets
)
// #if canImport(PackageConfig)
// import PackageConfig
// let config = PackageConfiguration([
// "komondor": [
// "pre-push": "swift test",
// "pre-commit": [
// "swift test",
// "swift test --generate-linuxmain",
// "swift run swiftformat .",
// "swift run swiftlint autocorrect --path Sources/",
// "git add ."
// ]
// ],
// "rocket": [
// "pre_release_checks": [
// "clean_git"
// ],
// "steps": [
// "Scripts/update_makefile.sh",
// "Scripts/update_danger_version.sh",
// "Scripts/update_changelog.sh",
// "Scripts/change_is_develop.sh false",
// "git_add",
// "commit",
// "tag",
// "push",
// "Scripts/change_is_develop.sh true",
// "git_add",
// ["commit": ["message": "Enable dev depdendencies"]],
// "push",
// "Scripts/create_homebrew_tap.sh"
// ]
// ]
// ]).write()
// #endif
// let package = Package(
// name: "SideStore",
// platforms: [
// .iOS(.v13),
// .tvOS(.v13),
// ],
// products: [
// .library(name: "DangerDeps[SideStore]", type: .dynamic, targets: ["DangerDependencies"]) // dev
// ],
// dependencies: [
// .package(url: "https://github.com/danger/swift.git", from: "3.0.0") // dev
// // Danger Plugins
// // .package(url: "https://github.com/username/DangerPlugin.git", from: "0.1.0") // dev
// ],
// targets: [
// .target(name: "DangerDependencies", dependencies: ["Danger", "DangerPlugin"]) // dev
// // name: "SideStore",
// // // dependencies: [
// // // .product(name: "RxSwift", package: "RxSwift")
// // // ],
// // path: "AltStore",
// // exclude: ["Info.plist", "*.m"],
// // cSettings: cSettings,
// // cxxSettings: cxxSettings),
// // .target(
// // name: "PVLibrary-ObjC",
// // // dependencies: [
// // // .product(name: "RxSwift", package: "RxSwift")
// // // ],
// // path: "PVLibrary",
// // exclude: ["Info.plist", "*.swift"],
// // cSettings: cSettings,
// // cxxSettings: cxxSettings),
// ]
// )

View File

@@ -4,17 +4,15 @@
[![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0) [![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://makeapullrequest.com) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://makeapullrequest.com)
[![Nightly SideStore build](https://github.com/SideStore/SideStore/actions/workflows/nightly.yml/badge.svg)](https://github.com/SideStore/SideStore/actions/workflows/nightly.yml) [![Build and Upload SideStore](https://github.com/SideStore/SideStore/actions/workflows/build.yml/badge.svg)](https://github.com/SideStore/SideStore/actions/workflows/build.yml)
[![.github/workflows/beta.yml](https://github.com/SideStore/SideStore/actions/workflows/beta.yml/badge.svg)](https://github.com/SideStore/SideStore/actions/workflows/beta.yml)
![Alt](https://repobeats.axiom.co/api/embed/3a329ce95955690b9a9366f8d5598626a847d96c.svg "Repobeats analytics image") SideStore is an iOS application that allows you to sideload apps onto your iOS device with just your Apple ID. SideStore resigns apps with your personal development certificate, and then uses a [specially designed VPN](https://github.com/jkcoxson/Secret-Tunnel) in order to trick iOS into installing them. SideStore will periodically "refresh" your apps in the background, to keep their normal 7-day development period from expiring.
SideStore is an iOS application that allows you to sideload apps onto your iOS device with just your Apple ID. SideStore resigns apps with your personal development certificate, and then uses a [specially designed VPN](https://github.com/jkcoxson/em_proxy) in order to trick iOS into installing them. SideStore will periodically "refresh" your apps in the background, to keep their normal 7-day development period from expiring.
SideStore's goal is to provide an untethered sideloading experience. It's a community driven fork of [AltStore](https://github.com/rileytestut/AltStore), and has already implemented some of the community's most-requested features. SideStore's goal is to provide an untethered sideloading experience. It's a community driven fork of [AltStore](https://github.com/rileytestut/AltStore), and has already implemented some of the community's most-requested features.
(Contributions are welcome! 🙂) (Contributions are welcome! 🙂)
## Requirements ## Requirements
- Xcode 14 - Xcode 14
- iOS 14+ - iOS 14+

View File

@@ -55,7 +55,7 @@ public extension Bundle
public extension Bundle public extension Bundle
{ {
static var baseAltStoreAppGroupID = "group." + Bundle.Info.appbundleIdentifier static var baseAltStoreAppGroupID = "group.com.SideStore.SideStore"
var appGroups: [String] { var appGroups: [String] {
return self.infoDictionary?[Bundle.Info.appGroups] as? [String] ?? [] return self.infoDictionary?[Bundle.Info.appGroups] as? [String] ?? []

View File

@@ -1,9 +0,0 @@
[Interface]
PrivateKey = AIIeeUDvk3NeAFJ9BWCQvPJize/9WZibMnGJ/0rt5k4=
Address = 10.7.0.10/24
[Peer]
PublicKey = kHDoekeYhBvfW9a9UQ+UCmpbG423eejTjcjW+DT+JF0=
AllowedIPs = 10.7.0.1/32
Endpoint = 127.0.0.1:51820
PersistentKeepalive = 25

79
app.json Normal file
View File

@@ -0,0 +1,79 @@
{
"name": "SideStore Offical",
"identifier": "com.SideStore.SideStore",
"sourceURL": "https://apps.sidestore.io/",
"apps": [
{
"name": "SideStore",
"bundleIdentifier": "com.SideStore.SideStore",
"developerName": "SideStore Team",
"version": "0.1.1",
"versionDate": "2022-010-15T12:00:00-05:00",
"versionDescription": "If you see this then please sideload the new version of SideStore via AltServer!",
"downloadURL": "https://github.com/SideStore/SideStore/releases/download/0.1.1/SideStore.ipa",
"localizedDescription": "SideStore is an alternative app store for non-jailbroken devices. \n\nSideStore allows you to sideload other .ipa files and apps from the Files app or via the SideStore Library",
"iconURL": "https://raw.githubusercontent.com/SideStore/apps.json/main/105070799.jpeg",
"tintColor": "8043FF",
"size": 5465976,
"screenshotURLs": [
"https://user-images.githubusercontent.com/705880/78942028-acf54300-7a6d-11ea-821c-5bb7a9b3e73a.PNG",
"https://user-images.githubusercontent.com/705880/78942222-0fe6da00-7a6e-11ea-9f2a-dda16157583c.PNG",
"https://user-images.githubusercontent.com/705880/65605577-332cba80-df5e-11e9-9f00-b369ce974f71.PNG"
],
"permissions": [
{
"type": "background-fetch",
"usageDescription": "SideStore periodically refreshes apps in the background to prevent them from expiring."
},
{
"type": "background-audio",
"usageDescription": "Allows SideStore to run longer than 30 seconds when refreshing apps in background."
}
]
}
],
"news": [
{
"title": "Rick on the rocks",
"identifier": "rick",
"caption": "never gonna give ya rocks",
"tintColor": "912F8D",
"imageURL": "https://variety.com/wp-content/uploads/2021/07/Rick-Astley-Never-Gonna-Give-You-Up.png?w=681&h=383&crop=1",
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"date": "2022-05-06",
"notify": false
},
{
"title": "Rick waves his arms around",
"identifier": "no",
"caption": "never gonna",
"tintColor": "912F8D",
"imageURL": "https://variety.com/wp-content/uploads/2021/07/Rick-Astley-Never-Gonna-Give-You-Up.png?w=681&h=383&crop=1",
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"date": "2022-05-05",
"notify": false
},
{
"title": "#StandWithUkraine",
"identifier": "support-ukraine",
"caption": "Find out how you can help support those impacted by the Russian invasion.",
"tintColor": "003e80",
"imageURL": "https://user-images.githubusercontent.com/705880/156053447-a158cac7-df5f-4497-8025-15c3c2e10b48.png",
"url": "https://linktr.ee/razomforukraine",
"date": "2022-03-01",
"notify": false
},
{
"title": "New to SideStore?",
"identifier": "updated-faq",
"caption": "Good luck!",
"tintColor": "8043FF",
"url": "https://faq.sidestore.io",
"date": "2050-07-28",
"notify": false
}
],
"userInfo": {
"patreonAccessToken": "uqoDoTxH8dY1ImE8tK76wxrzKk67gjyjBAcK8sD3RLU"
}
}

111
minimuxer/minimuxer.swift Normal file
View File

@@ -0,0 +1,111 @@
//
// minimuxer.swift
// minimuxer
//
// Created by Jackson Coxson on 10/27/22.
//
import Foundation
public enum Uhoh: Error {
case Good
case Bad(code: Int32)
}
public func start_minimuxer(pairing_file: String) -> Int32 {
let pf = NSString(string: pairing_file)
let pf_pointer = UnsafeMutablePointer<CChar>(mutating: pf.utf8String)
let u = NSString(string: getDocumentsDirectory().absoluteString)
let u_ptr = UnsafeMutablePointer<CChar>(mutating: u.utf8String)
return minimuxer_c_start(pf_pointer, u_ptr)
}
public func set_usbmuxd_socket() {
target_minimuxer_address()
}
public func debug_app(app_id: String) throws -> Uhoh {
let ai = NSString(string: app_id)
let ai_pointer = UnsafeMutablePointer<CChar>(mutating: ai.utf8String)
#if false // Retries
var res = minimuxer_debug_app(ai_pointer)
var attempts = 10
while (attempts != 0 && res != 0) {
print("(JIT) ATTEMPTS: \(attempts)")
res = minimuxer_debug_app(ai_pointer)
attempts -= 1
}
#else
let res = minimuxer_debug_app(ai_pointer)
#endif
if res != 0 {
throw Uhoh.Bad(code: res)
}
return Uhoh.Good
}
public func install_provisioning_profile(plist: Data) throws -> Uhoh {
let pls = String(decoding: plist, as: UTF8.self)
print(pls)
print(plist)
#if false // Retries
var res = minimuxer_install_provisioning_profile(x, UInt32(plist.count))
var attempts = 10
while (attempts != 0 && res != 0) {
print("(INSTALL) ATTEMPTS: \(attempts)")
res = minimuxer_install_provisioning_profile(x, UInt32(plist.count))
attempts -= 1
}
#else
let x = plist.withUnsafeBytes { buf in UnsafeMutableRawPointer(mutating: buf) }
#endif
let res = minimuxer_install_provisioning_profile(x, UInt32(plist.count))
if res != 0 {
throw Uhoh.Bad(code: res)
}
return Uhoh.Good
}
public func remove_provisioning_profile(id: String) throws -> Uhoh {
let id_ns = NSString(string: id)
let id_pointer = UnsafeMutablePointer<CChar>(mutating: id_ns.utf8String)
#if false // Retries
var res = minimuxer_remove_provisioning_profile(id_pointer)
var attempts = 10
while (attempts != 0 && res != 0) {
print("(REMOVE PROFILE) ATTEMPTS: \(attempts)")
res = minimuxer_remove_provisioning_profile(id_pointer)
attempts -= 1
}
#else
let res = minimuxer_remove_provisioning_profile(id_pointer)
#endif
if res != 0 {
throw Uhoh.Bad(code: res)
}
return Uhoh.Good
}
public func remove_app(app_id: String) throws -> Uhoh {
let ai = NSString(string: app_id)
let ai_pointer = UnsafeMutablePointer<CChar>(mutating: ai.utf8String)
let res = minimuxer_remove_app(ai_pointer)
if res != 0 {
throw Uhoh.Bad(code: res)
}
return Uhoh.Good
}
public func auto_mount_dev_image() {
let u = NSString(string: getDocumentsDirectory().absoluteString)
let u_ptr = UnsafeMutablePointer<CChar>(mutating: u.utf8String)
minimuxer_auto_mount(u_ptr)
}
func getDocumentsDirectory() -> URL {
// find all possible documents directories for this user
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
// just send back the first one, which ought to be the only one
return paths[0]
}

View File

@@ -32,17 +32,9 @@
"identifier": "eu.pokemmo.altstore", "identifier": "eu.pokemmo.altstore",
"sourceURL": "https://pokemmo.eu/altstore/" "sourceURL": "https://pokemmo.eu/altstore/"
}, },
{
"identifier": "dev.theodyssey.sidestore",
"sourceURL": "https://theodyssey.dev/altstore/odysseysource.json"
},
{ {
"identifier": "stream.yattee", "identifier": "stream.yattee",
"sourceURL": "https://repos.yattee.stream/alt/apps.json" "sourceURL": "https://repos.yattee.stream/alt/apps.json"
},
{
"identifier": "com.litritt.litsource",
"sourceURL": "https://altstore.ignitedemulator.com/"
} }
] ]
} }