Adds pull #12 and changes version number

This commit is contained in:
Stossy11 2025-03-01 21:03:07 +11:00
parent edc56316cc
commit c6ff0b60bf
7 changed files with 110 additions and 139 deletions

View File

@ -672,6 +672,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", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
); );
GCC_OPTIMIZATION_LEVEL = fast; GCC_OPTIMIZATION_LEVEL = fast;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
@ -755,8 +757,12 @@
"$(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",
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
); );
MARKETING_VERSION = 1.2.0; MARKETING_VERSION = 1.3.0;
PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX; PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_EMIT_LOC_STRINGS = YES;
@ -814,6 +820,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", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
); );
GCC_OPTIMIZATION_LEVEL = fast; GCC_OPTIMIZATION_LEVEL = fast;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
@ -897,8 +905,12 @@
"$(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",
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
); );
MARKETING_VERSION = 1.2.0; MARKETING_VERSION = 1.3.0;
PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX; PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_EMIT_LOC_STRINGS = YES;

View File

@ -12,12 +12,12 @@
<key>Ryujinx.xcscheme_^#shared#^_</key> <key>Ryujinx.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>1</integer> <integer>3</integer>
</dict> </dict>
<key>com.Stossy11.MeloNX.RyujinxAg.xcscheme_^#shared#^_</key> <key>com.Stossy11.MeloNX.RyujinxAg.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>2</integer> <integer>4</integer>
</dict> </dict>
</dict> </dict>
<key>SuppressBuildableAutocreation</key> <key>SuppressBuildableAutocreation</key>

View File

@ -484,7 +484,7 @@ class Ryujinx {
func repeatuntilfindLayer() { func repeatuntilfindLayer() {
DispatchQueue.global(qos: .background).async { Task { @MainActor in
while self.metalLayer == nil { while self.metalLayer == nil {
let layer = self.getMetalLayer(nil) let layer = self.getMetalLayer(nil)
@ -492,15 +492,18 @@ class Ryujinx {
DispatchQueue.main.async { DispatchQueue.main.async {
self.metalLayer = layer self.metalLayer = layer
} }
self.metalLayer = layer
break break
} }
Thread.sleep(forTimeInterval: 0.1) Thread.sleep(forTimeInterval: 0.1)
try await Task.sleep(nanoseconds: 100_000_000)
} }
} }
} }
@MainActor
func getMetalLayer(_ window: OpaquePointer?) -> CAMetalLayer? { func getMetalLayer(_ window: OpaquePointer?) -> CAMetalLayer? {
var window = window var window = window
if window == nil { if window == nil {

View File

@ -9,7 +9,7 @@ import SwiftUI
import UniformTypeIdentifiers import UniformTypeIdentifiers
public struct Game: Identifiable, Equatable, Hashable { public struct Game: Identifiable, Equatable, Hashable {
public var id = UUID() public var id: URL { fileURL }
var containerFolder: URL var containerFolder: URL
var fileType: UTType var fileType: UTType

View File

@ -39,7 +39,9 @@ struct GameLibraryView: View {
var filteredGames: [Game] { var filteredGames: [Game] {
if searchText.isEmpty { if searchText.isEmpty {
return Ryujinx.shared.games return Ryujinx.shared.games.filter { game in
!realRecentGames.contains(where: { $0.fileURL == game.fileURL })
}
} }
return Ryujinx.shared.games.filter { return Ryujinx.shared.games.filter {
$0.titleName.localizedCaseInsensitiveContains(searchText) || $0.titleName.localizedCaseInsensitiveContains(searchText) ||
@ -47,6 +49,13 @@ struct GameLibraryView: View {
} }
} }
var realRecentGames: [Game] {
let games = Ryujinx.shared.games
return recentGames.compactMap { recentGame in
games.first(where: { $0.fileURL == recentGame.fileURL })
}
}
var body: some View { var body: some View {
iOSNav { iOSNav {
List { List {
@ -66,46 +75,32 @@ struct GameLibraryView: View {
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
.padding(.top, 40) .padding(.top, 40)
} else { } else {
if !isSearching && !recentGames.isEmpty { if !isSearching && !realRecentGames.isEmpty {
VStack(alignment: .leading, spacing: 12) { Section {
ForEach(realRecentGames) { game in
GameListRow(game: game, startemu: $startemu, games: games, isViewingGameInfo: $isViewingGameInfo, isSelectingGameUpdate: $isSelectingGameUpdate, isSelectingGameDLC: $isSelectingGameDLC, gameInfo: $gameInfo)
.swipeActions(edge: .trailing, allowsFullSwipe: true) {
Button(role: .destructive) {
removeFromRecentGames(game)
} label: {
Label("Delete", systemImage: "trash")
}
}
}
} header: {
Text("Recent") Text("Recent")
.font(.title2.bold())
.padding(.horizontal)
ScrollView(.horizontal, showsIndicators: false) {
LazyHStack(spacing: 16) {
ForEach(recentGames) { game in
RecentGameCard(game: game, startemu: $startemu)
.onTapGesture {
addToRecentGames(game)
startemu = game
}
}
}
.padding(.horizontal)
}
} }
VStack(alignment: .leading, spacing: 12) { Section {
Text("All Games")
.font(.title2.bold())
.padding(.horizontal)
LazyVStack(spacing: 2) {
ForEach(filteredGames) { game in ForEach(filteredGames) { game in
GameListRow(game: game, startemu: $startemu, games: games, isViewingGameInfo: $isViewingGameInfo, isSelectingGameUpdate: $isSelectingGameUpdate, isSelectingGameDLC: $isSelectingGameDLC, gameInfo: $gameInfo) GameListRow(game: game, startemu: $startemu, games: games, isViewingGameInfo: $isViewingGameInfo, isSelectingGameUpdate: $isSelectingGameUpdate, isSelectingGameDLC: $isSelectingGameDLC, gameInfo: $gameInfo)
.onTapGesture {
addToRecentGames(game)
}
}
} }
} header: {
Text("Others")
} }
} else { } else {
ForEach(filteredGames) { game in ForEach(filteredGames) { game in
GameListRow(game: game, startemu: $startemu, games: games, isViewingGameInfo: $isViewingGameInfo, isSelectingGameUpdate: $isSelectingGameUpdate, isSelectingGameDLC: $isSelectingGameDLC, gameInfo: $gameInfo) GameListRow(game: game, startemu: $startemu, games: games, isViewingGameInfo: $isViewingGameInfo, isSelectingGameUpdate: $isSelectingGameUpdate, isSelectingGameDLC: $isSelectingGameDLC, gameInfo: $gameInfo)
.onTapGesture {
addToRecentGames(game)
}
} }
} }
} }
@ -206,8 +201,13 @@ struct GameLibraryView: View {
} }
} }
} }
.onChange(of: startemu) { game in
guard let game else { return }
addToRecentGames(game)
}
} }
.searchable(text: $searchText) .searchable(text: $searchText)
.animation(.easeInOut, value: searchText)
.onChange(of: searchText) { _ in .onChange(of: searchText) { _ in
isSearching = !searchText.isEmpty isSearching = !searchText.isEmpty
} }
@ -291,7 +291,7 @@ struct GameLibraryView: View {
} }
private func addToRecentGames(_ game: Game) { private func addToRecentGames(_ game: Game) {
recentGames.removeAll { $0.id == game.id } recentGames.removeAll { $0.titleId == game.titleId }
recentGames.insert(game, at: 0) recentGames.insert(game, at: 0)
@ -302,6 +302,11 @@ struct GameLibraryView: View {
saveRecentGames() saveRecentGames()
} }
private func removeFromRecentGames(_ game: Game) {
recentGames.removeAll { $0.titleId == game.titleId }
saveRecentGames()
}
private func saveRecentGames() { private func saveRecentGames() {
do { do {
let encoder = JSONEncoder() let encoder = JSONEncoder()
@ -364,53 +369,6 @@ extension Game: Codable {
} }
} }
// MARK: - Recent Game Card
struct RecentGameCard: View {
let game: Game
@Binding var startemu: Game?
@Environment(\.colorScheme) var colorScheme
var body: some View {
Button(action: {
startemu = game
}) {
VStack(alignment: .leading, spacing: 8) {
if let icon = game.icon {
Image(uiImage: icon)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 140, height: 140)
.cornerRadius(12)
} else {
ZStack {
RoundedRectangle(cornerRadius: 12)
.fill(colorScheme == .dark ?
Color(.systemGray5) : Color(.systemGray6))
.frame(width: 140, height: 140)
Image(systemName: "gamecontroller.fill")
.font(.system(size: 40))
.foregroundColor(.gray)
}
}
VStack(alignment: .leading, spacing: 2) {
Text(game.titleName)
.font(.subheadline.bold())
.lineLimit(1)
Text(game.developer)
.font(.caption)
.foregroundColor(.secondary)
.lineLimit(1)
}
.padding(.horizontal, 4)
}
}
.buttonStyle(.plain)
}
}
// MARK: - Game List Item // MARK: - Game List Item
struct GameListRow: View { struct GameListRow: View {
let game: Game let game: Game
@ -469,6 +427,7 @@ struct GameListRow: View {
.foregroundColor(.accentColor) .foregroundColor(.accentColor)
.opacity(0.8) .opacity(0.8)
} }
}
.contextMenu { .contextMenu {
Section { Section {
Button { Button {
@ -507,7 +466,6 @@ struct GameListRow: View {
} }
} }
Section { Section {
Button(role: .destructive) { Button(role: .destructive) {
gametoDelete = game gametoDelete = game
@ -517,8 +475,6 @@ struct GameListRow: View {
} }
} }
} }
}
.buttonStyle(.plain)
.confirmationDialog("Are you sure you want to delete this game?", isPresented: $showGameDeleteConfirmation) { .confirmationDialog("Are you sure you want to delete this game?", isPresented: $showGameDeleteConfirmation) {
Button("Delete", role: .destructive) { Button("Delete", role: .destructive) {
if let game = gametoDelete { if let game = gametoDelete {

View File

@ -45,7 +45,7 @@ struct DLCManagerSheet: View {
Self.saveDlcs(game, dlc: dlcs) Self.saveDlcs(game, dlc: dlcs)
}) { }) {
HStack { HStack {
Text(dlc.containerPath) Text((dlc.containerPath as NSString).lastPathComponent)
.foregroundStyle(Color(uiColor: .label)) .foregroundStyle(Color(uiColor: .label))
Spacer() Spacer()
if dlc.downloadableContentNcaList.first?.enabled == true { if dlc.downloadableContentNcaList.first?.enabled == true {