Opens Error Log when tapping ToastView

This commit is contained in:
nythepegasus
2024-05-06 19:55:44 -04:00
committed by ny
parent 4365ba0f1a
commit b024e67fee
8 changed files with 74 additions and 43 deletions

View File

@@ -510,7 +510,7 @@ extension AppViewController
catch catch
{ {
DispatchQueue.main.async { DispatchQueue.main.async {
let toastView = ToastView(error: error) let toastView = ToastView(error: error, opensLog: true)
toastView.show(in: self) toastView.show(in: self)
} }
} }

View File

@@ -278,7 +278,7 @@ private extension BrowseViewController
{ {
case .failure(OperationError.cancelled): break // Ignore case .failure(OperationError.cancelled): break // Ignore
case .failure(let error): case .failure(let error):
let toastView = ToastView(error: error) let toastView = ToastView(error: error, opensLog: true)
toastView.show(in: self) toastView.show(in: self)
case .success: print("Installed app:", app.bundleIdentifier) case .success: print("Installed app:", app.bundleIdentifier)

View File

@@ -18,8 +18,17 @@ extension TimeInterval
final class ToastView: RSTToastView final class ToastView: RSTToastView
{ {
static let openErrorLogNotification = Notification.Name("ALTOpenErrorLogNotification")
var preferredDuration: TimeInterval var preferredDuration: TimeInterval
var opensErrorLog: Bool = false
convenience init(text: String, detailText: String?, opensLog: Bool = false) {
self.init(text: text, detailText: detailText)
self.opensErrorLog = opensLog
}
override init(text: String, detailText detailedText: String?) override init(text: String, detailText detailedText: String?)
{ {
if detailedText == nil if detailedText == nil
@@ -43,7 +52,14 @@ final class ToastView: RSTToastView
// RSTToastView does not expose stack view containing labels, // RSTToastView does not expose stack view containing labels,
// so we access it indirectly as the labels' superview. // so we access it indirectly as the labels' superview.
stackView.spacing = (detailedText != nil) ? 4.0 : 0.0 stackView.spacing = (detailedText != nil) ? 4.0 : 0.0
stackView.alignment = .leading
} }
self.addTarget(self, action: #selector(ToastView.showErrorLog), for: .touchUpInside)
}
convenience init(error: Error, opensLog: Bool = false) {
self.init(error: error)
self.opensErrorLog = opensLog
} }
convenience init(error: Error) convenience init(error: Error)
@@ -95,6 +111,18 @@ final class ToastView: RSTToastView
override func show(in view: UIView, duration: TimeInterval) override func show(in view: UIView, duration: TimeInterval)
{ {
if opensErrorLog, #available(iOS 13.0, *), case let configuration = UIImage.SymbolConfiguration(font: self.textLabel.font),
let icon = UIImage(systemName: "chevron.right.circle", withConfiguration: configuration) {
let tintedIcon = icon.withTintColor(.white, renderingMode: .alwaysOriginal)
let moreIconImageView = UIImageView(image: tintedIcon)
moreIconImageView.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(moreIconImageView)
NSLayoutConstraint.activate([
moreIconImageView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -self.layoutMargins.right),
moreIconImageView.centerYAnchor.constraint(equalTo: self.textLabel.centerYAnchor),
moreIconImageView.leadingAnchor.constraint(greaterThanOrEqualToSystemSpacingAfter: self.textLabel.trailingAnchor, multiplier: 1.0)
])
}
super.show(in: view, duration: duration) super.show(in: view, duration: duration)
let announcement = (self.textLabel.text ?? "") + ". " + (self.detailTextLabel.text ?? "") let announcement = (self.textLabel.text ?? "") + ". " + (self.detailTextLabel.text ?? "")
@@ -110,4 +138,10 @@ final class ToastView: RSTToastView
{ {
self.show(in: view, duration: self.preferredDuration) self.show(in: view, duration: self.preferredDuration)
} }
@objc
func showErrorLog() {
guard self.opensErrorLog else { return }
NotificationCenter.default.post(name: ToastView.openErrorLogNotification, object: self)
}
} }

View File

@@ -535,11 +535,9 @@ private extension MyAppsViewController
guard !failures.isEmpty else { return } guard !failures.isEmpty else { return }
let toastView: ToastView
if let failure = failures.first, results.count == 1 if let failure = failures.first, results.count == 1
{ {
toastView = ToastView(error: failure.value) ToastView(error: failure.value).show(in: self)
} }
else else
{ {
@@ -557,12 +555,11 @@ private extension MyAppsViewController
let error = failures.first?.value as NSError? let error = failures.first?.value as NSError?
let detailText = error?.localizedFailure ?? error?.localizedFailureReason ?? error?.localizedDescription let detailText = error?.localizedFailure ?? error?.localizedFailureReason ?? error?.localizedDescription
toastView = ToastView(text: localizedText, detailText: detailText) let toastView = ToastView(text: localizedText, detailText: detailText, opensLog: true)
toastView.preferredDuration = 4.0 toastView.preferredDuration = 4.0
}
toastView.show(in: self) toastView.show(in: self)
} }
}
self.refreshGroup = nil self.refreshGroup = nil
completionHandler(results) completionHandler(results)
@@ -697,8 +694,7 @@ private extension MyAppsViewController
self.collectionView.reloadItems(at: [indexPath]) self.collectionView.reloadItems(at: [indexPath])
case .failure(let error): case .failure(let error):
let toastView = ToastView(error: error) ToastView(error: error, opensLog: true).show(in: self)
toastView.show(in: self)
self.collectionView.reloadItems(at: [indexPath]) self.collectionView.reloadItems(at: [indexPath])
@@ -899,8 +895,7 @@ private extension MyAppsViewController
completion(.failure((OperationError.cancelled))) completion(.failure((OperationError.cancelled)))
case .failure(let error): case .failure(let error):
let toastView = ToastView(error: error) ToastView(error: error, opensLog: true).show(in: self)
toastView.show(in: self)
completion(.failure(error)) completion(.failure(error))
} }
@@ -1015,8 +1010,7 @@ private extension MyAppsViewController
UIApplication.shared.open(installedApp.openAppURL) { success in UIApplication.shared.open(installedApp.openAppURL) { success in
guard !success else { return } guard !success else { return }
let toastView = ToastView(error: OperationError.openAppFailed(name: installedApp.name)) ToastView(error: OperationError.openAppFailed(name: installedApp.name), opensLog: true).show(in: self)
toastView.show(in: self)
} }
} }
@@ -1067,8 +1061,7 @@ private extension MyAppsViewController
DispatchQueue.main.async { DispatchQueue.main.async {
installedApp.isActive = false installedApp.isActive = false
let toastView = ToastView(error: error) ToastView(error: error, opensLog: true).show(in: self)
toastView.show(in: self)
} }
} }
} }
@@ -1141,8 +1134,7 @@ private extension MyAppsViewController
DispatchQueue.main.async { DispatchQueue.main.async {
installedApp.isActive = true installedApp.isActive = true
let toastView = ToastView(error: error) ToastView(error: error, opensLog: true).show(in: self)
toastView.show(in: self)
} }
} }
@@ -1173,8 +1165,7 @@ private extension MyAppsViewController
case .success: break case .success: break
case .failure(let error): case .failure(let error):
DispatchQueue.main.async { DispatchQueue.main.async {
let toastView = ToastView(error: error) ToastView(error: error, opensLog: true).show(in: self)
toastView.show(in: self)
} }
} }
} }
@@ -1208,8 +1199,7 @@ private extension MyAppsViewController
print("Failed to back up app:", error) print("Failed to back up app:", error)
DispatchQueue.main.async { DispatchQueue.main.async {
let toastView = ToastView(error: error) ToastView(error: error, opensLog: true).show(in: self)
toastView.show(in: self)
self.collectionView.reloadSections([Section.activeApps.rawValue, Section.inactiveApps.rawValue]) self.collectionView.reloadSections([Section.activeApps.rawValue, Section.inactiveApps.rawValue])
} }
@@ -1245,8 +1235,7 @@ private extension MyAppsViewController
print("Failed to restore app:", error) print("Failed to restore app:", error)
DispatchQueue.main.async { DispatchQueue.main.async {
let toastView = ToastView(error: error) ToastView(error: error, opensLog: true).show(in: self)
toastView.show(in: self)
} }
} }
} }
@@ -1321,8 +1310,7 @@ private extension MyAppsViewController
print("Failed to change app icon.", error) print("Failed to change app icon.", error)
DispatchQueue.main.async { DispatchQueue.main.async {
let toastView = ToastView(error: error) ToastView(error: error, opensLog: true).show(in: self)
toastView.show(in: self)
} }
} }
} }
@@ -1334,9 +1322,8 @@ private extension MyAppsViewController
guard minimuxerStatus else { return } guard minimuxerStatus else { return }
if #available(iOS 17, *) { if #available(iOS 17, *) {
let toastView = ToastView(error: (OperationError.tooNewError as NSError).withLocalizedTitle("No iOS 17 On Device JIT!")) ToastView(error: (OperationError.tooNewError as NSError).withLocalizedTitle("No iOS 17 On Device JIT!"), opensLog: true).show(in: self)
AppManager.shared.log(OperationError.tooNewError, operation: .enableJIT, app: installedApp) AppManager.shared.log(OperationError.tooNewError, operation: .enableJIT, app: installedApp)
toastView.show(in: self)
return return
} }
@@ -1346,8 +1333,8 @@ private extension MyAppsViewController
{ {
case .success: break case .success: break
case .failure(let error): case .failure(let error):
let toastView = ToastView(error: error) ToastView(error: error, opensLog: true).show(in: self)
toastView.show(in: self.navigationController?.view ?? self.view, duration: 5) AppManager.shared.log(error, operation: .enableJIT, app: installedApp)
} }
} }
} }

View File

@@ -313,8 +313,7 @@ private extension NewsViewController
{ {
case .failure(OperationError.cancelled): break // Ignore case .failure(OperationError.cancelled): break // Ignore
case .failure(let error): case .failure(let error):
let toastView = ToastView(error: error) ToastView(error: error, opensLog: true).show(in: self)
toastView.show(in: self)
case .success: print("Installed app:", storeApp.bundleIdentifier) case .success: print("Installed app:", storeApp.bundleIdentifier)
} }

View File

@@ -21,7 +21,7 @@
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="separatorColor" white="1" alpha="0.25" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="separatorColor" white="1" alpha="0.25" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<label key="tableFooterView" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="SideStore 1.0" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="bUR-rp-Nw2"> <label key="tableFooterView" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="SideStore 1.0" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="bUR-rp-Nw2">
<rect key="frame" x="0.0" y="1296" width="375" height="25"/> <rect key="frame" x="0.0" y="1209" 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"/>
@@ -618,7 +618,7 @@
<userDefinedRuntimeAttribute type="boolean" keyPath="isSelectable" value="YES"/> <userDefinedRuntimeAttribute type="boolean" keyPath="isSelectable" value="YES"/>
</userDefinedRuntimeAttributes> </userDefinedRuntimeAttributes>
<connections> <connections>
<segue destination="g8a-Rf-zWa" kind="show" id="vFC-Id-Ww6"/> <segue destination="g8a-Rf-zWa" kind="show" identifier="showErrorLog" id="vFC-Id-Ww6"/>
</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">
@@ -1210,7 +1210,7 @@ Settings by i cons from the Noun Project</string>
<!--Error Details View Controller--> <!--Error Details View Controller-->
<scene sceneID="XNO-Yg-I7t"> <scene sceneID="XNO-Yg-I7t">
<objects> <objects>
<viewController id="xB2-Se-VVg" customClass="ErrorDetailsViewController" customModule="AltStore" customModuleProvider="target" sceneMemberID="viewController"> <viewController id="xB2-Se-VVg" customClass="ErrorDetailsViewController" customModule="SideStore" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="eBQ-se-VIy"> <view key="view" contentMode="scaleToFill" id="eBQ-se-VIy">
<rect key="frame" x="0.0" y="0.0" width="375" height="647"/> <rect key="frame" x="0.0" y="0.0" width="375" height="647"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>

View File

@@ -92,6 +92,7 @@ final class SettingsViewController: UITableViewController
super.init(coder: aDecoder) super.init(coder: aDecoder)
NotificationCenter.default.addObserver(self, selector: #selector(SettingsViewController.openPatreonSettings(_:)), name: AppDelegate.openPatreonSettingsDeepLinkNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(SettingsViewController.openPatreonSettings(_:)), name: AppDelegate.openPatreonSettingsDeepLinkNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(SettingsViewController.openErrorLog(_:)), name: ToastView.openErrorLogNotification, object: nil)
} }
override func viewDidLoad() override func viewDidLoad()
@@ -109,16 +110,13 @@ final class SettingsViewController: UITableViewController
debugModeGestureRecognizer.numberOfTouchesRequired = 3 debugModeGestureRecognizer.numberOfTouchesRequired = 3
self.tableView.addGestureRecognizer(debugModeGestureRecognizer) self.tableView.addGestureRecognizer(debugModeGestureRecognizer)
print(Bundle.main.infoDictionary)
var versionString: String = "" var versionString: String = ""
if let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String if let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String
{ {
versionString += "SideStore \(version)" versionString += "SideStore \(version)"
if let xcode = Bundle.main.object(forInfoDictionaryKey: "DTXcode") as? String { if let xcode = Bundle.main.object(forInfoDictionaryKey: "DTXcode") as? String {
print(xcode)
versionString += " - Xcode \(xcode) - " versionString += " - Xcode \(xcode) - "
if let build = Bundle.main.object(forInfoDictionaryKey: "DTXcodeBuild") as? String { if let build = Bundle.main.object(forInfoDictionaryKey: "DTXcodeBuild") as? String {
print(build)
versionString += "\(build)" versionString += "\(build)"
} }
} }
@@ -408,6 +406,15 @@ private extension SettingsViewController
self.performSegue(withIdentifier: "showPatreon", sender: nil) self.performSegue(withIdentifier: "showPatreon", sender: nil)
} }
} }
@objc func openErrorLog(_: Notification) {
guard self.presentedViewController == nil else { return }
self.navigationController?.popViewController(animated: false)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.performSegue(withIdentifier: "showErrorLog", sender: nil)
}
}
} }
extension SettingsViewController extension SettingsViewController

View File

@@ -33,6 +33,7 @@ final class TabBarController: UITabBarController
NotificationCenter.default.addObserver(self, selector: #selector(TabBarController.openPatreonSettings(_:)), name: AppDelegate.openPatreonSettingsDeepLinkNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(TabBarController.openPatreonSettings(_:)), name: AppDelegate.openPatreonSettingsDeepLinkNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(TabBarController.importApp(_:)), name: AppDelegate.importAppDeepLinkNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(TabBarController.importApp(_:)), name: AppDelegate.importAppDeepLinkNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(TabBarController.presentSources(_:)), name: AppDelegate.addSourceDeepLinkNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(TabBarController.presentSources(_:)), name: AppDelegate.addSourceDeepLinkNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(TabBarController.openErrorLog(_:)), name: ToastView.openErrorLogNotification, object: nil)
} }
override func viewDidAppear(_ animated: Bool) override func viewDidAppear(_ animated: Bool)
@@ -141,4 +142,7 @@ private extension TabBarController
{ {
self.selectedIndex = Tab.myApps.rawValue self.selectedIndex = Tab.myApps.rawValue
} }
@objc func openErrorLog(_: Notification){
self.selectedIndex = Tab.settings.rawValue
}
} }