Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
98396c6bcd | ||
|
|
403a883e0b | ||
|
|
53c749aaea | ||
|
|
addc31c7c1 | ||
|
|
25978bcd8f | ||
|
|
117eaad9ff | ||
|
|
ae2992d7f8 |
No files matched your search
@@ -22,5 +22,5 @@ jobs:
|
|||||||
node-version-file: .nvmrc
|
node-version-file: .nvmrc
|
||||||
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
|
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
|
||||||
- uses: cargo-bins/cargo-binstall@dc19f1e48450eefe5a29b8da6c6b00a87d730b37 # v1.18.1
|
- uses: cargo-bins/cargo-binstall@dc19f1e48450eefe5a29b8da6c6b00a87d730b37 # v1.18.1
|
||||||
- run: cargo binstall --no-confirm cargo-shear
|
- run: cargo binstall --no-confirm cargo-shear@1.13.4
|
||||||
- run: cargo shear
|
- run: cargo shear
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { CheckIcon, RotateCounterClockwiseIcon, XIcon } from '@modrinth/assets'
|
||||||
|
import {
|
||||||
|
type ArmorPreviewConfig,
|
||||||
|
ArmorTrimPanel,
|
||||||
|
Button,
|
||||||
|
defineMessages,
|
||||||
|
useVIntl,
|
||||||
|
} from '@modrinth/ui'
|
||||||
|
import { computed, onMounted, onUnmounted } from 'vue'
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
title: { id: 'app.skins.armor.title', defaultMessage: 'Armour and trims' },
|
||||||
|
description: {
|
||||||
|
id: 'app.skins.armor.description',
|
||||||
|
defaultMessage: 'Try armour and trims on your skin. Nothing is stored until you save it.',
|
||||||
|
},
|
||||||
|
unsaved: { id: 'app.skins.armor.unsaved', defaultMessage: 'Unsaved changes' },
|
||||||
|
resetToSaved: { id: 'app.skins.armor.reset-to-saved', defaultMessage: 'Reset to saved' },
|
||||||
|
restoreDefaults: {
|
||||||
|
id: 'app.skins.armor.restore-defaults',
|
||||||
|
defaultMessage: 'Restore defaults',
|
||||||
|
},
|
||||||
|
save: { id: 'app.skins.armor.save', defaultMessage: 'Save' },
|
||||||
|
close: { id: 'app.skins.armor.close', defaultMessage: 'Close' },
|
||||||
|
})
|
||||||
|
|
||||||
|
const draft = defineModel<ArmorPreviewConfig>({ required: true })
|
||||||
|
const props = defineProps<{
|
||||||
|
saved: ArmorPreviewConfig
|
||||||
|
/** Stable id shared with the toggle so it can point `aria-controls` here. */
|
||||||
|
panelId: string
|
||||||
|
}>()
|
||||||
|
const emit = defineEmits<{
|
||||||
|
save: []
|
||||||
|
reset: []
|
||||||
|
defaults: []
|
||||||
|
close: []
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const { formatMessage } = useVIntl()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tab is mounted only while it is showing, so this listens exactly for that
|
||||||
|
* window. It listens in the capture phase because the app's own global
|
||||||
|
* shortcuts listen on `window` the same way, and a bubble-phase listener here
|
||||||
|
* would be skipped as soon as anything closer stopped the event. A modal on top
|
||||||
|
* of the page owns Escape while it is up, and focus sits inside it, so the key
|
||||||
|
* is left to it.
|
||||||
|
*/
|
||||||
|
function handleKeydown(event: KeyboardEvent) {
|
||||||
|
if (event.key !== 'Escape') return
|
||||||
|
if (
|
||||||
|
event.target instanceof Element &&
|
||||||
|
event.target.closest('[role="dialog"], [role="alertdialog"], [aria-modal="true"]')
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
emit('close')
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => window.addEventListener('keydown', handleKeydown, true))
|
||||||
|
onUnmounted(() => window.removeEventListener('keydown', handleKeydown, true))
|
||||||
|
|
||||||
|
const isDirty = computed(() =>
|
||||||
|
Object.entries(draft.value).some(([slot, piece]) => {
|
||||||
|
const applied = props.saved[slot as keyof ArmorPreviewConfig]
|
||||||
|
return (
|
||||||
|
!applied ||
|
||||||
|
applied.material !== piece.material ||
|
||||||
|
applied.trimPattern !== piece.trimPattern ||
|
||||||
|
applied.trimMaterial !== piece.trimMaterial
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
:id="panelId"
|
||||||
|
role="region"
|
||||||
|
:aria-label="formatMessage(messages.title)"
|
||||||
|
class="flex min-h-[24rem] flex-col gap-4 rounded-2xl border border-solid border-surface-5 bg-surface-2 p-4"
|
||||||
|
>
|
||||||
|
<header class="flex flex-wrap items-start justify-between gap-3">
|
||||||
|
<div class="min-w-0">
|
||||||
|
<h2 class="m-0 text-lg font-bold text-[var(--color-text-primary)]">
|
||||||
|
{{ formatMessage(messages.title) }}
|
||||||
|
</h2>
|
||||||
|
<p class="m-0 mt-1 text-sm leading-6 text-[var(--color-text-tertiary)]">
|
||||||
|
{{ formatMessage(messages.description) }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex shrink-0 flex-wrap items-center gap-2">
|
||||||
|
<span v-if="isDirty" class="text-sm font-semibold text-[var(--color-text-tertiary)]">
|
||||||
|
{{ formatMessage(messages.unsaved) }}
|
||||||
|
</span>
|
||||||
|
<Button type="outlined" @click="emit('close')"
|
||||||
|
><XIcon />{{ formatMessage(messages.close) }}</Button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<ArmorTrimPanel v-model="draft" />
|
||||||
|
|
||||||
|
<footer
|
||||||
|
class="mt-auto flex flex-wrap items-center justify-between gap-2 border-0 border-t border-solid border-surface-5 pt-3"
|
||||||
|
>
|
||||||
|
<div class="flex flex-wrap items-center gap-2">
|
||||||
|
<Button type="outlined" :disabled="!isDirty" @click="emit('reset')"
|
||||||
|
><RotateCounterClockwiseIcon />{{ formatMessage(messages.resetToSaved) }}</Button
|
||||||
|
>
|
||||||
|
<Button type="outlined" @click="emit('defaults')">{{
|
||||||
|
formatMessage(messages.restoreDefaults)
|
||||||
|
}}</Button>
|
||||||
|
</div>
|
||||||
|
<Button type="colored" color="brand" :disabled="!isDirty" @click="emit('save')"
|
||||||
|
><CheckIcon />{{ formatMessage(messages.save) }}</Button
|
||||||
|
>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
const { sections = 2, cards = 12 } = defineProps<{
|
||||||
|
sections?: number
|
||||||
|
cards?: number
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<!--
|
||||||
|
Shaped after VirtualSkinSectionList: the same grid breakpoints and card
|
||||||
|
ratio, so the swap to real content does not move anything. Decorative, so
|
||||||
|
it stays out of the accessibility tree.
|
||||||
|
-->
|
||||||
|
<div class="flex flex-col gap-8" aria-hidden="true">
|
||||||
|
<div v-for="section in sections" :key="section" class="flex flex-col gap-4">
|
||||||
|
<div class="h-7 w-44 animate-pulse rounded-lg bg-surface-4" />
|
||||||
|
<div
|
||||||
|
class="grid w-full grid-cols-3 gap-3 min-[1300px]:grid-cols-4 min-[1750px]:grid-cols-5 min-[2050px]:grid-cols-6"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="card in cards"
|
||||||
|
:key="card"
|
||||||
|
class="aspect-[31/40] w-full animate-pulse rounded-[20px] bg-surface-4"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
import assert from 'node:assert/strict'
|
||||||
|
import test from 'node:test'
|
||||||
|
|
||||||
|
import { loadSkinArmorPreview, saveSkinArmorPreview } from './skin-armor-preview.ts'
|
||||||
|
|
||||||
|
const originalStorage = Object.getOwnPropertyDescriptor(globalThis, 'localStorage')
|
||||||
|
|
||||||
|
function withStorage(run: (values: Map<string, string>) => void): void {
|
||||||
|
const values = new Map<string, string>()
|
||||||
|
Object.defineProperty(globalThis, 'localStorage', {
|
||||||
|
configurable: true,
|
||||||
|
value: {
|
||||||
|
getItem: (key: string) => values.get(key) ?? null,
|
||||||
|
setItem: (key: string, value: string) => values.set(key, value),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
try {
|
||||||
|
run(values)
|
||||||
|
} finally {
|
||||||
|
if (originalStorage) Object.defineProperty(globalThis, 'localStorage', originalStorage)
|
||||||
|
else delete (globalThis as { localStorage?: Storage }).localStorage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test('armor preview selections survive storage round trips', () => {
|
||||||
|
withStorage(() => {
|
||||||
|
const config = loadSkinArmorPreview()
|
||||||
|
config.helmet.material = 'diamond'
|
||||||
|
config.helmet.trimPattern = 'sentry'
|
||||||
|
config.helmet.trimMaterial = 'gold'
|
||||||
|
saveSkinArmorPreview(config)
|
||||||
|
|
||||||
|
assert.deepEqual(loadSkinArmorPreview(), config)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('invalid stored armor values fall back per slot and field', () => {
|
||||||
|
withStorage((values) => {
|
||||||
|
values.set(
|
||||||
|
'axolotl:skin-armor-preview',
|
||||||
|
JSON.stringify({
|
||||||
|
helmet: { material: 'diamond', trimPattern: 'invalid', trimMaterial: 'gold' },
|
||||||
|
boots: { material: 'turtle', trimPattern: 'sentry', trimMaterial: 'invalid' },
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
const config = loadSkinArmorPreview()
|
||||||
|
assert.deepEqual(config.helmet, {
|
||||||
|
material: 'diamond',
|
||||||
|
trimPattern: null,
|
||||||
|
trimMaterial: 'gold',
|
||||||
|
})
|
||||||
|
assert.deepEqual(config.boots, {
|
||||||
|
material: null,
|
||||||
|
trimPattern: 'sentry',
|
||||||
|
trimMaterial: 'iron',
|
||||||
|
})
|
||||||
|
assert.equal(config.chestplate.material, null)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import {
|
||||||
|
ARMOR_SLOTS,
|
||||||
|
ARMOR_TRIM_MATERIALS,
|
||||||
|
ARMOR_TRIM_PATTERNS,
|
||||||
|
armorMaterialsForSlot,
|
||||||
|
type ArmorPreviewConfig,
|
||||||
|
createDefaultArmorPreviewConfig,
|
||||||
|
} from '@modrinth/ui'
|
||||||
|
|
||||||
|
const STORAGE_KEY = 'axolotl:skin-armor-preview'
|
||||||
|
|
||||||
|
function includes<T extends string>(values: readonly T[], value: unknown): value is T {
|
||||||
|
return typeof value === 'string' && values.some((item) => item === value)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function loadSkinArmorPreview(): ArmorPreviewConfig {
|
||||||
|
const config = createDefaultArmorPreviewConfig()
|
||||||
|
try {
|
||||||
|
const saved = JSON.parse(globalThis.localStorage?.getItem(STORAGE_KEY) ?? 'null')
|
||||||
|
if (!saved || typeof saved !== 'object' || Array.isArray(saved)) return config
|
||||||
|
|
||||||
|
for (const slot of ARMOR_SLOTS) {
|
||||||
|
const piece = saved[slot]
|
||||||
|
if (!piece || typeof piece !== 'object' || Array.isArray(piece)) continue
|
||||||
|
if (piece.material === null || includes(armorMaterialsForSlot(slot), piece.material)) {
|
||||||
|
config[slot].material = piece.material
|
||||||
|
}
|
||||||
|
if (piece.trimPattern === null || includes(ARMOR_TRIM_PATTERNS, piece.trimPattern)) {
|
||||||
|
config[slot].trimPattern = piece.trimPattern
|
||||||
|
}
|
||||||
|
if (includes(ARMOR_TRIM_MATERIALS, piece.trimMaterial)) {
|
||||||
|
config[slot].trimMaterial = piece.trimMaterial
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Invalid or unavailable local storage falls back to a fresh preview.
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
export function saveSkinArmorPreview(config: ArmorPreviewConfig): void {
|
||||||
|
try {
|
||||||
|
globalThis.localStorage?.setItem(STORAGE_KEY, JSON.stringify(config))
|
||||||
|
} catch {
|
||||||
|
// The preview remains usable when local storage is unavailable.
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,9 +9,13 @@ import {
|
|||||||
SpinnerIcon,
|
SpinnerIcon,
|
||||||
} from '@modrinth/assets'
|
} from '@modrinth/assets'
|
||||||
import {
|
import {
|
||||||
|
type ArmorPreviewConfig,
|
||||||
|
ArmorPreviewControls,
|
||||||
ButtonStyled,
|
ButtonStyled,
|
||||||
|
cloneArmorPreviewConfig,
|
||||||
commonMessages,
|
commonMessages,
|
||||||
ConfirmModal,
|
ConfirmModal,
|
||||||
|
createDefaultArmorPreviewConfig,
|
||||||
defineMessages,
|
defineMessages,
|
||||||
injectNotificationManager,
|
injectNotificationManager,
|
||||||
NavTabs,
|
NavTabs,
|
||||||
@@ -24,12 +28,14 @@ import { invoke } from '@tauri-apps/api/core'
|
|||||||
import type { DragDropEvent } from '@tauri-apps/api/webview'
|
import type { DragDropEvent } from '@tauri-apps/api/webview'
|
||||||
import { getCurrentWebview } from '@tauri-apps/api/webview'
|
import { getCurrentWebview } from '@tauri-apps/api/webview'
|
||||||
import { computedAsync } from '@vueuse/core'
|
import { computedAsync } from '@vueuse/core'
|
||||||
import type { Ref } from 'vue'
|
import type { ComponentPublicInstance, Ref } from 'vue'
|
||||||
import { computed, inject, onMounted, onUnmounted, ref, useTemplateRef, watch } from 'vue'
|
import { computed, inject, onMounted, onUnmounted, ref, useTemplateRef, watch } from 'vue'
|
||||||
import { onBeforeRouteLeave, useRouter } from 'vue-router'
|
import { onBeforeRouteLeave, useRouter } from 'vue-router'
|
||||||
|
|
||||||
import type AccountsCard from '@/components/ui/AccountsCard.vue'
|
import type AccountsCard from '@/components/ui/AccountsCard.vue'
|
||||||
|
import ArmorTrimTab from '@/components/ui/skin/ArmorTrimTab.vue'
|
||||||
import EditSkinModal from '@/components/ui/skin/EditSkinModal.vue'
|
import EditSkinModal from '@/components/ui/skin/EditSkinModal.vue'
|
||||||
|
import SkinListSkeleton from '@/components/ui/skin/SkinListSkeleton.vue'
|
||||||
import VirtualSkinSectionList from '@/components/ui/skin/VirtualSkinSectionList.vue'
|
import VirtualSkinSectionList from '@/components/ui/skin/VirtualSkinSectionList.vue'
|
||||||
import {
|
import {
|
||||||
openSkinSiteLogin,
|
openSkinSiteLogin,
|
||||||
@@ -45,6 +51,7 @@ import { useNetworkStatus } from '@/composables/useNetworkStatus'
|
|||||||
import { check_reachable, get_default_user, users } from '@/helpers/auth'
|
import { check_reachable, get_default_user, users } from '@/helpers/auth'
|
||||||
import type { RenderResult } from '@/helpers/rendering/batch-skin-renderer.ts'
|
import type { RenderResult } from '@/helpers/rendering/batch-skin-renderer.ts'
|
||||||
import { skinBlobUrlMap } from '@/helpers/rendering/batch-skin-renderer.ts'
|
import { skinBlobUrlMap } from '@/helpers/rendering/batch-skin-renderer.ts'
|
||||||
|
import { loadSkinArmorPreview, saveSkinArmorPreview } from '@/helpers/skin-armor-preview'
|
||||||
import type { Cape, Skin, SkinTextureUrl } from '@/helpers/skins.ts'
|
import type { Cape, Skin, SkinTextureUrl } from '@/helpers/skins.ts'
|
||||||
import {
|
import {
|
||||||
determineModelType,
|
determineModelType,
|
||||||
@@ -252,6 +259,8 @@ const editSkinModal = useTemplateRef('editSkinModal')
|
|||||||
const addSkinFileInput = useTemplateRef<HTMLInputElement>('addSkinFileInput')
|
const addSkinFileInput = useTemplateRef<HTMLInputElement>('addSkinFileInput')
|
||||||
const skinSectionList = useTemplateRef<VirtualSkinSectionListExpose>('skinSectionList')
|
const skinSectionList = useTemplateRef<VirtualSkinSectionListExpose>('skinSectionList')
|
||||||
const skinPreviewArea = useTemplateRef<HTMLElement>('skinPreviewArea')
|
const skinPreviewArea = useTemplateRef<HTMLElement>('skinPreviewArea')
|
||||||
|
const armorTrimTab = useTemplateRef<ComponentPublicInstance>('armorTrimTab')
|
||||||
|
const armorPreviewControls = useTemplateRef<ComponentPublicInstance>('armorPreviewControls')
|
||||||
|
|
||||||
const { formatMessage } = useVIntl()
|
const { formatMessage } = useVIntl()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -391,7 +400,8 @@ const isAddSkinButtonDragActive = ref(false)
|
|||||||
|
|
||||||
const deleteSkinModal = ref()
|
const deleteSkinModal = ref()
|
||||||
const skinToDelete = ref<Skin | null>(null)
|
const skinToDelete = ref<Skin | null>(null)
|
||||||
const skinListTab = ref<'saved' | 'default'>('saved')
|
const lastSkinListTab = ref<'saved' | 'default'>('saved')
|
||||||
|
const skinListTab = ref<'saved' | 'default' | 'armor'>('saved')
|
||||||
|
|
||||||
const skinListTabLinks = computed(() => [
|
const skinListTabLinks = computed(() => [
|
||||||
{
|
{
|
||||||
@@ -403,6 +413,70 @@ const skinListTabLinks = computed(() => [
|
|||||||
label: formatMessage(messages.defaultTab),
|
label: formatMessage(messages.defaultTab),
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
const ARMOR_TRIM_PANEL_ID = 'skins-armor-trim-panel'
|
||||||
|
const savedArmorPreview = ref<ArmorPreviewConfig>(loadSkinArmorPreview())
|
||||||
|
const armorPreviewConfig = ref<ArmorPreviewConfig>(cloneArmorPreviewConfig(savedArmorPreview.value))
|
||||||
|
|
||||||
|
function saveArmorPreview() {
|
||||||
|
savedArmorPreview.value = cloneArmorPreviewConfig(armorPreviewConfig.value)
|
||||||
|
saveSkinArmorPreview(savedArmorPreview.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetArmorPreviewToSaved() {
|
||||||
|
armorPreviewConfig.value = cloneArmorPreviewConfig(savedArmorPreview.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function restoreDefaultArmorPreview() {
|
||||||
|
armorPreviewConfig.value = createDefaultArmorPreviewConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A third tab behind the two list tabs, opened from the preview's action row. */
|
||||||
|
function openArmorTab() {
|
||||||
|
if (skinListTab.value !== 'armor') lastSkinListTab.value = skinListTab.value
|
||||||
|
|
||||||
|
skinListTab.value = 'armor'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether an element belongs to the armour surface: somewhere inside the open
|
||||||
|
* armour tab or the button that toggles it. Only those hold a focus ring that
|
||||||
|
* would be left behind when the tab closes.
|
||||||
|
*/
|
||||||
|
function isArmorPreviewElement(element: Element) {
|
||||||
|
const tabElement: unknown = armorTrimTab.value?.$el
|
||||||
|
const toggleElement: unknown = armorPreviewControls.value?.$el
|
||||||
|
|
||||||
|
return (
|
||||||
|
(tabElement instanceof Element && tabElement.contains(element)) ||
|
||||||
|
(toggleElement instanceof Element && toggleElement.contains(element))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeArmorTab() {
|
||||||
|
// Leaving the tab drops whatever was not saved on purpose.
|
||||||
|
resetArmorPreviewToSaved()
|
||||||
|
skinListTab.value = lastSkinListTab.value
|
||||||
|
|
||||||
|
// Escape and the toggle both leave the armour button holding focus, which
|
||||||
|
// keeps its focus ring drawn until something else is clicked. Only drop that
|
||||||
|
// ring when the focus sits on the armour surface, never on an unrelated
|
||||||
|
// control that happened to hold it when Escape was pressed.
|
||||||
|
const focused = document.activeElement
|
||||||
|
if (focused instanceof HTMLElement && isArmorPreviewElement(focused)) focused.blur()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tab bar keeps the last list tab highlighted while the armour tab shows, so
|
||||||
|
* picking one of them leaves the armour tab. That transition has to drop the
|
||||||
|
* draft exactly like the toggle and Escape paths do, or it lingers on the model
|
||||||
|
* while the panel is gone.
|
||||||
|
*/
|
||||||
|
function selectSkinListTab(index: number) {
|
||||||
|
if (skinListTab.value === 'armor') resetArmorPreviewToSaved()
|
||||||
|
|
||||||
|
lastSkinListTab.value = index === 0 ? 'saved' : 'default'
|
||||||
|
skinListTab.value = lastSkinListTab.value
|
||||||
|
}
|
||||||
|
|
||||||
function confirmDeleteSkin(skin: Skin) {
|
function confirmDeleteSkin(skin: Skin) {
|
||||||
if (isSkinManagementReadOnly.value) return
|
if (isSkinManagementReadOnly.value) return
|
||||||
@@ -1211,6 +1285,9 @@ await loadSkins()
|
|||||||
class="ml-5 mt-4 flex h-[calc(80vh-1rem)] items-center justify-center max-[700px]:h-[calc(50vh-1rem)]"
|
class="ml-5 mt-4 flex h-[calc(80vh-1rem)] items-center justify-center max-[700px]:h-[calc(50vh-1rem)]"
|
||||||
>
|
>
|
||||||
<SkinPreviewRenderer
|
<SkinPreviewRenderer
|
||||||
|
v-model:armor-config="armorPreviewConfig"
|
||||||
|
armor-preview
|
||||||
|
:armor-controls="false"
|
||||||
:cape-src="capeTexture"
|
:cape-src="capeTexture"
|
||||||
:texture-src="skinTexture || ''"
|
:texture-src="skinTexture || ''"
|
||||||
:variant="skinVariant"
|
:variant="skinVariant"
|
||||||
@@ -1257,6 +1334,16 @@ await loadSkins()
|
|||||||
<EditIcon />
|
<EditIcon />
|
||||||
{{ formatMessage(messages.editSkinButton) }}
|
{{ formatMessage(messages.editSkinButton) }}
|
||||||
</button>
|
</button>
|
||||||
|
<ArmorPreviewControls
|
||||||
|
v-if="!isSkinSiteProfile"
|
||||||
|
ref="armorPreviewControls"
|
||||||
|
v-model="armorPreviewConfig"
|
||||||
|
panel="external"
|
||||||
|
:panel-id="ARMOR_TRIM_PANEL_ID"
|
||||||
|
:open="skinListTab === 'armor'"
|
||||||
|
@open="openArmorTab"
|
||||||
|
@close="closeArmorTab"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</SkinPreviewRenderer>
|
</SkinPreviewRenderer>
|
||||||
</div>
|
</div>
|
||||||
@@ -1265,14 +1352,10 @@ await loadSkins()
|
|||||||
<div class="pt-2">
|
<div class="pt-2">
|
||||||
<div class="mb-4 flex flex-wrap items-center justify-between gap-3">
|
<div class="mb-4 flex flex-wrap items-center justify-between gap-3">
|
||||||
<NavTabs
|
<NavTabs
|
||||||
:active-index="skinListTab === 'saved' ? 0 : 1"
|
:active-index="lastSkinListTab === 'saved' ? 0 : 1"
|
||||||
:links="skinListTabLinks"
|
:links="skinListTabLinks"
|
||||||
mode="local"
|
mode="local"
|
||||||
@tab-click="
|
@tab-click="selectSkinListTab"
|
||||||
(index: number) => {
|
|
||||||
skinListTab = index === 0 ? 'saved' : 'default'
|
|
||||||
}
|
|
||||||
"
|
|
||||||
/>
|
/>
|
||||||
<ButtonStyled v-if="!isSkinSiteProfile" color="brand">
|
<ButtonStyled v-if="!isSkinSiteProfile" color="brand">
|
||||||
<button @click="router.push('/lab/skin-editor')">
|
<button @click="router.push('/lab/skin-editor')">
|
||||||
@@ -1281,27 +1364,45 @@ await loadSkins()
|
|||||||
</button>
|
</button>
|
||||||
</ButtonStyled>
|
</ButtonStyled>
|
||||||
</div>
|
</div>
|
||||||
<VirtualSkinSectionList
|
<Transition name="armor-tab" mode="out-in">
|
||||||
ref="skinSectionList"
|
<div v-if="skinListTab !== 'armor'" key="list">
|
||||||
:active-tab="skinListTab"
|
<SkinListSkeleton v-if="isSkinListBuffering" />
|
||||||
:saved-skins="savedSkins"
|
<VirtualSkinSectionList
|
||||||
:default-skin-sections="defaultSkinSections"
|
v-show="!isSkinListBuffering"
|
||||||
:get-baked-skin-textures="getBakedSkinTextures"
|
ref="skinSectionList"
|
||||||
:is-skin-selected="isSkinSelected"
|
:active-tab="skinListTab"
|
||||||
:is-skin-active="isSkinActive"
|
:saved-skins="savedSkins"
|
||||||
:is-add-skin-button-drag-active="isAddSkinButtonDragActive"
|
:default-skin-sections="defaultSkinSections"
|
||||||
:read-only="isSkinManagementReadOnly"
|
:get-baked-skin-textures="getBakedSkinTextures"
|
||||||
:manage-saved-skins="!isSkinSiteProfile"
|
:is-skin-selected="isSkinSelected"
|
||||||
@select="changeSkin"
|
:is-skin-active="isSkinActive"
|
||||||
@edit="(skin, event) => !isSkinSiteProfile && editSkinModal?.show(event, skin)"
|
:is-add-skin-button-drag-active="isAddSkinButtonDragActive"
|
||||||
@delete="confirmDeleteSkin"
|
:read-only="isSkinManagementReadOnly"
|
||||||
@reorder-saved-skins="reorderSavedSkins"
|
:manage-saved-skins="!isSkinSiteProfile"
|
||||||
@add-skin="openAddSkinFileBrowser"
|
@select="changeSkin"
|
||||||
@add-skin-dragenter="onAddSkinDragOver"
|
@edit="(skin, event) => !isSkinSiteProfile && editSkinModal?.show(event, skin)"
|
||||||
@add-skin-dragover="onAddSkinDragOver"
|
@delete="confirmDeleteSkin"
|
||||||
@add-skin-dragleave="onAddSkinDragLeave"
|
@reorder-saved-skins="reorderSavedSkins"
|
||||||
@add-skin-drop="onAddSkinDrop"
|
@add-skin="openAddSkinFileBrowser"
|
||||||
/>
|
@add-skin-dragenter="onAddSkinDragOver"
|
||||||
|
@add-skin-dragover="onAddSkinDragOver"
|
||||||
|
@add-skin-dragleave="onAddSkinDragLeave"
|
||||||
|
@add-skin-drop="onAddSkinDrop"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<ArmorTrimTab
|
||||||
|
v-else
|
||||||
|
ref="armorTrimTab"
|
||||||
|
key="armor"
|
||||||
|
v-model="armorPreviewConfig"
|
||||||
|
:panel-id="ARMOR_TRIM_PANEL_ID"
|
||||||
|
:saved="savedArmorPreview"
|
||||||
|
@save="saveArmorPreview"
|
||||||
|
@reset="resetArmorPreviewToSaved"
|
||||||
|
@defaults="restoreDefaultArmorPreview"
|
||||||
|
@close="closeArmorTab"
|
||||||
|
/>
|
||||||
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -1382,4 +1483,17 @@ await loadSkins()
|
|||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// The armour tab crossfades with the skin list it replaces.
|
||||||
|
.armor-tab-enter-active,
|
||||||
|
.armor-tab-leave-active {
|
||||||
|
transition:
|
||||||
|
opacity 180ms ease,
|
||||||
|
transform 180ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.armor-tab-enter-from,
|
||||||
|
.armor-tab-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(0.5rem);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -19,7 +19,7 @@ use uuid::Uuid;
|
|||||||
|
|
||||||
use crate::{ErrorKind, State};
|
use crate::{ErrorKind, State};
|
||||||
|
|
||||||
const CATALOG_SOURCE: &str = "LobeHub 906b10e03029648655e0257bda4f785a9e0973f0";
|
const CATALOG_SOURCE: &str = "LobeHub 6c7a6fb033e443bc27bf34cbd5509ab3db7f22f3";
|
||||||
const KEYRING_PREFIX: &str = "ai-provider";
|
const KEYRING_PREFIX: &str = "ai-provider";
|
||||||
const OAUTH_CREDENTIAL: &str = "oauth";
|
const OAUTH_CREDENTIAL: &str = "oauth";
|
||||||
const API_KEY_CREDENTIAL: &str = "api-key";
|
const API_KEY_CREDENTIAL: &str = "api-key";
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"source": "LobeHub 906b10e03029648655e0257bda4f785a9e0973f0 model-bank chat models",
|
"source": "LobeHub 6c7a6fb033e443bc27bf34cbd5509ab3db7f22f3 model-bank chat models",
|
||||||
"providers": {
|
"providers": {
|
||||||
"ai21": [
|
"ai21": [
|
||||||
{
|
{
|
||||||
@@ -203,6 +203,16 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"aihubmix": [
|
"aihubmix": [
|
||||||
|
{
|
||||||
|
"id": "gpt-6-sol",
|
||||||
|
"name": "GPT-6 Sol",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gpt-6-luna",
|
||||||
|
"name": "GPT-6 Luna",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "gpt-5.5",
|
"id": "gpt-5.5",
|
||||||
"name": "GPT-5.5",
|
"name": "GPT-5.5",
|
||||||
@@ -343,6 +353,11 @@
|
|||||||
"name": "ChatGPT-4o",
|
"name": "ChatGPT-4o",
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "grok-4.7",
|
||||||
|
"name": "Grok 4.7",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "grok-4-20-non-reasoning",
|
"id": "grok-4-20-non-reasoning",
|
||||||
"name": "Grok 4.20 (Non-Reasoning)",
|
"name": "Grok 4.20 (Non-Reasoning)",
|
||||||
@@ -368,6 +383,11 @@
|
|||||||
"name": "Grok 3 Mini",
|
"name": "Grok 3 Mini",
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "claude-opus-5-5",
|
||||||
|
"name": "Claude Opus 5.5",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "claude-opus-4-7",
|
"id": "claude-opus-4-7",
|
||||||
"name": "Claude Opus 4.7",
|
"name": "Claude Opus 4.7",
|
||||||
@@ -383,11 +403,6 @@
|
|||||||
"name": "Claude Opus 4.5",
|
"name": "Claude Opus 4.5",
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "claude-opus-4-1-20250805",
|
|
||||||
"name": "Claude Opus 4.1",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "claude-sonnet-4-6",
|
"id": "claude-sonnet-4-6",
|
||||||
"name": "Claude Sonnet 4.6",
|
"name": "Claude Sonnet 4.6",
|
||||||
@@ -403,6 +418,21 @@
|
|||||||
"name": "Claude Haiku 4.5",
|
"name": "Claude Haiku 4.5",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "mimo-v2.6-pro",
|
||||||
|
"name": "MiMo-V2.6 Pro",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "mimo-v2.6-pro-ultraspeed",
|
||||||
|
"name": "MiMo-V2.6 Pro UltraSpeed",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "mimo-v2.6-flash",
|
||||||
|
"name": "MiMo-V2.6 Flash",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "DeepSeek-V3.1-Think",
|
"id": "DeepSeek-V3.1-Think",
|
||||||
"name": "DeepSeek V3.1 (Think)",
|
"name": "DeepSeek V3.1 (Think)",
|
||||||
@@ -542,11 +572,6 @@
|
|||||||
"name": "Ring-2.6-1T",
|
"name": "Ring-2.6-1T",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "Ring-2.5-1T",
|
|
||||||
"name": "Ring-2.5-1T",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "Ling-3.0-flash",
|
"id": "Ling-3.0-flash",
|
||||||
"name": "Ling-3.0-flash",
|
"name": "Ling-3.0-flash",
|
||||||
@@ -561,14 +586,14 @@
|
|||||||
"id": "Ling-2.6-flash",
|
"id": "Ling-2.6-flash",
|
||||||
"name": "Ling-2.6-flash",
|
"name": "Ling-2.6-flash",
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Ling-2.5-1T",
|
|
||||||
"name": "Ling-2.5-1T",
|
|
||||||
"enabled": false
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"anthropic": [
|
"anthropic": [
|
||||||
|
{
|
||||||
|
"id": "claude-opus-5-5",
|
||||||
|
"name": "Claude Opus 5.5",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "claude-fable-5-1",
|
"id": "claude-fable-5-1",
|
||||||
"name": "Claude Fable 5.1",
|
"name": "Claude Fable 5.1",
|
||||||
@@ -623,14 +648,24 @@
|
|||||||
"id": "claude-haiku-4-5-20251001",
|
"id": "claude-haiku-4-5-20251001",
|
||||||
"name": "Claude Haiku 4.5",
|
"name": "Claude Haiku 4.5",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "claude-opus-4-1-20250805",
|
|
||||||
"name": "Claude Opus 4.1",
|
|
||||||
"enabled": false
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"azure": [
|
"azure": [
|
||||||
|
{
|
||||||
|
"id": "gpt-6-astra",
|
||||||
|
"name": "GPT-6 Astra",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gpt-6-sol",
|
||||||
|
"name": "GPT-6 Sol",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gpt-6-luna",
|
||||||
|
"name": "GPT-6 Luna",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "gpt-5.4",
|
"id": "gpt-5.4",
|
||||||
"name": "GPT-5.4",
|
"name": "GPT-5.4",
|
||||||
@@ -914,6 +949,11 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"bedrock": [
|
"bedrock": [
|
||||||
|
{
|
||||||
|
"id": "global.anthropic.claude-opus-5-5",
|
||||||
|
"name": "Claude Opus 5.5",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "global.anthropic.claude-opus-4-7",
|
"id": "global.anthropic.claude-opus-4-7",
|
||||||
"name": "Claude Opus 4.7",
|
"name": "Claude Opus 4.7",
|
||||||
@@ -1030,14 +1070,29 @@
|
|||||||
"id": "gpt-oss-120b",
|
"id": "gpt-oss-120b",
|
||||||
"name": "GPT OSS 120B",
|
"name": "GPT OSS 120B",
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "zai-glm-4.7",
|
|
||||||
"name": "GLM-4.7",
|
|
||||||
"enabled": false
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"chatgpt": [
|
"chatgpt": [
|
||||||
|
{
|
||||||
|
"id": "gpt-6.1-sol",
|
||||||
|
"name": "GPT-6.1 Sol",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gpt-6-astra",
|
||||||
|
"name": "GPT-6 Astra",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gpt-6-sol",
|
||||||
|
"name": "GPT-6 Sol",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gpt-6-luna",
|
||||||
|
"name": "GPT-6 Luna",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "gpt-5.6-sol",
|
"id": "gpt-5.6-sol",
|
||||||
"name": "GPT-5.6 Sol",
|
"name": "GPT-5.6 Sol",
|
||||||
@@ -1056,7 +1111,7 @@
|
|||||||
{
|
{
|
||||||
"id": "gpt-5.5",
|
"id": "gpt-5.5",
|
||||||
"name": "GPT-5.5",
|
"name": "GPT-5.5",
|
||||||
"enabled": true
|
"enabled": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"cloudflare": [
|
"cloudflare": [
|
||||||
@@ -1883,10 +1938,15 @@
|
|||||||
"name": "Gemini Flash-Lite Latest",
|
"name": "Gemini Flash-Lite Latest",
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "gemini-3.8-flash",
|
||||||
|
"name": "Gemini 3.8 Flash",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "gemini-3.7-flash",
|
"id": "gemini-3.7-flash",
|
||||||
"name": "Gemini 3.7 Flash",
|
"name": "Gemini 3.7 Flash",
|
||||||
"enabled": true
|
"enabled": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "gemini-3.6-flash",
|
"id": "gemini-3.6-flash",
|
||||||
@@ -1972,26 +2032,6 @@
|
|||||||
"id": "gemini-2.5-flash-lite",
|
"id": "gemini-2.5-flash-lite",
|
||||||
"name": "Gemini 2.5 Flash-Lite",
|
"name": "Gemini 2.5 Flash-Lite",
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "gemini-2.0-flash",
|
|
||||||
"name": "Gemini 2.0 Flash",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "gemini-2.0-flash-001",
|
|
||||||
"name": "Gemini 2.0 Flash 001",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "gemini-2.0-flash-lite",
|
|
||||||
"name": "Gemini 2.0 Flash-Lite",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "gemini-2.0-flash-lite-001",
|
|
||||||
"name": "Gemini 2.0 Flash-Lite 001",
|
|
||||||
"enabled": false
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"groq": [
|
"groq": [
|
||||||
@@ -2005,10 +2045,15 @@
|
|||||||
"name": "Compound Mini",
|
"name": "Compound Mini",
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "qwen/qwen3.8-27b",
|
||||||
|
"name": "Qwen3.8 27B",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "qwen/qwen3.6-27b",
|
"id": "qwen/qwen3.6-27b",
|
||||||
"name": "Qwen3.6 27B",
|
"name": "Qwen3.6 27B",
|
||||||
"enabled": true
|
"enabled": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "minimaxai/minimax-m2.7",
|
"id": "minimaxai/minimax-m2.7",
|
||||||
@@ -2025,16 +2070,6 @@
|
|||||||
"name": "GPT OSS 20B",
|
"name": "GPT OSS 20B",
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "llama-3.1-8b-instant",
|
|
||||||
"name": "Llama 3.1 8B Instant",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "llama-3.3-70b-versatile",
|
|
||||||
"name": "Llama 3.3 70B Versatile",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "meta-llama/llama-prompt-guard-2-22m",
|
"id": "meta-llama/llama-prompt-guard-2-22m",
|
||||||
"name": "Llama Prompt Guard 2 22M",
|
"name": "Llama Prompt Guard 2 22M",
|
||||||
@@ -3575,13 +3610,13 @@
|
|||||||
],
|
],
|
||||||
"mistral": [
|
"mistral": [
|
||||||
{
|
{
|
||||||
"id": "mistral-medium-3.5",
|
"id": "zai-glm-5-2",
|
||||||
"name": "Mistral Medium 3.5",
|
"name": "Z.ai GLM 5.2",
|
||||||
"enabled": true
|
"enabled": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "devstral-2512",
|
"id": "mistral-medium-3.5",
|
||||||
"name": "Devstral 2",
|
"name": "Mistral Medium 3.5",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -3589,61 +3624,21 @@
|
|||||||
"name": "Devstral Small 2",
|
"name": "Devstral Small 2",
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "mistral-medium-2508",
|
|
||||||
"name": "Mistral Medium 3.1",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "magistral-medium-2509",
|
|
||||||
"name": "Magistral Medium 1.2",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "magistral-small-2509",
|
|
||||||
"name": "Magistral Small 1.2",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "open-mistral-nemo",
|
|
||||||
"name": "Mistral Nemo",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "mistral-small-2603",
|
"id": "mistral-small-2603",
|
||||||
"name": "Mistral Small 4",
|
"name": "Mistral Small 4",
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "mistral-small-2506",
|
|
||||||
"name": "Mistral Small 3.2",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "mistral-large-2512",
|
"id": "mistral-large-2512",
|
||||||
"name": "Mistral Large 3",
|
"name": "Mistral Large 3",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "mistral-large-2411",
|
|
||||||
"name": "Mistral Large 2.1",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "codestral-latest",
|
"id": "codestral-latest",
|
||||||
"name": "Codestral 2508",
|
"name": "Codestral 2508",
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "pixtral-large-latest",
|
|
||||||
"name": "Pixtral Large",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "pixtral-12b-2409",
|
|
||||||
"name": "Pixtral 12B",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "ministral-3b-latest",
|
"id": "ministral-3b-latest",
|
||||||
"name": "Ministral 3B",
|
"name": "Ministral 3B",
|
||||||
@@ -3653,16 +3648,6 @@
|
|||||||
"id": "ministral-8b-latest",
|
"id": "ministral-8b-latest",
|
||||||
"name": "Ministral 8B",
|
"name": "Ministral 8B",
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "open-codestral-mamba",
|
|
||||||
"name": "Codestral Mamba",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "labs-leanstral-2603",
|
|
||||||
"name": "Leanstral",
|
|
||||||
"enabled": false
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modelscope": [
|
"modelscope": [
|
||||||
@@ -3676,30 +3661,10 @@
|
|||||||
"name": "Qwen3 Next 80B A3B Instruct",
|
"name": "Qwen3 Next 80B A3B Instruct",
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "deepseek-ai/DeepSeek-V3.2",
|
|
||||||
"name": "DeepSeek V3.2",
|
|
||||||
"enabled": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "deepseek-ai/DeepSeek-V3.2-Exp",
|
|
||||||
"name": "DeepSeek V3.2 Exp",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "deepseek-ai/DeepSeek-V3.1",
|
|
||||||
"name": "DeepSeek V3.1",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "Qwen/Qwen3-235B-A22B",
|
"id": "Qwen/Qwen3-235B-A22B",
|
||||||
"name": "Qwen3 235B A22B",
|
"name": "Qwen3 235B A22B",
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Qwen/Qwen3-32B",
|
|
||||||
"name": "Qwen3 32B",
|
|
||||||
"enabled": false
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"moonshot": [
|
"moonshot": [
|
||||||
@@ -3722,41 +3687,6 @@
|
|||||||
"id": "kimi-k2.6",
|
"id": "kimi-k2.6",
|
||||||
"name": "Kimi K2.6",
|
"name": "Kimi K2.6",
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "kimi-k2.5",
|
|
||||||
"name": "Kimi K2.5",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "moonshot-v1-8k",
|
|
||||||
"name": "Moonshot V1 8K",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "moonshot-v1-32k",
|
|
||||||
"name": "Moonshot V1 32K",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "moonshot-v1-128k",
|
|
||||||
"name": "Moonshot V1 128K",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "moonshot-v1-8k-vision-preview",
|
|
||||||
"name": "Moonshot V1 8K Vision Preview",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "moonshot-v1-32k-vision-preview",
|
|
||||||
"name": "Moonshot V1 32K Vision Preview",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "moonshot-v1-128k-vision-preview",
|
|
||||||
"name": "Moonshot V1 128K Vision Preview",
|
|
||||||
"enabled": false
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"nebius": [
|
"nebius": [
|
||||||
@@ -4424,16 +4354,6 @@
|
|||||||
"name": "Qwen3.5 397B A17B",
|
"name": "Qwen3.5 397B A17B",
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "minimax-m2.5",
|
|
||||||
"name": "MiniMax M2.5",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "kimi-k2.5",
|
|
||||||
"name": "Kimi K2.5",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "gpt-oss:20b",
|
"id": "gpt-oss:20b",
|
||||||
"name": "GPT-OSS 20B",
|
"name": "GPT-OSS 20B",
|
||||||
@@ -4451,6 +4371,26 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"openai": [
|
"openai": [
|
||||||
|
{
|
||||||
|
"id": "gpt-6.1-sol",
|
||||||
|
"name": "GPT-6.1 Sol",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gpt-6-astra",
|
||||||
|
"name": "GPT-6 Astra",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gpt-6-sol",
|
||||||
|
"name": "GPT-6 Sol",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gpt-6-luna",
|
||||||
|
"name": "GPT-6 Luna",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "chat-latest",
|
"id": "chat-latest",
|
||||||
"name": "Chat Latest",
|
"name": "Chat Latest",
|
||||||
@@ -4474,7 +4414,7 @@
|
|||||||
{
|
{
|
||||||
"id": "gpt-5.5",
|
"id": "gpt-5.5",
|
||||||
"name": "GPT-5.5",
|
"name": "GPT-5.5",
|
||||||
"enabled": true
|
"enabled": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "gpt-5.5-pro",
|
"id": "gpt-5.5-pro",
|
||||||
@@ -4484,7 +4424,7 @@
|
|||||||
{
|
{
|
||||||
"id": "gpt-5.4",
|
"id": "gpt-5.4",
|
||||||
"name": "GPT-5.4",
|
"name": "GPT-5.4",
|
||||||
"enabled": true
|
"enabled": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "gpt-5.4-pro",
|
"id": "gpt-5.4-pro",
|
||||||
@@ -4494,7 +4434,7 @@
|
|||||||
{
|
{
|
||||||
"id": "gpt-5.4-mini",
|
"id": "gpt-5.4-mini",
|
||||||
"name": "GPT-5.4 mini",
|
"name": "GPT-5.4 mini",
|
||||||
"enabled": true
|
"enabled": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "gpt-5.4-nano",
|
"id": "gpt-5.4-nano",
|
||||||
@@ -4708,6 +4648,16 @@
|
|||||||
"name": "MiniMax M3",
|
"name": "MiniMax M3",
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "muse-spark-1.2-contributor",
|
||||||
|
"name": "Muse Spark 1.2 Contributor",
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "muse-spark-1.3-contributor",
|
||||||
|
"name": "Muse Spark 1.3 Contributor",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "qwen3.6-plus",
|
"id": "qwen3.6-plus",
|
||||||
"name": "Qwen3.6 Plus",
|
"name": "Qwen3.6 Plus",
|
||||||
@@ -4912,6 +4862,41 @@
|
|||||||
"name": "Auto (best for prompt)",
|
"name": "Auto (best for prompt)",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "anthropic/claude-opus-5.5",
|
||||||
|
"name": "Claude Opus 5.5",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "openai/gpt-6-sol",
|
||||||
|
"name": "GPT-6 Sol",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "openai/gpt-6-luna",
|
||||||
|
"name": "GPT-6 Luna",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "x-ai/grok-4.7",
|
||||||
|
"name": "Grok 4.7",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "xiaomi/mimo-v2.6-pro",
|
||||||
|
"name": "MiMo-V2.6 Pro",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "xiaomi/mimo-v2.6-pro-ultraspeed",
|
||||||
|
"name": "MiMo-V2.6 Pro UltraSpeed",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "xiaomi/mimo-v2.6-flash",
|
||||||
|
"name": "MiMo-V2.6 Flash",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "deepseek/deepseek-chat-v3.1",
|
"id": "deepseek/deepseek-chat-v3.1",
|
||||||
"name": "DeepSeek V3.1",
|
"name": "DeepSeek V3.1",
|
||||||
@@ -5260,6 +5245,26 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"qwen": [
|
"qwen": [
|
||||||
|
{
|
||||||
|
"id": "deepseek-v4-pro-0813",
|
||||||
|
"name": "DeepSeek V4 Pro 0813",
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "deepseek-v4-flash-0731",
|
||||||
|
"name": "DeepSeek V4 Flash 0731",
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "qwen3.8-max-0902",
|
||||||
|
"name": "Qwen3.8 Max 0902",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "qwen3.8-max",
|
||||||
|
"name": "Qwen3.8 Max",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "kimi-k2.6",
|
"id": "kimi-k2.6",
|
||||||
"name": "Kimi K2.6",
|
"name": "Kimi K2.6",
|
||||||
@@ -5490,10 +5495,15 @@
|
|||||||
"name": "QwQ Plus",
|
"name": "QwQ Plus",
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "qwen3.8-flash",
|
||||||
|
"name": "Qwen3.8 Flash",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "qwen3.7-flash",
|
"id": "qwen3.7-flash",
|
||||||
"name": "Qwen3.7 Flash",
|
"name": "Qwen3.7 Flash",
|
||||||
"enabled": true
|
"enabled": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "qwen3.6-flash",
|
"id": "qwen3.6-flash",
|
||||||
@@ -5802,75 +5812,40 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"sambanova": [
|
"sambanova": [
|
||||||
|
{
|
||||||
|
"id": "MiniMax-M2.7",
|
||||||
|
"name": "MiniMax M2.7",
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "DeepSeek-V3.1",
|
||||||
|
"name": "DeepSeek V3.1",
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "Meta-Llama-3.3-70B-Instruct",
|
"id": "Meta-Llama-3.3-70B-Instruct",
|
||||||
"name": "Meta Llama 3.3 70B Instruct",
|
"name": "Meta Llama 3.3 70B Instruct",
|
||||||
"enabled": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Meta-Llama-3.2-1B-Instruct",
|
|
||||||
"name": "Meta Llama 3.2 1B Instruct",
|
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "Meta-Llama-3.2-3B-Instruct",
|
"id": "gpt-oss-120b",
|
||||||
"name": "Meta Llama 3.2 3B Instruct",
|
"name": "GPT OSS 120B",
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Llama-3.2-11B-Vision-Instruct",
|
|
||||||
"name": "Meta Llama 3.2 11B Vision Instruct",
|
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "Llama-3.2-90B-Vision-Instruct",
|
"id": "MiniMax-M3",
|
||||||
"name": "Meta Llama 3.2 90B Vision Instruct",
|
"name": "MiniMax M3",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "Meta-Llama-3.1-8B-Instruct",
|
"id": "DeepSeek-V3.2",
|
||||||
"name": "Meta Llama 3.1 8B Instruct",
|
"name": "DeepSeek V3.2",
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "Meta-Llama-3.1-70B-Instruct",
|
"id": "gemma-4-31B-it",
|
||||||
"name": "Meta Llama 3.1 70B Instruct",
|
"name": "Gemma 4 31B IT",
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Meta-Llama-3.1-405B-Instruct",
|
|
||||||
"name": "Meta Llama 3.1 405B Instruct",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Llama-3.1-Tulu-3-405B",
|
|
||||||
"name": "Llama 3.1 Tulu 3 405B",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "DeepSeek-R1",
|
|
||||||
"name": "DeepSeek R1",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "DeepSeek-R1-Distill-Llama-70B",
|
|
||||||
"name": "DeepSeek R1 Distill Llama 70B",
|
|
||||||
"enabled": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "QwQ-32B-Preview",
|
|
||||||
"name": "QwQ 32B Preview",
|
|
||||||
"enabled": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Qwen2.5-72B-Instruct",
|
|
||||||
"name": "Qwen2.5 72B Instruct",
|
|
||||||
"enabled": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Qwen2.5-Coder-32B-Instruct",
|
|
||||||
"name": "Qwen2.5 Coder 32B Instruct",
|
|
||||||
"enabled": true
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"search1api": [
|
"search1api": [
|
||||||
@@ -6262,6 +6237,11 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"stepfun": [
|
"stepfun": [
|
||||||
|
{
|
||||||
|
"id": "step-5-preview",
|
||||||
|
"name": "Step 5 Preview",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "step-3.7-flash",
|
"id": "step-3.7-flash",
|
||||||
"name": "Step 3.7 Flash",
|
"name": "Step 3.7 Flash",
|
||||||
@@ -6407,6 +6387,16 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"supergrok": [
|
"supergrok": [
|
||||||
|
{
|
||||||
|
"id": "grok-4.7",
|
||||||
|
"name": "Grok 4.7",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "grok-4.6",
|
||||||
|
"name": "Grok 4.6",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "grok-4.5",
|
"id": "grok-4.5",
|
||||||
"name": "Grok 4.5",
|
"name": "Grok 4.5",
|
||||||
@@ -7166,10 +7156,15 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"vertexai": [
|
"vertexai": [
|
||||||
|
{
|
||||||
|
"id": "gemini-3.8-flash",
|
||||||
|
"name": "Gemini 3.8 Flash",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "gemini-3.7-flash",
|
"id": "gemini-3.7-flash",
|
||||||
"name": "Gemini 3.7 Flash",
|
"name": "Gemini 3.7 Flash",
|
||||||
"enabled": true
|
"enabled": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "gemini-3.6-flash",
|
"id": "gemini-3.6-flash",
|
||||||
@@ -7345,20 +7340,30 @@
|
|||||||
"name": "Doubao Seed 2.1 Turbo",
|
"name": "Doubao Seed 2.1 Turbo",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "deepseek-v4-pro-ga",
|
||||||
|
"name": "DeepSeek V4 Pro 0813",
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "deepseek-v4-flash-ga",
|
||||||
|
"name": "DeepSeek V4 Flash 0731",
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "glm-5-2",
|
"id": "glm-5-2",
|
||||||
"name": "GLM-5.2",
|
"name": "GLM-5.2",
|
||||||
"enabled": true
|
"enabled": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "deepseek-v4-pro",
|
"id": "deepseek-v4-pro",
|
||||||
"name": "DeepSeek V4 Pro",
|
"name": "DeepSeek V4 Pro",
|
||||||
"enabled": true
|
"enabled": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "deepseek-v4-flash",
|
"id": "deepseek-v4-flash",
|
||||||
"name": "DeepSeek V4 Flash",
|
"name": "DeepSeek V4 Flash",
|
||||||
"enabled": true
|
"enabled": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "doubao-seed-2.0-pro",
|
"id": "doubao-seed-2.0-pro",
|
||||||
@@ -7701,6 +7706,16 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"xai": [
|
"xai": [
|
||||||
|
{
|
||||||
|
"id": "grok-4.7",
|
||||||
|
"name": "Grok 4.7",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "grok-4.6",
|
||||||
|
"name": "Grok 4.6",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "grok-4.5",
|
"id": "grok-4.5",
|
||||||
"name": "Grok 4.5",
|
"name": "Grok 4.5",
|
||||||
@@ -7728,6 +7743,21 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"xiaomimimo": [
|
"xiaomimimo": [
|
||||||
|
{
|
||||||
|
"id": "mimo-v2.6-pro",
|
||||||
|
"name": "MiMo-V2.6 Pro",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "mimo-v2.6-pro-ultraspeed",
|
||||||
|
"name": "MiMo-V2.6 Pro UltraSpeed",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "mimo-v2.6-flash",
|
||||||
|
"name": "MiMo-V2.6 Flash",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "mimo-v2.5-pro",
|
"id": "mimo-v2.5-pro",
|
||||||
"name": "MiMo-V2.5 Pro",
|
"name": "MiMo-V2.5 Pro",
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use crate::api::pack::import::{
|
use crate::api::pack::import::{
|
||||||
ImportLauncherType,
|
ImportLauncherType, direct_link::resolve_direct_link,
|
||||||
direct_link::resolve_direct_link,
|
|
||||||
};
|
};
|
||||||
use crate::launcher::ExternalGameDirMode;
|
use crate::launcher::ExternalGameDirMode;
|
||||||
use crate::state::instances::{
|
use crate::state::instances::{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use super::create_direct_link_instance::create_direct_link_instance;
|
use super::create_direct_link_instance::create_direct_link_instance;
|
||||||
use crate::api::pack::import::direct_link::{
|
use crate::api::pack::import::direct_link::{
|
||||||
detect_direct_link_source,
|
detect_direct_link_source, has_minecraft_version_manifest,
|
||||||
has_minecraft_version_manifest, resolve_direct_link,
|
resolve_direct_link,
|
||||||
};
|
};
|
||||||
use crate::event::{InstancePayloadType, emit::emit_instance};
|
use crate::event::{InstancePayloadType, emit::emit_instance};
|
||||||
use crate::launcher::ExternalGameDirMode;
|
use crate::launcher::ExternalGameDirMode;
|
||||||
|
|||||||
|
After Width: | Height: | Size: 251 B |
|
After Width: | Height: | Size: 423 B |
|
After Width: | Height: | Size: 438 B |
|
After Width: | Height: | Size: 434 B |
|
After Width: | Height: | Size: 424 B |
|
After Width: | Height: | Size: 413 B |
|
After Width: | Height: | Size: 170 B |
|
After Width: | Height: | Size: 467 B |
|
After Width: | Height: | Size: 253 B |
|
After Width: | Height: | Size: 167 B |
|
After Width: | Height: | Size: 258 B |
|
After Width: | Height: | Size: 272 B |
|
After Width: | Height: | Size: 261 B |
|
After Width: | Height: | Size: 243 B |
|
After Width: | Height: | Size: 254 B |
|
After Width: | Height: | Size: 180 B |
|
After Width: | Height: | Size: 258 B |
|
After Width: | Height: | Size: 183 B |
|
After Width: | Height: | Size: 225 B |
|
After Width: | Height: | Size: 149 B |
|
After Width: | Height: | Size: 165 B |
|
After Width: | Height: | Size: 135 B |
|
After Width: | Height: | Size: 148 B |
|
After Width: | Height: | Size: 267 B |
|
After Width: | Height: | Size: 171 B |
|
After Width: | Height: | Size: 189 B |
|
After Width: | Height: | Size: 160 B |
|
After Width: | Height: | Size: 196 B |
|
After Width: | Height: | Size: 177 B |
|
After Width: | Height: | Size: 207 B |
|
After Width: | Height: | Size: 175 B |
|
After Width: | Height: | Size: 189 B |
|
After Width: | Height: | Size: 165 B |
|
After Width: | Height: | Size: 177 B |
|
After Width: | Height: | Size: 224 B |
|
After Width: | Height: | Size: 182 B |
|
After Width: | Height: | Size: 211 B |
|
After Width: | Height: | Size: 210 B |
|
After Width: | Height: | Size: 187 B |
|
After Width: | Height: | Size: 169 B |
|
After Width: | Height: | Size: 189 B |
|
After Width: | Height: | Size: 158 B |
|
After Width: | Height: | Size: 174 B |
|
After Width: | Height: | Size: 203 B |
|
After Width: | Height: | Size: 143 B |
|
After Width: | Height: | Size: 161 B |
|
After Width: | Height: | Size: 134 B |
|
After Width: | Height: | Size: 157 B |
|
After Width: | Height: | Size: 151 B |
|
After Width: | Height: | Size: 181 B |
|
After Width: | Height: | Size: 200 B |
|
After Width: | Height: | Size: 245 B |
|
After Width: | Height: | Size: 202 B |
|
After Width: | Height: | Size: 209 B |
|
After Width: | Height: | Size: 171 B |
|
After Width: | Height: | Size: 216 B |
|
After Width: | Height: | Size: 161 B |
|
After Width: | Height: | Size: 208 B |
|
After Width: | Height: | Size: 176 B |
|
After Width: | Height: | Size: 223 B |
|
After Width: | Height: | Size: 215 B |
|
After Width: | Height: | Size: 179 B |
|
After Width: | Height: | Size: 198 B |
|
After Width: | Height: | Size: 227 B |
|
After Width: | Height: | Size: 207 B |
|
After Width: | Height: | Size: 208 B |
|
After Width: | Height: | Size: 254 B |
|
After Width: | Height: | Size: 208 B |
|
After Width: | Height: | Size: 209 B |
|
After Width: | Height: | Size: 221 B |
|
After Width: | Height: | Size: 152 B |
|
After Width: | Height: | Size: 213 B |
|
After Width: | Height: | Size: 218 B |
|
After Width: | Height: | Size: 216 B |
|
After Width: | Height: | Size: 252 B |
|
After Width: | Height: | Size: 103 B |
|
After Width: | Height: | Size: 104 B |
|
After Width: | Height: | Size: 108 B |
|
After Width: | Height: | Size: 93 B |
|
After Width: | Height: | Size: 265 B |
|
After Width: | Height: | Size: 166 B |
|
After Width: | Height: | Size: 218 B |
|
After Width: | Height: | Size: 181 B |
|
After Width: | Height: | Size: 247 B |
|
After Width: | Height: | Size: 177 B |
|
After Width: | Height: | Size: 192 B |
|
After Width: | Height: | Size: 163 B |
|
After Width: | Height: | Size: 170 B |
|
After Width: | Height: | Size: 169 B |
|
After Width: | Height: | Size: 401 B |