Show game profiles in a support carousel and require users own files
This commit is contained in:
1 parent
ac7f2fca0f
commit
ba508a0c37
6 files changed
+35
-39
No files matched your search
+1
-1
@@ -49,7 +49,7 @@ Para actualizar, usa la misma cuenta y el mismo bundle ID efectivo de Sideloadly
|
||||
|
||||
## Juegos incluidos
|
||||
|
||||
En la app pulsa **Ver todos** para consultar los perfiles de esta copia. Busca por nombre, versión o Title ID; cada resultado enlaza a su ficha. El catálogo vuelve a leer los perfiles locales cada vez que lo abres.
|
||||
El carrusel muestra los perfiles de esta copia; no proporciona ni descarga juegos. Debes añadir tus propios archivos del juego. Pulsa **Ver todos** debajo para consultar la lista completa de soporte. Busca por nombre, versión o Title ID; cada resultado enlaza a su ficha. El catálogo vuelve a leer los perfiles locales cada vez que lo abres.
|
||||
|
||||
**Las pruebas propias cubren compilación y empaquetado en Mac, no una verificación automática de juego en iPhone.** Los perfiles y reportes de juego proceden de upstream; revisa [la ficha de tu juego](dm/games/README.md#games) antes de prepararlo. Un perfil no garantiza que cualquier versión funcione en cualquier iPhone.
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ For updates, keep the same Apple account and effective bundle ID used in Sideloa
|
||||
|
||||
## Included game profiles
|
||||
|
||||
In the desktop app, click **View all** to browse every profile in your checkout. Search by name, version or Title ID; each result links to its game notes. The catalog reads the local profiles each time you open it.
|
||||
The home carousel shows the game profiles in your checkout; it does not provide or download games. You must add your own game files. Click **View all** below it to browse the complete support list. Search by name, version or Title ID; each result links to its game notes. The catalog reads the local profiles each time you open it.
|
||||
|
||||
**Our own checks cover macOS compilation and packaging, not automatic iPhone gameplay verification.** Profiles and gameplay reports come from upstream and may concern Mac or iPhone; read [your game's notes](dm/games/README.md#games). A profile does not guarantee that every game version works on every device.
|
||||
|
||||
|
||||
@@ -12,6 +12,9 @@ enum EasyLanguage: String, CaseIterable {
|
||||
|
||||
struct EasyStrings {
|
||||
static let english: [String:String] = [
|
||||
"Juegos con soporte en la herramienta": "Supported game profiles",
|
||||
"No incluye ni descarga juegos. Debes añadir tus propios archivos.": "No games are included or downloaded. You must add your own files.",
|
||||
"Carpeta de tu juego": "Your game folder",
|
||||
"Descargar Sideloadly": "Get Sideloadly",
|
||||
"Enviar a Sideloadly": "Send to Sideloadly",
|
||||
"Prepara tu juego.": "Prepare your game.",
|
||||
|
||||
@@ -3,13 +3,6 @@ import AppKit
|
||||
import Foundation
|
||||
import Darwin
|
||||
|
||||
struct GameCard: Identifiable {
|
||||
let id: String
|
||||
let name: String
|
||||
let symbol: String
|
||||
let tint: Color
|
||||
}
|
||||
|
||||
@MainActor final class BuildModel: ObservableObject {
|
||||
@Published var language: EasyLanguage = EasyLanguage.load() {
|
||||
didSet {language.save()}
|
||||
@@ -31,14 +24,10 @@ struct GameCard: Identifiable {
|
||||
private var process: Process?
|
||||
private var cancelled = false
|
||||
let repo: URL
|
||||
let cards: [GameCard] = [
|
||||
.init(id:"dread",name:"Metroid Dread",symbol:"scope",tint:.orange),
|
||||
.init(id:"wonder",name:"Super Mario Bros. Wonder",symbol:"sparkles",tint:.mint),
|
||||
.init(id:"zelda",name:"Zelda: Breath of the Wild",symbol:"mountain.2",tint:.cyan)
|
||||
]
|
||||
init() {
|
||||
let configured = Bundle.main.object(forInfoDictionaryKey:"NxNativeSource") as? String ?? ""
|
||||
repo = URL(fileURLWithPath:configured)
|
||||
refreshCatalog()
|
||||
if let path=UserDefaults.standard.string(forKey:"keysDirectory"), FileManager.default.fileExists(atPath:path+"/prod.keys") {
|
||||
keysFolder=URL(fileURLWithPath:path)
|
||||
}
|
||||
@@ -48,9 +37,12 @@ struct GameCard: Identifiable {
|
||||
}
|
||||
}
|
||||
var gameName: String { folder?.lastPathComponent ?? text("Ningún juego seleccionado") }
|
||||
func openCatalog() {
|
||||
private func refreshCatalog() {
|
||||
do {catalog=try GameCatalog.load(repo:repo);catalogFailed=false}
|
||||
catch {catalog=[];catalogFailed=true}
|
||||
}
|
||||
func openCatalog() {
|
||||
refreshCatalog()
|
||||
showCatalog=true
|
||||
}
|
||||
func chooseFolder() {
|
||||
@@ -201,42 +193,43 @@ struct ContentView: View {
|
||||
Text(model.text("Creamos la IPA. La instalas en tu iPhone con Sideloadly."))
|
||||
.font(.system(size:14)).foregroundStyle(.secondary)
|
||||
}
|
||||
HStack(spacing:12) {
|
||||
ForEach(model.cards) {card in
|
||||
VStack(alignment:.leading,spacing:7) {
|
||||
ZStack {
|
||||
RoundedRectangle(cornerRadius:12).fill(card.tint.opacity(0.12))
|
||||
Image(systemName:card.symbol).font(.system(size:29,weight:.light)).foregroundStyle(card.tint)
|
||||
}.frame(height:74)
|
||||
Text(card.name).font(.system(size:10,weight:.medium)).foregroundStyle(ink).lineLimit(1)
|
||||
}.frame(maxWidth:.infinity)
|
||||
VStack(alignment:.leading,spacing:10) {
|
||||
Text(model.text("Juegos con soporte en la herramienta"))
|
||||
.font(.system(size:14,weight:.semibold)).foregroundStyle(ink)
|
||||
Text(model.text("No incluye ni descarga juegos. Debes añadir tus propios archivos."))
|
||||
.font(.system(size:12)).foregroundStyle(.secondary)
|
||||
ScrollView(.horizontal,showsIndicators:true) {
|
||||
LazyHStack(spacing:12) {
|
||||
ForEach(Array(model.catalog.enumerated()),id:\.element.id) { index, game in
|
||||
let tint: Color = [.orange,.mint,.cyan,.purple,.pink][index % 5]
|
||||
VStack(alignment:.leading,spacing:7) {
|
||||
ZStack {
|
||||
RoundedRectangle(cornerRadius:12).fill(tint.opacity(0.12))
|
||||
Image(systemName:"gamecontroller").font(.system(size:29,weight:.light)).foregroundStyle(tint)
|
||||
}.frame(height:66)
|
||||
Text(game.name).font(.system(size:11,weight:.medium))
|
||||
.foregroundStyle(ink).lineLimit(2).frame(height:30,alignment:.topLeading)
|
||||
}.frame(width:165)
|
||||
}
|
||||
}.padding(.bottom,8)
|
||||
}
|
||||
Button {model.openCatalog()} label: {
|
||||
VStack(alignment:.leading,spacing:7) {
|
||||
ZStack {
|
||||
RoundedRectangle(cornerRadius:12).fill(lime.opacity(0.12))
|
||||
Image(systemName:"square.grid.2x2").font(.system(size:28,weight:.light)).foregroundStyle(lime)
|
||||
}.frame(height:74)
|
||||
HStack {
|
||||
Text(model.text("Ver todos")).font(.system(size:10,weight:.semibold))
|
||||
Spacer()
|
||||
Image(systemName:"arrow.up.right").font(.system(size:10))
|
||||
}.foregroundStyle(ink)
|
||||
}.frame(maxWidth:.infinity)
|
||||
}.buttonStyle(.plain).accessibilityIdentifier("view-all-games")
|
||||
Label(model.text("Ver todos"),systemImage:"magnifyingglass")
|
||||
.font(.system(size:12,weight:.semibold))
|
||||
}.buttonStyle(.plain).foregroundStyle(lime).accessibilityIdentifier("view-all-games")
|
||||
}
|
||||
VStack(alignment:.leading,spacing:18) {
|
||||
HStack(spacing:12) {
|
||||
Image(systemName:"folder.fill").font(.system(size:24)).foregroundStyle(lime)
|
||||
VStack(alignment:.leading,spacing:4) {
|
||||
Text(model.folder == nil ? model.text("Carpeta del juego") : model.gameName)
|
||||
Text(model.folder == nil ? model.text("Carpeta de tu juego") : model.gameName)
|
||||
.font(.system(size:16,weight:.semibold)).foregroundStyle(ink)
|
||||
if model.folder == nil {
|
||||
Text(model.text("Con el juego base y sus actualizaciones.")).font(.system(size:12)).foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
Spacer()
|
||||
Button(model.folder == nil ? model.text("Elegir") : model.text("Cambiar")) {model.chooseFolder()}.disabled(model.running).accessibilityLabel(model.text("Carpeta del juego"))
|
||||
Button(model.folder == nil ? model.text("Elegir") : model.text("Cambiar")) {model.chooseFolder()}.disabled(model.running).accessibilityLabel(model.text("Carpeta de tu juego"))
|
||||
}
|
||||
HStack(spacing:12) {
|
||||
Image(systemName:"key.horizontal").font(.system(size:19)).foregroundStyle(lime).frame(width:24)
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 414 KiB |
@@ -153,7 +153,7 @@ bytes, not Nintendo key material.
|
||||
|
||||
## Game catalog
|
||||
|
||||
The fourth home card opens **View all / Ver todos**. The native catalog reads every
|
||||
The home carousel lists all local game profiles as a support reference, with an explicit reminder that users must supply their own game files. **View all / Ver todos** below the carousel opens the searchable catalog. The native catalog reads every
|
||||
16-digit title directory containing `dm/games/<id>/game.tsv` from the current checkout
|
||||
when opened. It shows the profile name, registered build display versions and title ID,
|
||||
with a link to the corresponding repository game note. Search ignores case and accents
|
||||
|
||||
Reference in new issue
Block a user