mirror of
https://github.com/SideStore/SideStore.git
synced 2026-03-29 23:05:39 +02:00
Compare commits
1 Commits
0.5.9
...
junepark67
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d49098a8be |
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -7,7 +7,6 @@ body:
|
|||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
value: |
|
value: |
|
||||||
## Please note that the issue tracker is not for support
|
|
||||||
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/sidestore-949183273383395328) or [GitHub Discussions](https://github.com/SideStore/SideStore/discussions) for support.**
|
||||||
|
|||||||
12
.github/workflows/beta.yml
vendored
12
.github/workflows/beta.yml
vendored
@@ -11,13 +11,13 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: 'macos-14'
|
- os: 'macos-12'
|
||||||
version: '15.4'
|
version: '14.2'
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ jobs:
|
|||||||
run: echo "${{ steps.version.outputs.version }}"
|
run: echo "${{ steps.version.outputs.version }}"
|
||||||
|
|
||||||
- name: Setup Xcode
|
- name: Setup Xcode
|
||||||
uses: maxim-lobanov/setup-xcode@v1
|
uses: maxim-lobanov/setup-xcode@v1.4.1
|
||||||
with:
|
with:
|
||||||
xcode-version: ${{ matrix.version }}
|
xcode-version: ${{ matrix.version }}
|
||||||
|
|
||||||
@@ -91,13 +91,13 @@ jobs:
|
|||||||
run: mv SideStore.ipa SideStore-${{ steps.version.outputs.version }}.ipa
|
run: mv SideStore.ipa SideStore-${{ steps.version.outputs.version }}.ipa
|
||||||
|
|
||||||
- name: Upload SideStore.ipa Artifact
|
- name: Upload SideStore.ipa Artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v3.1.0
|
||||||
with:
|
with:
|
||||||
name: SideStore-${{ steps.version.outputs.version }}.ipa
|
name: SideStore-${{ steps.version.outputs.version }}.ipa
|
||||||
path: SideStore-${{ steps.version.outputs.version }}.ipa
|
path: SideStore-${{ steps.version.outputs.version }}.ipa
|
||||||
|
|
||||||
- name: Upload *.dSYM Artifact
|
- name: Upload *.dSYM Artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v3.1.0
|
||||||
with:
|
with:
|
||||||
name: SideStore-${{ steps.version.outputs.version }}-dSYM
|
name: SideStore-${{ steps.version.outputs.version }}-dSYM
|
||||||
path: ./*.dSYM/
|
path: ./*.dSYM/
|
||||||
|
|||||||
22
.github/workflows/nightly.yml
vendored
22
.github/workflows/nightly.yml
vendored
@@ -14,24 +14,21 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: 'macos-14'
|
- os: 'macos-12'
|
||||||
version: '15.4'
|
version: '14.2'
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: brew install ldid
|
run: brew install ldid
|
||||||
|
|
||||||
- name: Install xcbeautify
|
|
||||||
run: brew install xcbeautify
|
|
||||||
|
|
||||||
- name: Cache .nightly-build-num
|
- name: Cache .nightly-build-num
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: .nightly-build-num
|
path: .nightly-build-num
|
||||||
key: nightly-build-num
|
key: nightly-build-num
|
||||||
@@ -47,7 +44,7 @@ jobs:
|
|||||||
run: echo "${{ steps.version.outputs.version }}"
|
run: echo "${{ steps.version.outputs.version }}"
|
||||||
|
|
||||||
- name: Setup Xcode
|
- name: Setup Xcode
|
||||||
uses: maxim-lobanov/setup-xcode@v1.6.0
|
uses: maxim-lobanov/setup-xcode@v1.4.1
|
||||||
with:
|
with:
|
||||||
xcode-version: ${{ matrix.version }}
|
xcode-version: ${{ matrix.version }}
|
||||||
|
|
||||||
@@ -56,12 +53,9 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
key: xcode-cache-deriveddata-${{ github.sha }}
|
key: xcode-cache-deriveddata-${{ github.sha }}
|
||||||
restore-keys: xcode-cache-deriveddata-
|
restore-keys: xcode-cache-deriveddata-
|
||||||
swiftpm-cache-key: xcode-cache-sourcedata-${{ github.sha }}
|
|
||||||
swiftpm-cache-restore-keys: |
|
|
||||||
xcode-cache-sourcedata-
|
|
||||||
|
|
||||||
- name: Build SideStore
|
- name: Build SideStore
|
||||||
run: NSUnbufferedIO=YES make build 2>&1 | xcbeautify --renderer github-actions && exit ${PIPESTATUS[0]}
|
run: make build | xcpretty && exit ${PIPESTATUS[0]}
|
||||||
|
|
||||||
- name: Fakesign app
|
- name: Fakesign app
|
||||||
run: make fakesign
|
run: make fakesign
|
||||||
@@ -103,13 +97,13 @@ jobs:
|
|||||||
run: mv SideStore.ipa SideStore-${{ steps.version.outputs.version }}.ipa
|
run: mv SideStore.ipa SideStore-${{ steps.version.outputs.version }}.ipa
|
||||||
|
|
||||||
- name: Upload SideStore.ipa Artifact
|
- name: Upload SideStore.ipa Artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v3.1.0
|
||||||
with:
|
with:
|
||||||
name: SideStore-${{ steps.version.outputs.version }}.ipa
|
name: SideStore-${{ steps.version.outputs.version }}.ipa
|
||||||
path: SideStore-${{ steps.version.outputs.version }}.ipa
|
path: SideStore-${{ steps.version.outputs.version }}.ipa
|
||||||
|
|
||||||
- name: Upload *.dSYM Artifact
|
- name: Upload *.dSYM Artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v3.1.0
|
||||||
with:
|
with:
|
||||||
name: SideStore-${{ steps.version.outputs.version }}-dSYM
|
name: SideStore-${{ steps.version.outputs.version }}-dSYM
|
||||||
path: ./*.dSYM/
|
path: ./*.dSYM/
|
||||||
|
|||||||
14
.github/workflows/pr.yml
vendored
14
.github/workflows/pr.yml
vendored
@@ -9,13 +9,13 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: 'macos-14'
|
- os: 'macos-12'
|
||||||
version: '15.4'
|
version: '14.2'
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ jobs:
|
|||||||
run: echo "${{ steps.version.outputs.version }}"
|
run: echo "${{ steps.version.outputs.version }}"
|
||||||
|
|
||||||
- name: Setup Xcode
|
- name: Setup Xcode
|
||||||
uses: maxim-lobanov/setup-xcode@v1.6.0
|
uses: maxim-lobanov/setup-xcode@v1.4.1
|
||||||
with:
|
with:
|
||||||
xcode-version: ${{ matrix.version }}
|
xcode-version: ${{ matrix.version }}
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ jobs:
|
|||||||
restore-keys: xcode-cache-deriveddata-
|
restore-keys: xcode-cache-deriveddata-
|
||||||
|
|
||||||
- name: Build SideStore
|
- name: Build SideStore
|
||||||
run: NSUnbufferedIO=YES make build | xcbeautify --renderer github-actions && exit ${PIPESTATUS[0]}
|
run: make build | xcpretty && exit ${PIPESTATUS[0]}
|
||||||
|
|
||||||
- name: Fakesign app
|
- name: Fakesign app
|
||||||
run: make fakesign
|
run: make fakesign
|
||||||
@@ -58,13 +58,13 @@ jobs:
|
|||||||
run: mv SideStore.ipa SideStore-${{ steps.version.outputs.version }}.ipa
|
run: mv SideStore.ipa SideStore-${{ steps.version.outputs.version }}.ipa
|
||||||
|
|
||||||
- name: Upload SideStore.ipa Artifact
|
- name: Upload SideStore.ipa Artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v3.1.0
|
||||||
with:
|
with:
|
||||||
name: SideStore-${{ steps.version.outputs.version }}.ipa
|
name: SideStore-${{ steps.version.outputs.version }}.ipa
|
||||||
path: SideStore-${{ steps.version.outputs.version }}.ipa
|
path: SideStore-${{ steps.version.outputs.version }}.ipa
|
||||||
|
|
||||||
- name: Upload *.dSYM Artifact
|
- name: Upload *.dSYM Artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v3.1.0
|
||||||
with:
|
with:
|
||||||
name: SideStore-${{ steps.version.outputs.version }}-dSYM
|
name: SideStore-${{ steps.version.outputs.version }}-dSYM
|
||||||
path: ./*.dSYM/
|
path: ./*.dSYM/
|
||||||
|
|||||||
18
.github/workflows/stable.yml
vendored
18
.github/workflows/stable.yml
vendored
@@ -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:
|
||||||
@@ -12,13 +11,13 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: 'macos-14'
|
- os: 'macos-12'
|
||||||
version: '15.4'
|
version: '14.2'
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
@@ -36,7 +35,7 @@ jobs:
|
|||||||
run: echo "${{ steps.version.outputs.version }}"
|
run: echo "${{ steps.version.outputs.version }}"
|
||||||
|
|
||||||
- name: Setup Xcode
|
- name: Setup Xcode
|
||||||
uses: maxim-lobanov/setup-xcode@v1.6.0
|
uses: maxim-lobanov/setup-xcode@v1.4.1
|
||||||
with:
|
with:
|
||||||
xcode-version: ${{ matrix.version }}
|
xcode-version: ${{ matrix.version }}
|
||||||
|
|
||||||
@@ -45,12 +44,9 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
key: xcode-cache-deriveddata-${{ github.sha }}
|
key: xcode-cache-deriveddata-${{ github.sha }}
|
||||||
restore-keys: xcode-cache-deriveddata-
|
restore-keys: xcode-cache-deriveddata-
|
||||||
swiftpm-cache-key: xcode-cache-sourcedata-${{ github.sha }}
|
|
||||||
swiftpm-cache-restore-keys: |
|
|
||||||
xcode-cache-sourcedata-
|
|
||||||
|
|
||||||
- name: Build SideStore
|
- name: Build SideStore
|
||||||
run: NSUnbufferedIO=YES make build | xcbeautify --renderer github-actions && exit ${PIPESTATUS[0]}
|
run: make build | xcpretty && exit ${PIPESTATUS[0]}
|
||||||
|
|
||||||
- name: Fakesign app
|
- name: Fakesign app
|
||||||
run: make fakesign
|
run: make fakesign
|
||||||
@@ -91,13 +87,13 @@ jobs:
|
|||||||
run: mv SideStore.ipa SideStore-${{ steps.version.outputs.version }}.ipa
|
run: mv SideStore.ipa SideStore-${{ steps.version.outputs.version }}.ipa
|
||||||
|
|
||||||
- name: Upload SideStore.ipa Artifact
|
- name: Upload SideStore.ipa Artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v3.1.0
|
||||||
with:
|
with:
|
||||||
name: SideStore-${{ steps.version.outputs.version }}.ipa
|
name: SideStore-${{ steps.version.outputs.version }}.ipa
|
||||||
path: SideStore-${{ steps.version.outputs.version }}.ipa
|
path: SideStore-${{ steps.version.outputs.version }}.ipa
|
||||||
|
|
||||||
- name: Upload *.dSYM Artifact
|
- name: Upload *.dSYM Artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v3.1.0
|
||||||
with:
|
with:
|
||||||
name: SideStore-${{ steps.version.outputs.version }}-dSYM
|
name: SideStore-${{ steps.version.outputs.version }}-dSYM
|
||||||
path: ./*.dSYM/
|
path: ./*.dSYM/
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -19,6 +19,7 @@ archive.xcarchive
|
|||||||
*.perspectivev3
|
*.perspectivev3
|
||||||
!default.perspectivev3
|
!default.perspectivev3
|
||||||
xcuserdata
|
xcuserdata
|
||||||
|
AltStore.xcodeproj/project.xcworkspace/xcshareddata/swiftpm
|
||||||
## Other
|
## Other
|
||||||
*.xccheckout
|
*.xccheckout
|
||||||
*.moved-aside
|
*.moved-aside
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
//
|
|
||||||
// ErrorDetailsViewController.swift
|
|
||||||
// AltServer
|
|
||||||
//
|
|
||||||
// Created by Riley Testut on 10/4/22.
|
|
||||||
// Copyright © 2022 Riley Testut. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
import AppKit
|
|
||||||
|
|
||||||
class ErrorDetailsViewController: NSViewController
|
|
||||||
{
|
|
||||||
var error: NSError? {
|
|
||||||
didSet {
|
|
||||||
self.update()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@IBOutlet private var errorCodeLabel: NSTextField!
|
|
||||||
@IBOutlet private var detailedDescriptionLabel: NSTextField!
|
|
||||||
|
|
||||||
override func viewDidLoad()
|
|
||||||
{
|
|
||||||
super.viewDidLoad()
|
|
||||||
|
|
||||||
self.detailedDescriptionLabel.preferredMaxLayoutWidth = 800
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private extension ErrorDetailsViewController
|
|
||||||
{
|
|
||||||
func update()
|
|
||||||
{
|
|
||||||
if !self.isViewLoaded
|
|
||||||
{
|
|
||||||
self.loadView()
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let error = self.error else { return }
|
|
||||||
|
|
||||||
self.errorCodeLabel.stringValue = error.localizedErrorCode
|
|
||||||
|
|
||||||
let font = self.detailedDescriptionLabel.font ?? NSFont.systemFont(ofSize: 12)
|
|
||||||
let detailedDescription = error.formattedDetailedDescription(with: font)
|
|
||||||
self.detailedDescriptionLabel.attributedStringValue = detailedDescription
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -10,7 +10,6 @@
|
|||||||
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 */; };
|
||||||
0E05025A2BEC83C500879B5C /* OperatingSystemVersion+Comparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0502592BEC83C500879B5C /* OperatingSystemVersion+Comparable.swift */; };
|
0E05025A2BEC83C500879B5C /* OperatingSystemVersion+Comparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0502592BEC83C500879B5C /* OperatingSystemVersion+Comparable.swift */; };
|
||||||
0E05025C2BEC947000879B5C /* String+SideStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E05025B2BEC947000879B5C /* String+SideStore.swift */; };
|
0E05025C2BEC947000879B5C /* String+SideStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E05025B2BEC947000879B5C /* String+SideStore.swift */; };
|
||||||
0E13E5862CC8F55900E9C0DF /* ProcessInfo+SideStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E13E5852CC8F55900E9C0DF /* ProcessInfo+SideStore.swift */; };
|
|
||||||
0E1A1F912AE36A9700364CAD /* bytearray.c in Sources */ = {isa = PBXBuildFile; fileRef = 0E1A1F902AE36A9600364CAD /* bytearray.c */; };
|
0E1A1F912AE36A9700364CAD /* bytearray.c in Sources */ = {isa = PBXBuildFile; fileRef = 0E1A1F902AE36A9600364CAD /* bytearray.c */; };
|
||||||
0E764E172ADFF5740043DD4E /* AltBackup.ipa in Resources */ = {isa = PBXBuildFile; fileRef = 0E764E162ADFF5740043DD4E /* AltBackup.ipa */; };
|
0E764E172ADFF5740043DD4E /* AltBackup.ipa in Resources */ = {isa = PBXBuildFile; fileRef = 0E764E162ADFF5740043DD4E /* AltBackup.ipa */; };
|
||||||
0EA1665B2ADFE0D2003015C1 /* out-limd.c in Sources */ = {isa = PBXBuildFile; fileRef = 0EA166472ADFE0D1003015C1 /* out-limd.c */; };
|
0EA1665B2ADFE0D2003015C1 /* out-limd.c in Sources */ = {isa = PBXBuildFile; fileRef = 0EA166472ADFE0D1003015C1 /* out-limd.c */; };
|
||||||
@@ -60,7 +59,6 @@
|
|||||||
99F87D0529D8B4E200B40039 /* minimuxer-helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9961EC2D29BE9F2E00AF2C6F /* minimuxer-helpers.swift */; };
|
99F87D0529D8B4E200B40039 /* minimuxer-helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9961EC2D29BE9F2E00AF2C6F /* minimuxer-helpers.swift */; };
|
||||||
99F87D1829D8E4C900B40039 /* SwiftBridgeCore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99F87D1629D8E4C900B40039 /* SwiftBridgeCore.swift */; };
|
99F87D1829D8E4C900B40039 /* SwiftBridgeCore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99F87D1629D8E4C900B40039 /* SwiftBridgeCore.swift */; };
|
||||||
99F87D1929D8E4C900B40039 /* minimuxer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99F87D1729D8E4C900B40039 /* minimuxer.swift */; };
|
99F87D1929D8E4C900B40039 /* minimuxer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99F87D1729D8E4C900B40039 /* minimuxer.swift */; };
|
||||||
A800F7042CE28E3800208744 /* View+AltWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = A800F7032CE28E2F00208744 /* View+AltWidget.swift */; };
|
|
||||||
B3146ED2284F581E00BBC3FD /* Roxas.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B3146ECD284F580500BBC3FD /* Roxas.framework */; };
|
B3146ED2284F581E00BBC3FD /* Roxas.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B3146ECD284F580500BBC3FD /* Roxas.framework */; };
|
||||||
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 */; };
|
||||||
@@ -511,7 +509,6 @@
|
|||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
0E0502592BEC83C500879B5C /* OperatingSystemVersion+Comparable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OperatingSystemVersion+Comparable.swift"; sourceTree = "<group>"; };
|
0E0502592BEC83C500879B5C /* OperatingSystemVersion+Comparable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OperatingSystemVersion+Comparable.swift"; sourceTree = "<group>"; };
|
||||||
0E05025B2BEC947000879B5C /* String+SideStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+SideStore.swift"; sourceTree = "<group>"; };
|
0E05025B2BEC947000879B5C /* String+SideStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+SideStore.swift"; sourceTree = "<group>"; };
|
||||||
0E13E5852CC8F55900E9C0DF /* ProcessInfo+SideStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProcessInfo+SideStore.swift"; sourceTree = "<group>"; };
|
|
||||||
0E1A1F902AE36A9600364CAD /* bytearray.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = bytearray.c; path = src/bytearray.c; sourceTree = "<group>"; };
|
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; };
|
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; };
|
0EA166412ADFE0D1003015C1 /* jplist.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = jplist.c; path = Dependencies/libplist/src/jplist.c; sourceTree = SOURCE_ROOT; };
|
||||||
@@ -560,7 +557,6 @@
|
|||||||
9961EC2D29BE9F2E00AF2C6F /* minimuxer-helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "minimuxer-helpers.swift"; path = "Dependencies/minimuxer/minimuxer-helpers.swift"; sourceTree = SOURCE_ROOT; };
|
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; };
|
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; };
|
99F87D1729D8E4C900B40039 /* minimuxer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = minimuxer.swift; path = Dependencies/minimuxer/minimuxer.swift; sourceTree = SOURCE_ROOT; };
|
||||||
A800F7032CE28E2F00208744 /* View+AltWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+AltWidget.swift"; sourceTree = "<group>"; };
|
|
||||||
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>"; };
|
||||||
@@ -1010,14 +1006,6 @@
|
|||||||
name = Generated;
|
name = Generated;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
A800F6FE2CE28DE300208744 /* Extensions */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
A800F7032CE28E2F00208744 /* View+AltWidget.swift */,
|
|
||||||
);
|
|
||||||
path = Extensions;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
B3146EC7284F580500BBC3FD /* Products */ = {
|
B3146EC7284F580500BBC3FD /* Products */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -1475,7 +1463,6 @@
|
|||||||
BF98916C250AABF3002ACF50 /* AltWidget */ = {
|
BF98916C250AABF3002ACF50 /* AltWidget */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
A800F6FE2CE28DE300208744 /* Extensions */,
|
|
||||||
BF8B17F0250AC62400F8157F /* AltWidgetExtension.entitlements */,
|
BF8B17F0250AC62400F8157F /* AltWidgetExtension.entitlements */,
|
||||||
BF98917D250AAC4F002ACF50 /* AltWidget.swift */,
|
BF98917D250AAC4F002ACF50 /* AltWidget.swift */,
|
||||||
BF42345825101C1D006D1EB2 /* WidgetView.swift */,
|
BF42345825101C1D006D1EB2 /* WidgetView.swift */,
|
||||||
@@ -1691,7 +1678,6 @@
|
|||||||
BFE00A1F2503097F00EB4D0C /* INInteraction+AltStore.swift */,
|
BFE00A1F2503097F00EB4D0C /* INInteraction+AltStore.swift */,
|
||||||
D57F2C9326E01BC700B9FA39 /* UIDevice+Vibration.swift */,
|
D57F2C9326E01BC700B9FA39 /* UIDevice+Vibration.swift */,
|
||||||
B376FE3D29258C8900E18883 /* OSLog+SideStore.swift */,
|
B376FE3D29258C8900E18883 /* OSLog+SideStore.swift */,
|
||||||
0E13E5852CC8F55900E9C0DF /* ProcessInfo+SideStore.swift */,
|
|
||||||
);
|
);
|
||||||
path = Extensions;
|
path = Extensions;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -2500,7 +2486,6 @@
|
|||||||
BF42345A25101C35006D1EB2 /* WidgetView.swift in Sources */,
|
BF42345A25101C35006D1EB2 /* WidgetView.swift in Sources */,
|
||||||
D55E163728776CB700A627A1 /* ComplicationView.swift in Sources */,
|
D55E163728776CB700A627A1 /* ComplicationView.swift in Sources */,
|
||||||
BF98917F250AAC4F002ACF50 /* AltWidget.swift in Sources */,
|
BF98917F250AAC4F002ACF50 /* AltWidget.swift in Sources */,
|
||||||
A800F7042CE28E3800208744 /* View+AltWidget.swift in Sources */,
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -2567,7 +2552,6 @@
|
|||||||
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 */,
|
99F87D0529D8B4E200B40039 /* minimuxer-helpers.swift in Sources */,
|
||||||
0E13E5862CC8F55900E9C0DF /* ProcessInfo+SideStore.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 */,
|
||||||
@@ -3085,7 +3069,6 @@
|
|||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)";
|
DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)";
|
||||||
ENABLE_DEBUG_DYLIB = NO;
|
|
||||||
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||||
INFOPLIST_FILE = AltWidget/Info.plist;
|
INFOPLIST_FILE = AltWidget/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||||
@@ -3116,7 +3099,6 @@
|
|||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)";
|
DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)";
|
||||||
ENABLE_DEBUG_DYLIB = NO;
|
|
||||||
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||||
INFOPLIST_FILE = AltWidget/Info.plist;
|
INFOPLIST_FILE = AltWidget/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||||
@@ -3283,7 +3265,6 @@
|
|||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)";
|
DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)";
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
ENABLE_DEBUG_DYLIB = NO;
|
|
||||||
GCC_UNROLL_LOOPS = YES;
|
GCC_UNROLL_LOOPS = YES;
|
||||||
INFOPLIST_FILE = AltStore/Info.plist;
|
INFOPLIST_FILE = AltStore/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||||
@@ -3323,7 +3304,6 @@
|
|||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)";
|
DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)";
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
ENABLE_DEBUG_DYLIB = NO;
|
|
||||||
GCC_OPTIMIZATION_LEVEL = fast;
|
GCC_OPTIMIZATION_LEVEL = fast;
|
||||||
GCC_UNROLL_LOOPS = YES;
|
GCC_UNROLL_LOOPS = YES;
|
||||||
INFOPLIST_FILE = AltStore/Info.plist;
|
INFOPLIST_FILE = AltStore/Info.plist;
|
||||||
|
|||||||
@@ -1,114 +0,0 @@
|
|||||||
{
|
|
||||||
"originHash" : "ee46302f91cbb62c5234c36750d40856658e961e191f5536cf4fe74d10fc2c94",
|
|
||||||
"pins" : [
|
|
||||||
{
|
|
||||||
"identity" : "altsign",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/SideStore/AltSign",
|
|
||||||
"state" : {
|
|
||||||
"branch" : "master",
|
|
||||||
"revision" : "4323ff794e600ce1759cb6ea57275e13b7ea72f2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "appcenter-sdk-apple",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/microsoft/appcenter-sdk-apple.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "b2dc99cfedead0bad4e6573d86c5228c89cff332",
|
|
||||||
"version" : "4.4.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "imobiledevice.swift",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/SideStore/iMobileDevice.swift",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "74e481106dd155c0cd21bca6795fd9fe5f751654",
|
|
||||||
"version" : "1.0.5"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "keychainaccess",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/kishikawakatsumi/KeychainAccess.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "84e546727d66f1adc5439debad16270d0fdd04e7",
|
|
||||||
"version" : "4.2.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "launchatlogin",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/sindresorhus/LaunchAtLogin.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "e8171b3e38a2816f579f58f3dac1522aa39efe41",
|
|
||||||
"version" : "4.2.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "nuke",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/kean/Nuke.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "9318d02a8a6d20af56505c9673261c1fd3b3aebe",
|
|
||||||
"version" : "7.6.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "openssl",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/krzyzanowskim/OpenSSL",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "8cb1d641ab5ebce2cd7cf31c93baef07bed672d4",
|
|
||||||
"version" : "1.1.2301"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "plcrashreporter",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/microsoft/PLCrashReporter.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "81cdec2b3827feb03286cb297f4c501a8eb98df1",
|
|
||||||
"version" : "1.10.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "semanticversion",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/SwiftPackageIndex/SemanticVersion.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "ea8eea9d89842a29af1b8e6c7677f1c86e72fa42",
|
|
||||||
"version" : "0.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "sparkle",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/sparkle-project/Sparkle.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "0ef1ee0220239b3776f433314515fd849025673f",
|
|
||||||
"version" : "2.6.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "starscream",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/daltoniam/Starscream.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "c6bfd1af48efcc9a9ad203665db12375ba6b145a",
|
|
||||||
"version" : "4.0.8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "stprivilegedtask",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/JoeMatt/STPrivilegedTask.git",
|
|
||||||
"state" : {
|
|
||||||
"branch" : "master",
|
|
||||||
"revision" : "10a9150ef32d444af326beba76356ae9af95a3e7"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"version" : 3
|
|
||||||
}
|
|
||||||
111
AltStore.xcodeproj/xcshareddata/xcschemes/AltDaemon.xcscheme
Normal file
111
AltStore.xcodeproj/xcshareddata/xcschemes/AltDaemon.xcscheme
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1150"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "NO"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "A7A6DC28A6D60809855FE404C6A3EA29"
|
||||||
|
BuildableName = "libPods-AltDaemon.a"
|
||||||
|
BlueprintName = "Pods-AltDaemon"
|
||||||
|
ReferencedContainer = "container:Pods/Pods.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "BF1E314F22A0616100370A3C"
|
||||||
|
BuildableName = "libAltKit.a"
|
||||||
|
BlueprintName = "AltKit"
|
||||||
|
ReferencedContainer = "container:AltStore.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "BF18BFE624857D7900DD5981"
|
||||||
|
BuildableName = "AltDaemon"
|
||||||
|
BlueprintName = "AltDaemon"
|
||||||
|
ReferencedContainer = "container:AltStore.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "BF18BFE624857D7900DD5981"
|
||||||
|
BuildableName = "AltDaemon"
|
||||||
|
BlueprintName = "AltDaemon"
|
||||||
|
ReferencedContainer = "container:AltStore.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
<EnvironmentVariables>
|
||||||
|
<EnvironmentVariable
|
||||||
|
key = "THEOS"
|
||||||
|
value = "~/theos"
|
||||||
|
isEnabled = "YES">
|
||||||
|
</EnvironmentVariable>
|
||||||
|
</EnvironmentVariables>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "BF18BFE624857D7900DD5981"
|
||||||
|
BuildableName = "AltDaemon"
|
||||||
|
BlueprintName = "AltDaemon"
|
||||||
|
ReferencedContainer = "container:AltStore.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
67
AltStore.xcodeproj/xcshareddata/xcschemes/AltPlugin.xcscheme
Normal file
67
AltStore.xcodeproj/xcshareddata/xcschemes/AltPlugin.xcscheme
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1120"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "BF5C5FC4237DF5AE00EDD0C6"
|
||||||
|
BuildableName = "AltPlugin.mailbundle"
|
||||||
|
BlueprintName = "AltPlugin"
|
||||||
|
ReferencedContainer = "container:AltStore.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "1"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "BF5C5FC4237DF5AE00EDD0C6"
|
||||||
|
BuildableName = "AltPlugin.mailbundle"
|
||||||
|
BlueprintName = "AltPlugin"
|
||||||
|
ReferencedContainer = "container:AltStore.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
91
AltStore.xcodeproj/xcshareddata/xcschemes/AltServer.xcscheme
Normal file
91
AltStore.xcodeproj/xcshareddata/xcschemes/AltServer.xcscheme
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1020"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "BF45868C229872EA00BD7491"
|
||||||
|
BuildableName = "AltServer.app"
|
||||||
|
BlueprintName = "AltServer"
|
||||||
|
ReferencedContainer = "container:AltStore.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "BF45868C229872EA00BD7491"
|
||||||
|
BuildableName = "AltServer.app"
|
||||||
|
BlueprintName = "AltServer"
|
||||||
|
ReferencedContainer = "container:AltStore.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "BF45868C229872EA00BD7491"
|
||||||
|
BuildableName = "AltServer.app"
|
||||||
|
BlueprintName = "AltServer"
|
||||||
|
ReferencedContainer = "container:AltStore.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "BF45868C229872EA00BD7491"
|
||||||
|
BuildableName = "AltServer.app"
|
||||||
|
BlueprintName = "AltServer"
|
||||||
|
ReferencedContainer = "container:AltStore.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
@@ -55,26 +55,7 @@
|
|||||||
argument = "-com.apple.CoreData.ConcurrencyDebug 1"
|
argument = "-com.apple.CoreData.ConcurrencyDebug 1"
|
||||||
isEnabled = "YES">
|
isEnabled = "YES">
|
||||||
</CommandLineArgument>
|
</CommandLineArgument>
|
||||||
<CommandLineArgument
|
|
||||||
argument = "-com.apple.CoreData.MigrationDebug 1"
|
|
||||||
isEnabled = "YES">
|
|
||||||
</CommandLineArgument>
|
|
||||||
<CommandLineArgument
|
|
||||||
argument = "-com.apple.CoreData.SQLiteIntegrityCheck 1"
|
|
||||||
isEnabled = "NO">
|
|
||||||
</CommandLineArgument>
|
|
||||||
<CommandLineArgument
|
|
||||||
argument = "-com.apple.CoreData.SQLDebug 1"
|
|
||||||
isEnabled = "NO">
|
|
||||||
</CommandLineArgument>
|
|
||||||
</CommandLineArguments>
|
</CommandLineArguments>
|
||||||
<EnvironmentVariables>
|
|
||||||
<EnvironmentVariable
|
|
||||||
key = "OS_ACTIVITY_MODE"
|
|
||||||
value = "$(DEBUG_ACTIVITY_MODE)"
|
|
||||||
isEnabled = "YES">
|
|
||||||
</EnvironmentVariable>
|
|
||||||
</EnvironmentVariables>
|
|
||||||
</LaunchAction>
|
</LaunchAction>
|
||||||
<ProfileAction
|
<ProfileAction
|
||||||
buildConfiguration = "Release"
|
buildConfiguration = "Release"
|
||||||
@@ -55,26 +55,7 @@
|
|||||||
argument = "-com.apple.CoreData.ConcurrencyDebug 1"
|
argument = "-com.apple.CoreData.ConcurrencyDebug 1"
|
||||||
isEnabled = "YES">
|
isEnabled = "YES">
|
||||||
</CommandLineArgument>
|
</CommandLineArgument>
|
||||||
<CommandLineArgument
|
|
||||||
argument = "-com.apple.CoreData.MigrationDebug 1"
|
|
||||||
isEnabled = "YES">
|
|
||||||
</CommandLineArgument>
|
|
||||||
<CommandLineArgument
|
|
||||||
argument = "-com.apple.CoreData.SQLiteIntegrityCheck 1"
|
|
||||||
isEnabled = "NO">
|
|
||||||
</CommandLineArgument>
|
|
||||||
<CommandLineArgument
|
|
||||||
argument = "-com.apple.CoreData.SQLDebug 1"
|
|
||||||
isEnabled = "NO">
|
|
||||||
</CommandLineArgument>
|
|
||||||
</CommandLineArguments>
|
</CommandLineArguments>
|
||||||
<EnvironmentVariables>
|
|
||||||
<EnvironmentVariable
|
|
||||||
key = "OS_ACTIVITY_MODE"
|
|
||||||
value = "$(DEBUG_ACTIVITY_MODE)"
|
|
||||||
isEnabled = "YES">
|
|
||||||
</EnvironmentVariable>
|
|
||||||
</EnvironmentVariables>
|
|
||||||
</LaunchAction>
|
</LaunchAction>
|
||||||
<ProfileAction
|
<ProfileAction
|
||||||
buildConfiguration = "Release"
|
buildConfiguration = "Release"
|
||||||
77
AltStore.xcodeproj/xcshareddata/xcschemes/AltXPC.xcscheme
Normal file
77
AltStore.xcodeproj/xcshareddata/xcschemes/AltXPC.xcscheme
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1230"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "BFF7C903257844C900E55F36"
|
||||||
|
BuildableName = "AltXPC.xpc"
|
||||||
|
BlueprintName = "AltXPC"
|
||||||
|
ReferencedContainer = "container:AltStore.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "BF45868C229872EA00BD7491"
|
||||||
|
BuildableName = "AltServer.app"
|
||||||
|
BlueprintName = "AltServer"
|
||||||
|
ReferencedContainer = "container:AltStore.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "BFF7C903257844C900E55F36"
|
||||||
|
BuildableName = "AltXPC.xpc"
|
||||||
|
BlueprintName = "AltXPC"
|
||||||
|
ReferencedContainer = "container:AltStore.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
@@ -2,12 +2,6 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>com.apple.developer.kernel.extended-virtual-addressing</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.developer.kernel.increased-debugging-memory-limit</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.developer.kernel.increased-memory-limit</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.developer.siri</key>
|
<key>com.apple.developer.siri</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>com.apple.security.application-groups</key>
|
<key>com.apple.security.application-groups</key>
|
||||||
|
|||||||
@@ -112,8 +112,6 @@ private extension AuthenticationViewController
|
|||||||
|
|
||||||
let toastView = ToastView(error: error)
|
let toastView = ToastView(error: error)
|
||||||
toastView.show(in: self)
|
toastView.show(in: self)
|
||||||
toastView.textLabel.textColor = .altPrimary
|
|
||||||
toastView.detailTextLabel.textColor = .altPrimary
|
|
||||||
self.toastView = toastView
|
self.toastView = toastView
|
||||||
|
|
||||||
self.signInButton.isIndicatingActivity = false
|
self.signInButton.isIndicatingActivity = false
|
||||||
|
|||||||
@@ -1,96 +0,0 @@
|
|||||||
//
|
|
||||||
// ProcessInfo+SideStore.swift
|
|
||||||
// SideStore
|
|
||||||
//
|
|
||||||
// Created by ny on 10/23/24.
|
|
||||||
// Copyright © 2024 SideStore. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
fileprivate struct BuildVersion: Comparable {
|
|
||||||
let prefix: String
|
|
||||||
let numericPart: Int
|
|
||||||
let suffix: Character?
|
|
||||||
|
|
||||||
init?(_ buildString: String) {
|
|
||||||
// Initialize indices
|
|
||||||
var index = buildString.startIndex
|
|
||||||
|
|
||||||
// Extract prefix (letters before the numeric part)
|
|
||||||
while index < buildString.endIndex, !buildString[index].isNumber {
|
|
||||||
index = buildString.index(after: index)
|
|
||||||
}
|
|
||||||
guard index > buildString.startIndex else { return nil }
|
|
||||||
self.prefix = String(buildString[buildString.startIndex..<index])
|
|
||||||
|
|
||||||
// Extract numeric part
|
|
||||||
let startOfNumeric = index
|
|
||||||
while index < buildString.endIndex, buildString[index].isNumber {
|
|
||||||
index = buildString.index(after: index)
|
|
||||||
}
|
|
||||||
guard let numericValue = Int(buildString[startOfNumeric..<index]) else { return nil }
|
|
||||||
self.numericPart = numericValue
|
|
||||||
|
|
||||||
// Extract suffix (if any)
|
|
||||||
if index < buildString.endIndex {
|
|
||||||
self.suffix = buildString[index]
|
|
||||||
} else {
|
|
||||||
self.suffix = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implement Comparable protocol
|
|
||||||
static func < (lhs: BuildVersion, rhs: BuildVersion) -> Bool {
|
|
||||||
// Compare prefixes
|
|
||||||
if lhs.prefix != rhs.prefix {
|
|
||||||
return lhs.prefix < rhs.prefix
|
|
||||||
}
|
|
||||||
// Compare numeric parts
|
|
||||||
if lhs.numericPart != rhs.numericPart {
|
|
||||||
return lhs.numericPart < rhs.numericPart
|
|
||||||
}
|
|
||||||
// Compare suffixes
|
|
||||||
switch (lhs.suffix, rhs.suffix) {
|
|
||||||
case let (l?, r?):
|
|
||||||
return l < r
|
|
||||||
case (nil, _?):
|
|
||||||
return true // nil is considered less than any character
|
|
||||||
case (_?, nil):
|
|
||||||
return false
|
|
||||||
default:
|
|
||||||
return false // Both are nil and equal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static func == (lhs: BuildVersion, rhs: BuildVersion) -> Bool {
|
|
||||||
return lhs.prefix == rhs.prefix &&
|
|
||||||
lhs.numericPart == rhs.numericPart &&
|
|
||||||
lhs.suffix == rhs.suffix
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension ProcessInfo {
|
|
||||||
var shortVersion: String {
|
|
||||||
operatingSystemVersionString
|
|
||||||
.replacingOccurrences(of: "Version ", with: "")
|
|
||||||
.replacingOccurrences(of: "Build ", with: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
var operatingSystemBuild: String {
|
|
||||||
if let start = shortVersion.range(of: "(")?.upperBound,
|
|
||||||
let end = shortVersion.range(of: ")")?.lowerBound {
|
|
||||||
shortVersion[start..<end].replacingOccurrences(of: "Build ", with: "")
|
|
||||||
} else { "???" }
|
|
||||||
}
|
|
||||||
|
|
||||||
var sparseRestorePatched: Bool {
|
|
||||||
if operatingSystemVersion < OperatingSystemVersion(majorVersion: 18, minorVersion: 1, patchVersion: 0) { false }
|
|
||||||
else if operatingSystemVersion > OperatingSystemVersion(majorVersion: 18, minorVersion: 1, patchVersion: 1) { true }
|
|
||||||
else if operatingSystemVersion >= OperatingSystemVersion(majorVersion: 18, minorVersion: 1, patchVersion: 0),
|
|
||||||
let currentBuild = BuildVersion(operatingSystemBuild),
|
|
||||||
let targetBuild = BuildVersion("22B5054e") {
|
|
||||||
currentBuild >= targetBuild
|
|
||||||
} else { false }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -92,7 +92,7 @@
|
|||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>LSSupportsOpeningDocumentsInPlace</key>
|
<key>LSSupportsOpeningDocumentsInPlace</key>
|
||||||
<false/>
|
<true/>
|
||||||
<key>NSAppTransportSecurity</key>
|
<key>NSAppTransportSecurity</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSAllowsArbitraryLoads</key>
|
<key>NSAllowsArbitraryLoads</key>
|
||||||
|
|||||||
@@ -118,9 +118,8 @@ private extension IntentHandler
|
|||||||
{
|
{
|
||||||
// Queue response in case refreshing finishes after confirm() but before handle().
|
// Queue response in case refreshing finishes after confirm() but before handle().
|
||||||
self.queuedResponses[intent] = response
|
self.queuedResponses[intent] = response
|
||||||
DispatchQueue.main.async {
|
|
||||||
UIApplication.shared.perform(#selector(NSXPCConnection.suspend))
|
UIApplication.shared.perform(#selector(NSXPCConnection.suspend))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ extension AppManager
|
|||||||
|
|
||||||
func deactivateApps(for app: ALTApplication, presentingViewController: UIViewController, completion: @escaping (Result<Void, Error>) -> Void)
|
func deactivateApps(for app: ALTApplication, presentingViewController: UIViewController, completion: @escaping (Result<Void, Error>) -> Void)
|
||||||
{
|
{
|
||||||
guard !UserDefaults.standard.isAppLimitDisabled, let activeAppsLimit = UserDefaults.standard.activeAppsLimit else { return completion(.success(())) }
|
guard let activeAppsLimit = UserDefaults.standard.activeAppsLimit else { return completion(.success(())) }
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
let activeApps = InstalledApp.fetchActiveApps(in: DatabaseManager.shared.viewContext)
|
let activeApps = InstalledApp.fetchActiveApps(in: DatabaseManager.shared.viewContext)
|
||||||
@@ -1015,133 +1015,89 @@ private extension AppManager
|
|||||||
return group
|
return group
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeAppExtensions(
|
func removeAppExtensions(from application: ALTApplication, extensions: Set<ALTApplication>, _ presentingViewController: UIViewController, completion: @escaping (Result<Void, Error>) -> Void)
|
||||||
from application: ALTApplication,
|
{
|
||||||
existingApp: InstalledApp?,
|
|
||||||
extensions: Set<ALTApplication>,
|
|
||||||
_ presentingViewController: UIViewController?,
|
|
||||||
completion: @escaping (Result<Void, Error>) -> Void
|
|
||||||
) {
|
|
||||||
|
|
||||||
// App-Extensions: Ensure existing app's extensions and currently installing app's extensions must match
|
|
||||||
if let existingApp {
|
|
||||||
_ = RSTAsyncBlockOperation { _ in
|
|
||||||
let existingAppEx: Set<InstalledExtension> = existingApp.appExtensions
|
|
||||||
let currentAppEx: Set<ALTApplication> = application.appExtensions
|
|
||||||
|
|
||||||
let currentAppExNames = currentAppEx.map{ appEx in appEx.bundleIdentifier}
|
|
||||||
let existingAppExNames = existingAppEx.map{ appEx in appEx.bundleIdentifier}
|
|
||||||
|
|
||||||
let excessExtensions = currentAppEx.filter{
|
|
||||||
!(existingAppExNames.contains($0.bundleIdentifier))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let isMatching = (currentAppEx.count == existingAppEx.count) && excessExtensions.isEmpty
|
|
||||||
let diagnosticsMsg = "AppManager.removeAppExtensions: App Extensions in existingApp and currentApp are matching: \(isMatching)\n"
|
|
||||||
+ "AppManager.removeAppExtensions: existingAppEx: \(existingAppExNames); currentAppEx: \(String(describing: currentAppExNames))\n"
|
|
||||||
print(diagnosticsMsg)
|
|
||||||
|
|
||||||
|
|
||||||
// if background mode, then remove only the excess extensions
|
|
||||||
guard let presentingViewController: UIViewController = presentingViewController else {
|
|
||||||
// perform silent extensions cleanup for those that aren't already present in existing app
|
|
||||||
print("\n Performing background mode Extensions removal \n")
|
|
||||||
print("AppManager.removeAppExtensions: Excess Extensions: \(excessExtensions)")
|
|
||||||
|
|
||||||
do {
|
|
||||||
for appExtension in excessExtensions {
|
|
||||||
print("Deleting extension \(appExtension.bundleIdentifier)")
|
|
||||||
try FileManager.default.removeItem(at: appExtension.fileURL)
|
|
||||||
}
|
|
||||||
return completion(.success(()))
|
|
||||||
} catch {
|
|
||||||
return completion(.failure(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
guard !application.appExtensions.isEmpty else { return completion(.success(())) }
|
guard !application.appExtensions.isEmpty else { return completion(.success(())) }
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
let firstSentence: String
|
||||||
let firstSentence: String
|
|
||||||
|
if UserDefaults.standard.activeAppLimitIncludesExtensions
|
||||||
if UserDefaults.standard.activeAppLimitIncludesExtensions
|
{
|
||||||
|
firstSentence = NSLocalizedString("Non-developer Apple IDs are limited to 3 active apps and app extensions.", comment: "")
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
firstSentence = NSLocalizedString("Non-developer Apple IDs are limited to creating 10 App IDs per week.", comment: "")
|
||||||
|
}
|
||||||
|
|
||||||
|
let message = firstSentence + " " + NSLocalizedString("Would you like to remove this app's extensions so they don't count towards your limit? There are \(extensions.count) Extensions", comment: "")
|
||||||
|
|
||||||
|
let alertController = UIAlertController(title: NSLocalizedString("App Contains Extensions", comment: ""), message: message, preferredStyle: .alert)
|
||||||
|
alertController.addAction(UIAlertAction(title: UIAlertAction.cancel.title, style: UIAlertAction.cancel.style, handler: { (action) in
|
||||||
|
completion(.failure(OperationError.cancelled))
|
||||||
|
}))
|
||||||
|
alertController.addAction(UIAlertAction(title: NSLocalizedString("Keep App Extensions", comment: ""), style: .default) { (action) in
|
||||||
|
completion(.success(()))
|
||||||
|
})
|
||||||
|
alertController.addAction(UIAlertAction(title: NSLocalizedString("Remove App Extensions", comment: ""), style: .destructive) { (action) in
|
||||||
|
do
|
||||||
{
|
{
|
||||||
firstSentence = NSLocalizedString("Non-developer Apple IDs are limited to 3 active apps and app extensions.", comment: "")
|
for appExtension in application.appExtensions
|
||||||
}
|
{
|
||||||
else
|
try FileManager.default.removeItem(at: appExtension.fileURL)
|
||||||
{
|
}
|
||||||
firstSentence = NSLocalizedString("Non-developer Apple IDs are limited to creating 10 App IDs per week.", comment: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
let message = firstSentence + " " + NSLocalizedString("Would you like to remove this app's extensions so they don't count towards your limit? There are \(extensions.count) Extensions", comment: "")
|
|
||||||
|
|
||||||
let alertController = UIAlertController(title: NSLocalizedString("App Contains Extensions", comment: ""), message: message, preferredStyle: .alert)
|
|
||||||
alertController.addAction(UIAlertAction(title: UIAlertAction.cancel.title, style: UIAlertAction.cancel.style, handler: { (action) in
|
|
||||||
completion(.failure(OperationError.cancelled))
|
|
||||||
}))
|
|
||||||
alertController.addAction(UIAlertAction(title: NSLocalizedString("Keep App Extensions", comment: ""), style: .default) { (action) in
|
|
||||||
completion(.success(()))
|
completion(.success(()))
|
||||||
})
|
}
|
||||||
alertController.addAction(UIAlertAction(title: NSLocalizedString("Remove App Extensions", comment: ""), style: .destructive) { (action) in
|
catch
|
||||||
|
{
|
||||||
|
completion(.failure(error))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
alertController.addAction(UIAlertAction(title: NSLocalizedString("Choose App Extensions", comment: ""), style: .default) { (action) in
|
||||||
|
let popoverContentController = AppExtensionViewHostingController(extensions: extensions) { (selection) in
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
for appExtension in application.appExtensions
|
for appExtension in selection
|
||||||
{
|
{
|
||||||
print("Deleting extension \(appExtension.bundleIdentifier)")
|
print("Deleting extension \(appExtension.bundleIdentifier)")
|
||||||
|
|
||||||
try FileManager.default.removeItem(at: appExtension.fileURL)
|
try FileManager.default.removeItem(at: appExtension.fileURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
completion(.success(()))
|
completion(.success(()))
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
})
|
return nil
|
||||||
|
|
||||||
if let presentingViewController {
|
|
||||||
alertController.addAction(UIAlertAction(title: NSLocalizedString("Choose App Extensions", comment: ""), style: .default) { (action) in
|
|
||||||
let popoverContentController = AppExtensionViewHostingController(extensions: extensions) { (selection) in
|
|
||||||
do
|
|
||||||
{
|
|
||||||
for appExtension in selection
|
|
||||||
{
|
|
||||||
print("Deleting extension \(appExtension.bundleIdentifier)")
|
|
||||||
|
|
||||||
try FileManager.default.removeItem(at: appExtension.fileURL)
|
|
||||||
}
|
|
||||||
completion(.success(()))
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
let suiview = popoverContentController.view!
|
|
||||||
suiview.translatesAutoresizingMaskIntoConstraints = false
|
|
||||||
|
|
||||||
popoverContentController.modalPresentationStyle = .popover
|
|
||||||
|
|
||||||
if let popoverPresentationController = popoverContentController.popoverPresentationController {
|
|
||||||
popoverPresentationController.sourceView = presentingViewController.view
|
|
||||||
popoverPresentationController.sourceRect = CGRect(x: 50, y: 50, width: 4, height: 4)
|
|
||||||
popoverPresentationController.delegate = popoverContentController
|
|
||||||
|
|
||||||
presentingViewController.present(popoverContentController, animated: true)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
presentingViewController.present(alertController, animated: true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let suiview = popoverContentController.view!
|
||||||
|
suiview.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
|
||||||
|
popoverContentController.modalPresentationStyle = .popover
|
||||||
|
|
||||||
|
if let popoverPresentationController = popoverContentController.popoverPresentationController {
|
||||||
|
popoverPresentationController.sourceView = presentingViewController.view
|
||||||
|
popoverPresentationController.sourceRect = CGRect(x: 50, y: 50, width: 4, height: 4)
|
||||||
|
popoverPresentationController.delegate = popoverContentController
|
||||||
|
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
presentingViewController.present(popoverContentController, animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
presentingViewController.present(alertController, animated: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func _install(_ app: AppProtocol, operation appOperation: AppOperation, group: RefreshGroup, context: InstallAppOperationContext? = nil, additionalEntitlements: [ALTEntitlement: Any] = [.increasedDebuggingMemoryLimit: ALTEntitlement.increasedDebuggingMemoryLimit, .increasedMemoryLimit: ALTEntitlement.increasedMemoryLimit, .extendedVirtualAddressing: ALTEntitlement.extendedVirtualAddressing], cacheApp: Bool = true, completionHandler: @escaping (Result<InstalledApp, Error>) -> Void) -> Progress
|
private func _install(_ app: AppProtocol, operation appOperation: AppOperation, group: RefreshGroup, context: InstallAppOperationContext? = nil, additionalEntitlements: [ALTEntitlement: Any]? = nil, cacheApp: Bool = true, completionHandler: @escaping (Result<InstalledApp, Error>) -> Void) -> Progress
|
||||||
{
|
{
|
||||||
let progress = Progress.discreteProgress(totalUnitCount: 100)
|
let progress = Progress.discreteProgress(totalUnitCount: 100)
|
||||||
|
|
||||||
@@ -1222,26 +1178,18 @@ private extension AppManager
|
|||||||
{
|
{
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
guard case .install = appOperation else {
|
guard case .install = appOperation else {
|
||||||
operation.finish()
|
operation.finish()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
guard let extensions = context.app?.appExtensions else {
|
|
||||||
throw OperationError.invalidParameters("AppManager._install.removeAppExtensionsOperation: context.app?.appExtensions is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let currentApp = context.app else {
|
guard let extensions = context.app?.appExtensions else { throw OperationError.invalidParameters }
|
||||||
throw OperationError.invalidParameters("AppManager._install.removeAppExtensionsOperation: context.app is nil")
|
|
||||||
}
|
guard let app = context.app, let presentingViewController = context.authenticatedContext.presentingViewController else { throw OperationError.invalidParameters }
|
||||||
|
|
||||||
|
|
||||||
self?.removeAppExtensions(from: currentApp,
|
self?.removeAppExtensions(from: app, extensions: extensions, presentingViewController) { result in
|
||||||
existingApp: app as? InstalledApp,
|
|
||||||
extensions: extensions,
|
|
||||||
context.authenticatedContext.presentingViewController
|
|
||||||
) { result in
|
|
||||||
switch result {
|
switch result {
|
||||||
case .success(): break
|
case .success(): break
|
||||||
case .failure(let error): context.error = error
|
case .failure(let error): context.error = error
|
||||||
@@ -1252,7 +1200,7 @@ private extension AppManager
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
context.error = error
|
group.context.error = error
|
||||||
operation.finish()
|
operation.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1304,20 +1252,13 @@ private extension AppManager
|
|||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let profiles = context.provisioningProfiles else {
|
guard let profiles = context.provisioningProfiles else { throw OperationError.invalidParameters }
|
||||||
throw OperationError.invalidParameters("AppManager._install.deactivateAppsOperation: context.provisioningProfiles is nil")
|
|
||||||
}
|
|
||||||
if !profiles.contains(where: { $1.isFreeProvisioningProfile == true }) {
|
if !profiles.contains(where: { $1.isFreeProvisioningProfile == true }) {
|
||||||
operation.finish()
|
operation.finish()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard
|
guard let app = context.app, let presentingViewController = context.authenticatedContext.presentingViewController else { throw OperationError.invalidParameters }
|
||||||
let app = context.app,
|
|
||||||
let presentingViewController = context.authenticatedContext.presentingViewController
|
|
||||||
else {
|
|
||||||
throw OperationError.invalidParameters("AppManager._install.deactivateAppsOperation: self.context.app or context.authenticatedContext.presentingViewController is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
self?.deactivateApps(for: app, presentingViewController: presentingViewController) { result in
|
self?.deactivateApps(for: app, presentingViewController: presentingViewController) { result in
|
||||||
switch result
|
switch result
|
||||||
@@ -1356,9 +1297,7 @@ private extension AppManager
|
|||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let app = context.app else {
|
guard let app = context.app else { throw OperationError.invalidParameters }
|
||||||
throw OperationError.invalidParameters("AppManager._install.patchAppOperation: context.app is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let isUntetherRequired = app.bundle.infoDictionary?[Bundle.Info.untetherRequired] as? Bool,
|
guard let isUntetherRequired = app.bundle.infoDictionary?[Bundle.Info.untetherRequired] as? Bool,
|
||||||
let minimumiOSVersionString = app.bundle.infoDictionary?[Bundle.Info.untetherMinimumiOSVersion] as? String,
|
let minimumiOSVersionString = app.bundle.infoDictionary?[Bundle.Info.untetherMinimumiOSVersion] as? String,
|
||||||
@@ -1463,7 +1402,57 @@ 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, removeAppExtensionsOperation, refreshAnisetteDataOperation, fetchProvisioningProfilesOperation, deactivateAppsOperation, patchAppOperation, resignAppOperation, sendAppOperation, installOperation]
|
let notificationRegistrationOperation = RSTAsyncBlockOperation { (operation) in
|
||||||
|
do
|
||||||
|
{
|
||||||
|
|
||||||
|
if let error = context.error
|
||||||
|
{
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
guard let app = context.installedApp else { operation.finish(); return }
|
||||||
|
let content = UNMutableNotificationContent()
|
||||||
|
content.title = "App Expiring Soon"
|
||||||
|
let formatter = DateComponentsFormatter()
|
||||||
|
formatter.unitsStyle = .full
|
||||||
|
formatter.includesApproximationPhrase = false
|
||||||
|
formatter.includesTimeRemainingPhrase = false
|
||||||
|
|
||||||
|
formatter.allowedUnits = [.day, .hour, .minute]
|
||||||
|
|
||||||
|
formatter.maximumUnitCount = 1
|
||||||
|
|
||||||
|
let scheduledDate = DateInterval(start: Date(), duration: 60 * 60 * 24 * 6)
|
||||||
|
|
||||||
|
|
||||||
|
guard let timeLeft = formatter.string(from: scheduledDate.end, to: app.expirationDate) else { operation.finish(); return }
|
||||||
|
|
||||||
|
content.body = "App \(app.name) is expiring in \(timeLeft). Open SideStore to refresh now"
|
||||||
|
|
||||||
|
var dateComponents = DateComponents()
|
||||||
|
dateComponents.calendar = Calendar.current
|
||||||
|
|
||||||
|
let trigger = UNCalendarNotificationTrigger(
|
||||||
|
dateMatching: dateComponents, repeats: true)
|
||||||
|
|
||||||
|
let request = UNNotificationRequest(identifier: app.bundleIdentifier, content: content, trigger: trigger)
|
||||||
|
|
||||||
|
let notificationCenter = UNUserNotificationCenter.current()
|
||||||
|
|
||||||
|
notificationCenter.add(request) {_ in
|
||||||
|
operation.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
operation.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
notificationRegistrationOperation.addDependency(installOperation)
|
||||||
|
|
||||||
|
|
||||||
|
let operations = [downloadOperation, verifyOperation, removeAppExtensionsOperation, refreshAnisetteDataOperation, fetchProvisioningProfilesOperation, deactivateAppsOperation, patchAppOperation, resignAppOperation, sendAppOperation, installOperation, notificationRegistrationOperation]
|
||||||
group.add(operations)
|
group.add(operations)
|
||||||
self.run(operations, context: group.context)
|
self.run(operations, context: group.context)
|
||||||
|
|
||||||
@@ -1477,24 +1466,6 @@ private extension AppManager
|
|||||||
let context = AppOperationContext(bundleIdentifier: app.bundleIdentifier, authenticatedContext: group.context)
|
let context = AppOperationContext(bundleIdentifier: app.bundleIdentifier, authenticatedContext: group.context)
|
||||||
context.app = ALTApplication(fileURL: app.fileURL)
|
context.app = ALTApplication(fileURL: app.fileURL)
|
||||||
|
|
||||||
//App-Extensions: Ensure DB data and disk state must match
|
|
||||||
let dbAppEx: Set<InstalledExtension> = Set(app.appExtensions)
|
|
||||||
let diskAppEx: Set<ALTApplication> = Set(context.app!.appExtensions)
|
|
||||||
let diskAppExNames = diskAppEx.map { $0.bundleIdentifier }
|
|
||||||
let dbAppExNames = dbAppEx.map{ $0.bundleIdentifier }
|
|
||||||
let isMatching = Set(dbAppExNames) == Set(diskAppExNames)
|
|
||||||
|
|
||||||
let validateAppExtensionsOperation = RSTAsyncBlockOperation { op in
|
|
||||||
|
|
||||||
let errMessage = "AppManager.refresh: App Extensions in DB and Disk are matching: \(isMatching)\n"
|
|
||||||
+ "AppManager.refresh: dbAppEx: \(dbAppExNames); diskAppEx: \(String(describing: diskAppExNames))\n"
|
|
||||||
print(errMessage)
|
|
||||||
if(!isMatching){
|
|
||||||
completionHandler(.failure(OperationError.refreshAppFailed(message: errMessage)))
|
|
||||||
}
|
|
||||||
op.finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fetch Provisioning Profiles */
|
/* Fetch Provisioning Profiles */
|
||||||
let fetchProvisioningProfilesOperation = FetchProvisioningProfilesOperation(context: context)
|
let fetchProvisioningProfilesOperation = FetchProvisioningProfilesOperation(context: context)
|
||||||
fetchProvisioningProfilesOperation.resultHandler = { (result) in
|
fetchProvisioningProfilesOperation.resultHandler = { (result) in
|
||||||
@@ -1505,8 +1476,6 @@ private extension AppManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
progress.addChild(fetchProvisioningProfilesOperation.progress, withPendingUnitCount: 60)
|
progress.addChild(fetchProvisioningProfilesOperation.progress, withPendingUnitCount: 60)
|
||||||
fetchProvisioningProfilesOperation.addDependency(validateAppExtensionsOperation)
|
|
||||||
|
|
||||||
|
|
||||||
/* Refresh */
|
/* Refresh */
|
||||||
let refreshAppOperation = RefreshAppOperation(context: context)
|
let refreshAppOperation = RefreshAppOperation(context: context)
|
||||||
@@ -1540,7 +1509,7 @@ private extension AppManager
|
|||||||
progress.addChild(refreshAppOperation.progress, withPendingUnitCount: 40)
|
progress.addChild(refreshAppOperation.progress, withPendingUnitCount: 40)
|
||||||
refreshAppOperation.addDependency(fetchProvisioningProfilesOperation)
|
refreshAppOperation.addDependency(fetchProvisioningProfilesOperation)
|
||||||
|
|
||||||
let operations = [validateAppExtensionsOperation, fetchProvisioningProfilesOperation, refreshAppOperation]
|
let operations = [fetchProvisioningProfilesOperation, refreshAppOperation]
|
||||||
group.add(operations)
|
group.add(operations)
|
||||||
self.run(operations, context: group.context)
|
self.run(operations, context: group.context)
|
||||||
|
|
||||||
@@ -2001,43 +1970,7 @@ private extension AppManager
|
|||||||
UNUserNotificationCenter.current().add(request)
|
UNUserNotificationCenter.current().add(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
func log(_ error: Error, for operation: AppOperation)
|
|
||||||
{
|
|
||||||
// Sanitize NSError on same thread before performing background task.
|
|
||||||
let sanitizedError = (error as NSError).sanitizedForSerialization()
|
|
||||||
|
|
||||||
let loggedErrorOperation: LoggedError.Operation = {
|
|
||||||
switch operation
|
|
||||||
{
|
|
||||||
case .install: return .install
|
|
||||||
case .update: return .update
|
|
||||||
case .refresh: return .refresh
|
|
||||||
case .activate: return .activate
|
|
||||||
case .deactivate: return .deactivate
|
|
||||||
case .backup: return .backup
|
|
||||||
case .restore: return .restore
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
DatabaseManager.shared.persistentContainer.performBackgroundTask { context in
|
|
||||||
var app = operation.app
|
|
||||||
if let managedApp = app as? NSManagedObject, let tempApp = context.object(with: managedApp.objectID) as? AppProtocol
|
|
||||||
{
|
|
||||||
app = tempApp
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
_ = LoggedError(error: sanitizedError, app: app, operation: loggedErrorOperation, context: context)
|
|
||||||
try context.save()
|
|
||||||
}
|
|
||||||
catch let saveError
|
|
||||||
{
|
|
||||||
print("[ALTLog] Failed to log error \(sanitizedError.domain) code \(sanitizedError.code) for \(app.bundleIdentifier):", saveError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func run(_ operations: [Foundation.Operation], context: OperationContext?, requiresSerialQueue: Bool = false)
|
func run(_ operations: [Foundation.Operation], context: OperationContext?, requiresSerialQueue: Bool = false)
|
||||||
{
|
{
|
||||||
// Find "Install AltStore" operation if it already exists in `context`
|
// Find "Install AltStore" operation if it already exists in `context`
|
||||||
|
|||||||
@@ -791,9 +791,7 @@ private extension MyAppsViewController
|
|||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let fileURL = context.fileURL else {
|
guard let fileURL = context.fileURL else { throw OperationError.invalidParameters }
|
||||||
throw OperationError.invalidParameters("MyAppsViewController.sideloadApp.unzipAppOperation: context.fileURL is nil")
|
|
||||||
}
|
|
||||||
defer {
|
defer {
|
||||||
try? FileManager.default.removeItem(at: fileURL)
|
try? FileManager.default.removeItem(at: fileURL)
|
||||||
}
|
}
|
||||||
@@ -827,9 +825,7 @@ private extension MyAppsViewController
|
|||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let application = context.application else {
|
guard let application = context.application else { throw OperationError.invalidParameters }
|
||||||
throw OperationError.invalidParameters("MyAppsViewController.sideloadApp.installAppOperation: context.application is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
let group = AppManager.shared.install(application, presentingViewController: self) { (result) in
|
let group = AppManager.shared.install(application, presentingViewController: self) { (result) in
|
||||||
switch result
|
switch result
|
||||||
@@ -998,7 +994,7 @@ private extension MyAppsViewController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !UserDefaults.standard.isAppLimitDisabled && UserDefaults.standard.activeAppsLimit != nil, #available(iOS 13, *)
|
if UserDefaults.standard.activeAppsLimit != nil, #available(iOS 13, *)
|
||||||
{
|
{
|
||||||
// UserDefaults.standard.activeAppsLimit is only non-nil on iOS 13.3.1 or later, so the #available check is just so we can use Combine.
|
// UserDefaults.standard.activeAppsLimit is only non-nil on iOS 13.3.1 or later, so the #available check is just so we can use Combine.
|
||||||
|
|
||||||
@@ -1358,7 +1354,7 @@ extension MyAppsViewController
|
|||||||
headerView.layoutMargins.left = self.view.layoutMargins.left
|
headerView.layoutMargins.left = self.view.layoutMargins.left
|
||||||
headerView.layoutMargins.right = self.view.layoutMargins.right
|
headerView.layoutMargins.right = self.view.layoutMargins.right
|
||||||
|
|
||||||
if UserDefaults.standard.activeAppsLimit == nil || UserDefaults.standard.isAppLimitDisabled
|
if UserDefaults.standard.activeAppsLimit == nil
|
||||||
{
|
{
|
||||||
headerView.textLabel.text = NSLocalizedString("Installed", comment: "")
|
headerView.textLabel.text = NSLocalizedString("Installed", comment: "")
|
||||||
}
|
}
|
||||||
@@ -1757,7 +1753,7 @@ extension MyAppsViewController: UICollectionViewDragDelegate
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
case .activeApps, .inactiveApps:
|
case .activeApps, .inactiveApps:
|
||||||
guard UserDefaults.standard.activeAppsLimit != nil && !UserDefaults.standard.isAppLimitDisabled else { return [] }
|
guard UserDefaults.standard.activeAppsLimit != nil else { return [] }
|
||||||
guard let cell = collectionView.cellForItem(at: indexPath as IndexPath) as? InstalledAppCollectionViewCell else { return [] }
|
guard let cell = collectionView.cellForItem(at: indexPath as IndexPath) as? InstalledAppCollectionViewCell else { return [] }
|
||||||
|
|
||||||
let item = self.dataSource.item(at: indexPath)
|
let item = self.dataSource.item(at: indexPath)
|
||||||
@@ -1812,7 +1808,6 @@ extension MyAppsViewController: UICollectionViewDropDelegate
|
|||||||
func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal
|
func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal
|
||||||
{
|
{
|
||||||
guard
|
guard
|
||||||
!UserDefaults.standard.isAppLimitDisabled,
|
|
||||||
let activeAppsLimit = UserDefaults.standard.activeAppsLimit,
|
let activeAppsLimit = UserDefaults.standard.activeAppsLimit,
|
||||||
let installedApp = session.items.first?.localObject as? InstalledApp
|
let installedApp = session.items.first?.localObject as? InstalledApp
|
||||||
else { return UICollectionViewDropProposal(operation: .cancel) }
|
else { return UICollectionViewDropProposal(operation: .cancel) }
|
||||||
|
|||||||
@@ -241,11 +241,12 @@ final class AuthenticationOperation: ResultOperation<(ALTTeam, ALTCertificate, A
|
|||||||
}
|
}
|
||||||
|
|
||||||
let activeAppsMinimumVersion = OperatingSystemVersion(majorVersion: 13, minorVersion: 3, patchVersion: 1)
|
let activeAppsMinimumVersion = OperatingSystemVersion(majorVersion: 13, minorVersion: 3, patchVersion: 1)
|
||||||
if team.type == .free, !UserDefaults.standard.isAppLimitDisabled, ProcessInfo().sparseRestorePatched {
|
if team.type == .free, ProcessInfo.processInfo.isOperatingSystemAtLeast(activeAppsMinimumVersion)
|
||||||
|
{
|
||||||
UserDefaults.standard.activeAppsLimit = ALTActiveAppsLimit
|
UserDefaults.standard.activeAppsLimit = ALTActiveAppsLimit
|
||||||
} else if UserDefaults.standard.isAppLimitDisabled, !ProcessInfo().sparseRestorePatched {
|
}
|
||||||
UserDefaults.standard.activeAppsLimit = 10
|
else
|
||||||
} else {
|
{
|
||||||
UserDefaults.standard.activeAppsLimit = nil
|
UserDefaults.standard.activeAppsLimit = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,9 +48,7 @@ class BackupAppOperation: ResultOperation<Void>
|
|||||||
{
|
{
|
||||||
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 {
|
guard let installedApp = self.context.installedApp, let context = installedApp.managedObjectContext else { throw OperationError.invalidParameters }
|
||||||
throw OperationError.invalidParameters("BackupAppOperation.main: self.context.installedApp or installedApp.managedObjectContext is nil")
|
|
||||||
}
|
|
||||||
context.perform {
|
context.perform {
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ final class DownloadAppOperation: ResultOperation<ALTApplication>
|
|||||||
|
|
||||||
private let appName: String
|
private let appName: String
|
||||||
private let bundleIdentifier: String
|
private let bundleIdentifier: String
|
||||||
private var sourceURL: URL?
|
|
||||||
private let destinationURL: URL
|
private let destinationURL: URL
|
||||||
|
|
||||||
private let session = URLSession(configuration: .default)
|
private let session = URLSession(configuration: .default)
|
||||||
@@ -33,7 +32,6 @@ final class DownloadAppOperation: ResultOperation<ALTApplication>
|
|||||||
|
|
||||||
self.appName = app.name
|
self.appName = app.name
|
||||||
self.bundleIdentifier = app.bundleIdentifier
|
self.bundleIdentifier = app.bundleIdentifier
|
||||||
self.sourceURL = app.url
|
|
||||||
self.destinationURL = destinationURL
|
self.destinationURL = destinationURL
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
@@ -113,7 +111,7 @@ private extension DownloadAppOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func download(@Managed _ app: AppProtocol) {
|
func download(@Managed _ app: AppProtocol) {
|
||||||
guard let sourceURL = self.sourceURL else { return self.finish(.failure(OperationError.appNotFound(name: self.appName))) }
|
guard let sourceURL = $app.url else { return self.finish(.failure(OperationError.appNotFound(name: self.appName))) }
|
||||||
|
|
||||||
self.downloadIPA(from: sourceURL) { result in
|
self.downloadIPA(from: sourceURL) { result in
|
||||||
do
|
do
|
||||||
|
|||||||
@@ -50,9 +50,7 @@ final class EnableJITOperation<Context: EnableJITContext>: ResultOperation<Void>
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let installedApp = self.context.installedApp else {
|
guard let installedApp = self.context.installedApp else { return self.finish(.failure(OperationError.invalidParameters)) }
|
||||||
return self.finish(.failure(OperationError.invalidParameters("EnableJITOperation.main: self.context.installedApp is nil")))
|
|
||||||
}
|
|
||||||
if #available(iOS 17, *) {
|
if #available(iOS 17, *) {
|
||||||
let sideJITenabled = UserDefaults.standard.sidejitenable
|
let sideJITenabled = UserDefaults.standard.sidejitenable
|
||||||
let SideJITIP = UserDefaults.standard.textInputSideJITServerurl ?? ""
|
let SideJITIP = UserDefaults.standard.textInputSideJITServerurl ?? ""
|
||||||
|
|||||||
@@ -45,122 +45,17 @@ final class FetchAnisetteDataOperation: ResultOperation<ALTAnisetteData>, WebSoc
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Pass in proper view context to show the Toast messages
|
self.url = URL(string: UserDefaults.standard.menuAnisetteURL)
|
||||||
let viewContext = context.presentingViewController
|
print("Anisette URL: \(self.url!.absoluteString)")
|
||||||
|
|
||||||
getAnisetteServerUrl(viewContext){ url, error in
|
if let identifier = Keychain.shared.identifier,
|
||||||
guard let urlString = url else {
|
let adiPb = Keychain.shared.adiPb {
|
||||||
self.finish(.failure(error!))
|
fetchAnisetteV3(identifier, adiPb)
|
||||||
return
|
} else {
|
||||||
}
|
provision()
|
||||||
|
|
||||||
// set as preferred
|
|
||||||
UserDefaults.standard.menuAnisetteURL = urlString
|
|
||||||
let url = URL(string: urlString)
|
|
||||||
self.url = url
|
|
||||||
print("Anisette URL: \(self.url!.absoluteString)")
|
|
||||||
|
|
||||||
if let identifier = Keychain.shared.identifier,
|
|
||||||
let adiPb = Keychain.shared.adiPb {
|
|
||||||
self.fetchAnisetteV3(identifier, adiPb)
|
|
||||||
} else {
|
|
||||||
self.provision()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func getAnisetteServerUrl(_ viewContext: UIViewController?, completion: @escaping (String?, Error?) -> Void) {
|
|
||||||
var serverUrls = UserDefaults.standard.menuAnisetteServersList
|
|
||||||
let currentServer = UserDefaults.standard.menuAnisetteURL
|
|
||||||
|
|
||||||
// Prioritize the current server by moving it to the top of the list
|
|
||||||
if let currentServerIndex = serverUrls.firstIndex(of: currentServer) {
|
|
||||||
serverUrls.remove(at: currentServerIndex)
|
|
||||||
serverUrls.insert(currentServer, at: 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
tryNextServer(from: serverUrls, viewContext, currentIndex: 0, completion: completion)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func showToast(viewContext: UIViewController?, message: String){
|
|
||||||
if let viewContext = viewContext{
|
|
||||||
let error = OperationError.anisetteV1Error(message: message)
|
|
||||||
let toastView = ToastView(error: error)
|
|
||||||
// toastView.textLabel.textColor = .altPrimary
|
|
||||||
// toastView.detailTextLabel.textColor = .altPrimary
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
toastView.show(in: viewContext)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func tryNextServer(from serverUrls: [String], _ viewContext: UIViewController?,currentIndex: Int, completion: @escaping (String?, Error?) -> Void) {
|
|
||||||
// Check if all URLs have been exhausted
|
|
||||||
guard currentIndex < serverUrls.count else {
|
|
||||||
let error = NSError(domain: "AnisetteError", code: 0, userInfo: [NSLocalizedDescriptionKey: "No valid server found."])
|
|
||||||
completion(nil, error)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let currentServerUrlString = serverUrls[currentIndex]
|
|
||||||
guard let url = URL(string: currentServerUrlString) else {
|
|
||||||
// Invalid URL, skip to next
|
|
||||||
let errmsg = "Skipping invalid URL: \(currentServerUrlString)"
|
|
||||||
print(errmsg)
|
|
||||||
showToast(viewContext: viewContext, message: errmsg)
|
|
||||||
tryNextServer(from: serverUrls, viewContext, currentIndex: currentIndex + 1, completion: completion)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt to ping the current URL
|
|
||||||
pingServer(url) { success, error in
|
|
||||||
if success {
|
|
||||||
// If the server is reachable, return the URL
|
|
||||||
let okmsg = "Found working server: \(url.absoluteString)"
|
|
||||||
print(okmsg)
|
|
||||||
if(currentIndex > 0){
|
|
||||||
// notify user if available server is different the user-specified one
|
|
||||||
self.showToast(viewContext: viewContext, message: okmsg)
|
|
||||||
}
|
|
||||||
completion(url.absoluteString, nil)
|
|
||||||
} else {
|
|
||||||
// If not, try the next URL
|
|
||||||
let errmsg = "Failed to reach server: \(url.absoluteString), trying next server."
|
|
||||||
print(errmsg)
|
|
||||||
self.showToast(viewContext: viewContext, message: errmsg)
|
|
||||||
self.tryNextServer(from: serverUrls, viewContext, currentIndex: currentIndex + 1, completion: completion)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func pingServer(_ url: URL, completion: @escaping (Bool, Error?) -> Void) {
|
|
||||||
var request = URLRequest(url: url)
|
|
||||||
request.timeoutInterval = 10 // Timeout after 10 seconds
|
|
||||||
|
|
||||||
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
|
|
||||||
if let error = error {
|
|
||||||
completion(false, error)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let httpResponse = response as? HTTPURLResponse
|
|
||||||
let statusCode = httpResponse?.statusCode
|
|
||||||
|
|
||||||
guard let statusCode = statusCode,
|
|
||||||
(200...299).contains(statusCode) else {
|
|
||||||
let serverError = OperationError.anisetteV3Error(message: "Server unreachable or invalid response: \(String(describing: statusCode ?? nil))")
|
|
||||||
completion(false, serverError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
completion(true, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
task.resume()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// MARK: - COMMON
|
// MARK: - COMMON
|
||||||
|
|
||||||
func extractAnisetteData(_ data: Data, _ response: HTTPURLResponse?, v3: Bool) throws {
|
func extractAnisetteData(_ data: Data, _ response: HTTPURLResponse?, v3: Bool) throws {
|
||||||
|
|||||||
@@ -39,9 +39,7 @@ final class FetchAppIDsOperation: ResultOperation<([AppID], NSManagedObjectConte
|
|||||||
guard
|
guard
|
||||||
let team = self.context.team,
|
let team = self.context.team,
|
||||||
let session = self.context.session
|
let session = self.context.session
|
||||||
else {
|
else { return self.finish(.failure(OperationError.invalidParameters)) }
|
||||||
return self.finish(.failure(OperationError.invalidParameters("FetchAppIDsOperation.main: self.context.team or self.context.session is nil")))
|
|
||||||
}
|
|
||||||
|
|
||||||
ALTAppleAPI.shared.fetchAppIDs(for: team, session: session) { (appIDs, error) in
|
ALTAppleAPI.shared.fetchAppIDs(for: team, session: session) { (appIDs, error) in
|
||||||
self.managedObjectContext.perform {
|
self.managedObjectContext.perform {
|
||||||
|
|||||||
@@ -43,8 +43,7 @@ final class FetchProvisioningProfilesOperation: ResultOperation<[String: ALTProv
|
|||||||
guard
|
guard
|
||||||
let team = self.context.team,
|
let team = self.context.team,
|
||||||
let session = self.context.session
|
let session = self.context.session
|
||||||
else {
|
else { return self.finish(.failure(OperationError.invalidParameters)) }
|
||||||
return self.finish(.failure(OperationError.invalidParameters("FetchProvisioningProfilesOperation.main: self.context.team or self.context.session is nil"))) }
|
|
||||||
|
|
||||||
guard let app = self.context.app else { return self.finish(.failure(OperationError.appNotFound(name: nil))) }
|
guard let app = self.context.app else { return self.finish(.failure(OperationError.appNotFound(name: nil))) }
|
||||||
|
|
||||||
@@ -263,10 +262,6 @@ extension FetchProvisioningProfilesOperation
|
|||||||
{
|
{
|
||||||
throw OperationError.maximumAppIDLimitReached(appName: application.name, requiredAppIDs: requiredAppIDs, availableAppIDs: availableAppIDs, expirationDate: expirationDate)
|
throw OperationError.maximumAppIDLimitReached(appName: application.name, requiredAppIDs: requiredAppIDs, availableAppIDs: availableAppIDs, expirationDate: expirationDate)
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
throw ALTAppleAPIError(.maximumAppIDLimitReached)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//App ID name must be ascii. If the name is not ascii, using bundleID instead
|
//App ID name must be ascii. If the name is not ascii, using bundleID instead
|
||||||
@@ -299,19 +294,6 @@ extension FetchProvisioningProfilesOperation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch ALTAppleAPIError.bundleIdentifierUnavailable {
|
|
||||||
ALTAppleAPI.shared.fetchAppIDs(for: team, session: session) {res, err in
|
|
||||||
if let err = err {
|
|
||||||
return completionHandler(.failure(err))
|
|
||||||
}
|
|
||||||
guard let res = res else {return completionHandler(.failure(ALTError(.unknown)))}
|
|
||||||
for appid in res {
|
|
||||||
if appid.bundleIdentifier == bundleIdentifier {
|
|
||||||
completionHandler(.success(appid))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
completionHandler(.failure(error))
|
completionHandler(.failure(error))
|
||||||
@@ -376,9 +358,7 @@ extension FetchProvisioningProfilesOperation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
appID.entitlements = entitlements
|
if updateFeatures
|
||||||
|
|
||||||
if updateFeatures || true
|
|
||||||
{
|
{
|
||||||
let appID = appID.copy() as! ALTAppID
|
let appID = appID.copy() as! ALTAppID
|
||||||
appID.features = features
|
appID.features = features
|
||||||
|
|||||||
@@ -43,9 +43,7 @@ final class InstallAppOperation: ResultOperation<InstalledApp>
|
|||||||
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
|
let provisioningProfiles = self.context.provisioningProfiles
|
||||||
else {
|
else { return self.finish(.failure(OperationError.invalidParameters)) }
|
||||||
return self.finish(.failure(OperationError.invalidParameters("InstallAppOperation.main: self.context.certificate or self.context.resignedApp or self.context.provisioningProfiles is nil")))
|
|
||||||
}
|
|
||||||
|
|
||||||
let backgroundContext = DatabaseManager.shared.persistentContainer.newBackgroundContext()
|
let backgroundContext = DatabaseManager.shared.persistentContainer.newBackgroundContext()
|
||||||
backgroundContext.perform {
|
backgroundContext.perform {
|
||||||
@@ -114,22 +112,6 @@ final class InstallAppOperation: ResultOperation<InstalledApp>
|
|||||||
}
|
}
|
||||||
|
|
||||||
installedApp.appExtensions = installedExtensions
|
installedApp.appExtensions = installedExtensions
|
||||||
|
|
||||||
// Remove stale "PlugIns" (Extensions) from currently installed App
|
|
||||||
if let installedAppExns = ALTApplication(fileURL: installedApp.fileURL)?.appExtensions {
|
|
||||||
let currentAppExns = Set(installedApp.appExtensions).map{ $0.bundleIdentifier }
|
|
||||||
let staleAppExns = installedAppExns.filter{ !currentAppExns.contains($0.bundleIdentifier) }
|
|
||||||
|
|
||||||
for staleAppExn in staleAppExns {
|
|
||||||
do {
|
|
||||||
try FileManager.default.removeItem(at: staleAppExn.fileURL)
|
|
||||||
print("InstallAppOperation.appExtensions: removed stale app-extension: \(staleAppExn.fileURL)")
|
|
||||||
} catch {
|
|
||||||
print("InstallAppOperation.appExtensions processing error Error: \(error)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
self.context.beginInstallationHandler?(installedApp)
|
self.context.beginInstallationHandler?(installedApp)
|
||||||
|
|
||||||
@@ -240,10 +222,8 @@ final class InstallAppOperation: ResultOperation<InstalledApp>
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if(FileManager.default.fileExists(atPath: fileURL.path)){
|
try FileManager.default.removeItem(at: fileURL)
|
||||||
try FileManager.default.removeItem(at: fileURL)
|
print("Removed refreshed IPA")
|
||||||
print("Removed refreshed IPA")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ extension OperationError
|
|||||||
case noSources
|
case noSources
|
||||||
case openAppFailed//(name: String)
|
case openAppFailed//(name: String)
|
||||||
case missingAppGroup
|
case missingAppGroup
|
||||||
case refreshAppFailed
|
|
||||||
|
|
||||||
// Connection
|
// Connection
|
||||||
case noWiFi = 1200
|
case noWiFi = 1200
|
||||||
@@ -56,6 +55,7 @@ extension OperationError
|
|||||||
static let notAuthenticated: OperationError = .init(code: .notAuthenticated)
|
static let notAuthenticated: OperationError = .init(code: .notAuthenticated)
|
||||||
static let unknownUDID: OperationError = .init(code: .unknownUDID)
|
static let unknownUDID: OperationError = .init(code: .unknownUDID)
|
||||||
static let invalidApp: OperationError = .init(code: .invalidApp)
|
static let invalidApp: OperationError = .init(code: .invalidApp)
|
||||||
|
static let invalidParameters: OperationError = .init(code: .invalidParameters)
|
||||||
static let noSources: OperationError = .init(code: .noSources)
|
static let noSources: OperationError = .init(code: .noSources)
|
||||||
static let missingAppGroup: OperationError = .init(code: .missingAppGroup)
|
static let missingAppGroup: OperationError = .init(code: .missingAppGroup)
|
||||||
|
|
||||||
@@ -78,7 +78,6 @@ extension OperationError
|
|||||||
static func openAppFailed(name: String?) -> OperationError {
|
static func openAppFailed(name: String?) -> OperationError {
|
||||||
OperationError(code: .openAppFailed, appName: name)
|
OperationError(code: .openAppFailed, appName: name)
|
||||||
}
|
}
|
||||||
static let domain = OperationError(code: .unknown)._domain
|
|
||||||
|
|
||||||
static func SideJITIssue(error: String?) -> OperationError {
|
static func SideJITIssue(error: String?) -> OperationError {
|
||||||
var o = OperationError(code: .SideJITIssue)
|
var o = OperationError(code: .SideJITIssue)
|
||||||
@@ -108,13 +107,6 @@ extension OperationError
|
|||||||
OperationError(code: .anisetteV3Error, failureReason: message)
|
OperationError(code: .anisetteV3Error, failureReason: message)
|
||||||
}
|
}
|
||||||
|
|
||||||
static func refreshAppFailed(message: String) -> OperationError {
|
|
||||||
OperationError(code: .refreshAppFailed, failureReason: message)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func invalidParameters(_ message: String? = nil) -> OperationError {
|
|
||||||
OperationError(code: .invalidParameters, failureReason: message)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -163,6 +155,7 @@ struct OperationError: ALTLocalizedError {
|
|||||||
case .notAuthenticated: return NSLocalizedString("You are not signed in.", comment: "")
|
case .notAuthenticated: return NSLocalizedString("You are not signed in.", comment: "")
|
||||||
case .unknownUDID: return NSLocalizedString("SideStore could not determine this device's UDID.", comment: "")
|
case .unknownUDID: return NSLocalizedString("SideStore could not determine this device's UDID.", comment: "")
|
||||||
case .invalidApp: return NSLocalizedString("The app is in an invalid format.", comment: "")
|
case .invalidApp: return NSLocalizedString("The app is in an invalid format.", comment: "")
|
||||||
|
case .invalidParameters: return NSLocalizedString("Invalid parameters.", comment: "")
|
||||||
case .maximumAppIDLimitReached: return NSLocalizedString("Cannot register more than 10 App IDs within a 7 day period.", comment: "")
|
case .maximumAppIDLimitReached: return NSLocalizedString("Cannot register more than 10 App IDs within a 7 day period.", comment: "")
|
||||||
case .noSources: return NSLocalizedString("There are no SideStore sources.", comment: "")
|
case .noSources: return NSLocalizedString("There are no SideStore sources.", comment: "")
|
||||||
case .missingAppGroup: return NSLocalizedString("SideStore's shared app group could not be accessed.", comment: "")
|
case .missingAppGroup: return NSLocalizedString("SideStore's shared app group could not be accessed.", comment: "")
|
||||||
@@ -183,16 +176,7 @@ struct OperationError: ALTLocalizedError {
|
|||||||
case .anisetteV3Error: return 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: "")
|
case .anisetteV3Error: return 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: "")
|
||||||
case .cacheClearError: return NSLocalizedString("An error occurred while clearing cache: %@", comment: "")
|
case .cacheClearError: return NSLocalizedString("An error occurred while clearing cache: %@", comment: "")
|
||||||
case .SideJITIssue: return NSLocalizedString("An error occurred while using SideJIT: %@", comment: "")
|
case .SideJITIssue: return NSLocalizedString("An error occurred while using SideJIT: %@", comment: "")
|
||||||
|
|
||||||
case .refreshAppFailed:
|
|
||||||
let message = self._failureReason ?? ""
|
|
||||||
return String(format: NSLocalizedString("Unable to refresh App\n%@", comment: ""), message)
|
|
||||||
|
|
||||||
case .invalidParameters:
|
|
||||||
let message = self._failureReason.map { ": \n\($0)" } ?? "."
|
|
||||||
return String(format: NSLocalizedString("Invalid parameters%@", comment: ""), message)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var recoverySuggestion: String? {
|
var recoverySuggestion: String? {
|
||||||
|
|||||||
@@ -98,9 +98,7 @@ final class PatchAppOperation: ResultOperation<Void>
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let resignedApp = self.context.resignedApp else {
|
guard let resignedApp = self.context.resignedApp else { return self.finish(.failure(OperationError.invalidParameters)) }
|
||||||
return self.finish(.failure(OperationError.invalidParameters("PatchAppOperation.main: self.context.resignedApp is nil")))
|
|
||||||
}
|
|
||||||
|
|
||||||
self.progressHandler?(self.progress, NSLocalizedString("Downloading iOS firmware...", comment: ""))
|
self.progressHandler?(self.progress, NSLocalizedString("Downloading iOS firmware...", comment: ""))
|
||||||
|
|
||||||
|
|||||||
@@ -35,15 +35,9 @@ final class RefreshAppOperation: ResultOperation<InstalledApp>
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if let error = self.context.error {
|
if let error = self.context.error { return self.finish(.failure(error)) }
|
||||||
print("RefreshAppOperation.main: ERROR: self.context.app = \(self.context.app!); self.context.error is \(error)")
|
|
||||||
return self.finish(.failure(error))
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let profiles = self.context.provisioningProfiles else {
|
|
||||||
return self.finish(.failure(OperationError.invalidParameters("RefreshAppOperation.main: self.context.provisioningProfiles is nil")))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
guard let profiles = self.context.provisioningProfiles else { return self.finish(.failure(OperationError.invalidParameters)) }
|
||||||
guard let app = self.context.app else { return self.finish(.failure(OperationError(.appNotFound(name: nil)))) }
|
guard let app = self.context.app else { return self.finish(.failure(OperationError(.appNotFound(name: nil)))) }
|
||||||
|
|
||||||
for p in profiles {
|
for p in profiles {
|
||||||
|
|||||||
@@ -35,9 +35,7 @@ final class RemoveAppBackupOperation: ResultOperation<Void>
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let installedApp = self.context.installedApp else {
|
guard let installedApp = self.context.installedApp else { return self.finish(.failure(OperationError.invalidParameters)) }
|
||||||
return self.finish(.failure(OperationError.invalidParameters("RemoveAppBackupOperation.main: self.context.installedApp is nil")))
|
|
||||||
}
|
|
||||||
installedApp.managedObjectContext?.perform {
|
installedApp.managedObjectContext?.perform {
|
||||||
guard let backupDirectoryURL = FileManager.default.backupDirectoryURL(for: installedApp) else { return self.finish(.failure(OperationError.missingAppGroup)) }
|
guard let backupDirectoryURL = FileManager.default.backupDirectoryURL(for: installedApp) else { return self.finish(.failure(OperationError.missingAppGroup)) }
|
||||||
|
|
||||||
|
|||||||
@@ -33,9 +33,7 @@ final class RemoveAppOperation: ResultOperation<InstalledApp>
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let installedApp = self.context.installedApp else {
|
guard let installedApp = self.context.installedApp else { return self.finish(.failure(OperationError.invalidParameters)) }
|
||||||
return self.finish(.failure(OperationError.invalidParameters("RemoveAppOperation.main: self.context.installedApp is nil")))
|
|
||||||
}
|
|
||||||
|
|
||||||
installedApp.managedObjectContext?.perform {
|
installedApp.managedObjectContext?.perform {
|
||||||
let resignedBundleIdentifier = installedApp.resignedBundleIdentifier
|
let resignedBundleIdentifier = installedApp.resignedBundleIdentifier
|
||||||
|
|||||||
@@ -42,12 +42,7 @@ final class ResignAppOperation: ResultOperation<ALTApplication>
|
|||||||
let profiles = self.context.provisioningProfiles,
|
let profiles = self.context.provisioningProfiles,
|
||||||
let team = self.context.team,
|
let team = self.context.team,
|
||||||
let certificate = self.context.certificate
|
let certificate = self.context.certificate
|
||||||
else {
|
else { return self.finish(.failure(OperationError.invalidParameters)) }
|
||||||
return self.finish(.failure(OperationError.invalidParameters("ResignAppOperation.main: " +
|
|
||||||
"self.context.team or " +
|
|
||||||
"self.context.provisioningProfiles or" +
|
|
||||||
"self.context.certificate is nil")))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare app bundle
|
// Prepare app bundle
|
||||||
let prepareAppProgress = Progress.discreteProgress(totalUnitCount: 2)
|
let prepareAppProgress = Progress.discreteProgress(totalUnitCount: 2)
|
||||||
|
|||||||
@@ -36,9 +36,7 @@ final class SendAppOperation: ResultOperation<()>
|
|||||||
return self.finish(.failure(error))
|
return self.finish(.failure(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let resignedApp = self.context.resignedApp else {
|
guard let resignedApp = self.context.resignedApp else { return self.finish(.failure(OperationError.invalidParameters)) }
|
||||||
return self.finish(.failure(OperationError.invalidParameters("SendAppOperation.main: self.resignedApp is nil")))
|
|
||||||
}
|
|
||||||
|
|
||||||
// self.context.resignedApp.fileURL points to the app bundle, but we want the .ipa.
|
// self.context.resignedApp.fileURL points to the app bundle, but we want the .ipa.
|
||||||
let app = AnyApp(name: resignedApp.name, bundleIdentifier: self.context.bundleIdentifier, url: resignedApp.fileURL)
|
let app = AnyApp(name: resignedApp.name, bundleIdentifier: self.context.bundleIdentifier, url: resignedApp.fileURL)
|
||||||
|
|||||||
@@ -116,12 +116,8 @@ final class VerifyAppOperation: ResultOperation<Void>
|
|||||||
{
|
{
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
let appName = self.context.app?.name ?? NSLocalizedString("The app", comment: "")
|
|
||||||
self.localizedFailure = String(format: NSLocalizedString("%@ could not be installed.", comment: ""), appName)
|
|
||||||
|
|
||||||
guard let app = self.context.app else {
|
guard let app = self.context.app else { throw OperationError.invalidParameters }
|
||||||
throw OperationError.invalidParameters("VerifyAppOperation.main: self.context.app is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !["ny.litritt.ignited", "com.litritt.ignited"].contains(where: { $0 == app.bundleIdentifier }) {
|
if !["ny.litritt.ignited", "com.litritt.ignited"].contains(where: { $0 == app.bundleIdentifier }) {
|
||||||
guard app.bundleIdentifier == self.context.bundleIdentifier else {
|
guard app.bundleIdentifier == self.context.bundleIdentifier else {
|
||||||
|
|||||||
@@ -29,21 +29,9 @@ class AnisetteViewModel: ObservableObject {
|
|||||||
@Published var source: String = "https://servers.sidestore.io/servers.json"
|
@Published var source: String = "https://servers.sidestore.io/servers.json"
|
||||||
@Published var servers: [Server] = []
|
@Published var servers: [Server] = []
|
||||||
|
|
||||||
init() {
|
|
||||||
// using the custom Anisette list
|
|
||||||
if !UserDefaults.standard.menuAnisetteList.isEmpty {
|
|
||||||
self.source = UserDefaults.standard.menuAnisetteList
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getListOfServers() {
|
func getListOfServers() {
|
||||||
guard let url = URL(string: source) else { return }
|
guard let url = URL(string: source) else { return }
|
||||||
|
URLSession.shared.dataTask(with: url) { data, response, error in
|
||||||
// DO NOT use local cache when fetching anisette servers
|
|
||||||
var request = URLRequest(url: url)
|
|
||||||
request.cachePolicy = .reloadIgnoringLocalCacheData
|
|
||||||
|
|
||||||
URLSession.shared.dataTask(with: request) { data, response, error in
|
|
||||||
if let error = error {
|
if let error = error {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -53,8 +41,6 @@ class AnisetteViewModel: ObservableObject {
|
|||||||
let servers = try decoder.decode(AnisetteServerData.self, from: data)
|
let servers = try decoder.decode(AnisetteServerData.self, from: data)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.servers = servers.servers
|
self.servers = servers.servers
|
||||||
// store server addresses as list
|
|
||||||
UserDefaults.standard.menuAnisetteServersList = servers.servers.map(\.self.address)
|
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// Handle decoding error
|
// Handle decoding error
|
||||||
@@ -69,7 +55,6 @@ struct AnisetteServers: View {
|
|||||||
@Environment(\.presentationMode) var presentationMode
|
@Environment(\.presentationMode) var presentationMode
|
||||||
@StateObject var viewModel: AnisetteViewModel = AnisetteViewModel()
|
@StateObject var viewModel: AnisetteViewModel = AnisetteViewModel()
|
||||||
@State var selected: String? = nil
|
@State var selected: String? = nil
|
||||||
@State private var showingConfirmation = false
|
|
||||||
var errorCallback: () -> ()
|
var errorCallback: () -> ()
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
@@ -151,13 +136,9 @@ struct AnisetteServers: View {
|
|||||||
SUIButton(action: {
|
SUIButton(action: {
|
||||||
presentationMode.wrappedValue.dismiss()
|
presentationMode.wrappedValue.dismiss()
|
||||||
}) {
|
}) {
|
||||||
HStack{
|
Text("Back")
|
||||||
Spacer()
|
.fontWeight(.semibold)
|
||||||
Text("Back")
|
.frame(maxWidth: .infinity)
|
||||||
.fontWeight(.semibold)
|
|
||||||
Spacer()
|
|
||||||
}
|
|
||||||
.contentShape(Rectangle())
|
|
||||||
}
|
}
|
||||||
.buttonStyle(PlainButtonStyle())
|
.buttonStyle(PlainButtonStyle())
|
||||||
.padding()
|
.padding()
|
||||||
@@ -168,25 +149,26 @@ struct AnisetteServers: View {
|
|||||||
SUIButton(action: {
|
SUIButton(action: {
|
||||||
viewModel.getListOfServers()
|
viewModel.getListOfServers()
|
||||||
}) {
|
}) {
|
||||||
HStack{
|
Text("Refresh Servers")
|
||||||
Spacer()
|
.fontWeight(.semibold)
|
||||||
Text("Refresh Servers")
|
.frame(maxWidth: .infinity)
|
||||||
.fontWeight(.semibold)
|
|
||||||
.frame(maxWidth: .infinity)
|
|
||||||
Spacer()
|
|
||||||
}
|
|
||||||
.contentShape(Rectangle())
|
|
||||||
}
|
}
|
||||||
.buttonStyle(PlainButtonStyle())
|
.buttonStyle(PlainButtonStyle())
|
||||||
.padding()
|
.padding()
|
||||||
.background(RoundedRectangle(cornerRadius: 10).fill(Color.accentColor))
|
.background(RoundedRectangle(cornerRadius: 10).fill(Color.accentColor))
|
||||||
.foregroundColor(.white)
|
.foregroundColor(.white)
|
||||||
.shadow(color: Color.accentColor.opacity(0.4), radius: 10, x: 0, y: 5)
|
.shadow(color: Color.accentColor.opacity(0.4), radius: 10, x: 0, y: 5)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SUIButton(action: {
|
SUIButton(action: {
|
||||||
showingConfirmation = true
|
#if !DEBUG
|
||||||
|
if Keychain.shared.adiPb != nil {
|
||||||
|
Keychain.shared.adiPb = nil
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
print("Cleared adi.pb from keychain")
|
||||||
|
errorCallback()
|
||||||
|
presentationMode.wrappedValue.dismiss()
|
||||||
}) {
|
}) {
|
||||||
Text("Reset adi.pb")
|
Text("Reset adi.pb")
|
||||||
.fontWeight(.semibold)
|
.fontWeight(.semibold)
|
||||||
@@ -197,25 +179,6 @@ struct AnisetteServers: View {
|
|||||||
.background(RoundedRectangle(cornerRadius: 10).fill(Color.red))
|
.background(RoundedRectangle(cornerRadius: 10).fill(Color.red))
|
||||||
.foregroundColor(.white)
|
.foregroundColor(.white)
|
||||||
.shadow(color: Color.red.opacity(0.4), radius: 10, x: 0, y: 5)
|
.shadow(color: Color.red.opacity(0.4), radius: 10, x: 0, y: 5)
|
||||||
.alert(isPresented: $showingConfirmation) {
|
|
||||||
Alert(
|
|
||||||
title: Text("Reset adi.pb"),
|
|
||||||
message: Text("are you sure to clear the adi.pb from keychain?"),
|
|
||||||
primaryButton: .default(Text("do it")) {
|
|
||||||
#if !DEBUG
|
|
||||||
if Keychain.shared.adiPb != nil {
|
|
||||||
Keychain.shared.adiPb = nil
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
print("Cleared adi.pb from keychain")
|
|
||||||
errorCallback()
|
|
||||||
presentationMode.wrappedValue.dismiss()
|
|
||||||
},
|
|
||||||
secondaryButton: .cancel(Text("cancel")) {
|
|
||||||
print("canceled")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
.padding(.bottom)
|
.padding(.bottom)
|
||||||
|
|||||||
@@ -105,8 +105,8 @@ private extension ErrorLogViewController
|
|||||||
self?.searchFAQ(for: loggedError)
|
self?.searchFAQ(for: loggedError)
|
||||||
},
|
},
|
||||||
UIAction(title: NSLocalizedString("View More Details", comment: ""), image: UIImage(systemName: "ellipsis.circle")) { [weak self] _ in
|
UIAction(title: NSLocalizedString("View More Details", comment: ""), image: UIImage(systemName: "ellipsis.circle")) { [weak self] _ in
|
||||||
self?.viewMoreDetails(for: loggedError)
|
|
||||||
},
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
cell.menuButton.menu = menu
|
cell.menuButton.menu = menu
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ private extension PatreonViewController
|
|||||||
let isPatronText = NSLocalizedString("""
|
let isPatronText = NSLocalizedString("""
|
||||||
Hey ,
|
Hey ,
|
||||||
|
|
||||||
You’re the best. Your account was linked successfully, so you now have access to any beta versions of our apps. You can find them all in the Browse tab.
|
You’re the best. Your account was linked successfully, so you now have access to the beta versions of all of our apps. You can find them all in the Browse tab.
|
||||||
|
|
||||||
Thanks for all of your support. Enjoy!
|
Thanks for all of your support. Enjoy!
|
||||||
- SideTeam
|
- SideTeam
|
||||||
@@ -175,7 +175,7 @@ private extension PatreonViewController
|
|||||||
|
|
||||||
@objc func openPatreonURL(_ sender: UIButton)
|
@objc func openPatreonURL(_ sender: UIButton)
|
||||||
{
|
{
|
||||||
let patreonURL = URL(string: "https://www.patreon.com/SideStoreIO")!
|
let patreonURL = URL(string: "https://www.patreon.com/SideStore")!
|
||||||
|
|
||||||
let safariViewController = SFSafariViewController(url: patreonURL)
|
let safariViewController = SFSafariViewController(url: patreonURL)
|
||||||
safariViewController.preferredControlTintColor = self.view.tintColor
|
safariViewController.preferredControlTintColor = self.view.tintColor
|
||||||
@@ -184,7 +184,7 @@ private extension PatreonViewController
|
|||||||
|
|
||||||
@objc func openTwitterURL(_ sender: UIButton)
|
@objc func openTwitterURL(_ sender: UIButton)
|
||||||
{
|
{
|
||||||
let twitterURL = URL(string: "https://twitter.com/sidestoreio")!
|
let twitterURL = URL(string: "https://twitter.com/SideStore_io")!
|
||||||
|
|
||||||
let safariViewController = SFSafariViewController(url: twitterURL)
|
let safariViewController = SFSafariViewController(url: twitterURL)
|
||||||
safariViewController.preferredControlTintColor = self.view.tintColor
|
safariViewController.preferredControlTintColor = self.view.tintColor
|
||||||
@@ -348,7 +348,7 @@ extension PatreonViewController: UICollectionViewDelegateFlowLayout
|
|||||||
switch section
|
switch section
|
||||||
{
|
{
|
||||||
case .about: return .zero
|
case .about: return .zero
|
||||||
case .patrons: return CGSize(width: 320, height: 44)
|
case .patrons: return CGSize(width: 0, height: 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="5Rz-4h-jJ8">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23090" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="5Rz-4h-jJ8">
|
||||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22685"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23079"/>
|
||||||
<capability name="Named colors" minToolsVersion="9.0"/>
|
<capability name="Named colors" minToolsVersion="9.0"/>
|
||||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||||
@@ -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="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" 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="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" id="bUR-rp-Nw2">
|
||||||
<rect key="frame" x="0.0" y="1347" width="375" height="25"/>
|
<rect key="frame" x="0.0" y="1296" 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"/>
|
||||||
@@ -273,7 +273,7 @@
|
|||||||
</userDefinedRuntimeAttributes>
|
</userDefinedRuntimeAttributes>
|
||||||
</tableViewCell>
|
</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="546" width="375" height="51"/>
|
<rect key="frame" x="0.0" y="495" 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"/>
|
||||||
@@ -293,42 +293,6 @@
|
|||||||
</tableViewCellContentView>
|
</tableViewCellContentView>
|
||||||
<color key="backgroundColor" white="1" alpha="0.14999999999999999" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
<color key="backgroundColor" white="1" alpha="0.14999999999999999" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
<edgeInsets key="layoutMargins" top="8" left="30" bottom="8" right="30"/>
|
<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="7PQ-AW-GcV" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target">
|
|
||||||
<rect key="frame" x="0.0" y="495" width="375" height="51"/>
|
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="7PQ-AW-GcV" id="wQ8-9w-iiw">
|
|
||||||
<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 App Limit" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="W95-fD-NAd" userLabel="Disable App Limit">
|
|
||||||
<rect key="frame" x="30" y="15.5" width="142.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>
|
|
||||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1aa-og-ZXD">
|
|
||||||
<rect key="frame" x="296" y="10" width="51" height="31"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="toggleDisableAppLimit:" destination="aMk-Xp-UL8" eventType="valueChanged" id="zYc-B2-JPg"/>
|
|
||||||
</connections>
|
|
||||||
</switch>
|
|
||||||
</subviews>
|
|
||||||
<constraints>
|
|
||||||
<constraint firstAttribute="trailingMargin" secondItem="1aa-og-ZXD" secondAttribute="trailing" id="1Xa-t6-jAC"/>
|
|
||||||
<constraint firstItem="W95-fD-NAd" firstAttribute="leading" secondItem="wQ8-9w-iiw" secondAttribute="leadingMargin" id="J49-tg-KMa"/>
|
|
||||||
<constraint firstItem="1aa-og-ZXD" firstAttribute="centerY" secondItem="wQ8-9w-iiw" secondAttribute="centerY" id="UMz-ax-ln4"/>
|
|
||||||
<constraint firstItem="W95-fD-NAd" firstAttribute="centerY" secondItem="wQ8-9w-iiw" secondAttribute="centerY" id="bFd-lr-0xw"/>
|
|
||||||
</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>
|
<userDefinedRuntimeAttributes>
|
||||||
<userDefinedRuntimeAttribute type="number" keyPath="style">
|
<userDefinedRuntimeAttribute type="number" keyPath="style">
|
||||||
<integer key="value" value="3"/>
|
<integer key="value" value="3"/>
|
||||||
@@ -341,19 +305,19 @@
|
|||||||
<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="637" width="375" height="51"/>
|
<rect key="frame" x="0.0" y="586" 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"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="How it works" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2CC-iw-3bd">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="How it works" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2CC-iw-3bd">
|
||||||
<rect key="frame" x="30" y="15.5" width="105" height="20.5"/>
|
<rect key="frame" x="30" y="15.5" width="105" 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="WtV-Dt-sDn">
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Next" translatesAutoresizingMaskIntoConstraints="NO" id="WtV-Dt-sDn">
|
||||||
<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>
|
||||||
@@ -381,28 +345,28 @@
|
|||||||
<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="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="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"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Developers" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hRA-OK-Vjw">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Developers" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hRA-OK-Vjw">
|
||||||
<rect key="frame" x="30" y="15.5" width="86" height="20.5"/>
|
<rect key="frame" x="30" y="15.5" width="86" 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="lx9-35-OSk">
|
<stackView opaque="NO" contentMode="scaleToFill" spacing="14" translatesAutoresizingMaskIntoConstraints="NO" id="lx9-35-OSk">
|
||||||
<rect key="frame" x="187.5" y="15.5" width="157.5" height="20.5"/>
|
<rect key="frame" x="187.5" y="15.5" width="157.5" height="20.5"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="SideStore Team" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JAA-iZ-VGb">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="SideStore Team" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JAA-iZ-VGb">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="125.5" height="20.5"/>
|
<rect key="frame" x="0.0" y="0.0" width="125.5" 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="Mmj-3V-fTb">
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Next" translatesAutoresizingMaskIntoConstraints="NO" id="Mmj-3V-fTb">
|
||||||
<rect key="frame" x="139.5" y="0.0" width="18" height="20.5"/>
|
<rect key="frame" x="139.5" y="0.0" width="18" height="20.5"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
</subviews>
|
</subviews>
|
||||||
@@ -425,7 +389,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="774.5" 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="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"/>
|
||||||
@@ -469,7 +433,7 @@
|
|||||||
</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="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="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"/>
|
||||||
@@ -513,7 +477,7 @@
|
|||||||
</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="881" width="375" height="51"/>
|
<rect key="frame" x="0.0" y="830" 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"/>
|
||||||
@@ -553,7 +517,7 @@
|
|||||||
<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="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="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"/>
|
||||||
@@ -586,7 +550,7 @@
|
|||||||
</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="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="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"/>
|
||||||
@@ -622,7 +586,7 @@
|
|||||||
</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="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="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"/>
|
||||||
@@ -658,7 +622,7 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</tableViewCell>
|
</tableViewCell>
|
||||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="VrV-qI-zXF" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target">
|
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="VrV-qI-zXF" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target">
|
||||||
<rect key="frame" x="0.0" y="1125" 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="VrV-qI-zXF" id="w1r-uY-4pD">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="VrV-qI-zXF" id="w1r-uY-4pD">
|
||||||
<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"/>
|
||||||
@@ -691,7 +655,7 @@
|
|||||||
</userDefinedRuntimeAttributes>
|
</userDefinedRuntimeAttributes>
|
||||||
</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">
|
<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="1176" width="375" height="51"/>
|
<rect key="frame" x="0.0" y="1125" 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="eZ3-BT-q4D" id="17m-VV-hzf">
|
<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"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="51"/>
|
||||||
@@ -724,7 +688,7 @@
|
|||||||
</userDefinedRuntimeAttributes>
|
</userDefinedRuntimeAttributes>
|
||||||
</tableViewCell>
|
</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="1227" width="375" height="51"/>
|
<rect key="frame" x="0.0" y="1176" 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"/>
|
||||||
@@ -757,7 +721,7 @@
|
|||||||
</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">
|
<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="1278" width="375" height="51"/>
|
<rect key="frame" x="0.0" y="1227" 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="e7s-hL-kv9" id="yjL-Mu-HTk">
|
<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"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="51"/>
|
||||||
@@ -802,7 +766,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="disableAppLimitSwitch" destination="1aa-og-ZXD" id="oVL-Md-yZ8"/>
|
|
||||||
<outlet property="noIdleTimeoutSwitch" destination="iQA-wm-5ag" id="jHC-js-q0Y"/>
|
<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>
|
||||||
|
|||||||
@@ -31,19 +31,14 @@ extension SettingsViewController
|
|||||||
fileprivate enum AppRefreshRow: Int, CaseIterable
|
fileprivate enum AppRefreshRow: Int, CaseIterable
|
||||||
{
|
{
|
||||||
case backgroundRefresh
|
case backgroundRefresh
|
||||||
case noIdleTimeout
|
case noIdleTimeout
|
||||||
|
|
||||||
@available(iOS 14, *)
|
@available(iOS 14, *)
|
||||||
case addToSiri
|
case addToSiri
|
||||||
case disableAppLimit
|
|
||||||
|
|
||||||
static var allCases: [AppRefreshRow] {
|
static var allCases: [AppRefreshRow] {
|
||||||
var c: [AppRefreshRow] = [.backgroundRefresh, .noIdleTimeout]
|
guard #available(iOS 14, *) else { return [.backgroundRefresh, .noIdleTimeout] }
|
||||||
guard #available(iOS 14, *) else { return c }
|
return [.backgroundRefresh, .noIdleTimeout, .addToSiri]
|
||||||
c.append(.addToSiri)
|
|
||||||
|
|
||||||
// conditional entries go at the last to preserve ordering
|
|
||||||
if !ProcessInfo().sparseRestorePatched { c.append(.disableAppLimit) }
|
|
||||||
return c
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +79,6 @@ final class SettingsViewController: UITableViewController
|
|||||||
|
|
||||||
@IBOutlet private var backgroundRefreshSwitch: UISwitch!
|
@IBOutlet private var backgroundRefreshSwitch: UISwitch!
|
||||||
@IBOutlet private var noIdleTimeoutSwitch: UISwitch!
|
@IBOutlet private var noIdleTimeoutSwitch: UISwitch!
|
||||||
@IBOutlet private var disableAppLimitSwitch: UISwitch!
|
|
||||||
|
|
||||||
@IBOutlet private var refreshSideJITServer: UILabel!
|
@IBOutlet private var refreshSideJITServer: UILabel!
|
||||||
|
|
||||||
@@ -196,7 +190,6 @@ private extension SettingsViewController
|
|||||||
|
|
||||||
self.backgroundRefreshSwitch.isOn = UserDefaults.standard.isBackgroundRefreshEnabled
|
self.backgroundRefreshSwitch.isOn = UserDefaults.standard.isBackgroundRefreshEnabled
|
||||||
self.noIdleTimeoutSwitch.isOn = UserDefaults.standard.isIdleTimeoutDisableEnabled
|
self.noIdleTimeoutSwitch.isOn = UserDefaults.standard.isIdleTimeoutDisableEnabled
|
||||||
self.disableAppLimitSwitch.isOn = UserDefaults.standard.isAppLimitDisabled
|
|
||||||
|
|
||||||
if self.isViewLoaded
|
if self.isViewLoaded
|
||||||
{
|
{
|
||||||
@@ -248,7 +241,7 @@ private extension SettingsViewController
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
settingsHeaderFooterView.secondaryLabel.text = NSLocalizedString("Enable Background Refresh to automatically refresh apps in the background when connected to Wi-Fi. \n\nEnable Disable Idle Timeout to allow SideStore to keep your device awake during a refresh or install of any apps.", comment: "")
|
settingsHeaderFooterView.secondaryLabel.text = NSLocalizedString("Enable Background Refresh to automatically refresh apps in the background when connected to Wi-Fi. \n\nDisable the Idle Timeout toggle to allow SideStore to not let your device go to sleep during a refresh or install of any apps.", comment: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
case .instructions:
|
case .instructions:
|
||||||
@@ -324,10 +317,6 @@ private extension SettingsViewController
|
|||||||
self.present(alertController, animated: true, completion: nil)
|
self.present(alertController, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func toggleDisableAppLimit(_ sender: UISwitch) {
|
|
||||||
UserDefaults.standard.isAppLimitDisabled = sender.isOn
|
|
||||||
}
|
|
||||||
|
|
||||||
@IBAction func toggleIsBackgroundRefreshEnabled(_ sender: UISwitch)
|
@IBAction func toggleIsBackgroundRefreshEnabled(_ sender: UISwitch)
|
||||||
{
|
{
|
||||||
UserDefaults.standard.isBackgroundRefreshEnabled = sender.isOn
|
UserDefaults.standard.isBackgroundRefreshEnabled = sender.isOn
|
||||||
@@ -496,13 +485,6 @@ extension SettingsViewController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let cell = cell as? InsetGroupTableViewCell,
|
|
||||||
indexPath.section == Section.appRefresh.rawValue,
|
|
||||||
indexPath.row == AppRefreshRow.allCases.count-1 // last row
|
|
||||||
{
|
|
||||||
cell.setValue(3, forKey: "style")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
@@ -584,7 +566,6 @@ extension SettingsViewController
|
|||||||
{
|
{
|
||||||
case .backgroundRefresh: break
|
case .backgroundRefresh: break
|
||||||
case .noIdleTimeout: break
|
case .noIdleTimeout: break
|
||||||
case .disableAppLimit: break
|
|
||||||
case .addToSiri:
|
case .addToSiri:
|
||||||
guard #available(iOS 14, *) else { return }
|
guard #available(iOS 14, *) else { return }
|
||||||
self.addRefreshAppsShortcut()
|
self.addRefreshAppsShortcut()
|
||||||
@@ -595,8 +576,8 @@ extension SettingsViewController
|
|||||||
let row = CreditsRow.allCases[indexPath.row]
|
let row = CreditsRow.allCases[indexPath.row]
|
||||||
switch row
|
switch row
|
||||||
{
|
{
|
||||||
case .developer: self.openTwitter(username: "sidestoreio")
|
case .developer: self.openTwitter(username: "sidestore_io")
|
||||||
case .operations: self.openTwitter(username: "sidestoreio")
|
case .operations: self.openTwitter(username: "sidestore_io")
|
||||||
case .designer: self.openTwitter(username: "lit_ritt")
|
case .designer: self.openTwitter(username: "lit_ritt")
|
||||||
case .softwareLicenses: break
|
case .softwareLicenses: break
|
||||||
}
|
}
|
||||||
@@ -627,24 +608,24 @@ extension SettingsViewController
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Option 3: Mail
|
// Option 3: Mail
|
||||||
alertController.addAction(UIAlertAction(title: "Send Email", style: .default) { _ in
|
// alertController.addAction(UIAlertAction(title: "Send Email", style: .default) { _ in
|
||||||
if MFMailComposeViewController.canSendMail() {
|
// if MFMailComposeViewController.canSendMail() {
|
||||||
let mailViewController = MFMailComposeViewController()
|
// let mailViewController = MFMailComposeViewController()
|
||||||
mailViewController.mailComposeDelegate = self
|
// mailViewController.mailComposeDelegate = self
|
||||||
mailViewController.setToRecipients(["support@sidestore.io"])
|
// mailViewController.setToRecipients(["support@sidestore.io"])
|
||||||
|
//
|
||||||
if let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String {
|
// if let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String {
|
||||||
mailViewController.setSubject("SideStore Beta \(version) Feedback")
|
// mailViewController.setSubject("SideStore Beta \(version) Feedback")
|
||||||
} else {
|
// } else {
|
||||||
mailViewController.setSubject("SideStore Beta Feedback")
|
// mailViewController.setSubject("SideStore Beta Feedback")
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
self.present(mailViewController, animated: true, completion: nil)
|
// self.present(mailViewController, animated: true, completion: nil)
|
||||||
} else {
|
// } else {
|
||||||
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)
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
|
|
||||||
// Cancel action
|
// Cancel action
|
||||||
alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
|
alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
|
||||||
|
|||||||
@@ -28,12 +28,10 @@ public extension UserDefaults
|
|||||||
@NSManaged var customAnisetteURL: String?
|
@NSManaged var customAnisetteURL: String?
|
||||||
@NSManaged var menuAnisetteURL: String
|
@NSManaged var menuAnisetteURL: String
|
||||||
@NSManaged var menuAnisetteList: String
|
@NSManaged var menuAnisetteList: String
|
||||||
@NSManaged var menuAnisetteServersList: [String]
|
|
||||||
@NSManaged var preferredServerID: String?
|
@NSManaged var preferredServerID: String?
|
||||||
|
|
||||||
@NSManaged var isBackgroundRefreshEnabled: Bool
|
@NSManaged var isBackgroundRefreshEnabled: Bool
|
||||||
@NSManaged var isIdleTimeoutDisableEnabled: Bool
|
@NSManaged var isIdleTimeoutDisableEnabled: Bool
|
||||||
@NSManaged var isAppLimitDisabled: Bool
|
|
||||||
@NSManaged var isPairingReset: Bool
|
@NSManaged var isPairingReset: Bool
|
||||||
@NSManaged var isDebugModeEnabled: Bool
|
@NSManaged var isDebugModeEnabled: Bool
|
||||||
@NSManaged var presentedLaunchReminderNotification: Bool
|
@NSManaged var presentedLaunchReminderNotification: Bool
|
||||||
@@ -79,7 +77,6 @@ public extension UserDefaults
|
|||||||
let localServerSupportsRefreshing = !ProcessInfo.processInfo.isOperatingSystemAtLeast(ios14)
|
let localServerSupportsRefreshing = !ProcessInfo.processInfo.isOperatingSystemAtLeast(ios14)
|
||||||
|
|
||||||
let defaults = [
|
let defaults = [
|
||||||
#keyPath(UserDefaults.isAppLimitDisabled): false,
|
|
||||||
#keyPath(UserDefaults.isBackgroundRefreshEnabled): true,
|
#keyPath(UserDefaults.isBackgroundRefreshEnabled): true,
|
||||||
#keyPath(UserDefaults.isIdleTimeoutDisableEnabled): true,
|
#keyPath(UserDefaults.isIdleTimeoutDisableEnabled): true,
|
||||||
#keyPath(UserDefaults.isPairingReset): true,
|
#keyPath(UserDefaults.isPairingReset): true,
|
||||||
@@ -87,7 +84,6 @@ public extension UserDefaults
|
|||||||
#keyPath(UserDefaults.activeAppLimitIncludesExtensions): activeAppLimitIncludesExtensions,
|
#keyPath(UserDefaults.activeAppLimitIncludesExtensions): activeAppLimitIncludesExtensions,
|
||||||
#keyPath(UserDefaults.localServerSupportsRefreshing): localServerSupportsRefreshing,
|
#keyPath(UserDefaults.localServerSupportsRefreshing): localServerSupportsRefreshing,
|
||||||
#keyPath(UserDefaults.requiresAppGroupMigration): true,
|
#keyPath(UserDefaults.requiresAppGroupMigration): true,
|
||||||
#keyPath(UserDefaults.menuAnisetteList): "https://servers.sidestore.io/servers.json",
|
|
||||||
#keyPath(UserDefaults.menuAnisetteURL): "https://ani.sidestore.io"
|
#keyPath(UserDefaults.menuAnisetteURL): "https://ani.sidestore.io"
|
||||||
] as [String : Any]
|
] as [String : Any]
|
||||||
|
|
||||||
|
|||||||
@@ -407,10 +407,7 @@ private extension DatabaseManager
|
|||||||
// Migrate apps
|
// Migrate apps
|
||||||
if FileManager.default.fileExists(atPath: previousAppsDirectoryURL.path, isDirectory: nil)
|
if FileManager.default.fileExists(atPath: previousAppsDirectoryURL.path, isDirectory: nil)
|
||||||
{
|
{
|
||||||
if(previousAppsDirectoryURL.path != appsDirectoryURL.path)
|
_ = try FileManager.default.replaceItemAt(appsDirectoryURL, withItemAt: previousAppsDirectoryURL)
|
||||||
{
|
|
||||||
_ = try FileManager.default.replaceItemAt(appsDirectoryURL, withItemAt: previousAppsDirectoryURL)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
finish(.success(()))
|
finish(.success(()))
|
||||||
|
|||||||
@@ -163,9 +163,8 @@ public extension InstalledApp
|
|||||||
class func updatesFetchRequest() -> NSFetchRequest<InstalledApp>
|
class func updatesFetchRequest() -> NSFetchRequest<InstalledApp>
|
||||||
{
|
{
|
||||||
let fetchRequest = InstalledApp.fetchRequest() as NSFetchRequest<InstalledApp>
|
let fetchRequest = InstalledApp.fetchRequest() as NSFetchRequest<InstalledApp>
|
||||||
fetchRequest.predicate = NSPredicate(format: "%K == YES AND %K == YES",
|
fetchRequest.predicate = NSPredicate(format: "%K == YES AND %K != nil AND %K != %K",
|
||||||
#keyPath(InstalledApp.isActive), #keyPath(InstalledApp.hasUpdate))
|
#keyPath(InstalledApp.isActive), #keyPath(InstalledApp.storeApp), #keyPath(InstalledApp.version), #keyPath(InstalledApp.storeApp.latestSupportedVersion.version))
|
||||||
|
|
||||||
return fetchRequest
|
return fetchRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -169,31 +169,6 @@ public class StoreApp: NSManagedObject, Decodable, Fetchable
|
|||||||
return self._versions.array as! [AppVersion]
|
return self._versions.array as! [AppVersion]
|
||||||
}
|
}
|
||||||
|
|
||||||
@nonobjc public var size: Int64? {
|
|
||||||
guard let version = self.latestSupportedVersion else { return nil }
|
|
||||||
return version.size
|
|
||||||
}
|
|
||||||
|
|
||||||
@nonobjc public var version: String? {
|
|
||||||
guard let version = self.latestSupportedVersion else { return nil }
|
|
||||||
return version.version
|
|
||||||
}
|
|
||||||
|
|
||||||
@nonobjc public var versionDescription: String? {
|
|
||||||
guard let version = self.latestSupportedVersion else { return nil }
|
|
||||||
return version.localizedDescription
|
|
||||||
}
|
|
||||||
|
|
||||||
@nonobjc public var versionDate: Date? {
|
|
||||||
guard let version = self.latestSupportedVersion else { return nil }
|
|
||||||
return version.date
|
|
||||||
}
|
|
||||||
|
|
||||||
@nonobjc public var downloadURL: URL? {
|
|
||||||
guard let version = self.latestSupportedVersion else { return nil }
|
|
||||||
return version.downloadURL
|
|
||||||
}
|
|
||||||
|
|
||||||
private override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?)
|
private override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?)
|
||||||
{
|
{
|
||||||
super.init(entity: entity, insertInto: context)
|
super.init(entity: entity, insertInto: context)
|
||||||
@@ -240,7 +215,7 @@ public class StoreApp: NSManagedObject, Decodable, Fetchable
|
|||||||
self.iconURL = try container.decode(URL.self, forKey: .iconURL)
|
self.iconURL = try container.decode(URL.self, forKey: .iconURL)
|
||||||
self.screenshotURLs = try container.decodeIfPresent([URL].self, forKey: .screenshotURLs) ?? []
|
self.screenshotURLs = try container.decodeIfPresent([URL].self, forKey: .screenshotURLs) ?? []
|
||||||
|
|
||||||
var downloadURL = try container.decodeIfPresent(URL.self, forKey: .downloadURL)
|
let downloadURL = try container.decodeIfPresent(URL.self, forKey: .downloadURL)
|
||||||
let platformURLs = try container.decodeIfPresent(PlatformURLs.self.self, forKey: .platformURLs)
|
let platformURLs = try container.decodeIfPresent(PlatformURLs.self.self, forKey: .platformURLs)
|
||||||
if let platformURLs = platformURLs {
|
if let platformURLs = platformURLs {
|
||||||
self.platformURLs = platformURLs
|
self.platformURLs = platformURLs
|
||||||
@@ -255,22 +230,7 @@ public class StoreApp: NSManagedObject, Decodable, Fetchable
|
|||||||
} else if let downloadURL = downloadURL {
|
} else if let downloadURL = downloadURL {
|
||||||
self._downloadURL = downloadURL
|
self._downloadURL = downloadURL
|
||||||
} else {
|
} else {
|
||||||
let version = try container.decode(String.self, forKey: .version)
|
throw DecodingError.dataCorruptedError(forKey: .downloadURL, in: container, debugDescription: "E downloadURL:String or downloadURLs:[[Platform:URL]] key required.")
|
||||||
if let versions = try container.decodeIfPresent([AppVersion].self, forKey: .versions){
|
|
||||||
for ver in versions {
|
|
||||||
if ver.version == version {
|
|
||||||
self._downloadURL = ver.downloadURL
|
|
||||||
downloadURL = ver.downloadURL // not sure if this is needed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw DecodingError.dataCorruptedError(forKey: .downloadURL, in: container, debugDescription: "E downloadURL:String or downloadURLs:[[Platform:URL]] key required.")
|
|
||||||
} else {
|
|
||||||
throw DecodingError.dataCorruptedError(forKey: .downloadURL, in: container, debugDescription: "E downloadURL:String or downloadURLs:[[Platform:URL]] key required.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// else {
|
|
||||||
// throw DecodingError.dataCorruptedError(forKey: .downloadURL, in: container, debugDescription: "E downloadURL:String or downloadURLs:[[Platform:URL]] key required.")
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let tintColorHex = try container.decodeIfPresent(String.self, forKey: .tintColor)
|
if let tintColorHex = try container.decodeIfPresent(String.self, forKey: .tintColor)
|
||||||
@@ -290,9 +250,6 @@ public class StoreApp: NSManagedObject, Decodable, Fetchable
|
|||||||
if let versions = try container.decodeIfPresent([AppVersion].self, forKey: .versions)
|
if let versions = try container.decodeIfPresent([AppVersion].self, forKey: .versions)
|
||||||
{
|
{
|
||||||
//TODO: Throw error if there isn't at least one version.
|
//TODO: Throw error if there isn't at least one version.
|
||||||
if (versions.count == 0){
|
|
||||||
throw DecodingError.dataCorruptedError(forKey: .versions, in: container, debugDescription: "At least one version is required in key: versions")
|
|
||||||
}
|
|
||||||
|
|
||||||
for version in versions
|
for version in versions
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,30 +10,29 @@ import Foundation
|
|||||||
import AuthenticationServices
|
import AuthenticationServices
|
||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
private let clientID = "my4hpHHG4iVRme6QALnQGlhSBQiKdB_AinrVgPpIpiC-xiHstTYiLKO5vfariFo1"
|
private let clientID = "ZMx0EGUWe4TVWYXNZZwK_fbIK5jHFVWoUf1Qb-sqNXmT-YzAGwDPxxq7ak3_W5Q2"
|
||||||
private let clientSecret = "Zow0ggt9YgwIyd4DVLoO9Z02KuuIXW44xhx4lfL27x2u-_u4FE4rYR48bEKREPS5"
|
private let clientSecret = "1hktsZB89QyN69cB4R0tu55R4TCPQGXxvebYUUh7Y-5TLSnRswuxs6OUjdJ74IJt"
|
||||||
|
|
||||||
private let campaignID = "12794837"
|
private let campaignID = "2863968"
|
||||||
|
|
||||||
typealias PatreonAPIError = PatreonAPIErrorCode.Error
|
|
||||||
enum PatreonAPIErrorCode: Int, ALTErrorEnum, CaseIterable
|
|
||||||
{
|
|
||||||
case unknown
|
|
||||||
case notAuthenticated
|
|
||||||
case invalidAccessToken
|
|
||||||
|
|
||||||
var errorFailureReason: String {
|
|
||||||
switch self
|
|
||||||
{
|
|
||||||
case .unknown: return NSLocalizedString("An unknown error occurred.", comment: "")
|
|
||||||
case .notAuthenticated: return NSLocalizedString("No connected Patreon account.", comment: "")
|
|
||||||
case .invalidAccessToken: return NSLocalizedString("Invalid access token.", comment: "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension PatreonAPI
|
extension PatreonAPI
|
||||||
{
|
{
|
||||||
|
enum Error: LocalizedError
|
||||||
|
{
|
||||||
|
case unknown
|
||||||
|
case notAuthenticated
|
||||||
|
case invalidAccessToken
|
||||||
|
|
||||||
|
var errorDescription: String? {
|
||||||
|
switch self
|
||||||
|
{
|
||||||
|
case .unknown: return NSLocalizedString("An unknown error occurred.", comment: "")
|
||||||
|
case .notAuthenticated: return NSLocalizedString("No connected Patreon account.", comment: "")
|
||||||
|
case .invalidAccessToken: return NSLocalizedString("Invalid access token.", comment: "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum AuthorizationType
|
enum AuthorizationType
|
||||||
{
|
{
|
||||||
case none
|
case none
|
||||||
@@ -111,7 +110,7 @@ public extension PatreonAPI
|
|||||||
let components = URLComponents(url: callbackURL, resolvingAgainstBaseURL: false),
|
let components = URLComponents(url: callbackURL, resolvingAgainstBaseURL: false),
|
||||||
let codeQueryItem = components.queryItems?.first(where: { $0.name == "code" }),
|
let codeQueryItem = components.queryItems?.first(where: { $0.name == "code" }),
|
||||||
let code = codeQueryItem.value
|
let code = codeQueryItem.value
|
||||||
else { throw PatreonAPIError(.unknown) }
|
else { throw Error.unknown }
|
||||||
|
|
||||||
self.fetchAccessToken(oauthCode: code) { (result) in
|
self.fetchAccessToken(oauthCode: code) { (result) in
|
||||||
switch result
|
switch result
|
||||||
@@ -152,9 +151,9 @@ public extension PatreonAPI
|
|||||||
self.send(request, authorizationType: .user) { (result: Result<AccountResponse, Swift.Error>) in
|
self.send(request, authorizationType: .user) { (result: Result<AccountResponse, Swift.Error>) in
|
||||||
switch result
|
switch result
|
||||||
{
|
{
|
||||||
case .failure(~PatreonAPIErrorCode.notAuthenticated):
|
case .failure(Error.notAuthenticated):
|
||||||
self.signOut() { (result) in
|
self.signOut() { (result) in
|
||||||
completion(.failure(PatreonAPIError(.notAuthenticated)))
|
completion(.failure(Error.notAuthenticated))
|
||||||
}
|
}
|
||||||
|
|
||||||
case .failure(let error): completion(.failure(error))
|
case .failure(let error): completion(.failure(error))
|
||||||
@@ -358,11 +357,11 @@ private extension PatreonAPI
|
|||||||
{
|
{
|
||||||
case .none: break
|
case .none: break
|
||||||
case .creator:
|
case .creator:
|
||||||
guard let creatorAccessToken = Keychain.shared.patreonCreatorAccessToken else { return completion(.failure(PatreonAPIError(.invalidAccessToken))) }
|
guard let creatorAccessToken = Keychain.shared.patreonCreatorAccessToken else { return completion(.failure(Error.invalidAccessToken)) }
|
||||||
request.setValue("Bearer " + creatorAccessToken, forHTTPHeaderField: "Authorization")
|
request.setValue("Bearer " + creatorAccessToken, forHTTPHeaderField: "Authorization")
|
||||||
|
|
||||||
case .user:
|
case .user:
|
||||||
guard let accessToken = Keychain.shared.patreonAccessToken else { return completion(.failure(PatreonAPIError(.notAuthenticated))) }
|
guard let accessToken = Keychain.shared.patreonAccessToken else { return completion(.failure(Error.notAuthenticated)) }
|
||||||
request.setValue("Bearer " + accessToken, forHTTPHeaderField: "Authorization")
|
request.setValue("Bearer " + accessToken, forHTTPHeaderField: "Authorization")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,8 +374,8 @@ private extension PatreonAPI
|
|||||||
{
|
{
|
||||||
switch authorizationType
|
switch authorizationType
|
||||||
{
|
{
|
||||||
case .creator: completion(.failure(PatreonAPIError(.invalidAccessToken)))
|
case .creator: completion(.failure(Error.invalidAccessToken))
|
||||||
case .none: completion(.failure(PatreonAPIError(.notAuthenticated)))
|
case .none: completion(.failure(Error.notAuthenticated))
|
||||||
case .user:
|
case .user:
|
||||||
self.refreshAccessToken() { (result) in
|
self.refreshAccessToken() { (result) in
|
||||||
switch result
|
switch result
|
||||||
|
|||||||
@@ -82,7 +82,6 @@ struct ComplicationView: View
|
|||||||
}
|
}
|
||||||
.gaugeStyle(.accessoryCircularCapacity)
|
.gaugeStyle(.accessoryCircularCapacity)
|
||||||
.unredacted()
|
.unredacted()
|
||||||
.widgetBackground(Color.clear)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
//
|
|
||||||
// View+AltWidget.swift
|
|
||||||
// AltStore
|
|
||||||
//
|
|
||||||
// Created by Riley Testut on 8/18/23.
|
|
||||||
// Copyright © 2023 Riley Testut. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
extension View
|
|
||||||
{
|
|
||||||
@ViewBuilder
|
|
||||||
func widgetBackground(_ backgroundView: some View) -> some View
|
|
||||||
{
|
|
||||||
if #available(iOSApplicationExtension 17, *)
|
|
||||||
{
|
|
||||||
containerBackground(for: .widget) {
|
|
||||||
backgroundView
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
background(backgroundView)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -104,8 +104,7 @@ struct WidgetView : View
|
|||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.widgetBackground(backgroundView(icon: entry.app?.icon, tintColor: entry.app?.tintColor))
|
.background(backgroundView(icon: entry.app?.icon, tintColor: entry.app?.tintColor))
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.9
|
MARKETING_VERSION = 0.5.8
|
||||||
CURRENT_PROJECT_VERSION = 5090
|
CURRENT_PROJECT_VERSION = 5080
|
||||||
|
|
||||||
// Vars to be overwritten by `CodeSigning.xcconfig` if exists
|
// Vars to be overwritten by `CodeSigning.xcconfig` if exists
|
||||||
DEVELOPMENT_TEAM = S32Z3HMYVQ
|
DEVELOPMENT_TEAM = S32Z3HMYVQ
|
||||||
@@ -25,6 +25,3 @@ PRODUCT_BUNDLE_IDENTIFIER[config=Debug] = $(ORG_PREFIX).SideStore.$(DEVELOPMENT_
|
|||||||
EXTENSION_PREFIX = $(PRODUCT_BUNDLE_IDENTIFIER)
|
EXTENSION_PREFIX = $(PRODUCT_BUNDLE_IDENTIFIER)
|
||||||
APP_GROUP_IDENTIFIER = $(PRODUCT_BUNDLE_IDENTIFIER)
|
APP_GROUP_IDENTIFIER = $(PRODUCT_BUNDLE_IDENTIFIER)
|
||||||
ICLOUD_CONTAINER_IDENTIFIER = iCloud.$(ORG_PREFIX).$(PROJECT_NAME)
|
ICLOUD_CONTAINER_IDENTIFIER = iCloud.$(ORG_PREFIX).$(PROJECT_NAME)
|
||||||
|
|
||||||
// Suppress noise from os activity in xcode console log for release builds
|
|
||||||
DEBUG_ACTIVITY_MODE = disable
|
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
Developer Certificate of Origin
|
|
||||||
Version 1.1
|
|
||||||
|
|
||||||
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
|
|
||||||
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies of this
|
|
||||||
license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
|
|
||||||
Developer's Certificate of Origin 1.1
|
|
||||||
|
|
||||||
By making a contribution to this project, I certify that:
|
|
||||||
|
|
||||||
(a) The contribution was created in whole or in part by me and I
|
|
||||||
have the right to submit it under the open source license
|
|
||||||
indicated in the file; or
|
|
||||||
|
|
||||||
(b) The contribution is based upon previous work that, to the best
|
|
||||||
of my knowledge, is covered under an appropriate open source
|
|
||||||
license and I have the right under that license to submit that
|
|
||||||
work with modifications, whether created in whole or in part
|
|
||||||
by me, under the same open source license (unless I am
|
|
||||||
permitted to submit under a different license), as indicated
|
|
||||||
in the file; or
|
|
||||||
|
|
||||||
(c) The contribution was provided directly to me by some other
|
|
||||||
person who certified (a), (b) or (c) and I have not modified
|
|
||||||
it.
|
|
||||||
|
|
||||||
(d) I understand and agree that this project and the contribution
|
|
||||||
are public and that a record of the contribution (including all
|
|
||||||
personal information I submit with it, including my sign-off) is
|
|
||||||
maintained indefinitely and may be redistributed consistent with
|
|
||||||
this project or the open source license(s) involved.
|
|
||||||
|
|
||||||
@@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
Thank you for your interest in contributing to SideStore! SideStore is a community driven project, and it's made possible by people like you.
|
Thank you for your interest in contributing to SideStore! SideStore is a community driven project, and it's made possible by people like you.
|
||||||
|
|
||||||
By contributing to this Project (SideStore), you agree to the Developer's Certificate of Origin found in [CERTIFICATE-OF-ORIGIN.md](CERTIFICATE-OF-ORIGIN.md). Any contributions to this project after the addition of the Developer's Certificate of Origin are subject to its policy.
|
|
||||||
|
|
||||||
There are many ways to contribute to SideStore, so if you aren't a developer, there are still many other ways you can help out:
|
There are many ways to contribute to SideStore, so if you aren't a developer, there are still many other ways you can help out:
|
||||||
|
|
||||||
- [Writing documentation](https://github.com/SideStore/SideStore-Docs)
|
- [Writing documentation](https://github.com/SideStore/SideStore-Docs)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
outputFiles = (
|
outputFiles = (
|
||||||
"$(OBJECT_FILE_DIR)/$(CARGO_XCODE_TARGET_ARCH)-$(EXECUTABLE_NAME)",
|
"$(OBJECT_FILE_DIR)/$(CARGO_XCODE_TARGET_ARCH)-$(EXECUTABLE_NAME)",
|
||||||
);
|
);
|
||||||
script = "# generated with cargo-xcode 1.5.0\n# modified to use prebuilt binaries\n\nset -eu;\n\nBUILT_SRC=\"./em_proxy/$LIB_FILE_NAME.a\"\necho Generating Static lib: $BUILT_SRC\nln -f -- \"$BUILT_SRC\" \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\" || cp \"$BUILT_SRC\" \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\necho \"$BUILT_SRC -> $TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\n\n# xcode generates dep file, but for its own path, so append our rename to it\n#DEP_FILE_SRC=\"minimuxer/target/${CARGO_XCODE_TARGET_TRIPLE}/release/${CARGO_XCODE_CARGO_DEP_FILE_NAME}\"\n#if [ -f \"$DEP_FILE_SRC\" ]; then\n# DEP_FILE_DST=\"${DERIVED_FILE_DIR}/${CARGO_XCODE_TARGET_ARCH}-${EXECUTABLE_NAME}.d\"\n# cp -f \"$DEP_FILE_SRC\" \"$DEP_FILE_DST\"\n# echo >> \"$DEP_FILE_DST\" \"$SCRIPT_OUTPUT_FILE_0: $BUILT_SRC\"\n#fi\n\n# lipo script needs to know all the platform-specific files that have been built\n# archs is in the file name, so that paths don't stay around after archs change\n# must match input for LipoScript\n#FILE_LIST=\"${DERIVED_FILE_DIR}/${ARCHS}-${EXECUTABLE_NAME}.xcfilelist\"\n#touch \"$FILE_LIST\"\n#if ! egrep -q \"$SCRIPT_OUTPUT_FILE_0\" \"$FILE_LIST\" ; then\n# echo >> \"$FILE_LIST\" \"$SCRIPT_OUTPUT_FILE_0\"\n#fi\n";
|
script = "# generated with cargo-xcode 1.5.0\n# modified to use prebuilt binaries\n\nset -eu;\n\nBUILT_SRC=\"./em_proxy/$LIB_FILE_NAME.a\"\nln -f -- \"$BUILT_SRC\" \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\" || cp \"$BUILT_SRC\" \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\necho \"$BUILT_SRC -> $TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\n\n# xcode generates dep file, but for its own path, so append our rename to it\n#DEP_FILE_SRC=\"minimuxer/target/${CARGO_XCODE_TARGET_TRIPLE}/release/${CARGO_XCODE_CARGO_DEP_FILE_NAME}\"\n#if [ -f \"$DEP_FILE_SRC\" ]; then\n# DEP_FILE_DST=\"${DERIVED_FILE_DIR}/${CARGO_XCODE_TARGET_ARCH}-${EXECUTABLE_NAME}.d\"\n# cp -f \"$DEP_FILE_SRC\" \"$DEP_FILE_DST\"\n# echo >> \"$DEP_FILE_DST\" \"$SCRIPT_OUTPUT_FILE_0: $BUILT_SRC\"\n#fi\n\n# lipo script needs to know all the platform-specific files that have been built\n# archs is in the file name, so that paths don't stay around after archs change\n# must match input for LipoScript\n#FILE_LIST=\"${DERIVED_FILE_DIR}/${ARCHS}-${EXECUTABLE_NAME}.xcfilelist\"\n#touch \"$FILE_LIST\"\n#if ! egrep -q \"$SCRIPT_OUTPUT_FILE_0\" \"$FILE_LIST\" ; then\n# echo >> \"$FILE_LIST\" \"$SCRIPT_OUTPUT_FILE_0\"\n#fi\n";
|
||||||
};
|
};
|
||||||
/* End PBXBuildRule section */
|
/* End PBXBuildRule section */
|
||||||
|
|
||||||
@@ -223,7 +223,7 @@
|
|||||||
INSTALL_MODE_FLAG = "";
|
INSTALL_MODE_FLAG = "";
|
||||||
INSTALL_OWNER = "";
|
INSTALL_OWNER = "";
|
||||||
LIB_FILE_NAME = "";
|
LIB_FILE_NAME = "";
|
||||||
"LIB_FILE_NAME[sdk=iphoneos*]" = "libem_proxy-ios";
|
"LIB_FILE_NAME[sdk=iphoneos*]" = libem_proxy;
|
||||||
"LIB_FILE_NAME[sdk=iphonesimulator*]" = "libem_proxy-sim";
|
"LIB_FILE_NAME[sdk=iphonesimulator*]" = "libem_proxy-sim";
|
||||||
PRODUCT_NAME = em_proxy_static;
|
PRODUCT_NAME = em_proxy_static;
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
@@ -299,7 +299,7 @@
|
|||||||
INSTALL_MODE_FLAG = "";
|
INSTALL_MODE_FLAG = "";
|
||||||
INSTALL_OWNER = "";
|
INSTALL_OWNER = "";
|
||||||
LIB_FILE_NAME = "";
|
LIB_FILE_NAME = "";
|
||||||
"LIB_FILE_NAME[sdk=iphoneos*]" = "libem_proxy-ios";
|
"LIB_FILE_NAME[sdk=iphoneos*]" = libem_proxy;
|
||||||
"LIB_FILE_NAME[sdk=iphonesimulator*]" = "libem_proxy-sim";
|
"LIB_FILE_NAME[sdk=iphonesimulator*]" = "libem_proxy-sim";
|
||||||
PRODUCT_NAME = em_proxy_static;
|
PRODUCT_NAME = em_proxy_static;
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
|
|||||||
60
Dependencies/fetch-prebuilt.sh
vendored
Executable file → Normal file
60
Dependencies/fetch-prebuilt.sh
vendored
Executable file → Normal file
@@ -3,34 +3,6 @@
|
|||||||
# Ensure we are in Dependencies directory
|
# Ensure we are in Dependencies directory
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
# Detect if Homebrew is in /opt/homebrew (Apple Silicon) or /usr/local (Intel)
|
|
||||||
if [[ -d "/opt/homebrew" ]]; then
|
|
||||||
export PATH="/opt/homebrew/bin:$PATH"
|
|
||||||
elif [[ -d "/usr/local" ]]; then
|
|
||||||
export PATH="/usr/local/bin:$PATH"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if wget and curl are installed; if not, install them via Homebrew
|
|
||||||
if ! command -v wget &> /dev/null; then
|
|
||||||
echo "wget not found, attempting to install via Homebrew..."
|
|
||||||
if command -v brew &> /dev/null; then
|
|
||||||
brew install wget
|
|
||||||
else
|
|
||||||
echo "Homebrew is not installed. Please install Homebrew and rerun the script."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! command -v curl &> /dev/null; then
|
|
||||||
echo "curl not found, attempting to install via Homebrew..."
|
|
||||||
if command -v brew &> /dev/null; then
|
|
||||||
brew install curl
|
|
||||||
else
|
|
||||||
echo "Homebrew is not installed. Please install Homebrew and rerun the script."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
check_for_update() {
|
check_for_update() {
|
||||||
if [ -f ".skip-prebuilt-fetch-$1" ]; then
|
if [ -f ".skip-prebuilt-fetch-$1" ]; then
|
||||||
echo "Skipping prebuilt fetch for $1 since .skip-prebuilt-fetch-$1 exists. If you are developing $1 alongside SideStore, don't remove this file, or this script will replace your locally built binaries with the ones built by GitHub Actions."
|
echo "Skipping prebuilt fetch for $1 since .skip-prebuilt-fetch-$1 exists. If you are developing $1 alongside SideStore, don't remove this file, or this script will replace your locally built binaries with the ones built by GitHub Actions."
|
||||||
@@ -44,40 +16,20 @@ 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'`
|
||||||
|
|
||||||
# Check if required library files exist
|
# fetch if last fetch was over 1 hour ago
|
||||||
FORCE_DOWNLOAD=false
|
if [[ $LAST_FETCH -lt $(expr $(date +%s) - 3600) ]] || [[ "$2" == "force" ]]; then
|
||||||
if [ ! -f "$1/lib$1-sim.a" ] || [ ! -f "$1/lib$1-ios.a" ]; then
|
|
||||||
echo "Required libraries missing for $1, forcing download..."
|
|
||||||
FORCE_DOWNLOAD=true
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Download if:
|
|
||||||
# 1. Libraries are missing (FORCE_DOWNLOAD), or
|
|
||||||
# 2. Last fetch was over 1 hour ago, or
|
|
||||||
# 3. Force flag was passed
|
|
||||||
if [ "$FORCE_DOWNLOAD" = true ] || [[ $LAST_FETCH -lt $(expr $(date +%s) - 3600) ]] || [[ "$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'`
|
||||||
echo
|
echo
|
||||||
echo "Last commit: $LAST_COMMIT"
|
echo "Last commit: $LAST_COMMIT"
|
||||||
echo "Latest commit: $LATEST_COMMIT"
|
echo "Latest commit: $LATEST_COMMIT"
|
||||||
|
|
||||||
NOT_UPTODATE=false
|
|
||||||
if [[ "$LAST_COMMIT" != "$LATEST_COMMIT" ]]; then
|
if [[ "$LAST_COMMIT" != "$LATEST_COMMIT" ]]; then
|
||||||
echo "Found update on the remote: https://api.github.com/repos/SideStore/$1/releases/latest"
|
echo "Found update, downloading binaries"
|
||||||
NOT_UPTODATE=true
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Download if:
|
|
||||||
# 1. Libraries are missing (FORCE_DOWNLOAD), or
|
|
||||||
# 2. New commit is available
|
|
||||||
if [ "$FORCE_DOWNLOAD" = true ] || [ "$NOT_UPTODATE" = true ] ;then
|
|
||||||
echo "downloading binaries"
|
|
||||||
echo
|
echo
|
||||||
wget -O "$1/lib$1-sim.a" "https://github.com/SideStore/$1/releases/latest/download/lib$1-sim.a"
|
wget -O "$1/lib$1-sim.a" "https://github.com/SideStore/$1/releases/latest/download/lib$1-sim.a"
|
||||||
if [[ "$1" != "minimuxer" ]]; then
|
if [[ "$1" != "minimuxer" ]]; then
|
||||||
wget -O "$1/lib$1-ios.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/$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
|
else
|
||||||
@@ -87,9 +39,7 @@ check_for_update() {
|
|||||||
echo "Unzipping generated.zip"
|
echo "Unzipping generated.zip"
|
||||||
cd "$1"
|
cd "$1"
|
||||||
unzip ./generated.zip
|
unzip ./generated.zip
|
||||||
cp -v generated/* .
|
mv -v generated/* .
|
||||||
# Remove all files except ones that comes checked-in from minimuxer repository
|
|
||||||
find generated -type f ! -name 'minimuxer-Bridging-Header.h' ! -name 'minimuxer-helpers.swift' -exec rm -v {} \;
|
|
||||||
rm generated.zip
|
rm generated.zip
|
||||||
rmdir generated/
|
rmdir generated/
|
||||||
cd ..
|
cd ..
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
outputFiles = (
|
outputFiles = (
|
||||||
"$(OBJECT_FILE_DIR)/$(CARGO_XCODE_TARGET_ARCH)-$(EXECUTABLE_NAME)",
|
"$(OBJECT_FILE_DIR)/$(CARGO_XCODE_TARGET_ARCH)-$(EXECUTABLE_NAME)",
|
||||||
);
|
);
|
||||||
script = "# generated with cargo-xcode 1.5.0\n# modified to use prebuilt binaries\n\nset -eu;\n\nBUILT_SRC=\"./minimuxer/${LIB_FILE_NAME}.a\"\necho Generating Static lib: $BUILT_SRC\nln -f -- \"$BUILT_SRC\" \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\" || cp \"$BUILT_SRC\" \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\necho \"$BUILT_SRC -> $TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\n\n# xcode generates dep file, but for its own path, so append our rename to it\n#DEP_FILE_SRC=\"minimuxer/target/${CARGO_XCODE_TARGET_TRIPLE}/release/${CARGO_XCODE_CARGO_DEP_FILE_NAME}\"\n#if [ -f \"$DEP_FILE_SRC\" ]; then\n# DEP_FILE_DST=\"${DERIVED_FILE_DIR}/${CARGO_XCODE_TARGET_ARCH}-${EXECUTABLE_NAME}.d\"\n# cp -f \"$DEP_FILE_SRC\" \"$DEP_FILE_DST\"\n# echo >> \"$DEP_FILE_DST\" \"$SCRIPT_OUTPUT_FILE_0: $BUILT_SRC\"\n#fi\n\n# lipo script needs to know all the platform-specific files that have been built\n# archs is in the file name, so that paths don't stay around after archs change\n# must match input for LipoScript\n#FILE_LIST=\"${DERIVED_FILE_DIR}/${ARCHS}-${EXECUTABLE_NAME}.xcfilelist\"\n#touch \"$FILE_LIST\"\n#if ! egrep -q \"$SCRIPT_OUTPUT_FILE_0\" \"$FILE_LIST\" ; then\n# echo >> \"$FILE_LIST\" \"$SCRIPT_OUTPUT_FILE_0\"\n#fi\n";
|
script = "# generated with cargo-xcode 1.5.0\n# modified to use prebuilt binaries\n\nset -eu;\n\nBUILT_SRC=\"./minimuxer/$LIB_FILE_NAME.a\"\nln -f -- \"$BUILT_SRC\" \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\" || cp \"$BUILT_SRC\" \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\necho \"$BUILT_SRC -> $TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\n\n# xcode generates dep file, but for its own path, so append our rename to it\n#DEP_FILE_SRC=\"minimuxer/target/${CARGO_XCODE_TARGET_TRIPLE}/release/${CARGO_XCODE_CARGO_DEP_FILE_NAME}\"\n#if [ -f \"$DEP_FILE_SRC\" ]; then\n# DEP_FILE_DST=\"${DERIVED_FILE_DIR}/${CARGO_XCODE_TARGET_ARCH}-${EXECUTABLE_NAME}.d\"\n# cp -f \"$DEP_FILE_SRC\" \"$DEP_FILE_DST\"\n# echo >> \"$DEP_FILE_DST\" \"$SCRIPT_OUTPUT_FILE_0: $BUILT_SRC\"\n#fi\n\n# lipo script needs to know all the platform-specific files that have been built\n# archs is in the file name, so that paths don't stay around after archs change\n# must match input for LipoScript\n#FILE_LIST=\"${DERIVED_FILE_DIR}/${ARCHS}-${EXECUTABLE_NAME}.xcfilelist\"\n#touch \"$FILE_LIST\"\n#if ! egrep -q \"$SCRIPT_OUTPUT_FILE_0\" \"$FILE_LIST\" ; then\n# echo >> \"$FILE_LIST\" \"$SCRIPT_OUTPUT_FILE_0\"\n#fi\n";
|
||||||
};
|
};
|
||||||
/* End PBXBuildRule section */
|
/* End PBXBuildRule section */
|
||||||
|
|
||||||
|
|||||||
2
Makefile
2
Makefile
@@ -158,7 +158,7 @@ test:
|
|||||||
|
|
||||||
build:
|
build:
|
||||||
@xcodebuild -project AltStore.xcodeproj \
|
@xcodebuild -project AltStore.xcodeproj \
|
||||||
-scheme SideStore \
|
-scheme AltStore \
|
||||||
-sdk iphoneos \
|
-sdk iphoneos \
|
||||||
archive -archivePath ./archive \
|
archive -archivePath ./archive \
|
||||||
CODE_SIGNING_REQUIRED=NO \
|
CODE_SIGNING_REQUIRED=NO \
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
[](https://makeapullrequest.com)
|
[](https://makeapullrequest.com)
|
||||||
[](https://github.com/SideStore/SideStore/actions/workflows/nightly.yml)
|
[](https://github.com/SideStore/SideStore/actions/workflows/nightly.yml)
|
||||||
[](https://github.com/SideStore/SideStore/actions/workflows/beta.yml)
|
[](https://github.com/SideStore/SideStore/actions/workflows/beta.yml)
|
||||||
[](https://discord.gg/sidestore)
|
[](https://discord.gg/sidestore-949183273383395328)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,6 @@ public extension NSError
|
|||||||
{
|
{
|
||||||
var userInfo = self.userInfo
|
var userInfo = self.userInfo
|
||||||
userInfo[NSLocalizedDescriptionKey] = self.localizedDescription
|
userInfo[NSLocalizedDescriptionKey] = self.localizedDescription
|
||||||
userInfo[NSLocalizedFailureErrorKey] = self.localizedFailure
|
|
||||||
userInfo[NSLocalizedFailureReasonErrorKey] = self.localizedFailureReason
|
userInfo[NSLocalizedFailureReasonErrorKey] = self.localizedFailureReason
|
||||||
userInfo[NSLocalizedRecoverySuggestionErrorKey] = self.localizedRecoverySuggestion
|
userInfo[NSLocalizedRecoverySuggestionErrorKey] = self.localizedRecoverySuggestion
|
||||||
userInfo[NSDebugDescriptionErrorKey] = self.localizedDebugDescription
|
userInfo[NSDebugDescriptionErrorKey] = self.localizedDebugDescription
|
||||||
@@ -125,7 +124,6 @@ public extension NSError
|
|||||||
|
|
||||||
var userInfo = self.userInfo
|
var userInfo = self.userInfo
|
||||||
userInfo[NSDebugDescriptionErrorKey] = self.localizedDebugDescription
|
userInfo[NSDebugDescriptionErrorKey] = self.localizedDebugDescription
|
||||||
userInfo[NSLocalizedDescriptionKey] = self.localizedDescription
|
|
||||||
userInfo[NSLocalizedFailureErrorKey] = self.localizedFailure
|
userInfo[NSLocalizedFailureErrorKey] = self.localizedFailure
|
||||||
userInfo[NSLocalizedFailureReasonErrorKey] = self.localizedFailureReason
|
userInfo[NSLocalizedFailureReasonErrorKey] = self.localizedFailureReason
|
||||||
userInfo[NSLocalizedRecoverySuggestionErrorKey] = self.localizedRecoverySuggestion
|
userInfo[NSLocalizedRecoverySuggestionErrorKey] = self.localizedRecoverySuggestion
|
||||||
|
|||||||
Reference in New Issue
Block a user