forked from akanyan/STARTLINER
feat: remember current tab
This commit is contained in:
@ -1,3 +1,11 @@
|
|||||||
|
## 0.16.0
|
||||||
|
|
||||||
|
- Fixed the clear cache button not working
|
||||||
|
- Fixed Linux builds
|
||||||
|
- Moved the store tab to the left
|
||||||
|
- STARTLINER now remembers the recently open tab and re-opens it on the next session
|
||||||
|
- Added "Beta" to the title as STARTLINER is approaching feature-completeness
|
||||||
|
|
||||||
## 0.15.0
|
## 0.15.0
|
||||||
|
|
||||||
- Added internationalization
|
- Added internationalization
|
||||||
|
@ -336,7 +336,7 @@ async fn update(app: tauri::AppHandle) -> tauri_plugin_updater::Result<()> {
|
|||||||
fn open_window(apph: AppHandle) -> anyhow::Result<()> {
|
fn open_window(apph: AppHandle) -> anyhow::Result<()> {
|
||||||
let config = apph.config().clone();
|
let config = apph.config().clone();
|
||||||
tauri::WebviewWindowBuilder::new(&apph, "main", tauri::WebviewUrl::App("index.html".into()))
|
tauri::WebviewWindowBuilder::new(&apph, "main", tauri::WebviewUrl::App("index.html".into()))
|
||||||
.title(format!("STARTLINER {}", config.version.unwrap_or_default()))
|
.title(format!("STARTLINER {} Beta", config.version.unwrap_or_default()))
|
||||||
.inner_size(900f64, 600f64)
|
.inner_size(900f64, 600f64)
|
||||||
.min_inner_size(900f64, 600f64)
|
.min_inner_size(900f64, 600f64)
|
||||||
.build()?;
|
.build()?;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "STARTLINER",
|
"productName": "STARTLINER",
|
||||||
"version": "0.15.0",
|
"version": "0.16.0",
|
||||||
"identifier": "zip.patafour.startliner",
|
"identifier": "zip.patafour.startliner",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "bun run dev",
|
"beforeDevCommand": "bun run dev",
|
||||||
|
@ -20,7 +20,6 @@ import OptionList from './OptionList.vue';
|
|||||||
import PatchList from './PatchList.vue';
|
import PatchList from './PatchList.vue';
|
||||||
import ProfileList from './ProfileList.vue';
|
import ProfileList from './ProfileList.vue';
|
||||||
import StartButton from './StartButton.vue';
|
import StartButton from './StartButton.vue';
|
||||||
import { invoke } from '../invoke';
|
|
||||||
import {
|
import {
|
||||||
useClientStore,
|
useClientStore,
|
||||||
useGeneralStore,
|
useGeneralStore,
|
||||||
@ -36,10 +35,10 @@ const prf = usePrfStore();
|
|||||||
const general = useGeneralStore();
|
const general = useGeneralStore();
|
||||||
const client = useClientStore();
|
const client = useClientStore();
|
||||||
|
|
||||||
|
client.load();
|
||||||
|
|
||||||
pkg.setupListeners();
|
pkg.setupListeners();
|
||||||
|
|
||||||
const currentTab: Ref<'users' | 'loc' | 'patches' | 'rmt' | 'cfg' | 'info'> =
|
|
||||||
ref('users');
|
|
||||||
const pkgSearchTerm = ref('');
|
const pkgSearchTerm = ref('');
|
||||||
|
|
||||||
const isProfileDisabled = computed(() => prf.current === null);
|
const isProfileDisabled = computed(() => prf.current === null);
|
||||||
@ -60,7 +59,6 @@ onMounted(async () => {
|
|||||||
await Promise.all([prf.reloadList(), prf.reload()]);
|
await Promise.all([prf.reloadList(), prf.reload()]);
|
||||||
|
|
||||||
if (prf.current !== null) {
|
if (prf.current !== null) {
|
||||||
currentTab.value = 'loc';
|
|
||||||
await pkg.reloadAll();
|
await pkg.reloadAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,10 +203,11 @@ listen<DownloadingStatus>('download-progress', (event) => {
|
|||||||
|
|
||||||
<Tabs
|
<Tabs
|
||||||
lazy
|
lazy
|
||||||
:value="currentTab"
|
:value="client.currentTab"
|
||||||
v-on:update:value="
|
v-on:update:value="
|
||||||
(value) => {
|
(value) => {
|
||||||
currentTab = value as any;
|
client.currentTab = value as string;
|
||||||
|
client.save();
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
class="h-screen"
|
class="h-screen"
|
||||||
@ -216,6 +215,13 @@ listen<DownloadingStatus>('download-progress', (event) => {
|
|||||||
<div class="fixed w-full flex z-100">
|
<div class="fixed w-full flex z-100">
|
||||||
<TabList class="grow" :show-navigators="false">
|
<TabList class="grow" :show-navigators="false">
|
||||||
<Tab value="users"><div class="pi pi-home"></div></Tab>
|
<Tab value="users"><div class="pi pi-home"></div></Tab>
|
||||||
|
<Tab
|
||||||
|
:disabled="
|
||||||
|
isProfileDisabled || pkg.networkStatus !== 'online'
|
||||||
|
"
|
||||||
|
value="rmt"
|
||||||
|
><div class="pi pi-download"></div
|
||||||
|
></Tab>
|
||||||
<Tab :disabled="isProfileDisabled" value="loc"
|
<Tab :disabled="isProfileDisabled" value="loc"
|
||||||
><div class="pi pi-box"></div
|
><div class="pi pi-box"></div
|
||||||
></Tab>
|
></Tab>
|
||||||
@ -224,13 +230,7 @@ listen<DownloadingStatus>('download-progress', (event) => {
|
|||||||
value="patches"
|
value="patches"
|
||||||
><div class="pi pi-ticket"></div
|
><div class="pi pi-ticket"></div
|
||||||
></Tab>
|
></Tab>
|
||||||
<Tab
|
|
||||||
:disabled="
|
|
||||||
isProfileDisabled || pkg.networkStatus !== 'online'
|
|
||||||
"
|
|
||||||
value="rmt"
|
|
||||||
><div class="pi pi-download"></div
|
|
||||||
></Tab>
|
|
||||||
<Tab :disabled="isProfileDisabled" value="cfg"
|
<Tab :disabled="isProfileDisabled" value="cfg"
|
||||||
><div class="pi pi-cog"></div
|
><div class="pi pi-cog"></div
|
||||||
></Tab>
|
></Tab>
|
||||||
@ -243,13 +243,17 @@ listen<DownloadingStatus>('download-progress', (event) => {
|
|||||||
<div class="flex gap-4">
|
<div class="flex gap-4">
|
||||||
<div
|
<div
|
||||||
class="flex"
|
class="flex"
|
||||||
v-if="['loc', 'rmt', 'cfg'].includes(currentTab)"
|
v-if="
|
||||||
|
['loc', 'rmt', 'cfg'].includes(
|
||||||
|
client.currentTab
|
||||||
|
)
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<InputIcon class="self-center mr-2">
|
<InputIcon class="self-center mr-2">
|
||||||
<i class="pi pi-search" />
|
<i class="pi pi-search" />
|
||||||
</InputIcon>
|
</InputIcon>
|
||||||
<InputText
|
<InputText
|
||||||
v-if="currentTab === 'cfg'"
|
v-if="client.currentTab === 'cfg'"
|
||||||
style="min-width: 0; width: 25dvw"
|
style="min-width: 0; width: 25dvw"
|
||||||
class="self-center"
|
class="self-center"
|
||||||
size="small"
|
size="small"
|
||||||
@ -342,7 +346,12 @@ listen<DownloadingStatus>('download-progress', (event) => {
|
|||||||
<InfoPage />
|
<InfoPage />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
</TabPanels>
|
</TabPanels>
|
||||||
<div v-if="currentTab === 'users' || currentTab === 'info'">
|
<div
|
||||||
|
v-if="
|
||||||
|
client.currentTab === 'users' ||
|
||||||
|
client.currentTab === 'info'
|
||||||
|
"
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
v-if="prf.current?.meta.game === 'ongeki'"
|
v-if="prf.current?.meta.game === 'ongeki'"
|
||||||
src="/sticker-ongeki.svg"
|
src="/sticker-ongeki.svg"
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Ref, ref } from 'vue';
|
import { Ref, ref } from 'vue';
|
||||||
|
// import Select from 'primevue/select';
|
||||||
import * as path from '@tauri-apps/api/path';
|
import * as path from '@tauri-apps/api/path';
|
||||||
import OptionCategory from './OptionCategory.vue';
|
import OptionCategory from './OptionCategory.vue';
|
||||||
import PatchEntry from './PatchEntry.vue';
|
import PatchEntry from './PatchEntry.vue';
|
||||||
@ -32,8 +33,6 @@ invoke('list_patches', { target: prf.current!.data.sgt.target }).then(
|
|||||||
target: amd,
|
target: amd,
|
||||||
})) as Patch[];
|
})) as Patch[];
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const errorMessage = t('patch.noneFound');
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -49,7 +48,7 @@ const errorMessage = t('patch.noneFound');
|
|||||||
/>
|
/>
|
||||||
<div v-if="gamePatches === null">{{ t('patch.loading') }}</div>
|
<div v-if="gamePatches === null">{{ t('patch.loading') }}</div>
|
||||||
<div v-if="gamePatches !== null && gamePatches.length === 0">
|
<div v-if="gamePatches !== null && gamePatches.length === 0">
|
||||||
{{ errorMessage }}
|
{{ t('patch.noneFound') }}
|
||||||
</div>
|
</div>
|
||||||
</OptionCategory>
|
</OptionCategory>
|
||||||
<OptionCategory title="amdaemon.exe" always-found>
|
<OptionCategory title="amdaemon.exe" always-found>
|
||||||
@ -60,7 +59,20 @@ const errorMessage = t('patch.noneFound');
|
|||||||
/>
|
/>
|
||||||
<div v-if="gamePatches === null">Loading...</div>
|
<div v-if="gamePatches === null">Loading...</div>
|
||||||
<div v-if="amdPatches !== null && amdPatches.length === 0">
|
<div v-if="amdPatches !== null && amdPatches.length === 0">
|
||||||
{{ errorMessage }}
|
{{ t('patch.noneFound') }}
|
||||||
|
<!-- <br />
|
||||||
|
<Select
|
||||||
|
class="mt-3"
|
||||||
|
style="width: 400px"
|
||||||
|
:options="[
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
]"
|
||||||
|
:placeholder="t('patch.forceLoad')"
|
||||||
|
size="small"
|
||||||
|
option-label="title"
|
||||||
|
option-value="value"
|
||||||
|
></Select> -->
|
||||||
</div>
|
</div>
|
||||||
</OptionCategory>
|
</OptionCategory>
|
||||||
</template>
|
</template>
|
||||||
|
@ -73,10 +73,12 @@ const promptDeleteProfile = async () => {
|
|||||||
|
|
||||||
const dataExists = ref(false);
|
const dataExists = ref(false);
|
||||||
|
|
||||||
path.join(general.dataDir, `profile-${props.p!.game}-${props.p!.name}`).then(
|
general.dataDir.then((dataDir) =>
|
||||||
async (p) => {
|
path
|
||||||
dataExists.value = await invoke('file_exists', { path: p });
|
.join(dataDir, `profile-${props.p!.game}-${props.p!.name}`)
|
||||||
}
|
.then(async (p) => {
|
||||||
|
dataExists.value = await invoke('file_exists', { path: p });
|
||||||
|
})
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -145,11 +147,15 @@ path.join(general.dataDir, `profile-${props.p!.game}-${props.p!.name}`).then(
|
|||||||
class="self-center"
|
class="self-center"
|
||||||
style="width: 2rem; height: 2rem"
|
style="width: 2rem; height: 2rem"
|
||||||
@click="
|
@click="
|
||||||
path
|
async () =>
|
||||||
.join(general.configDir, `profile-${p!.game}-${p!.name}`)
|
path
|
||||||
.then(async (path) => {
|
.join(
|
||||||
await invoke('open_file', { path });
|
await general.configDir,
|
||||||
})
|
`profile-${p!.game}-${p!.name}`
|
||||||
|
)
|
||||||
|
.then(async (path) => {
|
||||||
|
await invoke('open_file', { path });
|
||||||
|
})
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
@ -162,11 +168,15 @@ path.join(general.dataDir, `profile-${props.p!.game}-${props.p!.name}`).then(
|
|||||||
class="self-center"
|
class="self-center"
|
||||||
style="width: 2rem; height: 2rem"
|
style="width: 2rem; height: 2rem"
|
||||||
@click="
|
@click="
|
||||||
path
|
async () =>
|
||||||
.join(general.dataDir, `profile-${p!.game}-${p!.name}`)
|
path
|
||||||
.then(async (path) => {
|
.join(
|
||||||
await invoke('open_file', { path });
|
await general.dataDir,
|
||||||
})
|
`profile-${p!.game}-${p!.name}`
|
||||||
|
)
|
||||||
|
.then(async (path) => {
|
||||||
|
await invoke('open_file', { path });
|
||||||
|
})
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -194,9 +194,7 @@ const tryStart = () => {
|
|||||||
}
|
}
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<Lazy>
|
<ContextMenu ref="menu" :model="menuItems" />
|
||||||
<ContextMenu ref="menu" :model="menuItems" />
|
|
||||||
</Lazy>
|
|
||||||
<Button
|
<Button
|
||||||
v-if="startStatus === 'ready'"
|
v-if="startStatus === 'ready'"
|
||||||
v-tooltip="disabledTooltip"
|
v-tooltip="disabledTooltip"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Ref, computed, onMounted, ref } from 'vue';
|
import { Ref, computed, ref } from 'vue';
|
||||||
import InputNumber from 'primevue/inputnumber';
|
import InputNumber from 'primevue/inputnumber';
|
||||||
import Select from 'primevue/select';
|
import Select from 'primevue/select';
|
||||||
import SelectButton from 'primevue/selectbutton';
|
import SelectButton from 'primevue/selectbutton';
|
||||||
|
@ -51,6 +51,7 @@ export default {
|
|||||||
loading: 'Loading...',
|
loading: 'Loading...',
|
||||||
noneFound:
|
noneFound:
|
||||||
"No compatible patches found. Make sure you're using unpacked and unpatched files.",
|
"No compatible patches found. Make sure you're using unpacked and unpatched files.",
|
||||||
|
forceLoad: 'Force load',
|
||||||
// Example patch name override
|
// Example patch name override
|
||||||
'standard-no-encryption': 'No encryption',
|
'standard-no-encryption': 'No encryption',
|
||||||
},
|
},
|
||||||
|
@ -322,7 +322,7 @@ export const usePrfStore = defineStore('prf', () => {
|
|||||||
const generalStore = useGeneralStore();
|
const generalStore = useGeneralStore();
|
||||||
|
|
||||||
const configDir = computed(async () => {
|
const configDir = computed(async () => {
|
||||||
return await path.join(
|
return path.join(
|
||||||
await generalStore.configDir,
|
await generalStore.configDir,
|
||||||
`profile-${current.value?.meta.game}-${current.value?.meta.name}`
|
`profile-${current.value?.meta.game}-${current.value?.meta.name}`
|
||||||
);
|
);
|
||||||
@ -374,6 +374,7 @@ export const useClientStore = defineStore('client', () => {
|
|||||||
const theme: Ref<'light' | 'dark' | 'system'> = ref('system');
|
const theme: Ref<'light' | 'dark' | 'system'> = ref('system');
|
||||||
const onboarded: Ref<Game[]> = ref([]);
|
const onboarded: Ref<Game[]> = ref([]);
|
||||||
const locale: Ref<Locale> = ref('en');
|
const locale: Ref<Locale> = ref('en');
|
||||||
|
const currentTab: Ref<string> = ref('');
|
||||||
|
|
||||||
const _scaleValue = (value: ScaleType) =>
|
const _scaleValue = (value: ScaleType) =>
|
||||||
value === 's' ? 1 : value === 'm' ? 1.25 : value === 'l' ? 1.5 : 2;
|
value === 's' ? 1 : value === 'm' ? 1.25 : value === 'l' ? 1.5 : 2;
|
||||||
@ -440,6 +441,10 @@ export const useClientStore = defineStore('client', () => {
|
|||||||
if (input.locale) {
|
if (input.locale) {
|
||||||
locale.value = input.locale;
|
locale.value = input.locale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (input.currentTab) {
|
||||||
|
currentTab.value = input.currentTab;
|
||||||
|
}
|
||||||
await setLocale(locale.value);
|
await setLocale(locale.value);
|
||||||
await setTheme(theme.value);
|
await setTheme(theme.value);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -478,6 +483,7 @@ export const useClientStore = defineStore('client', () => {
|
|||||||
theme: theme.value,
|
theme: theme.value,
|
||||||
onboarded: onboarded.value,
|
onboarded: onboarded.value,
|
||||||
locale: locale.value,
|
locale: locale.value,
|
||||||
|
currentTab: currentTab.value,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -553,6 +559,7 @@ export const useClientStore = defineStore('client', () => {
|
|||||||
locale,
|
locale,
|
||||||
timeout,
|
timeout,
|
||||||
scaleModel,
|
scaleModel,
|
||||||
|
currentTab,
|
||||||
_scaleValue,
|
_scaleValue,
|
||||||
scaleValue,
|
scaleValue,
|
||||||
load,
|
load,
|
||||||
|
Reference in New Issue
Block a user