11 changed files with 487 additions and 575 deletions
-
5src/ios/CMakeLists.txt
-
432src/ios/ControllerView.swift
-
424src/ios/EmulationView.swift
-
51src/ios/FileManager.swift
-
12src/ios/GameButtonView.swift
-
1src/ios/GameListView.swift
-
1src/ios/LibraryView.swift
-
23src/ios/MetalView.swift
-
44src/ios/NavView.swift
-
51src/ios/PomeloApp.swift
-
18src/ios/SettingsView.swift
@ -1,432 +0,0 @@ |
|||||
// 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 GameController |
|
||||
|
|
||||
import SwiftUIJoystick |
|
||||
|
|
||||
struct ControllerView: View { |
|
||||
let appui = AppUI.shared |
|
||||
@State var isPressed = false |
|
||||
@State var controllerconnected = false |
|
||||
@State private var x: CGFloat = 0.0 |
|
||||
@State private var y: CGFloat = 0.0 |
|
||||
@Environment(\.presentationMode) var presentationMode |
|
||||
|
|
||||
var body: some View { |
|
||||
GeometryReader { geometry in |
|
||||
ZStack { |
|
||||
if !controllerconnected { |
|
||||
OnScreenController(geometry: geometry) // i did this to clean it up as it was quite long lmfao |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.onAppear { |
|
||||
print("checking for controller:") |
|
||||
controllerconnected = false |
|
||||
DispatchQueue.main.async { |
|
||||
setupControllers() // i dont know what half of this shit does |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Add a dictionary to track controller IDs |
|
||||
@State var controllerIDs: [GCController: Int] = [:] |
|
||||
|
|
||||
private func setupControllers() { |
|
||||
NotificationCenter.default.addObserver(forName: .GCControllerDidConnect, object: nil, queue: .main) { notification in |
|
||||
if let controller = notification.object as? GCController { |
|
||||
print("wow controller onstart") // yippeeee |
|
||||
self.setupController(controller) |
|
||||
self.controllerconnected = true |
|
||||
} else { |
|
||||
print("not GCController :((((((") // wahhhhhhh |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
NotificationCenter.default.addObserver(forName: .GCControllerDidDisconnect, object: nil, queue: .main) { notification in |
|
||||
if let controller = notification.object as? GCController { |
|
||||
print("wow controller gone") |
|
||||
if self.controllerIDs.isEmpty { |
|
||||
controllerconnected = false |
|
||||
} |
|
||||
self.controllerIDs.removeValue(forKey: controller) // Remove the controller ID |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
GCController.controllers().forEach { controller in |
|
||||
print("wow controller") |
|
||||
self.controllerconnected = true |
|
||||
self.setupController(controller) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private func setupController(_ controller: GCController) { |
|
||||
// Assign a unique ID to the controller, max 5 controllers |
|
||||
if controllerIDs.count < 6, controllerIDs[controller] == nil { |
|
||||
controllerIDs[controller] = controllerIDs.count |
|
||||
} |
|
||||
|
|
||||
guard let controllerId = controllerIDs[controller] else { return } |
|
||||
|
|
||||
if let extendedGamepad = controller.extendedGamepad { |
|
||||
|
|
||||
// Handle extended gamepad |
|
||||
extendedGamepad.dpad.up.pressedChangedHandler = { button, value, pressed in |
|
||||
pressed ? self.touchDown(.directionalPadUp, controllerId: controllerId) : self.touchUpInside(.directionalPadUp, controllerId: controllerId) |
|
||||
} |
|
||||
|
|
||||
extendedGamepad.dpad.down.pressedChangedHandler = { button, value, pressed in |
|
||||
pressed ? self.touchDown(.directionalPadDown, controllerId: controllerId) : self.touchUpInside(.directionalPadDown, controllerId: controllerId) |
|
||||
} |
|
||||
extendedGamepad.dpad.left.pressedChangedHandler = { button, value, pressed in |
|
||||
pressed ? self.touchDown(.directionalPadLeft, controllerId: controllerId) : self.touchUpInside(.directionalPadLeft, controllerId: controllerId) |
|
||||
} |
|
||||
extendedGamepad.dpad.right.pressedChangedHandler = { button, value, pressed in |
|
||||
pressed ? self.touchDown(.directionalPadRight, controllerId: controllerId) : self.touchUpInside(.directionalPadRight, controllerId: controllerId) |
|
||||
} |
|
||||
extendedGamepad.buttonOptions?.pressedChangedHandler = { button, value, pressed in |
|
||||
pressed ? self.touchDown(.minus, controllerId: controllerId) : self.touchUpInside(.minus, controllerId: controllerId) |
|
||||
} |
|
||||
extendedGamepad.buttonMenu.pressedChangedHandler = { button, value, pressed in |
|
||||
pressed ? self.touchDown(.plus, controllerId: controllerId) : self.touchUpInside(.plus, controllerId: controllerId) |
|
||||
} |
|
||||
extendedGamepad.buttonA.pressedChangedHandler = { button, value, pressed in |
|
||||
pressed ? self.touchDown(.A, controllerId: controllerId) : self.touchUpInside(.A, controllerId: controllerId) |
|
||||
} |
|
||||
extendedGamepad.buttonB.pressedChangedHandler = { button, value, pressed in |
|
||||
pressed ? self.touchDown(.B, controllerId: controllerId) : self.touchUpInside(.B, controllerId: controllerId) |
|
||||
} |
|
||||
extendedGamepad.buttonX.pressedChangedHandler = { button, value, pressed in |
|
||||
pressed ? self.touchDown(.X, controllerId: controllerId) : self.touchUpInside(.X, controllerId: controllerId) |
|
||||
} |
|
||||
extendedGamepad.buttonY.pressedChangedHandler = { button, value, pressed in |
|
||||
pressed ? self.touchDown(.Y, controllerId: controllerId) : self.touchUpInside(.Y, controllerId: controllerId) |
|
||||
} |
|
||||
extendedGamepad.leftShoulder.pressedChangedHandler = { button, value, pressed in |
|
||||
pressed ? self.touchDown(.triggerL, controllerId: controllerId) : self.touchUpInside(.L, controllerId: controllerId) |
|
||||
} |
|
||||
extendedGamepad.leftTrigger.pressedChangedHandler = { button, value, pressed in |
|
||||
pressed ? self.touchDown(.triggerZL, controllerId: controllerId) : self.touchUpInside(.triggerZL, controllerId: controllerId) |
|
||||
} |
|
||||
extendedGamepad.rightShoulder.pressedChangedHandler = { button, value, pressed in |
|
||||
pressed ? self.touchDown(.triggerR, controllerId: controllerId) : self.touchUpInside(.triggerR, controllerId: controllerId) |
|
||||
} |
|
||||
extendedGamepad.leftThumbstickButton?.pressedChangedHandler = { button, value, pressed in |
|
||||
pressed ? self.touchDown(.L, controllerId: controllerId) : self.touchUpInside(.triggerR, controllerId: controllerId) |
|
||||
} |
|
||||
extendedGamepad.rightThumbstickButton?.pressedChangedHandler = { button, value, pressed in |
|
||||
pressed ? self.touchDown(.R, controllerId: controllerId) : self.touchUpInside(.triggerR, controllerId: controllerId) |
|
||||
} |
|
||||
extendedGamepad.rightTrigger.pressedChangedHandler = { button, value, pressed in |
|
||||
pressed ? self.touchDown(.triggerZR, controllerId: controllerId) : self.touchUpInside(.triggerZR, controllerId: controllerId) |
|
||||
} |
|
||||
extendedGamepad.buttonHome?.pressedChangedHandler = { button, value, pressed in |
|
||||
if pressed { |
|
||||
appui.exit() |
|
||||
presentationMode.wrappedValue.dismiss() |
|
||||
} |
|
||||
} |
|
||||
extendedGamepad.leftThumbstick.valueChangedHandler = { dpad, x, y in |
|
||||
self.appui.thumbstickMoved(analog: .left, x: x, y: y, controllerid: controllerId) |
|
||||
} |
|
||||
|
|
||||
extendedGamepad.rightThumbstick.valueChangedHandler = { dpad, x, y in |
|
||||
self.appui.thumbstickMoved(analog: .right, x: x, y: y, controllerid: controllerId) |
|
||||
} |
|
||||
|
|
||||
if let motion = controller.motion { |
|
||||
var lastTimestamp = Date().timeIntervalSince1970 // Initialize timestamp when motion starts |
|
||||
|
|
||||
motion.valueChangedHandler = { motion in |
|
||||
// Get current time |
|
||||
let currentTimestamp = Date().timeIntervalSince1970 |
|
||||
let deltaTimestamp = Int32((currentTimestamp - lastTimestamp) * 1000) // Difference in milliseconds |
|
||||
|
|
||||
// Update last timestamp |
|
||||
lastTimestamp = currentTimestamp |
|
||||
|
|
||||
// Get gyroscope data |
|
||||
let gyroX = motion.rotationRate.x |
|
||||
let gyroY = motion.rotationRate.y |
|
||||
let gyroZ = motion.rotationRate.z |
|
||||
|
|
||||
// Get accelerometer data |
|
||||
let accelX = motion.gravity.x + motion.userAcceleration.x |
|
||||
let accelY = motion.gravity.y + motion.userAcceleration.y |
|
||||
let accelZ = motion.gravity.z + motion.userAcceleration.z |
|
||||
|
|
||||
print("\(gyroX), \(gyroY), \(gyroZ), \(accelX), \(accelY), \(accelZ)") |
|
||||
|
|
||||
// Call your gyroMoved function with the motion data |
|
||||
appui.gyroMoved(x: Float(gyroX), y: Float(gyroY), z: Float(gyroZ), accelX: Float(accelX), accelY: Float(accelY), accelZ: Float(accelZ), controllerId: Int32(controllerId), deltaTimestamp: Int32(lastTimestamp)) |
|
||||
} |
|
||||
} |
|
||||
} else if let microGamepad = controller.microGamepad { |
|
||||
// Handle micro gamepad |
|
||||
microGamepad.dpad.up.pressedChangedHandler = { button, value, pressed in |
|
||||
pressed ? self.touchDown(.directionalPadUp, controllerId: controllerId) : self.touchUpInside(.directionalPadUp, controllerId: controllerId) |
|
||||
} |
|
||||
microGamepad.dpad.down.pressedChangedHandler = { button, value, pressed in |
|
||||
pressed ? self.touchDown(.directionalPadDown, controllerId: controllerId) : self.touchUpInside(.directionalPadDown, controllerId: controllerId) |
|
||||
} |
|
||||
microGamepad.dpad.left.pressedChangedHandler = { button, value, pressed in |
|
||||
pressed ? self.touchDown(.directionalPadLeft, controllerId: controllerId) : self.touchUpInside(.directionalPadLeft, controllerId: controllerId) |
|
||||
} |
|
||||
microGamepad.dpad.right.pressedChangedHandler = { button, value, pressed in |
|
||||
pressed ? self.touchDown(.directionalPadRight, controllerId: controllerId) : self.touchUpInside(.directionalPadRight, controllerId: controllerId) |
|
||||
} |
|
||||
microGamepad.buttonA.pressedChangedHandler = { button, value, pressed in |
|
||||
pressed ? self.touchDown(.A, controllerId: controllerId) : self.touchUpInside(.A, controllerId: controllerId) |
|
||||
} |
|
||||
microGamepad.buttonX.pressedChangedHandler = { button, value, pressed in |
|
||||
pressed ? self.touchDown(.X, controllerId: controllerId) : self.touchUpInside(.X, controllerId: controllerId) |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private func touchDown(_ button: VirtualControllerButtonType, controllerId: Int) { |
|
||||
appui.virtualControllerButtonDown(button: button, controllerid: controllerId) } |
|
||||
|
|
||||
private func touchUpInside(_ button: VirtualControllerButtonType, controllerId: Int) { |
|
||||
appui.virtualControllerButtonUp(button: button, controllerid: controllerId) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
struct OnScreenController: View { |
|
||||
@State var geometry: GeometryProxy |
|
||||
var body: some View { |
|
||||
if geometry.size.height > geometry.size.width && UIDevice.current.userInterfaceIdiom != .pad { |
|
||||
// portrait |
|
||||
VStack { |
|
||||
Spacer() |
|
||||
VStack { |
|
||||
HStack { |
|
||||
VStack { |
|
||||
ShoulderButtonsViewLeft() |
|
||||
ZStack { |
|
||||
Joystick() |
|
||||
DPadView() |
|
||||
} |
|
||||
} |
|
||||
.padding() |
|
||||
VStack { |
|
||||
ShoulderButtonsViewRight() |
|
||||
ZStack { |
|
||||
Joystick(iscool: true) // hope this works |
|
||||
ABXYView() |
|
||||
} |
|
||||
} |
|
||||
.padding() |
|
||||
} |
|
||||
HStack { |
|
||||
ButtonView(button: .plus).padding(.horizontal, 40) |
|
||||
ButtonView(button: .minus).padding(.horizontal, 40) |
|
||||
} |
|
||||
} |
|
||||
.padding(.bottom, geometry.size.height / 3.2) // very broken |
|
||||
} |
|
||||
} else { |
|
||||
// could be landscape |
|
||||
VStack { |
|
||||
HStack { |
|
||||
Spacer() |
|
||||
ButtonView(button: .home) |
|
||||
.padding(.horizontal) |
|
||||
} |
|
||||
Spacer() |
|
||||
VStack { |
|
||||
HStack { |
|
||||
|
|
||||
// gotta fuckin add + and - now |
|
||||
VStack { |
|
||||
ShoulderButtonsViewLeft() |
|
||||
ZStack { |
|
||||
Joystick() |
|
||||
DPadView() |
|
||||
} |
|
||||
} |
|
||||
HStack { |
|
||||
Spacer() |
|
||||
VStack { |
|
||||
Spacer() |
|
||||
ButtonView(button: .plus) // Adding the + button |
|
||||
} |
|
||||
VStack { |
|
||||
Spacer() |
|
||||
ButtonView(button: .minus) // Adding the - button |
|
||||
} |
|
||||
Spacer() |
|
||||
} |
|
||||
VStack { |
|
||||
ShoulderButtonsViewRight() |
|
||||
ZStack { |
|
||||
Joystick(iscool: true) // hope this work s |
|
||||
ABXYView() |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
.padding(.bottom, geometry.size.height / 11) // also extremally broken ( |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
struct ShoulderButtonsViewLeft: View { |
|
||||
var body: some View { |
|
||||
HStack { |
|
||||
ButtonView(button: .triggerZL) |
|
||||
.padding(.horizontal) |
|
||||
ButtonView(button: .triggerL) |
|
||||
.padding(.horizontal) |
|
||||
} |
|
||||
.frame(width: 160, height: 20) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
struct ShoulderButtonsViewRight: View { |
|
||||
var body: some View { |
|
||||
HStack { |
|
||||
ButtonView(button: .triggerR) |
|
||||
.padding(.horizontal) |
|
||||
ButtonView(button: .triggerZR) |
|
||||
.padding(.horizontal) |
|
||||
} |
|
||||
.frame(width: 160, height: 20) |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
|
|
||||
struct DPadView: View { |
|
||||
var body: some View { |
|
||||
VStack { |
|
||||
ButtonView(button: .directionalPadUp) |
|
||||
HStack { |
|
||||
ButtonView(button: .directionalPadLeft) |
|
||||
Spacer(minLength: 20) |
|
||||
ButtonView(button: .directionalPadRight) |
|
||||
} |
|
||||
ButtonView(button: .directionalPadDown) |
|
||||
.padding(.horizontal) |
|
||||
} |
|
||||
.frame(width: 145, height: 145) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
struct ABXYView: View { |
|
||||
var body: some View { |
|
||||
VStack { |
|
||||
ButtonView(button: .X) |
|
||||
HStack { |
|
||||
ButtonView(button: .Y) |
|
||||
Spacer(minLength: 20) |
|
||||
ButtonView(button: .A) |
|
||||
} |
|
||||
ButtonView(button: .B) |
|
||||
.padding(.horizontal) |
|
||||
} |
|
||||
.frame(width: 145, height: 145) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
class Haptics { |
|
||||
static let shared = Haptics() |
|
||||
private init() { } |
|
||||
func play(_ feedbackStyle: UIImpactFeedbackGenerator.FeedbackStyle) { |
|
||||
print("haptics") |
|
||||
UIImpactFeedbackGenerator(style: feedbackStyle).impactOccurred() |
|
||||
} |
|
||||
func notify(_ feedbackType: UINotificationFeedbackGenerator.FeedbackType) { |
|
||||
UINotificationFeedbackGenerator().notificationOccurred(feedbackType) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
struct ButtonView: View { |
|
||||
var button: VirtualControllerButtonType |
|
||||
@StateObject private var viewModel: EmulationViewModel = EmulationViewModel(game: nil) |
|
||||
let appui = AppUI.shared |
|
||||
@State var mtkView: MTKView? |
|
||||
@State var width: CGFloat = 45 |
|
||||
@State var height: CGFloat = 45 |
|
||||
@State var isPressed = false |
|
||||
var id: Int { |
|
||||
if onscreenjoy { |
|
||||
return 8 |
|
||||
} |
|
||||
return 0 |
|
||||
} |
|
||||
@AppStorage("onscreenhandheld") var onscreenjoy: Bool = false |
|
||||
@Environment(\.colorScheme) var colorScheme |
|
||||
@Environment(\.presentationMode) var presentationMode |
|
||||
|
|
||||
var body: some View { |
|
||||
Image(systemName: buttonText) |
|
||||
.resizable() |
|
||||
.frame(width: width, height: height) |
|
||||
.foregroundColor(colorScheme == .dark ? Color.gray : Color.gray) |
|
||||
.opacity(isPressed ? 0.5 : 1) |
|
||||
.gesture( |
|
||||
DragGesture(minimumDistance: 0) |
|
||||
.onChanged { _ in |
|
||||
if !self.isPressed { |
|
||||
self.isPressed = true |
|
||||
DispatchQueue.main.async { |
|
||||
if button == .home { |
|
||||
presentationMode.wrappedValue.dismiss() |
|
||||
appui.exit() |
|
||||
} else { |
|
||||
appui.virtualControllerButtonDown(button: button, controllerid: id) |
|
||||
Haptics.shared.play(.heavy) |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.onEnded { _ in |
|
||||
self.isPressed = false |
|
||||
DispatchQueue.main.async { |
|
||||
if button != .home { |
|
||||
appui.virtualControllerButtonUp(button: button, controllerid: id) |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
) |
|
||||
.onAppear() { |
|
||||
if button == .triggerL || button == .triggerZL || button == .triggerZR || button == .triggerR { |
|
||||
width = 65 |
|
||||
} |
|
||||
|
|
||||
|
|
||||
if button == .minus || button == .plus || button == .home { |
|
||||
width = 35 |
|
||||
height = 35 |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private var buttonText: String { |
|
||||
switch button { |
|
||||
case .A: return "a.circle.fill" |
|
||||
case .B: return "b.circle.fill" |
|
||||
case .X: return "x.circle.fill" |
|
||||
case .Y: return "y.circle.fill" |
|
||||
case .directionalPadUp: return "arrowtriangle.up.circle.fill" |
|
||||
case .directionalPadDown: return "arrowtriangle.down.circle.fill" |
|
||||
case .directionalPadLeft: return "arrowtriangle.left.circle.fill" |
|
||||
case .directionalPadRight: return "arrowtriangle.right.circle.fill" |
|
||||
case .triggerZL: return"zl.rectangle.roundedtop.fill" |
|
||||
case .triggerZR: return "zr.rectangle.roundedtop.fill" |
|
||||
case .triggerL: return "l.rectangle.roundedbottom.fill" |
|
||||
case .triggerR: return "r.rectangle.roundedbottom.fill" |
|
||||
case .plus: return "plus.circle.fill" |
|
||||
case .minus: return "minus.circle.fill" |
|
||||
case .home: return "house.circle.fill" |
|
||||
default: return "" |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,23 +0,0 @@ |
|||||
// 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 Metal |
|
||||
|
|
||||
|
|
||||
struct MetalView: UIViewRepresentable { |
|
||||
let device: MTLDevice? |
|
||||
let configure: (UIView) -> Void |
|
||||
|
|
||||
func makeUIView(context: Context) -> EmulationScreenView { |
|
||||
let view = EmulationScreenView() |
|
||||
configure(view.primaryScreen) |
|
||||
return view |
|
||||
} |
|
||||
|
|
||||
func updateUIView(_ uiView: EmulationScreenView, context: Context) { |
|
||||
// |
|
||||
} |
|
||||
} |
|
||||
@ -1,44 +0,0 @@ |
|||||
// 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 |
|
||||
|
|
||||
struct BootOSView: View { |
|
||||
@Binding var core: Core |
|
||||
@Binding var currentnavigarion: Int |
|
||||
@State var appui = AppUI.shared |
|
||||
@AppStorage("cangetfullpath") var canGetFullPath: Bool = false |
|
||||
var body: some View { |
|
||||
if (appui.canGetFullPath() -- canGetFullPath) { |
|
||||
EmulationView(game: nil) |
|
||||
} else { |
|
||||
VStack { |
|
||||
Text("Unable Launch Switch OS") |
|
||||
.font(.largeTitle) |
|
||||
.padding() |
|
||||
Text("You do not have the Switch Home Menu Files Needed to launch the Ηome Menu") |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
struct NavView: View { |
|
||||
@Binding var core: Core |
|
||||
@State private var selectedTab = 0 |
|
||||
var body: some View { |
|
||||
TabView(selection: $selectedTab) { |
|
||||
LibraryView(core: $core) |
|
||||
.tabItem { Label("Library", systemImage: "rectangle.on.rectangle") } |
|
||||
.tag(0) |
|
||||
BootOSView(core: $core, currentnavigarion: $selectedTab) |
|
||||
.toolbar(.hidden, for: .tabBar) |
|
||||
.tabItem { Label("Boot OS", systemImage: "house") } |
|
||||
.tag(1) |
|
||||
SettingsView(core: core) |
|
||||
.tabItem { Label("Settings", systemImage: "gear") } |
|
||||
.tag(2) |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,18 +0,0 @@ |
|||||
// 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 |
|
||||
|
|
||||
struct SettingsView: View { |
|
||||
@State var core: Core |
|
||||
@State var showprompt = false |
|
||||
|
|
||||
@AppStorage("icon") var iconused = 1 |
|
||||
var body: some View { |
|
||||
NavigationStack { |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue