feat: instances v2 (#6431)

* feat: base of instances v2

* feat: use old profiles with compat layer

* prototype: instances v2

* fix: install_from using profile

* fix: skins migration fix

* fix: frontend still using profile path

* fix: add update proj multiselect guard

* fix: cargo fmt

* fix: content missing fields

* feat: break up app-lib/api/instance.rs

* fix: check_content_updates mismatch

* fix: updater modal cleanup w/new structure

* feat: better update all handling

* fix: remove preview_update_all

* fix: feedback on bulk update + lint

* fix: rem transitions

* fix: change to jsonb

* feat: app db backup after update

* fix: lint

* fix: sqlx prepare + use sqlx macros

* fix: lint

* fix: bugs

* feat: defuck the installing process up

* fix: bug of hell

* fix: shear

* fix: fmt

* fix: install progress spacing + change mc/content/overrides to bytes

* fix: lint

* fix: prepr

* fix: navtabs anim not working in app

* fix: worlds.vue improvements + browse page fixes

* feat: optimise queries + adapter fns

* fix: lint

* fix: lint

* feat: shared modrinth-content-management crate (#6469)

* feat: disable warnings setting

* feat: add instances shortcuts (#6329)

* Add modrinth://launch deep link to start a profile

Support external profile launching via modrinth://launch/{profile_path} for integrations such as Stream Deck.

* Change route to /launch/profile/{id} for future extensibility

* fix: ensure profile path is url decoded

* fix: URL-decode profile path from deep link

* fix: use urlencoding crate for URL decoding

* feat: implement app instance shortcuts

* feat: change windows shortcut creation to use windows api instead

* feat: implement creating a shortcut launching world/server

* format

* fmt

* fix multiline inline tables

* pnpm prepr

* feat: move create shortcut to last item

* refactor: split up shortcuts.rs for individual platforms

* refactor: turn profile launch url into url type

* use string literal and add safety comment

* pt2

* refactor: rename anything that's profile into instance

* update mac shortcut

---------

Co-authored-by: DJCheesusReal <134006619+DJCheesusReal@users.noreply.github.com>

---------

Co-authored-by: Truman Gao <106889354+tdgao@users.noreply.github.com>
Co-authored-by: DJCheesusReal <134006619+DJCheesusReal@users.noreply.github.com>
This commit is contained in:
Calum H.
2026-06-25 21:19:29 +00:00
committed by GitHub
co-authored by DJCheesusReal Truman Gao
parent ef4044534f
commit 734720e11e
353 changed files with 24745 additions and 9771 deletions
@@ -22,8 +22,8 @@ interface InstanceConsoleEntry {
const instances = new Map<string, InstanceConsoleEntry>()
function getOrCreate(profilePathId: string): InstanceConsoleEntry {
let entry = instances.get(profilePathId)
function getOrCreate(instanceId: string): InstanceConsoleEntry {
let entry = instances.get(instanceId)
if (entry) return entry
entry = {
@@ -32,25 +32,25 @@ function getOrCreate(profilePathId: string): InstanceConsoleEntry {
historicalCache: new Map(),
logList: null,
}
instances.set(profilePathId, entry)
instances.set(instanceId, entry)
return entry
}
async function hydrate(profilePathId: string): Promise<void> {
const entry = getOrCreate(profilePathId)
async function hydrate(instanceId: string): Promise<void> {
const entry = getOrCreate(instanceId)
if (entry.liveConsole.output.value.length > 0) return
const buffer = await get_live_log_buffer(profilePathId)
const buffer = await get_live_log_buffer(instanceId)
if (buffer) {
entry.liveConsole.addLegacyLog(buffer)
}
}
async function getHistoricalLogs(profilePathId: string, instancePath: string): Promise<LogEntry[]> {
const entry = getOrCreate(profilePathId)
async function getHistoricalLogs(instanceId: string): Promise<LogEntry[]> {
const entry = getOrCreate(instanceId)
if (entry.logList) return entry.logList
const logs: LogEntry[] = await get_logs(instancePath, true)
const logs: LogEntry[] = await get_logs(instanceId, true)
entry.logList = logs
for (const log of logs) {
@@ -62,38 +62,38 @@ async function getHistoricalLogs(profilePathId: string, instancePath: string): P
return logs
}
function getHistoricalContent(profilePathId: string, filename: string): string | undefined {
return instances.get(profilePathId)?.historicalCache.get(filename)
function getHistoricalContent(instanceId: string, filename: string): string | undefined {
return instances.get(instanceId)?.historicalCache.get(filename)
}
function invalidate(profilePathId: string): void {
const entry = instances.get(profilePathId)
function invalidate(instanceId: string): void {
const entry = instances.get(instanceId)
if (!entry) return
entry.historicalCache.clear()
entry.logList = null
}
async function clearLive(profilePathId: string): Promise<void> {
const entry = getOrCreate(profilePathId)
async function clearLive(instanceId: string): Promise<void> {
const entry = getOrCreate(instanceId)
entry.liveConsole.clear()
await clear_log_buffer(profilePathId).catch(() => {})
await clear_log_buffer(instanceId).catch(() => {})
}
async function destroy(profilePathId: string): Promise<void> {
instances.delete(profilePathId)
await clear_log_buffer(profilePathId).catch(() => {})
async function destroy(instanceId: string): Promise<void> {
instances.delete(instanceId)
await clear_log_buffer(instanceId).catch(() => {})
}
export function useInstanceConsole(profilePathId: string) {
const entry = getOrCreate(profilePathId)
export function useInstanceConsole(instanceId: string) {
const entry = getOrCreate(instanceId)
return {
liveConsole: entry.liveConsole,
historicalConsole: entry.historicalConsole,
hydrate: () => hydrate(profilePathId),
getHistoricalLogs: (instancePath: string) => getHistoricalLogs(profilePathId, instancePath),
getHistoricalContent: (filename: string) => getHistoricalContent(profilePathId, filename),
invalidate: () => invalidate(profilePathId),
clearLive: () => clearLive(profilePathId),
destroy: () => destroy(profilePathId),
hydrate: () => hydrate(instanceId),
getHistoricalLogs: () => getHistoricalLogs(instanceId),
getHistoricalContent: (filename: string) => getHistoricalContent(instanceId, filename),
invalidate: () => invalidate(instanceId),
clearLive: () => clearLive(instanceId),
destroy: () => destroy(instanceId),
}
}