forked from MeloNX/MeloNX
Add update handling and UI for latest version notifications
This commit is contained in:
parent
5009474e14
commit
bd35b9e2be
@ -24,6 +24,7 @@
|
||||
/* End PBXAggregateTarget section */
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
256C91642D8126E300F9736D /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = 256C91632D8126E300F9736D /* Alamofire */; };
|
||||
4E0DED342D05695D00FEF007 /* SwiftUIJoystick in Frameworks */ = {isa = PBXBuildFile; productRef = 4E0DED332D05695D00FEF007 /* SwiftUIJoystick */; };
|
||||
4E12B23C2D797CFA00FB2271 /* MeloNX.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 4E12B23B2D797CFA00FB2271 /* MeloNX.xcconfig */; };
|
||||
4E8A80772D5FDD2D0041B48F /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E80AA622CD7122800029585 /* GameController.framework */; };
|
||||
@ -205,6 +206,7 @@
|
||||
files = (
|
||||
4E0DED342D05695D00FEF007 /* SwiftUIJoystick in Frameworks */,
|
||||
CA8F9C322D3F5AB200D7E586 /* GameController.framework in Frameworks */,
|
||||
256C91642D8126E300F9736D /* Alamofire in Frameworks */,
|
||||
4EA5AE822D16807500AD0B9F /* SwiftSVG in Frameworks */,
|
||||
4E8A80772D5FDD2D0041B48F /* GameController.framework in Frameworks */,
|
||||
);
|
||||
@ -303,6 +305,7 @@
|
||||
packageProductDependencies = (
|
||||
4E0DED332D05695D00FEF007 /* SwiftUIJoystick */,
|
||||
4EA5AE812D16807500AD0B9F /* SwiftSVG */,
|
||||
256C91632D8126E300F9736D /* Alamofire */,
|
||||
);
|
||||
productName = MeloNX;
|
||||
productReference = 4E80A98D2CD6F54500029585 /* MeloNX.app */;
|
||||
@ -395,6 +398,7 @@
|
||||
packageReferences = (
|
||||
4E0DED322D05695D00FEF007 /* XCRemoteSwiftPackageReference "SwiftUIJoystick" */,
|
||||
4EA5AE802D16807500AD0B9F /* XCRemoteSwiftPackageReference "SwiftSVG" */,
|
||||
256C91622D8126E300F9736D /* XCRemoteSwiftPackageReference "Alamofire" */,
|
||||
);
|
||||
preferredProjectObjectVersion = 56;
|
||||
productRefGroup = 4E80A98E2CD6F54500029585 /* Products */;
|
||||
@ -651,7 +655,7 @@
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
DEVELOPMENT_TEAM = 95J8WZ4TN8;
|
||||
DEVELOPMENT_TEAM = 4TD3JXVDW7;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
ENABLE_TESTABILITY = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
@ -710,6 +714,8 @@
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
);
|
||||
GCC_OPTIMIZATION_LEVEL = s;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@ -833,9 +839,13 @@
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
);
|
||||
MARKETING_VERSION = "$(VERSION)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = xyz.belladev.MeloNX;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "MeloNX/App/Core/Headers/Ryujinx-Header.h";
|
||||
@ -854,7 +864,7 @@
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
DEVELOPMENT_TEAM = 95J8WZ4TN8;
|
||||
DEVELOPMENT_TEAM = 4TD3JXVDW7;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
@ -913,6 +923,8 @@
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
);
|
||||
GCC_OPTIMIZATION_LEVEL = s;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@ -1036,9 +1048,13 @@
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
|
||||
);
|
||||
MARKETING_VERSION = "$(VERSION)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = xyz.belladev.MeloNX;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "MeloNX/App/Core/Headers/Ryujinx-Header.h";
|
||||
@ -1235,6 +1251,14 @@
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCRemoteSwiftPackageReference section */
|
||||
256C91622D8126E300F9736D /* XCRemoteSwiftPackageReference "Alamofire" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/Alamofire/Alamofire";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 5.10.2;
|
||||
};
|
||||
};
|
||||
4E0DED322D05695D00FEF007 /* XCRemoteSwiftPackageReference "SwiftUIJoystick" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/michael94ellis/SwiftUIJoystick";
|
||||
@ -1254,6 +1278,11 @@
|
||||
/* End XCRemoteSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
256C91632D8126E300F9736D /* Alamofire */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 256C91622D8126E300F9736D /* XCRemoteSwiftPackageReference "Alamofire" */;
|
||||
productName = Alamofire;
|
||||
};
|
||||
4E0DED332D05695D00FEF007 /* SwiftUIJoystick */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 4E0DED322D05695D00FEF007 /* XCRemoteSwiftPackageReference "SwiftUIJoystick" */;
|
||||
|
@ -1,6 +1,15 @@
|
||||
{
|
||||
"originHash" : "d611b071fbe94fdc9900a07a218340eab4ce2c3c7168bf6542f2830c0400a72b",
|
||||
"originHash" : "587a0e7c5c7d612a2c16a973e66df9a6a582b963cb51df7c89fd96cb28ef4a63",
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "alamofire",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/Alamofire/Alamofire",
|
||||
"state" : {
|
||||
"revision" : "513364f870f6bfc468f9d2ff0a95caccc10044c5",
|
||||
"version" : "5.10.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swiftsvg",
|
||||
"kind" : "remoteSourceControl",
|
||||
|
Binary file not shown.
@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1610"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES"
|
||||
buildArchitectures = "Automatic">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "4E80A98C2CD6F54500029585"
|
||||
BuildableName = "MeloNX.app"
|
||||
BlueprintName = "MeloNX"
|
||||
ReferencedContainer = "container:MeloNX.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO"
|
||||
parallelizable = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "4E80A99C2CD6F54700029585"
|
||||
BuildableName = "MeloNXTests.xctest"
|
||||
BlueprintName = "MeloNXTests"
|
||||
ReferencedContainer = "container:MeloNX.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO"
|
||||
parallelizable = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "4E80A9A62CD6F54700029585"
|
||||
BuildableName = "MeloNXUITests.xctest"
|
||||
BlueprintName = "MeloNXUITests"
|
||||
ReferencedContainer = "container:MeloNX.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
enableGPUValidationMode = "1"
|
||||
showGraphicsOverview = "Yes"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "4E80A98C2CD6F54500029585"
|
||||
BuildableName = "MeloNX.app"
|
||||
BlueprintName = "MeloNX"
|
||||
ReferencedContainer = "container:MeloNX.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Debug"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "4E80A98C2CD6F54500029585"
|
||||
BuildableName = "MeloNX.app"
|
||||
BlueprintName = "MeloNX"
|
||||
ReferencedContainer = "container:MeloNX.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Debug"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
<PreActions>
|
||||
<ExecutionAction
|
||||
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
|
||||
<ActionContent
|
||||
title = "Run Script"
|
||||
scriptText = "REPO_DIR="$(cd "${SRCROOT}/../../" && pwd)" SCRIPT_PATH="$REPO_DIR/distribution/ios/set_current_version.sh" sh "${SCRIPT_PATH}" "
|
||||
shellToInvoke = "/bin/bash">
|
||||
</ActionContent>
|
||||
</ExecutionAction>
|
||||
</PreActions>
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
37
src/MeloNX/MeloNX/App/Models/LatestVersionResponse.swift
Normal file
37
src/MeloNX/MeloNX/App/Models/LatestVersionResponse.swift
Normal file
@ -0,0 +1,37 @@
|
||||
//
|
||||
// LatestVersionResponse.swift
|
||||
// MeloNX
|
||||
//
|
||||
// Created by Bella on 12/03/2025.
|
||||
//
|
||||
|
||||
struct LatestVersionResponse: Codable {
|
||||
let version_number: String
|
||||
let version_number_stripped: String
|
||||
let changelog: String
|
||||
let download_link: String
|
||||
|
||||
#if DEBUG
|
||||
static let example1 = LatestVersionResponse(
|
||||
version_number: "1.0.0",
|
||||
version_number_stripped: "100",
|
||||
changelog: """
|
||||
- Rewrite Display Code (SDL isn't used for display anymore)
|
||||
- Add New Onboarding / Setup
|
||||
- Better Performance
|
||||
- Remove "SDL Window" option in settings
|
||||
- Fix JIT Cache Regions
|
||||
- Fix how JIT is detected in Settings
|
||||
- Fix ABYX being swapped on controller.
|
||||
- Settings are now a config.json file
|
||||
- Fix Performance Overlay not showing when Virtual Controller is hidden
|
||||
- Add displaying logs when Loading or in-game
|
||||
- Fix Launching games from outside of the roms folder
|
||||
- Add Waiting for JIT popup
|
||||
- Fix spesific Games
|
||||
- Added Back Herobrine ("You were supposed to be the hero, Bryan")
|
||||
""",
|
||||
download_link: "https://example.com"
|
||||
)
|
||||
#endif
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
//
|
||||
// MeloNXUpdateSheet.swift
|
||||
// MeloNX
|
||||
//
|
||||
// Created by Bella on 12/03/2025.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct MeloNXUpdateSheet: View {
|
||||
let updateInfo: LatestVersionResponse
|
||||
@Binding var isPresented: Bool
|
||||
|
||||
var body: some View {
|
||||
iOSNav {
|
||||
VStack {
|
||||
Text("Version \(updateInfo.version_number) is available. You are currently on Version \(Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "Unknown").")
|
||||
|
||||
VStack {
|
||||
Text("Changelog:")
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.font(.headline)
|
||||
|
||||
ScrollView {
|
||||
Text(updateInfo.changelog)
|
||||
.padding()
|
||||
}
|
||||
.frame(maxHeight: 400)
|
||||
.background(Color(.secondarySystemBackground))
|
||||
.clipShape(RoundedRectangle(cornerRadius: 10))
|
||||
}
|
||||
.padding(.top, 15)
|
||||
|
||||
|
||||
Spacer()
|
||||
Button(action: {
|
||||
if let url = URL(string: updateInfo.download_link) {
|
||||
UIApplication.shared.open(url)
|
||||
}
|
||||
}) {
|
||||
Text("Download Now")
|
||||
.font(.title3)
|
||||
.bold()
|
||||
.frame(width: 300, height: 40)
|
||||
}
|
||||
.buttonStyle(.borderedProminent)
|
||||
.frame(alignment: .bottom)
|
||||
}
|
||||
.padding(.horizontal)
|
||||
.navigationTitle("Version \(updateInfo.version_number) Available!")
|
||||
.toolbar {
|
||||
Button(action: {
|
||||
isPresented = false
|
||||
}) {
|
||||
Text("Close")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
MeloNXUpdateSheet(updateInfo: LatestVersionResponse.example1, isPresented: .constant(true))
|
||||
}
|
@ -8,249 +8,82 @@
|
||||
import SwiftUI
|
||||
import UIKit
|
||||
import CryptoKit
|
||||
|
||||
|
||||
import Alamofire
|
||||
|
||||
@main
|
||||
struct MeloNXApp: App {
|
||||
|
||||
@State var showed = false
|
||||
@Environment(\.scenePhase) var scenePhase
|
||||
@State var alert: UIAlertController? = nil
|
||||
|
||||
@State var finished = false
|
||||
|
||||
// Variables for the update system :)
|
||||
@State var showOutOfDateSheet = false
|
||||
@State var updateInfo: LatestVersionResponse? = nil
|
||||
|
||||
@AppStorage("hasbeenfinished") var finishedStorage: Bool = false
|
||||
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
ZStack {
|
||||
if showed || DRM != 1 {
|
||||
|
||||
if finishedStorage {
|
||||
ContentView()
|
||||
} else {
|
||||
SetupView(finished: $finished)
|
||||
.onChange(of: finished) { newValue in
|
||||
withAnimation {
|
||||
withAnimation {
|
||||
finishedStorage = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
VStack {
|
||||
if finishedStorage {
|
||||
ContentView()
|
||||
} else {
|
||||
Group {
|
||||
VStack {
|
||||
Spacer()
|
||||
|
||||
HStack {
|
||||
Text("Loading...")
|
||||
ProgressView()
|
||||
}
|
||||
Spacer()
|
||||
|
||||
Text(UIDevice.current.identifierForVendor?.uuidString ?? "")
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
initR()
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.background(Color.black.opacity(1))
|
||||
.foregroundColor(.white)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func initR() {
|
||||
if DRM == 1 {
|
||||
DispatchQueue.main.async { [self] in
|
||||
// drmcheck()
|
||||
InitializeRyujinx() { bool in
|
||||
if bool {
|
||||
print("Ryujinx Files Initialized Successfully")
|
||||
DispatchQueue.main.async { [self] in
|
||||
SetupView(finished: $finished)
|
||||
.onChange(of: finished) { newValue in
|
||||
withAnimation {
|
||||
showed = true
|
||||
}
|
||||
|
||||
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
|
||||
InitializeRyujinx() { bool in
|
||||
if !bool, (scenePhase != .background || scenePhase == .inactive) {
|
||||
withAnimation {
|
||||
showed = false
|
||||
}
|
||||
if !(alert?.isViewLoaded ?? false) {
|
||||
alert = showDMCAAlert()
|
||||
}
|
||||
} else {
|
||||
DispatchQueue.main.async {
|
||||
alert?.dismiss(animated: true)
|
||||
showed = true
|
||||
}
|
||||
}
|
||||
withAnimation {
|
||||
finishedStorage = newValue
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
showDMCAAlert()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
func showAlert() -> UIAlertController? {
|
||||
// Create the alert controller
|
||||
if let mainWindow = UIApplication.shared.windows.last {
|
||||
let alertController = UIAlertController(title: "Enter license", message: "Enter license key:", preferredStyle: .alert)
|
||||
|
||||
// Add a text field to the alert
|
||||
alertController.addTextField { textField in
|
||||
textField.placeholder = "Enter key here"
|
||||
}
|
||||
|
||||
// Add the "OK" action
|
||||
let okAction = UIAlertAction(title: "OK", style: .default) { _ in
|
||||
// Get the text entered in the text field
|
||||
if let textField = alertController.textFields?.first, let enteredText = textField.text {
|
||||
print("Entered text: \(enteredText)")
|
||||
UserDefaults.standard.set(enteredText, forKey: "MeloDRMID")
|
||||
// drmcheck() { bool in
|
||||
// if bool {
|
||||
// showed = true
|
||||
// } else {
|
||||
// exit(0)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
alertController.addAction(okAction)
|
||||
|
||||
// Add a "Cancel" action
|
||||
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
|
||||
alertController.addAction(cancelAction)
|
||||
|
||||
// Present the alert
|
||||
mainWindow.rootViewController!.present(alertController, animated: true, completion: nil)
|
||||
|
||||
return alertController
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
func showDMCAAlert() -> UIAlertController? {
|
||||
if let mainWindow = UIApplication.shared.windows.first {
|
||||
let alertController = UIAlertController(title: "Unauthorized Copy Notice", message: "This app was illegally leaked. Please report the download on the MeloNX Discord. In the meantime, check out Pomelo! \n -Stossy11", preferredStyle: .alert)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
mainWindow.rootViewController!.present(alertController, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
return alertController
|
||||
} else {
|
||||
// uhoh
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
func drmcheck(completion: @escaping (Bool) -> Void) {
|
||||
if let deviceid = UIDevice.current.identifierForVendor?.uuidString, let base64device = deviceid.data(using: .utf8)?.base64EncodedString() {
|
||||
if let value = UserDefaults.standard.string(forKey: "MeloDRMID") {
|
||||
if let url = URL(string: "https://mx.stossy11.com/auth/\(value)/\(base64device)") {
|
||||
print(url)
|
||||
// Create a URLSession
|
||||
let session = URLSession.shared
|
||||
|
||||
// Create a data task
|
||||
let task = session.dataTask(with: url) { data, response, error in
|
||||
// Handle errors
|
||||
if let error = error {
|
||||
exit(0)
|
||||
}
|
||||
|
||||
// Check response and data
|
||||
if let response = response as? HTTPURLResponse, response.statusCode == 200 {
|
||||
print("Successfully Recieved API Data")
|
||||
completion(true)
|
||||
} else if let response = response as? HTTPURLResponse, response.statusCode == 201 {
|
||||
print("Successfully Created Auth UUID")
|
||||
completion(true)
|
||||
} else {
|
||||
completion(false)
|
||||
.onAppear {
|
||||
checkLatestVersion()
|
||||
}
|
||||
// this seems like a weird way to show the sheet but, from my history this is the most reliable way for the content to actually show in the sheet, otherwise its blank
|
||||
.sheet(isPresented: Binding(
|
||||
get: { showOutOfDateSheet && updateInfo != nil },
|
||||
set: { newValue in
|
||||
if !newValue {
|
||||
showOutOfDateSheet = false
|
||||
updateInfo = nil
|
||||
}
|
||||
}
|
||||
|
||||
// Start the task
|
||||
task.resume()
|
||||
)) {
|
||||
if let updateInfo = updateInfo {
|
||||
MeloNXUpdateSheet(updateInfo: updateInfo, isPresented: $showOutOfDateSheet)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
completion(false)
|
||||
}
|
||||
} else {
|
||||
completion(false)
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
func InitializeRyujinx(completion: @escaping (Bool) -> Void) {
|
||||
let path = "aHR0cHM6Ly9teC5zdG9zc3kxMS5jb20v"
|
||||
|
||||
guard let value = Bundle.main.object(forInfoDictionaryKey: "MeloID") as? String, !value.isEmpty else {
|
||||
completion(false)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (detectRoms(path: path) != value) {
|
||||
completion(false)
|
||||
}
|
||||
|
||||
let configuration = URLSessionConfiguration.default
|
||||
configuration.requestCachePolicy = .reloadIgnoringLocalAndRemoteCacheData
|
||||
configuration.urlCache = nil
|
||||
|
||||
let session = URLSession(configuration: configuration)
|
||||
|
||||
guard let url = URL(string: addFolders(path)!) else {
|
||||
completion(false)
|
||||
return
|
||||
}
|
||||
|
||||
let task = session.dataTask(with: url) { data, response, error in
|
||||
if error != nil {
|
||||
completion(false)
|
||||
}
|
||||
// sends a GET request to the MeloNXSite API and compares the version it returns to the current app version
|
||||
func checkLatestVersion() {
|
||||
let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "0.0.0"
|
||||
let strippedAppVersion = appVersion.replacingOccurrences(of: ".", with: "")
|
||||
|
||||
#if DEBUG
|
||||
// no this isnt a public ip address silly viewers (i know damn well someone thought this was my real ip), this is local :PP
|
||||
let url = "http://192.168.178.116:8000/api/latest_release"
|
||||
#else
|
||||
// dont spam this :pray:
|
||||
let url = "https://melonx.org/api/latest_release"
|
||||
#endif
|
||||
|
||||
guard let httpResponse = response as? HTTPURLResponse else {
|
||||
completion(false)
|
||||
return
|
||||
// actually sends the request
|
||||
AF.request(url).responseDecodable(of: LatestVersionResponse.self) { response in
|
||||
switch response.result {
|
||||
case .success(let latestVersionResponse):
|
||||
let latestAPIVersionStripped = latestVersionResponse.version_number_stripped
|
||||
if Int(strippedAppVersion) ?? 0 < Int(latestAPIVersionStripped) ?? 0 {
|
||||
updateInfo = latestVersionResponse
|
||||
showOutOfDateSheet = true
|
||||
}
|
||||
case .failure(let error):
|
||||
print("Error checking for new version: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
if httpResponse.statusCode == 200 {
|
||||
completion(true)
|
||||
} else {
|
||||
completion(false)
|
||||
}
|
||||
return
|
||||
}
|
||||
task.resume()
|
||||
}
|
||||
|
||||
func detectRoms(path string: String) -> String {
|
||||
@ -259,8 +92,6 @@ func detectRoms(path string: String) -> String {
|
||||
return romHash.compactMap { String(format: "%02x", $0) }.joined()
|
||||
}
|
||||
|
||||
|
||||
|
||||
func addFolders(_ folderPath: String) -> String? {
|
||||
let fileManager = FileManager.default
|
||||
if let data = Data(base64Encoded: folderPath),
|
||||
@ -271,7 +102,6 @@ func addFolders(_ folderPath: String) -> String? {
|
||||
}
|
||||
|
||||
extension String {
|
||||
|
||||
func print() {
|
||||
Swift.print(self)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user