swift reworks

This commit is contained in:
lizzie 2026-04-30 15:55:43 +00:00
parent 41ff70345b
commit a98398791a
7 changed files with 154 additions and 303 deletions

View file

@ -6,6 +6,7 @@
import UIKit
import Foundation
import QuartzCore.CAMetalLayer
import SwiftUI
public struct AppUI {
public static let shared = AppUI()
@ -101,3 +102,12 @@ public struct AppUI {
appUIObjC.settingsChanged()
}
}
struct EdenApp: App {
@StateObject private var core = EmulationViewModel()
var body: some Scene {
WindowGroup {
ContentView(core: core)
}
}
}

View file

@ -8,7 +8,7 @@ import SwiftUI
import Metal
import Foundation
class EmulationViewModel: ObservableObject {
class EmulationSessionViewModel: ObservableObject {
@Published var isShowingCustomButton = true
@State var should = false
var device: MTLDevice?
@ -93,4 +93,4 @@ class EmulationViewModel: ObservableObject {
return .unknown
}
}
}
}

View file

@ -349,7 +349,7 @@ class Haptics {
struct ButtonView: View {
var button: VirtualControllerButtonType
@StateObject private var viewModel: EmulationViewModel = EmulationViewModel(game: nil)
@StateObject private var viewModel: EmulationViewModel = EmulationViewModel()
let appui = AppUI.shared
@State var mtkView: MTKView?
@State var width: CGFloat = 45
@ -446,7 +446,7 @@ struct EmulationView: View {
@Environment(\.scenePhase) var scenePhase
init(game: EmulationGame?) {
_viewModel = StateObject(wrappedValue: EmulationViewModel(game: game))
_viewModel = StateObject(wrappedValue: EmulationViewModel())
}
var body: some View {
@ -555,4 +555,4 @@ struct SizePreferenceKey: PreferenceKey {
static func reduce(value: inout CGSize, nextValue: () -> CGSize) {
value = nextValue()
}
}
}

View file

@ -10,7 +10,7 @@ import UniformTypeIdentifiers
import Combine
struct SettingsView: View {
@State var core: Core
@ObservedObject var core: EmulationViewModel
@State var showprompt = false
@AppStorage("icon") var iconused = 1
@ -78,116 +78,70 @@ struct GameIconView: View {
}
}
struct BottomMenuView: View {
@State var core: Core
var body: some View {
HStack(spacing: 40) {
Button {
// Remove or refactor HomeView and GameCarouselView to not use Core or BottomMenuView(core: core) with Core.
// If these are not used in the iOS UI, comment them out to avoid build errors.
// struct HomeView: View {
// @State private var selectedGame: EmulationGame? = nil
} label: {
Circle()
.overlay {
Image(systemName: "message").font(.system(size: 30)).foregroundColor(.red)
}
.frame(width: 50, height: 50)
.foregroundColor(Color.init(uiColor: .lightGray))
}
Button {
// @State var core: Core
} label: {
Circle()
.overlay {
Image(systemName: "photo").font(.system(size: 30)).foregroundColor(.blue)
}
.frame(width: 50, height: 50)
.foregroundColor(Color.init(uiColor: .lightGray))
}
NavigationLink(destination: SettingsView(core: core)) {
Circle()
.overlay {
Image(systemName: "gearshape").foregroundColor(Color.init(uiColor: .darkGray)).font(.system(size: 30))
}
.frame(width: 50, height: 50)
.foregroundColor(Color.init(uiColor: .lightGray))
}
// init(selectedGame: EmulationGame? = nil, core: Core) {
// _core = State(wrappedValue: core)
// self.selectedGame = selectedGame
// refreshcore()
// }
Button {
// var body: some View {
// NavigationStack {
// GeometryReader { geometry in
// VStack {
// GameCarouselView(core: core, selectedGame: $selectedGame)
// Spacer()
// BottomMenuView(core: core)
// }
// }
// }
// .background(Color.gray.opacity(0.1))
// .edgesIgnoringSafeArea(.all)
// .onAppear {
// refreshcore()
// if let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
// let romsFolderURL = documentsDirectory.appendingPathComponent("roms")
// let folderMonitor = FolderMonitor(folderURL: romsFolderURL) {
// do {
// core = Core(games: [], root: documentsDirectory)
// core = try LibraryManager.shared.library()
// } catch {
// print("Error refreshing core: \(error)")
// }
// }
// }
// }
// }
} label: {
Circle()
.overlay {
Image(systemName: "power").foregroundColor(Color.init(uiColor: .darkGray)).font(.system(size: 30))
}
.frame(width: 50, height: 50)
.foregroundColor(Color.init(uiColor: .lightGray))
}
}
.padding(.bottom, 20)
}
}
// func refreshcore() {
// print("Loading library...")
// do {
// core = try LibraryManager.shared.library()
// print(core.games)
// } catch {
// print("Failed to fetch library: \(error)")
// return
// }
// }
// }
struct HomeView: View {
@State private var selectedGame: EmulationGame? = nil
@State var core: Core
init(selectedGame: EmulationGame? = nil, core: Core) {
_core = State(wrappedValue: core)
self.selectedGame = selectedGame
refreshcore()
}
var body: some View {
NavigationStack {
GeometryReader { geometry in
VStack {
GameCarouselView(core: core, selectedGame: $selectedGame)
Spacer()
BottomMenuView(core: core)
}
}
}
.background(Color.gray.opacity(0.1))
.edgesIgnoringSafeArea(.all)
.onAppear {
refreshcore()
if let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
let romsFolderURL = documentsDirectory.appendingPathComponent("roms")
let folderMonitor = FolderMonitor(folderURL: romsFolderURL) {
do {
core = Core(games: [], root: documentsDirectory)
core = try LibraryManager.shared.library()
} catch {
print("Error refreshing core: \(error)")
}
}
}
}
}
func refreshcore() {
print("Loading library...")
do {
core = try LibraryManager.shared.library()
print(core.games)
} catch {
print("Failed to fetch library: \(error)")
return
}
}
}
struct GameCarouselView: View {
// let games: [EmulationGame]
@State var core: Core
@Binding var selectedGame: EmulationGame?
var body: some View {
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 20) {
ForEach(core.games) { game in
GameIconView(game: game, selectedGame: $selectedGame)
}
}
}
}
}
// struct GameCarouselView: View {
// // let games: [EmulationGame]
// @State var core: Core
// @Binding var selectedGame: EmulationGame?
// var body: some View {
// ScrollView(.horizontal, showsIndicators: false) {
// HStack(spacing: 20) {
// ForEach(core.games) { game in
// GameIconView(game: game, selectedGame: $selectedGame)
// }
// }
// }
// }
// }

View file

@ -1,184 +1,89 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// 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 CryptoKit
import Foundation
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 {
NavigationStack {
if let importedgame = importedgame {
NavigationView {
GeometryReader { geometry in
VStack {
TopBarView()
if UIDevice.current.userInterfaceIdiom == .pad {
Spacer()
}
ScrollView {
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()
}
Spacer()
BottomMenuView(core: core)
}
NavigationLink(
isActive: $launchGame,
destination: {
EmulationView(game: importedgame).toolbar(.hidden, for: .tabBar)
},
destination: EmulationView(game: urlgame),
isActive: binding,
label: {
EmptyView() // This keeps the link hidden
EmptyView()
}
)
}
VStack {
if doesitexist.0, doesitexist.1 {
HomeView(core: core)
} else {
let (doesKeyExist, doesProdExist) = doesKeysExist()
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")
}
}
}
}
}
}
.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
DispatchQueue.main.async {
if iscustom {
elements.stopAccessingSecurityScopedResource()
}
launchGame = true
}
case .failure(let error):
print(error.localizedDescription)
}
})
.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()
}
}
.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")
.background(Color.gray.opacity(0.1))
.edgesIgnoringSafeArea(.all)
.onAppear {
}
if fileManager.fileExists(atPath: title.path) {
doestitleexist = true
} else {
print("File does not exist")
}
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)
}
}

View file

@ -50,28 +50,10 @@ class YuzuFileManager {
}
}
struct ContentView: View {
@State var core = Core(games: [], root: FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0])
var body: some View {
HomeView(core: core).onAppear() {
do {
try YuzuFileManager.shared.createdirectories() // this took a while to create the proper directories
do {
core = try LibraryManager.shared.library() // this shit is like you tried to throw a egg into a blender with no lid on
} catch {
print("Failed to fetch library: \(error)") // aaaaaaaaa
}
} catch {
print("Failed to create directories: \(error)") // i wonder why hmmmmmmm
return
}
}
}
}
@main
struct PomeloApp: App {
@StateObject private var core = EmulationViewModel(game: nil)
var body: some Scene {
WindowGroup { ContentView() }
WindowGroup { ContentView(core: core) }
}
}
}

View file

@ -13,7 +13,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleGetInfoString</key>
<string></string>
<key>CFBundleIconFile</key>