Skip to content

Commit

Permalink
forgor
Browse files Browse the repository at this point in the history
  • Loading branch information
Owen3H committed Sep 23, 2024
1 parent 689e819 commit a1919db
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 89 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,4 @@ Feel free to join the [discord](https://discord.gg/psBXpXF2JZ) to contact me! He
- See first-hand updates about the project and its progress.
- Chat about the project's development or anything mod related.
- Suggest ideas and get support if you are stuck.
- View the **TODO** list to see what needs fixing/implementing and if it's being currently worked on.
- View the **TODO** list to see what needs fixing/implementing and if it's being currently worked on.
37 changes: 25 additions & 12 deletions frontend/src/components/selected-game/ConfigEditLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Nullable } from 'primevue/ts-helpers'
interface ConfigProps {
config: game.BepinexConfig
fileName: Nullable<string>
fileName?: Nullable<string>
}
const props = defineProps<ConfigProps>()
Expand Down Expand Up @@ -39,6 +39,7 @@ const getEntryDescription = (comments: string[]) => {
c != "" && !c.startsWith('Setting type:') && !c.startsWith('Default value:')
)
arr.shift()
return arr
}
Expand All @@ -55,29 +56,39 @@ const asBool = (str: string) => {

<template>
<div class="config-edit-layout">
<div class="flex flex-column">
<h1 class="header mb-2">Config Editor</h1>
<h3 class="mt-0 mb-3">Currently editing: {{ fileName?.replace('.cfg', '') }}</h3>
<div class="flex column">
<div class="flex row align-items-center justify-content-between">
<h1 class="header mb-1">Config Editor</h1>
<div class="flex row gap-2 align-items-baseline">

<p class="mt-0 mb-0" style="font-size: 24px; color: var(--primary-color); text-shadow: 0px 0px 18px rgba(255, 255, 255, 0.3);">{{ fileName }}</p>
</div>
</div>
</div>

<div class="scroll-hidden">
<div v-for="(entries, section) in groupedEntries">
<Divider v-if="section != '__root'" align="center" type="solid" class="mb-0 mt-1">
<h3 class="category-divider mb-0 mt-0">{{ section }}</h3>
<Divider v-if="section != '__root'" align="center" type="solid" class="mb-0 mt-0">
<p class="category-divider mb-1 mt-1">{{ section }}</p>
</Divider>

<!-- Loop through each entry in the section -->
<div v-for="(entry, key) in entries" :key="key">
<div class="flex row pt-2 justify-content-between align-items-center">
<div class="flex column">
<p class="entry-key mt-0 mb-0">{{ key }}</p>
<div class="flex row pt-2 justify-content-between align-items-baseline">
<!-- Container of the key and comments -->
<div class="mb-1" style="width: 45rem;">
<p class="entry-key mt-0 mb-1">{{ key }}</p>

<div>{{ entry.comments[0].replaceAll('#', '') }}</div>
<div v-for="comment in getEntryDescription(entry.comments)">

{{ comment }}
</div>
</div>

<InputSwitch v-if="isBool(entry.default_value)" v-model="entry.checked"/>
<InputText v-else class="ml-3" style="font-size: 16.5px;" :value="entry.value"/>
<div>
<InputSwitch v-if="isBool(entry.default_value)" v-model="entry.checked"/>
<InputText v-else class="ml-3 flex-grow-1" style="font-size: 16px;" :value="entry.value"/>
</div>
</div>
</div>
</div>
Expand All @@ -104,5 +115,7 @@ const asBool = (str: string) => {
.category-divider {
position: sticky;
font-size: 22px;
font-weight: 600;
}
</style>
21 changes: 15 additions & 6 deletions frontend/src/components/selected-game/ConfigEditorOverlay.vue
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,20 @@ const getRelativeConfigPath = (absPath: string) => {
return normalizedFile.substring(startIndex)
}
const dialogStyle = () => {
if (selectedConfig) return {
"margin-left": "10px",
"width": 'auto',
"min-width": '45rem',
"max-width": '50rem'
}
}
</script>

<template>
<CardOverlay
class="no-drag"
<CardOverlay class="no-drag"
:dialogStyle="dialogStyle()"
v-model:visible="dialog.visible"
v-model:closable="dialog.closable"
v-model:draggable="dialog.draggable"
Expand All @@ -93,16 +102,16 @@ const getRelativeConfigPath = (absPath: string) => {
<p style="font-size: 18.5px; font-weight: 285; user-select: none;">{{ getRelativeConfigPath(path) }}</p>

<div class="flex gap-2">
<Button outlined plain
icon="pi pi-pen-to-square"
style="font-size: 17px; width: 3rem;"
<Button outlined plain
icon="pi pi-file-edit"
style="width: 3rem; height: 2.6rem;"
v-tooltip.top="'Open File'"
@click="openLink(`file://${path}`)"
/>

<Button plain
class="justify-content-center"
style="font-size: 17px; width: 5rem; height: 2.5rem;"
style="font-size: 18px; width: 6rem; height: 2.6rem;"
:label="t('selected-game.config-editor.edit-button')"
@click="editConfig(path)"
/>
Expand Down
5 changes: 2 additions & 3 deletions frontend/src/mocks/GameService.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ThunderstoreGame } from "@types"

// TODO: Replace with a call to a real service.
export const getGameList = (): ThunderstoreGame[] => [{
export const mockGameList: ThunderstoreGame[] = [{
title: "Lethal Company",
identifier: 'lethal-company',
image: "LethalCompany.png",
Expand All @@ -14,7 +13,7 @@ export const getGameList = (): ThunderstoreGame[] => [{
image: "RiskOfRain2.jpg",
path: "H:\\Program Files (x86)\\Steam\\steamapps\\common\\Risk of Rain 2",
aliases: ["ror2"],
steamID: 248820
steamID: 248820,
}, {
title: "Content Warning",
identifier: 'content-warning',
Expand Down
44 changes: 36 additions & 8 deletions frontend/src/stores/game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { defineStore } from 'pinia'
import { Save, SetFavouriteGames } from '@backend/app/Persistence'
import { Ref, computed, ref } from 'vue'
import { thunderstore } from '@backend/models.js'
import { GetPersistence } from '@backend/app/Application.js'
import { BepinexInstalled } from '@backend/game/GameManager.js'

export interface GameState {
selectedGame: ThunderstoreGame,
Expand All @@ -25,11 +27,10 @@ export const useGameStore = defineStore('GameStore', () => {

const gamesAsArray = computed(() => [...games.value.values()] as ThunderstoreGame[])

const isGameInstalled = computed(() => (id: string) => _gameByID(id)?.installed || false)
const isFavouriteGame = computed(() => (id: string) => {
const game = _gameByID(id)
return game?.favourited || false
})
// TODO: Evaluate if these are even useful.
// const isBepinexSetup = computed(() => (id: string) => _gameByID(id)?.bepinexSetup || false)
// const isGameInstalled = computed(() => (id: string) => _gameByID(id)?.installed || false)
// const isFavouriteGame = computed(() => (id: string) => _gameByID(id)?.favourited || false)

const favouriteGameIds = computed(() => gamesAsArray.value.reduce((acc: string[], game) => {
if (game.favourited) acc.push(game.identifier)
Expand Down Expand Up @@ -60,18 +61,45 @@ export const useGameStore = defineStore('GameStore', () => {
await SetFavouriteGames(favouriteGameIds.value)
await Save()
}

async function initGames(gameList: ThunderstoreGame[]) {
games.value = new Map<string, ThunderstoreGame>()
const persistence = await GetPersistence()

// Init game props.
for (const game of gameList) {
game.favourited = await persistence.favourite_games.includes(game.identifier)
game.installed = !!game.path // TODO: Check game executable exists. For now, assume installed if path specified.

if (game.path) {
game.bepinexSetup = await BepinexInstalled(game.path)
}

// Ensure modCache is kept between mounts.
const cachedGame = _gameByID(game.identifier)
if (cachedGame?.modCache) {
game.modCache = cachedGame.modCache
}

games.value.set(game.identifier, game)
}

return games.value.size
}
//#endregion

return {
selectedGame,
games,
gamesAsArray,
gameByID,
isGameInstalled,
isFavouriteGame,
// isBepinexSetup,
// isGameInstalled,
// isFavouriteGame,
favouriteGameIds,
setSelectedGame,
toggleFavouriteGame,
updateModCache
updateModCache,
initGames
}
})
4 changes: 2 additions & 2 deletions frontend/src/types/game.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { thunderstore } from "@backend/models.js"

export interface BaseGame {
export interface Game {
steamID: number
identifier: string
title: string
Expand All @@ -13,6 +13,6 @@ export interface BaseGame {
aliases?: string[]
}

export interface ThunderstoreGame extends BaseGame {
export interface ThunderstoreGame extends Game {
modCache?: thunderstore.StrippedPackage[]
}
61 changes: 16 additions & 45 deletions frontend/src/views/GameSelection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,17 @@ import DataViewLayoutOptions from 'primevue/dataviewlayoutoptions'
import Skeleton from 'primevue/skeleton'
// TODO: Replace with real external service.
import { getGameList } from '../mocks/GameService'
import { mockGameList } from '../mocks/GameService'
import {
ThunderstoreGame,
Layout, OptionItem,
ValueItem, ValueItemLabeled
ValueItem, ValueItemLabeled,
} from '@types'
import { Nullable } from 'primevue/ts-helpers'
import { t } from '@i18n'
import { BepinexInstalled } from '@backend/game/GameManager'
import { GetPersistence, } from '@backend/app/Application'
import { tooltipOpts, openLink } from "../../src/util"
import { useGameStore } from '@stores'
Expand All @@ -27,17 +25,14 @@ import { storeToRefs } from 'pinia'
import router from '../router'
const store = useGameStore()
const {
games,
isGameInstalled,
isFavouriteGame,
gamesAsArray
const {
gamesAsArray,
} = storeToRefs(store)
const {
toggleFavouriteGame,
setSelectedGame,
gameByID
initGames
} = store
const loading = ref(true)
Expand All @@ -60,8 +55,6 @@ const filters: ComputedRef<ValueItemLabeled<string>[]> = computed(() => [{
value: t('keywords.favourites')
}])
const alphabetSort = (games: ThunderstoreGame[]) => {
if ((searchInput.value?.length ?? 0) < 1) return games
return games.sort((g1, g2) => g1 > g2 ? 1 : (g1 === g2 ? 0 : -1))
Expand Down Expand Up @@ -134,29 +127,8 @@ const selectGame = (game: ThunderstoreGame) => {
}
onMounted(async () => {
loading.value = true
const persistence = await GetPersistence()
const gameList = getGameList()
for (const g of gameList) {
if (!!g.path) {
// TODO: Make sure the game executable exists (call backend)
g.installed = true
g.bepinexSetup = await BepinexInstalled(g.path)
}
// TODO: Set `g.favourited` using backend
g.favourited = persistence.favourite_games.includes(g.identifier)
}
games.value = new Map(gameList.map(g => {
// Make sure the cache persists through mounts
const modCache = gameByID(g.identifier)?.modCache
if (modCache) g.modCache = modCache
return [g.identifier, g]
}))
const size = await initGames(mockGameList)
console.info(`GameStore: Populated games map with ${size} items.`)
loading.value = false
})
Expand All @@ -167,7 +139,6 @@ onMounted(async () => {
<h2 class="header no-select">{{ $t('game-selection.header') }}</h2>

<div class="card game-container no-drag">

<!-- While loading, show a skeleton of a grid. -->
<DataView v-if="loading" data-key="game-selection-loading" layout="grid">
<template #empty>
Expand Down Expand Up @@ -286,8 +257,8 @@ onMounted(async () => {
<div class="flex gap-2 justify-content-center align-items-baseline">
<p class="m-0" style="font-size: 16.5px">{{ t('game-selection.bepinex-setup') }}</p>
<i
:class="['pi', isGameInstalled(game.identifier) ? 'pi-check' : 'pi-times']"
:style="{ color: isGameInstalled(game.identifier) ? 'lime' : 'red' }"
:class="['pi', game.bepinexSetup ? 'pi-check' : 'pi-times']"
:style="{ color: game.bepinexSetup ? 'lime' : 'red' }"
/>
</div>

Expand All @@ -309,9 +280,9 @@ onMounted(async () => {

<Button
outlined plain
v-tooltip.top="tooltipOpts(isFavouriteGame(game.identifier) ? t('keywords.unfavourite') : t('keywords.favourite'))"
:icon="isFavouriteGame(game.identifier) ? 'pi pi-heart-fill' : 'pi pi-heart'"
:style="isFavouriteGame(game.identifier) ? { color: 'var(--primary-color)' } : {}"
v-tooltip.top="tooltipOpts(game.favourited ? t('keywords.unfavourite') : t('keywords.favourite'))"
:icon="game.favourited ? 'pi pi-heart-fill' : 'pi pi-heart'"
:style="game.favourited ? { color: 'var(--primary-color)' } : {}"
@click="toggleFavouriteGame(game.identifier)"
/>
</div>
Expand All @@ -336,8 +307,8 @@ onMounted(async () => {
<div class="flex gap-2 justify-content-center align-items-baseline">
<p class="m-0" style="font-size: 16.5px">{{ t('game-selection.bepinex-setup') }}</p>
<i
:class="['pi', isGameInstalled(game.identifier) ? 'pi-check' : 'pi-times']"
:style="{ color: isGameInstalled(game.identifier) ? 'lime' : 'red' }"
:class="['pi', game.installed ? 'pi-check' : 'pi-times']"
:style="{ color: game.installed ? 'lime' : 'red' }"
/>
</div>
</div>
Expand All @@ -354,8 +325,8 @@ onMounted(async () => {

<Button
outlined plain
:icon="isFavouriteGame(game.identifier) ? 'pi pi-heart-fill' : 'pi pi-heart'"
:style="isFavouriteGame(game.identifier) ? { color: 'var(--primary-color)' } : {}"
:icon="game.favourited ? 'pi pi-heart-fill' : 'pi pi-heart'"
:style="game.favourited ? { color: 'var(--primary-color)' } : {}"
@click="toggleFavouriteGame(game.identifier)"
/>

Expand Down
Loading

0 comments on commit a1919db

Please sign in to comment.