Skip to content

Commit

Permalink
Improve config type satefy and fault tolerance (#44)
Browse files Browse the repository at this point in the history
  • Loading branch information
vasilvestre authored Jun 2, 2023
1 parent 9237b06 commit a9e63ba
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 85 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ They are sourced from https://github.com/HolographicWings/TOTK-Mods-collection
- There's another path for Yuzu, which isn't the one required.

#### Ryujinx
- Locate the directory shown in their documentation
- See here : https://github.com/Ryujinx/Ryujinx/wiki/Ryujinx-Setup-&-Configuration-Guide#managing-mods
- Locate the directory shown in their documentation : https://github.com/Ryujinx/Ryujinx/wiki/Ryujinx-Setup-&-Configuration-Guide#managing-mods
- Linux : `~/.config/ryujinx`
- Windows : `%appdata%/Roaming/Ryujinx`

## Contributing

Expand Down
21 changes: 1 addition & 20 deletions app/emulators/emulatorPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,32 +105,13 @@ export default function EmulatorPage(props: { emulatorName: string }) {
}
}}
>
Please locate Yuzu folder
Please locate {emulatorState.name} folder containing Mods folder
</button>
</div>
)}
<div className={'overflow-x-auto'}>
<ModsTable />
</div>
<dialog id="app_modal" className="modal">
<form method="dialog" className="modal-box flex flex-col items-center">
<h3 className="font-bold text-lg">Debug panel for {appVersion}</h3>
<p className="py-4">Got issues ? Try these.</p>
<p className="py-4">
<button className="btn" onClick={() => clearInnerCache()}>
Clear inner cache (force relaunch)
</button>
</p>
<p className="py-4">
<button className="btn" onClick={() => clearConfigFile()}>
Clear config file (force relaunch)
</button>
</p>
<div className="modal-action">
<button className="btn">Close</button>
</div>
</form>
</dialog>
</main>
</ModContext.Provider>
)
Expand Down
78 changes: 78 additions & 0 deletions app/header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
'use client'

import React from 'react'

export function Header() {
return (
<>
<div className="navbar bg-base-100">
<div className="navbar-start"></div>
<div className="navbar-end">
<span>Got issues ?</span>
<button
className={'btn btn-square btn-ghost'}
onClick={() => window.app_modal.showModal()}
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
>
<path
fill="currentColor"
d="m29.83 20l.34-2l-5.17-.85v-4.38l5.06-1.36l-.51-1.93l-4.83 1.29A9 9 0 0 0 20 5V2h-2v2.23a8.81 8.81 0 0 0-4 0V2h-2v3a9 9 0 0 0-4.71 5.82L2.46 9.48L2 11.41l5 1.36v4.38L1.84 18l.32 2L7 19.18a8.9 8.9 0 0 0 .82 3.57l-4.53 4.54l1.42 1.42l4.19-4.2a9 9 0 0 0 14.2 0l4.19 4.2l1.42-1.42l-4.54-4.54a8.9 8.9 0 0 0 .83-3.57ZM15 25.92A7 7 0 0 1 9 19v-6h6ZM9.29 11a7 7 0 0 1 13.42 0ZM23 19a7 7 0 0 1-6 6.92V13h6Z"
/>
</svg>
</button>
<button
className="btn btn-square btn-ghost"
onClick={(event) => toggleTheme(event)}
>
<label className="swap swap-rotate">
<input
type="checkbox"
data-toggle-theme="light,dark"
data-act-class="ACTIVECLASS"
/>
<svg
className="swap-on fill-current w-10 h-10"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
>
<path d="M5.64,17l-.71.71a1,1,0,0,0,0,1.41,1,1,0,0,0,1.41,0l.71-.71A1,1,0,0,0,5.64,17ZM5,12a1,1,0,0,0-1-1H3a1,1,0,0,0,0,2H4A1,1,0,0,0,5,12Zm7-7a1,1,0,0,0,1-1V3a1,1,0,0,0-2,0V4A1,1,0,0,0,12,5ZM5.64,7.05a1,1,0,0,0,.7.29,1,1,0,0,0,.71-.29,1,1,0,0,0,0-1.41l-.71-.71A1,1,0,0,0,4.93,6.34Zm12,.29a1,1,0,0,0,.7-.29l.71-.71a1,1,0,1,0-1.41-1.41L17,5.64a1,1,0,0,0,0,1.41A1,1,0,0,0,17.66,7.34ZM21,11H20a1,1,0,0,0,0,2h1a1,1,0,0,0,0-2Zm-9,8a1,1,0,0,0-1,1v1a1,1,0,0,0,2,0V20A1,1,0,0,0,12,19ZM18.36,17A1,1,0,0,0,17,18.36l.71.71a1,1,0,0,0,1.41,0,1,1,0,0,0,0-1.41ZM12,6.5A5.5,5.5,0,1,0,17.5,12,5.51,5.51,0,0,0,12,6.5Zm0,9A3.5,3.5,0,1,1,15.5,12,3.5,3.5,0,0,1,12,15.5Z" />
</svg>
<svg
className="swap-off fill-current w-10 h-10"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
>
<path d="M21.64,13a1,1,0,0,0-1.05-.14,8.05,8.05,0,0,1-3.37.73A8.15,8.15,0,0,1,9.08,5.49a8.59,8.59,0,0,1,.25-2A1,1,0,0,0,8,2.36,10.14,10.14,0,1,0,22,14.05,1,1,0,0,0,21.64,13Zm-9.5,6.69A8.14,8.14,0,0,1,7.08,5.22v.27A10.15,10.15,0,0,0,17.22,15.63a9.79,9.79,0,0,0,2.1-.22A8.11,8.11,0,0,1,12.14,19.73Z" />
</svg>
</label>
</button>
</div>
</div>
</>
)
}

function toggleTheme(evt: React.MouseEvent<HTMLButtonElement>) {
const target = evt.target as HTMLButtonElement
const themesList = target.getAttribute('data-toggle-theme')
if (themesList) {
const themesArray = themesList.split(',')
if (document.documentElement.getAttribute('data-theme') == themesArray[0]) {
if (themesArray.length == 1) {
document.documentElement.removeAttribute('data-theme')
localStorage.removeItem('theme')
} else {
document.documentElement.setAttribute('data-theme', themesArray[1])
localStorage.setItem('theme', themesArray[1])
}
} else {
document.documentElement.setAttribute('data-theme', themesArray[0])
localStorage.setItem('theme', themesArray[0])
}
}
}
21 changes: 21 additions & 0 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import Alert from '@/app/alert'
import { EmulatorChoiceContext } from '@/src/context/emulatorChoiceContext'
import { themeChange } from 'theme-change'
import { AlertType, EmulatorState, SupportedEmulator } from '@/src/types'
import { clearConfigFile, clearInnerCache } from '@/src/handler/debugHandler'
import { Header } from '@/app/header'

const inter = Inter({ subsets: ['latin'] })

Expand Down Expand Up @@ -62,6 +64,25 @@ export default function RootLayout({ children }: { children: React.ReactNode })
<body className={inter.className}>
{children}
<Alert />
<dialog id="app_modal" className="modal">
<form method="dialog" className="modal-box flex flex-col items-center">
<h3 className="font-bold text-lg">Debug panel for {appVersion}</h3>
<p className="py-4">Got issues ? Try these.</p>
<p className="py-4">
<button className="btn" onClick={() => clearInnerCache()}>
Clear inner cache (force relaunch)
</button>
</p>
<p className="py-4">
<button className="btn" onClick={() => clearConfigFile()}>
Clear config file (force relaunch)
</button>
</p>
<div className="modal-action">
<button className="btn">Close</button>
</div>
</form>
</dialog>
</body>
</html>
</EmulatorChoiceContext.Provider>
Expand Down
74 changes: 40 additions & 34 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
useEmulatorChoiceContext,
} from '@/src/context/emulatorChoiceContext'
import EmulatorPage from '@/app/emulators/emulatorPage'
import { Header } from '@/app/header'

export default function EmulatorChoice() {
const { supportedEmulators, emulatorState, setEmulatorState } =
Expand All @@ -16,44 +17,49 @@ export default function EmulatorChoice() {
return (
<>
{!emulatorState && (
<div className={'flex flex-row h-screen justify-evenly items-center'}>
{supportedEmulators &&
supportedEmulators.map((emulator) => {
return (
<button
className="relative block overflow-hidden rounded-lg border border-gray-100 p-4 sm:p-6 lg:p-8 bg-gray-200"
key={emulator.name}
onClick={() => setEmulatorState({ name: emulator.name })}
>
<span className="absolute inset-x-0 bottom-0 h-2 bg-gradient-to-r from-green-300 via-blue-500 to-purple-600"></span>
<>
<Header />
<div className={'flex flex-row h-screen justify-evenly items-center'}>
{supportedEmulators &&
supportedEmulators.map((emulator) => {
return (
<button
className="relative block overflow-hidden rounded-lg border border-gray-100 p-4 sm:p-6 lg:p-8 bg-gray-200"
key={emulator.name}
onClick={() =>
setEmulatorState({ name: emulator.name })
}
>
<span className="absolute inset-x-0 bottom-0 h-2 bg-gradient-to-r from-green-300 via-blue-500 to-purple-600"></span>

<div className="sm:flex sm:justify-between sm:gap-4">
<div>
<h3 className="text-lg font-bold text-gray-900 sm:text-xl capitalize">
{emulator.name}
</h3>
</div>
<div className="sm:flex sm:justify-between sm:gap-4">
<div>
<h3 className="text-lg font-bold text-gray-900 sm:text-xl capitalize">
{emulator.name}
</h3>
</div>

<div className="hidden sm:block sm:shrink-0">
<Image
alt={emulator.pictureAlt}
width={64}
height={64}
src={emulator.picture}
className="h-16 w-16 object-cover"
/>
<div className="hidden sm:block sm:shrink-0">
<Image
alt={emulator.pictureAlt}
width={64}
height={64}
src={emulator.picture}
className="h-16 w-16 object-cover"
/>
</div>
</div>
</div>

<div className="mt-4">
<p className="max-w-[40ch] text-sm text-gray-500">
{emulator.text}
</p>
</div>
</button>
)
})}
</div>
<div className="mt-4">
<p className="max-w-[40ch] text-sm text-gray-500">
{emulator.text}
</p>
</div>
</button>
)
})}
</div>
</>
)}
</>
)
Expand Down
71 changes: 42 additions & 29 deletions src/handler/emulatorHandler.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { SupportedEmulators } from '@/src/enum'
import { EmulatorState } from '@/src/types'

interface Emulator {
name: string
path?: string | undefined
}

type Config = {
emulators?: Emulator[]
}

export async function askEmulator(emulator: Emulator) {
switch (emulator.name.toLowerCase()) {
case 'yuzu':
Expand Down Expand Up @@ -65,14 +68,17 @@ async function check(emulator: Emulator) {
let emulatorDir
if (
configuration &&
configuration.find((e: Emulator) => e.name.toLowerCase() === emulator.name.toLowerCase())
configuration.emulators &&
configuration.emulators.find(
(e: Emulator) => e.name.toLowerCase() === emulator.name.toLowerCase()
)
) {
const emulatorConfig = configuration.find(
const emulatorConfig = configuration.emulators.find(
(e: Emulator) => e.name.toLowerCase() === emulator.name.toLowerCase()
)
emulatorDir = emulatorConfig?.path
}
if (!emulatorDir) {
if (typeof emulatorDir === 'undefined') {
emulatorDir = await emulatorDefaultFolder(emulator)
if (await fs.exists(emulatorDir)) {
await writeConfiguration({ ...emulator, path: emulatorDir })
Expand Down Expand Up @@ -118,7 +124,17 @@ async function askFor(emulator: Emulator, dialogTitle: string): Promise<Emulator
}
}

async function readConfiguration(): Promise<Emulator[] | null | undefined> {
async function isValidYAML(contents: string) {
const yaml = await import('yaml')
try {
yaml.parse(contents)
return true
} catch {
return false
}
}

async function readConfiguration(): Promise<Config | null | undefined> {
const { fs, path } = await import('@tauri-apps/api')
const yaml = await import('yaml')

Expand All @@ -131,20 +147,11 @@ async function readConfiguration(): Promise<Emulator[] | null | undefined> {
}

const configPath = await path.resolve(configDir, 'config.yaml')

if (!(await fs.exists(configPath))) {
const config: Emulator[] = []
for (const emulator in SupportedEmulators) {
config.push({
name: emulator.toLowerCase(),
path: undefined,
})
}
await fs.writeFile(configPath, yaml.stringify(config))
}

const contents = await fs.readTextFile(configPath)
return yaml.parse(contents)
if (await isValidYAML(contents)) {
return yaml.parse(contents)
}
return null
} catch (e: unknown) {
console.error(e)
}
Expand All @@ -165,19 +172,25 @@ async function writeConfiguration(content: Emulator) {
const configPath = await path.resolve(configDir, 'config.yaml')
const currentConfig = await readConfiguration()

const contentToWrite: Emulator[] = []

if (!currentConfig) {
contentToWrite.push(content)
let emulatorsConfig
if (currentConfig && currentConfig.emulators) {
if (currentConfig.emulators.find((e: Emulator) => e.name === content.name)) {
emulatorsConfig = currentConfig.emulators.map((config: Emulator) => {
if (config.name.toLowerCase() === content.name.toLowerCase()) {
config.path = content.path
}
return config
})
} else {
emulatorsConfig = [...currentConfig.emulators, content]
}
} else {
currentConfig.forEach((config: Emulator) => {
if (config.name.toLowerCase() === content.name.toLowerCase()) {
config.path = content.path
}
contentToWrite.push(config)
})
emulatorsConfig = [content]
}
await fs.writeFile(configPath, yaml.stringify(contentToWrite))
await fs.writeFile(
configPath,
yaml.stringify({ ...currentConfig, emulators: emulatorsConfig })
)
} catch (e: unknown) {
console.error(e)
}
Expand Down

0 comments on commit a9e63ba

Please sign in to comment.