7 changed files with 151 additions and 300 deletions
-
10src/ios/AppUI.swift
-
4src/ios/EmulationHandler.swift
-
6src/ios/EmulationView.swift
-
182src/ios/GameButtonView.swift
-
223src/ios/LibraryView.swift
-
24src/ios/PomeloApp.swift
-
2src/yuzu/Info.plist
@ -1,184 +1,89 @@ |
|||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project |
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project |
||||
// SPDX-License-Identifier: GPL-3.0-or-later |
// SPDX-License-Identifier: GPL-3.0-or-later |
||||
// SPDX-FileCopyrightText: Copyright 2024 Pomelo, Stossy11 |
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later |
|
||||
|
|
||||
import SwiftUI |
import SwiftUI |
||||
import CryptoKit |
|
||||
|
import Foundation |
||||
|
|
||||
struct LibraryView: View { |
struct LibraryView: View { |
||||
@Binding var core: Core |
|
||||
@State var isGridView: Bool = true |
|
||||
@State var doesitexist = (false, false) |
|
||||
@State var importedgame: EmulationGame? = nil |
|
||||
@State var importgame: Bool = false |
|
||||
@State var isimportingfirm: Bool = false |
|
||||
@State var launchGame: Bool = false |
|
||||
|
@State private var selectedGame: EmulationGame? = nil |
||||
|
@Binding var urlgame: EmulationGame? |
||||
|
@ObservedObject var core: EmulationViewModel |
||||
|
|
||||
|
var binding: Binding<Bool> { |
||||
|
Binding( |
||||
|
get: { urlgame != nil }, |
||||
|
set: { newValue in |
||||
|
if !newValue { |
||||
|
urlgame = nil |
||||
|
} |
||||
|
} |
||||
|
) |
||||
|
} |
||||
|
|
||||
var body: some View { |
var body: some View { |
||||
NavigationStack { |
|
||||
if let importedgame = importedgame { |
|
||||
NavigationLink( |
|
||||
isActive: $launchGame, |
|
||||
destination: { |
|
||||
EmulationView(game: importedgame).toolbar(.hidden, for: .tabBar) |
|
||||
}, |
|
||||
label: { |
|
||||
EmptyView() // This keeps the link hidden |
|
||||
|
NavigationView { |
||||
|
GeometryReader { geometry in |
||||
|
VStack { |
||||
|
TopBarView() |
||||
|
|
||||
|
if UIDevice.current.userInterfaceIdiom == .pad { |
||||
|
Spacer() |
||||
} |
} |
||||
) |
|
||||
} |
|
||||
|
|
||||
VStack { |
|
||||
if doesitexist.0, doesitexist.1 { |
|
||||
HomeView(core: core) |
|
||||
} else { |
|
||||
let (doesKeyExist, doesProdExist) = doesKeysExist() |
|
||||
ScrollView { |
ScrollView { |
||||
Text("You Are Missing These Files:") |
|
||||
.font(.headline) |
|
||||
.foregroundColor(.red) |
|
||||
HStack { |
|
||||
if !doesProdExist { |
|
||||
Text("Prod.keys") |
|
||||
.font(.subheadline) |
|
||||
.foregroundColor(.red) |
|
||||
} |
|
||||
if !doesKeyExist { |
|
||||
Text("Title.keys") |
|
||||
.font(.subheadline) |
|
||||
.foregroundColor(.red) |
|
||||
} |
|
||||
} |
|
||||
Text("These goes into the Keys folder") |
|
||||
.font(.caption) |
|
||||
.foregroundColor(.red) |
|
||||
.padding(.bottom) |
|
||||
|
|
||||
if !LibraryManager.shared.homebrewroms().isEmpty { |
|
||||
Text("Homebrew Roms:") |
|
||||
.font(.headline) |
|
||||
LazyVGrid(columns: [GridItem(.adaptive(minimum: 160))], spacing: 10) { |
|
||||
ForEach(LibraryManager.shared.homebrewroms()) { game in |
|
||||
NavigationLink(destination: EmulationView(game: game).toolbar(.hidden, for: .tabBar)) { |
|
||||
// GameButtonView(game: game) |
|
||||
// .frame(maxWidth: .infinity, minHeight: 200) |
|
||||
} |
|
||||
.contextMenu { |
|
||||
NavigationLink(destination: EmulationView(game: game)) { |
|
||||
Text("Launch") |
|
||||
} |
|
||||
|
LazyVGrid(columns: [ |
||||
|
GridItem(.adaptive(minimum: 140), spacing: 10) |
||||
|
], spacing: 10) { |
||||
|
ForEach(core.games, id: \EmulationGame.id) { game in |
||||
|
GameCardView(game: game) |
||||
|
.frame(width: 140, height: 160) |
||||
|
.onTapGesture { |
||||
|
selectedGame = game |
||||
|
urlgame = game |
||||
} |
} |
||||
} |
|
||||
} |
} |
||||
} |
} |
||||
|
.padding() |
||||
} |
} |
||||
.refreshable { |
|
||||
doesitexist = doesKeysExist() |
|
||||
} |
|
||||
|
|
||||
|
|
||||
} |
|
||||
|
|
||||
} |
|
||||
.fileImporter(isPresented: $isimportingfirm, allowedContentTypes: [.zip], onCompletion: { result in |
|
||||
switch result { |
|
||||
case .success(let elements): |
|
||||
core.AddFirmware(at: elements) |
|
||||
case .failure(let error): |
|
||||
|
|
||||
print(error.localizedDescription) |
|
||||
} |
|
||||
}) |
|
||||
.fileImporter(isPresented: $importgame, allowedContentTypes: [.item], onCompletion: { result in |
|
||||
switch result { |
|
||||
case .success(let elements): |
|
||||
let iscustom = elements.startAccessingSecurityScopedResource() |
|
||||
let information = AppUI.shared.information(for: elements) |
|
||||
|
|
||||
let game = EmulationGame(developer: information.developer, fileURL: elements, |
|
||||
imageData: information.iconData, |
|
||||
title: information.title) |
|
||||
|
|
||||
importedgame = game |
|
||||
|
|
||||
|
Spacer() |
||||
|
|
||||
DispatchQueue.main.async { |
|
||||
|
|
||||
if iscustom { |
|
||||
elements.stopAccessingSecurityScopedResource() |
|
||||
} |
|
||||
|
|
||||
launchGame = true |
|
||||
} |
|
||||
case .failure(let error): |
|
||||
|
|
||||
print(error.localizedDescription) |
|
||||
|
BottomMenuView(core: core) |
||||
} |
} |
||||
}) |
|
||||
.onAppear() { |
|
||||
doesitexist = doesKeysExist() |
|
||||
} |
|
||||
.navigationBarTitle("Library", displayMode: .inline) |
|
||||
.toolbar { |
|
||||
ToolbarItem(placement: .navigationBarLeading) { // why did this take me so long to figure out lmfao |
|
||||
Button(action: { |
|
||||
isGridView.toggle() |
|
||||
}) { |
|
||||
Image(systemName: isGridView ? "rectangle.grid.1x2" : "square.grid.2x2") |
|
||||
.imageScale(.large) |
|
||||
.padding() |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
ToolbarItem(placement: .navigationBarTrailing) { // funsies |
|
||||
Menu { |
|
||||
Button(action: { |
|
||||
importgame = true // this part took a while |
|
||||
|
|
||||
}) { |
|
||||
Text("Launch Game") |
|
||||
} |
|
||||
|
|
||||
Button(action: { |
|
||||
isimportingfirm = true |
|
||||
}) { |
|
||||
Text("Import Firmware") |
|
||||
} |
|
||||
} label: { |
|
||||
Image(systemName: "plus.circle.fill") |
|
||||
.imageScale(.large) |
|
||||
.padding() |
|
||||
|
NavigationLink( |
||||
|
destination: EmulationView(game: urlgame), |
||||
|
isActive: binding, |
||||
|
label: { |
||||
|
EmptyView() |
||||
} |
} |
||||
|
|
||||
} |
|
||||
|
) |
||||
|
.hidden() |
||||
} |
} |
||||
} |
} |
||||
} |
|
||||
|
|
||||
func doesKeysExist() -> (Bool, Bool) { |
|
||||
var doesprodexist = false |
|
||||
var doestitleexist = false |
|
||||
let title = core.root.appendingPathComponent("keys").appendingPathComponent("title.keys") |
|
||||
let prod = core.root.appendingPathComponent("keys").appendingPathComponent("prod.keys") |
|
||||
let fileManager = FileManager.default |
|
||||
if fileManager.fileExists(atPath: prod.path) { |
|
||||
doesprodexist = true |
|
||||
} else { |
|
||||
print("File does not exist") |
|
||||
} |
|
||||
if fileManager.fileExists(atPath: title.path) { |
|
||||
doestitleexist = true |
|
||||
} else { |
|
||||
print("File does not exist") |
|
||||
|
.background(Color.gray.opacity(0.1)) |
||||
|
.edgesIgnoringSafeArea(.all) |
||||
|
.onAppear { |
||||
} |
} |
||||
return (doestitleexist, doesprodexist) |
|
||||
} |
} |
||||
} |
} |
||||
|
|
||||
func getDeveloperNames() -> String { |
|
||||
// guard let s = infoDictionary?["CFBundleIdentifier"] as? String else { |
|
||||
// return "Unknown" |
|
||||
// } |
|
||||
// return s |
|
||||
return "what" |
|
||||
} |
|
||||
|
struct GameCardView: View { |
||||
|
let game: EmulationGame |
||||
|
|
||||
|
var body: some View { |
||||
|
VStack { |
||||
|
Rectangle() |
||||
|
.fill(Color.gray) |
||||
|
.frame(height: 120) |
||||
|
|
||||
|
Text(game.title) |
||||
|
.font(.caption) |
||||
|
.lineLimit(1) |
||||
|
.truncationMode(.tail) |
||||
|
} |
||||
|
.background(Color.white) |
||||
|
.cornerRadius(8) |
||||
|
.shadow(radius: 4) |
||||
|
} |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue