Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/app-frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ const {
searchModpacks,
getProjectVersions,
getLoaderManifest,
showCreationModal,
setModpackAlreadyInstalledModal,
handleModpackDuplicateCreateAnyway,
handleModpackDuplicateGoToInstance,
Expand Down Expand Up @@ -1462,7 +1463,7 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
</suspense>
<NavButton
v-tooltip.right="'Create new instance'"
:to="() => installationModal?.show()"
:to="showCreationModal"
:disabled="offline"
>
<PlusIcon />
Expand Down
8 changes: 4 additions & 4 deletions apps/app-frontend/src/helpers/metadata.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { invoke } from '@tauri-apps/api/core'

/// Gets the game versions from daedalus
// Returns a VersionManifest
export async function get_game_versions() {
return await invoke('plugin:metadata|metadata_get_game_versions')
export async function get_game_versions(cacheBehaviour) {
return await invoke('plugin:metadata|metadata_get_game_versions', { cacheBehaviour })
}

// Gets the given loader versions from daedalus
// Returns Manifest
export async function get_loader_versions(loader) {
return await invoke('plugin:metadata|metadata_get_loader_versions', { loader })
export async function get_loader_versions(loader, cacheBehaviour) {
return await invoke('plugin:metadata|metadata_get_loader_versions', { loader, cacheBehaviour })
}
4 changes: 2 additions & 2 deletions apps/app-frontend/src/helpers/tags.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ export async function get_loaders() {
}

// Gets cached game_versions tags
export async function get_game_versions() {
return await invoke('plugin:tags|tags_get_game_versions')
export async function get_game_versions(cacheBehaviour) {
return await invoke('plugin:tags|tags_get_game_versions', { cacheBehaviour })
}

// Gets cached donation_platforms tags
Expand Down
4 changes: 2 additions & 2 deletions apps/app-frontend/src/providers/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ export function setupProviders(
notificationManager: AbstractWebNotificationManager,
_popupNotificationManager: AbstractPopupNotificationManager,
) {
setupTagsProvider(notificationManager)
const { loadGameVersions } = setupTagsProvider(notificationManager)
setupFileDropProvider()
setupFilePickerProvider()
setupInstanceImportProvider(notificationManager)

return {
...setupCreationModal(notificationManager),
...setupCreationModal(notificationManager, loadGameVersions),
}
}
19 changes: 14 additions & 5 deletions apps/app-frontend/src/providers/setup/creation-modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,13 @@ import {
} from '@/helpers/install'
import { list } from '@/helpers/instance'
import { get_loader_versions as getLoaderManifest } from '@/helpers/metadata.js'
import type { InstanceLoader } from '@/helpers/types'
import type { CacheBehaviour, InstanceLoader } from '@/helpers/types'
import { useTheming } from '@/store/state'

export function setupCreationModal(notificationManager: AbstractWebNotificationManager) {
export function setupCreationModal(
notificationManager: AbstractWebNotificationManager,
loadGameVersions?: (cacheBehaviour?: CacheBehaviour) => Promise<void>,
) {
const { handleError } = notificationManager
const router = useRouter()
const themeStore = useTheming()
Expand All @@ -45,9 +48,14 @@ export function setupCreationModal(notificationManager: AbstractWebNotificationM
return instances?.map((i) => i.name) ?? []
}

provide('showCreationModal', () => {
installationModal.value?.show()
})
async function showCreationModal() {
await installationModal.value?.show()
// bypass cache to get up to date versions
void loadGameVersions?.('bypass').catch(handleError)
void installationModal.value?.ctx.prefetchLoaderMetadata(true)
}

provide('showCreationModal', showCreationModal)

async function proceedWithModpackCreation(
projectId: string,
Expand Down Expand Up @@ -204,6 +212,7 @@ export function setupCreationModal(notificationManager: AbstractWebNotificationM
searchModpacks,
getProjectVersions,
getLoaderManifest,
showCreationModal,
setModpackAlreadyInstalledModal,
handleModpackDuplicateCreateAnyway,
handleModpackDuplicateGoToInstance,
Expand Down
22 changes: 16 additions & 6 deletions apps/app-frontend/src/providers/setup/tags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,32 @@ import { provideTags } from '@modrinth/ui'
import { ref } from 'vue'

import { get_game_versions, get_loaders } from '@/helpers/tags'
import type { CacheBehaviour } from '@/helpers/types'

export function setupTagsProvider(notificationManager: AbstractWebNotificationManager) {
const { handleError } = notificationManager

const gameVersions = ref([])
const loaders = ref([])
get_game_versions()
.then((v) => {
gameVersions.value = v
})
.catch(handleError)
get_loaders()

async function loadGameVersions(cacheBehaviour?: CacheBehaviour) {
const versions = await get_game_versions(cacheBehaviour)
if (versions) {
gameVersions.value = versions
}
}

// load game versions from cache
void loadGameVersions().catch(handleError)
void get_loaders()
.then((v) => {
loaders.value = v
})
.catch(handleError)

provideTags({ gameVersions, loaders })

return {
loadGameVersions,
}
}
14 changes: 10 additions & 4 deletions apps/app/src/api/metadata.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::api::Result;
use daedalus::minecraft::VersionManifest;
use daedalus::modded::Manifest;
use theseus::prelude::CacheBehaviour;

pub fn init<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {
tauri::plugin::Builder::new("metadata")
Expand All @@ -13,12 +14,17 @@ pub fn init<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {

/// Gets the game versions from daedalus
#[tauri::command]
pub async fn metadata_get_game_versions() -> Result<VersionManifest> {
Ok(theseus::metadata::get_minecraft_versions().await?)
pub async fn metadata_get_game_versions(
cache_behaviour: Option<CacheBehaviour>,
) -> Result<VersionManifest> {
Ok(theseus::metadata::get_minecraft_versions(cache_behaviour).await?)
}

/// Gets the fabric versions from daedalus
#[tauri::command]
pub async fn metadata_get_loader_versions(loader: &str) -> Result<Manifest> {
Ok(theseus::metadata::get_loader_versions(loader).await?)
pub async fn metadata_get_loader_versions(
loader: &str,
cache_behaviour: Option<CacheBehaviour>,
) -> Result<Manifest> {
Ok(theseus::metadata::get_loader_versions(loader, cache_behaviour).await?)
}
7 changes: 5 additions & 2 deletions apps/app/src/api/tags.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::api::Result;
use theseus::prelude::CacheBehaviour;
use theseus::tags::{Category, DonationPlatform, GameVersion, Loader};

pub fn init<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {
Expand Down Expand Up @@ -33,8 +34,10 @@ pub async fn tags_get_loaders() -> Result<Vec<Loader>> {

/// Gets cached game version tags from the database
#[tauri::command]
pub async fn tags_get_game_versions() -> Result<Vec<GameVersion>> {
Ok(theseus::tags::get_game_version_tags().await?)
pub async fn tags_get_game_versions(
cache_behaviour: Option<CacheBehaviour>,
) -> Result<Vec<GameVersion>> {
Ok(theseus::tags::get_game_version_tags(cache_behaviour).await?)
}

/// Gets cached donation platform tags from the database
Expand Down
15 changes: 10 additions & 5 deletions packages/app-lib/src/api/metadata.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use crate::State;
use crate::state::CachedEntry;
use crate::state::{CacheBehaviour, CachedEntry};
pub use daedalus::minecraft::VersionManifest;
pub use daedalus::modded::Manifest;

#[tracing::instrument]
pub async fn get_minecraft_versions() -> crate::Result<VersionManifest> {
pub async fn get_minecraft_versions(
cache_behaviour: Option<CacheBehaviour>,
) -> crate::Result<VersionManifest> {
let state = State::get().await?;
let minecraft_versions = CachedEntry::get_minecraft_manifest(
None,
cache_behaviour,
&state.pool,
&state.api_semaphore,
)
Expand All @@ -20,11 +22,14 @@ pub async fn get_minecraft_versions() -> crate::Result<VersionManifest> {
}

// #[tracing::instrument]
pub async fn get_loader_versions(loader: &str) -> crate::Result<Manifest> {
pub async fn get_loader_versions(
loader: &str,
cache_behaviour: Option<CacheBehaviour>,
) -> crate::Result<Manifest> {
let state = State::get().await?;
let loaders = CachedEntry::get_loader_manifest(
loader,
None,
cache_behaviour,
&state.pool,
&state.api_semaphore,
)
Expand Down
21 changes: 13 additions & 8 deletions packages/app-lib/src/api/tags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use crate::state::CachedEntry;
pub use crate::{
State,
state::{Category, DonationPlatform, GameVersion, Loader},
state::{CacheBehaviour, Category, DonationPlatform, GameVersion, Loader},
};

/// Get category tags
Expand Down Expand Up @@ -49,14 +49,19 @@ pub async fn get_loader_tags() -> crate::Result<Vec<Loader>> {

/// Get game version tags
#[tracing::instrument]
pub async fn get_game_version_tags() -> crate::Result<Vec<GameVersion>> {
pub async fn get_game_version_tags(
cache_behaviour: Option<CacheBehaviour>,
) -> crate::Result<Vec<GameVersion>> {
let state = State::get().await?;
let game_versions =
CachedEntry::get_game_versions(None, &state.pool, &state.api_semaphore)
.await?
.ok_or_else(|| {
crate::ErrorKind::NoValueFor("game version tags".to_string())
})?;
let game_versions = CachedEntry::get_game_versions(
cache_behaviour,
&state.pool,
&state.api_semaphore,
)
.await?
.ok_or_else(|| {
crate::ErrorKind::NoValueFor("game version tags".to_string())
})?;

Ok(game_versions)
}
Expand Down
5 changes: 3 additions & 2 deletions packages/app-lib/src/launcher/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,8 @@ pub async fn get_loader_version_from_profile(
};

let versions =
crate::api::metadata::get_loader_versions(loader.as_meta_str()).await?;
crate::api::metadata::get_loader_versions(loader.as_meta_str(), None)
.await?;

let loaders = versions.game_versions.into_iter().find(|x| {
x.id.replace(daedalus::modded::DUMMY_REPLACE_STRING, game_version)
Expand Down Expand Up @@ -202,7 +203,7 @@ pub async fn resolve_minecraft_manifest(
game_version: &str,
state: &State,
) -> crate::Result<(d::minecraft::VersionManifest, usize)> {
let minecraft = crate::api::metadata::get_minecraft_versions().await?;
let minecraft = crate::api::metadata::get_minecraft_versions(None).await?;

if let Some(idx) = minecraft
.versions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,17 @@ export type Gamemode = 'survival' | 'creative' | 'hardcore'
export type Difficulty = 'peaceful' | 'easy' | 'normal' | 'hard'
export type LoaderVersionType = 'stable' | 'latest' | 'other'
export type GeneratorSettingsMode = 'default' | 'flat' | 'custom'
export type LoaderManifestResolver = (loader: string) => Promise<LauncherMeta.Manifest.v0.Manifest>
export type LoaderManifestResolver = (
loader: string,
cacheBehaviour?: 'bypass',
) => Promise<LauncherMeta.Manifest.v0.Manifest>
export interface LoaderVersionEntry {
id: string
stable: boolean
}

const loaderManifestQueryKey = (loader: string) =>
['creation-flow', 'loader-manifest', loader] as const
const loaderManifestQueryKey = (loader: string, bypassCache = false) =>
['creation-flow', 'loader-manifest', loader, bypassCache ? 'bypass' : 'cached'] as const
const paperSupportedVersionsQueryKey = ['creation-flow', 'paper', 'supported-versions'] as const
const purpurSupportedVersionsQueryKey = ['creation-flow', 'purpur', 'supported-versions'] as const

Expand Down Expand Up @@ -207,8 +210,8 @@ export interface CreationFlowContextValue {
browseModpacks: () => void
finish: () => void
buildProperties: () => Archon.Content.v1.PropertiesFields
fetchLoaderMetadata: (loader?: string | null) => Promise<void>
prefetchLoaderMetadata: () => Promise<void>
fetchLoaderMetadata: (loader?: string | null, bypassCache?: boolean) => Promise<void>
prefetchLoaderMetadata: (bypassCache?: boolean) => Promise<void>

// Platform-provided search
searchModpacks: (query: string, limit?: number) => Promise<ModpackSearchResult>
Expand Down Expand Up @@ -352,23 +355,28 @@ export function createCreationFlowContext(
return loader === 'neoforge' ? 'neo' : loader
}

async function fetchLoaderManifest(loader: string) {
async function fetchLoaderManifest(loader: string, bypassCache = false) {
const apiLoader = toApiLoaderName(loader)
if (loaderVersionsCache.value[apiLoader]) return
if (!bypassCache && loaderVersionsCache.value[apiLoader]) return

try {
const data = await queryClient.fetchQuery({
queryKey: loaderManifestQueryKey(apiLoader),
queryKey: loaderManifestQueryKey(apiLoader, bypassCache),
queryFn: async () =>
(await getLoaderManifest?.(apiLoader)) ??
(await getLoaderManifest?.(apiLoader, bypassCache ? 'bypass' : undefined)) ??
(await client.launchermeta.manifest_v0.getManifest(apiLoader)),
staleTime: Infinity,
staleTime: bypassCache ? 0 : Infinity,
})
if (bypassCache) {
queryClient.setQueryData(loaderManifestQueryKey(apiLoader), data)
}
loaderVersionsCache.value[apiLoader] = data.gameVersions
debug('fetchLoaderManifest: loaded', apiLoader, 'gameVersions:', data.gameVersions.length)
} catch (error) {
debug('fetchLoaderManifest: failed', apiLoader, error)
loaderVersionsCache.value[apiLoader] = []
if (!loaderVersionsCache.value[apiLoader]) {
loaderVersionsCache.value[apiLoader] = []
}
}
}

Expand Down Expand Up @@ -404,7 +412,7 @@ export function createCreationFlowContext(
}
}

async function fetchLoaderMetadata(loader?: string | null) {
async function fetchLoaderMetadata(loader?: string | null, bypassCache = false) {
if (!loader || loader === 'vanilla') return
if (loader === 'paper') {
await fetchPaperSupportedVersions()
Expand All @@ -414,14 +422,14 @@ export function createCreationFlowContext(
await fetchPurpurSupportedVersions()
return
}
await fetchLoaderManifest(loader)
await fetchLoaderManifest(loader, bypassCache)
}

async function prefetchLoaderMetadata() {
async function prefetchLoaderMetadata(bypassCache = false) {
await Promise.allSettled(
availableLoaders
.filter((loader) => loader !== 'vanilla')
.map((loader) => fetchLoaderMetadata(loader)),
.map((loader) => fetchLoaderMetadata(loader, bypassCache)),
)
}

Expand Down
Loading