diff --git a/apps/app-frontend/src/App.vue b/apps/app-frontend/src/App.vue index 52f7a10e15..94204d32a0 100644 --- a/apps/app-frontend/src/App.vue +++ b/apps/app-frontend/src/App.vue @@ -449,8 +449,6 @@ window.addEventListener('online', () => { offline.value = false }) -const nativeDecorations = ref(false) - const os = ref('') const isDevEnvironment = ref(false) @@ -760,7 +758,7 @@ async function setupApp() { const dev = await isDev() isDevEnvironment.value = dev const version = await getVersion() - nativeDecorations.value = native_decorations + appSettings.nativeDecorations = native_decorations if (os.value !== 'MacOS') await getCurrentWindow().setDecorations(native_decorations) appTheme.preferred = theme @@ -2216,7 +2214,6 @@ provideAppUpdateDownloadProgress(appUpdateDownload) > -
:deep(*) { + flex-shrink: 0; + } } .app-grid-statusbar { diff --git a/apps/app-frontend/src/components/ui/QuickInstanceSwitcher.vue b/apps/app-frontend/src/components/ui/QuickInstanceSwitcher.vue index 7387eaca6a..b0cdbe9b72 100644 --- a/apps/app-frontend/src/components/ui/QuickInstanceSwitcher.vue +++ b/apps/app-frontend/src/components/ui/QuickInstanceSwitcher.vue @@ -27,7 +27,6 @@ import { showInstanceInFolder } from '@/helpers/utils' import { instanceListQueryOptions } from '@/pages/instance/query-options' const ITEM_SIZE = 52 -const APPROX_USED_VERTICAL_SPACE = 475 // doesn't need to be exact lol just close enough so there's a little gap and no overflow const { handleError } = injectNotificationManager() const instancesQuery = useQuery(instanceListQueryOptions()) const router = useRouter() @@ -36,6 +35,8 @@ const runningInstances = ref([]) const { formatMessage } = useVIntl() +const container = ref() +let resizeObserver const maxAuto = ref(0) const allInstances = computed(() => (instancesQuery.data.value ?? []).slice().sort((a, b) => { @@ -69,9 +70,13 @@ const canDrag = computed(() => maxVisible.value > 0) const showOverdrag = ref(false) const updateMaxAuto = () => { + if (!container.value) return + const rem = Number.parseFloat(getComputedStyle(document.documentElement).fontSize) + const dividerHeight = rem + 1 + const gap = rem / 4 maxAuto.value = Math.max( 0, - Math.floor((window.innerHeight - APPROX_USED_VERTICAL_SPACE) / ITEM_SIZE), + Math.floor((container.value.clientHeight - 2 * dividerHeight - gap) / (3 * rem + gap)), ) } @@ -154,17 +159,18 @@ const onDividerPointerUp = (event) => { } await instancesQuery.suspense().catch(handleError) -updateMaxAuto() useAppEvent('process', checkProcesses) onMounted(() => { - window.addEventListener('resize', updateMaxAuto) + resizeObserver = new ResizeObserver(updateMaxAuto) + resizeObserver.observe(container.value) + updateMaxAuto() checkProcesses() }) onUnmounted(() => { - window.removeEventListener('resize', updateMaxAuto) + resizeObserver?.disconnect() document.body.classList.remove('quick-instance-dragging') clearOverdragFlash() }) @@ -264,55 +270,61 @@ function openContextMenu(event, instance) { diff --git a/apps/app-frontend/src/components/ui/library/instance-group/index.vue b/apps/app-frontend/src/components/ui/library/instance-group/index.vue index 8662927fd1..644246aee4 100644 --- a/apps/app-frontend/src/components/ui/library/instance-group/index.vue +++ b/apps/app-frontend/src/components/ui/library/instance-group/index.vue @@ -128,7 +128,9 @@ const cardWidth = computed( () => (gridWidth.value - gap.value * (columnCount.value - 1)) / columnCount.value, ) const cardHeight = computed(() => - compactMode.value ? remSize.value * 3.875 : Math.max(0, cardWidth.value) + remSize.value * 3.375, + compactMode.value + ? remSize.value * 3.875 + 2 + : Math.max(0, cardWidth.value) + remSize.value * 3.375, ) const gridHeight = computed(() => Math.max( diff --git a/apps/app-frontend/src/components/ui/modal/AppSettingsModal.vue b/apps/app-frontend/src/components/ui/modal/AppSettingsModal.vue index dd2218b22e..6a4503023f 100644 --- a/apps/app-frontend/src/components/ui/modal/AppSettingsModal.vue +++ b/apps/app-frontend/src/components/ui/modal/AppSettingsModal.vue @@ -25,8 +25,19 @@ import { } from '@modrinth/ui' import { getVersion } from '@tauri-apps/api/app' import { platform as getOsPlatform, version as getOsVersion } from '@tauri-apps/plugin-os' -import { computed, defineAsyncComponent, provide, ref, watch } from 'vue' +import { computed, provide, ref, watch } from 'vue' +import PrivacySettings from '@/components/ui/settings/account/PrivacySettings.vue' +import ProfileSettings from '@/components/ui/settings/account/ProfileSettings.vue' +import SocialSettings from '@/components/ui/settings/account/SocialSettings.vue' +import AppearanceSettings from '@/components/ui/settings/display/AppearanceSettings.vue' +import BehaviorSettings from '@/components/ui/settings/display/BehaviorSettings.vue' +import FeatureFlagSettings from '@/components/ui/settings/display/FeatureFlagSettings.vue' +import FeaturesSettings from '@/components/ui/settings/display/FeaturesSettings.vue' +import LanguageSettings from '@/components/ui/settings/display/LanguageSettings.vue' +import InstancesSyncedSettings from '@/components/ui/settings/instances/instances-synced-settings/index.vue' +import JavaSettings from '@/components/ui/settings/instances/JavaSettings.vue' +import ResourceManagementSettings from '@/components/ui/settings/instances/ResourceManagementSettings.vue' import { useAppSettings } from '@/composables/use-app-settings.ts' import { get, set } from '@/helpers/settings.ts' import { @@ -35,40 +46,6 @@ import { } from '@/providers/app-settings-modal' import { injectAppUpdateDownloadProgress } from '@/providers/download-progress.ts' -const PrivacySettings = defineAsyncComponent( - () => import('@/components/ui/settings/account/PrivacySettings.vue'), -) -const ProfileSettings = defineAsyncComponent( - () => import('@/components/ui/settings/account/ProfileSettings.vue'), -) -const SocialSettings = defineAsyncComponent( - () => import('@/components/ui/settings/account/SocialSettings.vue'), -) -const AppearanceSettings = defineAsyncComponent( - () => import('@/components/ui/settings/display/AppearanceSettings.vue'), -) -const BehaviorSettings = defineAsyncComponent( - () => import('@/components/ui/settings/display/BehaviorSettings.vue'), -) -const FeatureFlagSettings = defineAsyncComponent( - () => import('@/components/ui/settings/display/FeatureFlagSettings.vue'), -) -const FeaturesSettings = defineAsyncComponent( - () => import('@/components/ui/settings/display/FeaturesSettings.vue'), -) -const LanguageSettings = defineAsyncComponent( - () => import('@/components/ui/settings/display/LanguageSettings.vue'), -) -const InstancesSyncedSettings = defineAsyncComponent( - () => import('@/components/ui/settings/instances/instances-synced-settings/index.vue'), -) -const JavaSettings = defineAsyncComponent( - () => import('@/components/ui/settings/instances/JavaSettings.vue'), -) -const ResourceManagementSettings = defineAsyncComponent( - () => import('@/components/ui/settings/instances/ResourceManagementSettings.vue'), -) - // TODO: Apply COMPONENT_STRUCTURE.md here and extract out common setting option components const appSettings = useAppSettings() diff --git a/apps/app-frontend/src/components/ui/settings/display/AppearanceSettings.vue b/apps/app-frontend/src/components/ui/settings/display/AppearanceSettings.vue index 040cd599db..1c51953150 100644 --- a/apps/app-frontend/src/components/ui/settings/display/AppearanceSettings.vue +++ b/apps/app-frontend/src/components/ui/settings/display/AppearanceSettings.vue @@ -6,19 +6,20 @@ import { provideAppearanceSettings, useSavable, } from '@modrinth/ui' -import { computed, inject, onBeforeUnmount, onMounted, ref, watch } from 'vue' +import { platform } from '@tauri-apps/plugin-os' +import { computed, inject, onBeforeUnmount, onMounted, watch } from 'vue' +import { useAppSettings } from '@/composables/use-app-settings.ts' import { type ColorTheme, isDarkTheme, useTheme } from '@/composables/use-theme.ts' import { type AppSettings, get, set } from '@/helpers/settings.ts' -import { getOS } from '@/helpers/utils' import { appSettingsModalContextKey } from '@/providers/app-settings-modal' const theme = useTheme() +const appSettings = useAppSettings() const auth = injectAuth() const { updatePreferences } = injectUserPreferences() const settingsModal = inject(appSettingsModalContextKey, null) -const os = await getOS() -const settings = ref(await get()) +const os = platform() type AppearanceSettingsState = { theme: ColorTheme @@ -27,17 +28,17 @@ type AppearanceSettingsState = { nativeDecorations: boolean } -function getAppearanceSettingsState(settings: AppSettings): AppearanceSettingsState { +function getAppearanceSettingsState(): AppearanceSettingsState { return { - theme: settings.theme, - syncAcrossDevices: settings.sync_theme_across_devices, - advancedRendering: settings.advanced_rendering, - nativeDecorations: settings.native_decorations, + theme: theme.preferred, + syncAcrossDevices: theme.syncAcrossDevices, + advancedRendering: theme.advancedRendering, + nativeDecorations: appSettings.nativeDecorations, } } const { saved, current, changes, saving, hasChanges, reset, save } = useSavable( - () => getAppearanceSettingsState(settings.value), + getAppearanceSettingsState, async (appearanceChanges) => { const value = current.value if ( @@ -51,7 +52,7 @@ const { saved, current, changes, saving, hasChanges, reset, save } = useSavable( } const nextSettings: AppSettings = { - ...settings.value, + ...(await get()), theme: value.theme, sync_theme_across_devices: value.syncAcrossDevices, advanced_rendering: value.advancedRendering, @@ -59,20 +60,19 @@ const { saved, current, changes, saving, hasChanges, reset, save } = useSavable( } await set(nextSettings) - settings.value = nextSettings if (isDarkTheme(value.theme)) { theme.preferredDark = value.theme } theme.preferred = value.theme theme.syncAcrossDevices = value.syncAcrossDevices theme.advancedRendering = value.advancedRendering + appSettings.nativeDecorations = value.nativeDecorations }, ) const themeOptions = computed(() => theme.options.filter( - (option) => - option !== 'retro' || settings.value.developer_mode || current.value.theme === 'retro', + (option) => option !== 'retro' || appSettings.devMode || current.value.theme === 'retro', ), ) @@ -147,7 +147,7 @@ provideAppearanceSettings({ set: setAdvancedRendering, }, nativeDecorations: - os !== 'MacOS' + os !== 'macos' ? { value: computed(() => current.value.nativeDecorations), set: setNativeDecorations, diff --git a/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/editors.ts b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/editors.ts index 0ccd80d64d..16908ab858 100644 --- a/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/editors.ts +++ b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/editors.ts @@ -64,6 +64,11 @@ export function gameSettingChanges( }) } +export function gameSettingNumberScale(setting: EditableGameSetting): number { + if (setting.editor.unit !== 'percent') return 1 + return setting.option_id === 'sensitivity' ? 200 : 100 +} + export function canonicalValueText(setting: EditableGameSetting): string { const value = setting.canonical_value if (!value) return '' @@ -74,7 +79,7 @@ export function canonicalValueText(setting: EditableGameSetting): string { case 'integer': case 'decimal': return setting.editor.unit === 'percent' - ? String(Number((Number(value.value) * 100).toFixed(8))) + ? String(Number((Number(value.value) * gameSettingNumberScale(setting)).toFixed(8))) : String(value.value) case 'string_list': return value.value.join(', ') @@ -90,7 +95,7 @@ export function canonicalBooleanValue(setting: EditableGameSetting): boolean | u export function isKeybindSetting(setting: EditableGameSetting): boolean { return ( setting.editor.type === 'key_binding' || - (setting.editor.type === 'external_raw' && !!setting.raw_key?.startsWith('key_key')) + (setting.editor.type === 'external_raw' && !!setting.raw_key?.startsWith('key_')) ) } @@ -114,7 +119,7 @@ export function canonicalValueFromInput( type: 'decimal', value: setting.editor.unit === 'percent' - ? String(Number((parsed / 100).toFixed(8))) + ? String(Number((parsed / gameSettingNumberScale(setting)).toFixed(8))) : String(value), } } diff --git a/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/index.vue b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/index.vue index f1a826bb1d..d5d4bade03 100644 --- a/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/index.vue +++ b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/index.vue @@ -29,9 +29,12 @@ import { useVIntl, } from '@modrinth/ui' import type { Component } from 'vue' -import { computed, ref } from 'vue' +import { computed, inject, ref } from 'vue' +import { type RouteLocationRaw, useRouter } from 'vue-router' import type { EditableGameSetting, GameSettingCategory } from '@/helpers/game-options' +import { injectInstanceSettings } from '@/pages/instance/components/settings-modal/instance-settings-context' +import { appSettingsModalContextKey } from '@/providers/app-settings-modal' import { canonicalValueText, @@ -47,6 +50,7 @@ import { } from './messages' import GameSettingRow from './row.vue' import { useGameSettingsEditor } from './use-editor' +import { useGameSettingLabels } from './use-labels' const props = defineProps<{ instanceId?: string @@ -57,6 +61,9 @@ const emit = defineEmits<{ }>() const { formatMessage } = useVIntl() +const router = useRouter() +const appSettingsModal = inject(appSettingsModalContextKey, null) +const instanceSettings = injectInstanceSettings(null) const messages = defineMessages({ title: { @@ -119,6 +126,7 @@ const modal = ref | null>(null) const confirmLeaveModal = ref | null>(null) const activeCategoryId = ref('') const search = ref('') +const opened = ref(false) let allowClose = false const { @@ -154,6 +162,21 @@ const categoryIcons: Record = { custom_settings: WrenchIcon, } +const localeLabels = useGameSettingLabels( + opened, + () => props.instanceId, + () => draftState.value?.settings ?? [], +) + +function settingLabel(setting: EditableGameSetting) { + if (setting.kind === 'external') { + return ( + localeLabels.value[setting.option_id]?.label ?? formatGameSettingLabel(formatMessage, setting) + ) + } + return formatGameSettingLabel(formatMessage, setting) +} + const categories = computed(() => { if (!draftState.value) return [] @@ -192,8 +215,12 @@ const categorySettings = computed(() => { query && !settingSearchText( setting, - formatGameSettingLabel(formatMessage, setting), - formatGameSettingDescription(formatMessage, setting), + settingLabel(setting), + setting.kind === 'external' + ? (localeLabels.value[setting.option_id]?.source?.project?.title ?? + localeLabels.value[setting.option_id]?.source?.file_name ?? + '') + : formatGameSettingDescription(formatMessage, setting), ).includes(query) ) return false @@ -220,7 +247,7 @@ const keybindConflicts = computed(() => { setting.option_id, settings .filter((candidate) => candidate.option_id !== setting.option_id) - .map((candidate) => formatGameSettingLabel(formatMessage, candidate)), + .map((candidate) => settingLabel(candidate)), ) } } @@ -267,6 +294,7 @@ async function load() { } function show() { + opened.value = true allowClose = false search.value = '' modal.value?.show() @@ -278,6 +306,7 @@ function hide() { } function reset() { + opened.value = false resetEditor() allowClose = false } @@ -295,6 +324,18 @@ async function confirmDiscard() { modal.value?.hide() } +async function openSource(location: RouteLocationRaw) { + if (isDirty.value || saving.value) return + if (appSettingsModal && !appSettingsModal.close()) return + allowClose = true + modal.value?.hide() + if (instanceSettings?.closeModal) { + instanceSettings.closeModal(() => void router.push(location)) + } else { + await router.push(location) + } +} + function toggleVisibleSync() { const enabled = !allCategorySettingsSynced.value const candidates = enabled ? enableCandidates.value : disableCandidates.value @@ -394,8 +435,11 @@ defineExpose({ show, hide }) v-for="setting in categorySettings" :key="setting.option_id" :setting="setting" + :locale-label="localeLabels[setting.option_id]" :keybind-conflicts="keybindConflicts.get(setting.option_id)" :show-sync-toggle="!isLocalEditor" + :source-navigation-disabled="isDirty || saving" + @open-source="openSource" @update:sync-enabled="setSyncEnabled([setting.option_id], $event)" @update:canonical-value="setCanonicalValue(setting.option_id, $event)" /> diff --git a/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/languages.ts b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/languages.ts new file mode 100644 index 0000000000..752e3aa928 --- /dev/null +++ b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/languages.ts @@ -0,0 +1,152 @@ +import type { ComboboxOption } from '@modrinth/ui' + +/** Java Edition language names and regions from https://github.com/misode/mcmeta/blob/assets/pack.mcmeta. */ +const languageNames: Record = { + en_us: 'English (US)', + af_za: 'Afrikaans (Suid-Afrika)', + esan: 'Andalûh (Andaluçía)', + enp: 'Anglish (Oned Riches)', + ast_es: 'Asturianu (Asturies)', + az_az: 'Azərbaycanca (Azərbaycan)', + id_id: 'Bahasa Indonesia (Indonesia)', + ms_my: 'Bahasa Melayu (Malaysia)', + tzo_mx: "Bats'i k'op (Jobel)", + qid: 'Bhs. Indonesia edjaän lama (Indonesia tempo doeloe)', + be_latn: 'Biełaruskaja (Biełaruś)', + bar: 'Boarisch (Bayern)', + bs_ba: 'Bosanski (Bosna i Hercegovina)', + brb: 'Braobans (Braobant)', + br_fr: 'Brezhoneg (Breizh)', + ca_es: 'Català (Catalunya)', + val_es: 'Català (Valencià) (País Valencià)', + cy_gb: 'Cymraeg (Cymru)', + qcb_es: 'Cántabru/Montañés (Cantabria)', + da_dk: 'Dansk (Danmark)', + se_no: 'Davvisámegiella (Sápmi)', + de_at: 'Deitsch (Österreich)', + de_de: 'Deutsch (Deutschland)', + et_ee: 'Eesti keel (Eesti)', + en_au: 'English (Australia)', + en_ca: 'English (Canada)', + en_nz: 'English (New Zealand)', + en_gb: 'English (United Kingdom)', + es_ar: 'Español (Argentina)', + es_cl: 'Español (Chile)', + es_ec: 'Español (Ecuador)', + es_es: 'Español (España)', + es_mx: 'Español (México)', + es_uy: 'Español (Uruguay)', + es_ve: 'Español (Venezuela)', + eo_uy: 'Esperanto (Esperantujo)', + eu_es: 'Euskara (Euskal Herria)', + fil_ph: 'Filipino (Pilipinas)', + fr_ca: 'Français (Canada)', + fr_fr: 'Français (France)', + fr_ch: 'Français (Suisse)', + fy_nl: 'Frysk (Fryslân)', + fra_de: 'Fränggisch (Franggn)', + fur_it: 'Furlan (Friûl)', + fo_fo: 'Føroyskt (Føroyar)', + ga_ie: 'Gaeilge (Éire)', + gl_es: 'Galego (Galicia / Galiza)', + go_fr: 'Galo (Bertègn)', + gd_gb: 'Gàidhlig (Alba)', + hr_hr: 'Hrvatski (Hrvatska)', + hn_no: 'Høgnorsk (Norig)', + io_en: 'Ido (Idia)', + ig_ng: 'Igbo (Naigeria)', + it_it: 'Italiano (Italia)', + kw_gb: 'Kernewek (Kernow)', + ksh: 'Kölsch/Ripoarisch (Rhingland)', + lol_us: 'LOLCAT (Kingdom of Cats)', + la_la: 'Latina (Latium)', + lv_lv: 'Latviešu (Latvija)', + lt_lt: 'Lietuvių (Lietuva)', + li_li: 'Limburgs (Limburg)', + lmo: 'Lombard (Lombardia)', + lb_lu: 'Lëtzebuergesch (Lëtzebuerg)', + hu_hu: 'Magyar (Magyarország)', + mt_mt: 'Malti (Malta)', + isv: 'Medžuslovjansky (Slovjanščina)', + nah: 'Mēxikatlahtōlli (Mēxiko)', + nl_nl: 'Nederlands (Nederland)', + pls: 'Ngiiwà (Ndanìꞌngà)', + no_no: 'Norsk bokmål (Norge)', + nn_no: 'Norsk nynorsk (Noreg)', + uz_uz: "O'zbekcha (O'zbekiston)", + oc_fr: 'Occitan (Occitània)', + en_pt: 'Pirate Speak (The Seven Seas)', + nds_de: 'Plattdüütsch (Düütschland)', + pl_pl: 'Polski (Polska)', + pt_br: 'Português (Brasil)', + pt_pt: 'Português (Portugal)', + qya_aa: 'Quenya (Arda)', + ro_ro: 'Română (România)', + de_ch: 'Schwiizerdütsch (Schwiiz)', + enws: 'Shakespearean English (Kingdom of England)', + sq_al: 'Shqip (Shqipëri)', + sk_sk: 'Slovenčina (Slovensko)', + sl_si: 'Slovenščina (Slovenija)', + so_so: 'Soomaali (Soomaaliya)', + sr_cs: 'Srpski (Srbija)', + fi_fi: 'Suomi (Suomi)', + sv_se: 'Svenska (Sverige)', + sxu: 'Säggs’sch (Saggsn)', + tl_ph: 'Tagalog (Pilipinas)', + vi_vn: 'Tiếng Việt (Việt Nam)', + tr_tr: 'Türkçe (Türkiye)', + vp_vl: 'Viossa (Vilant)', + nl_be: 'Vlaams (België)', + vec_it: 'Vèneto (Veneto)', + vro: 'Võro (Eesti)', + yo_ng: 'Yorùbá (Nàìjíríà)', + jbo_en: "la .lojban. (la jbogu'e)", + tlh_aa: "tlhIngan Hol (tlhIngan wo')", + tok: 'toki pona (kulupu pona)', + is_is: 'Íslenska (Ísland)', + ovd: 'Övdalska (Swerre)', + cs_cz: 'Čeština (Česko)', + szl: 'Ślōnski (Gōrny Ślōnsk)', + en_ud: 'ɥsᴉꞁᵷuƎ (uʍoᗡ ǝpᴉsd∩)', + haw_us: 'ʻŌlelo Hawaiʻi (Hawaiʻi)', + el_gr: 'Ελληνικά (Ελλάδα)', + ba_ru: 'Башҡортса (Башҡортостан, Рәсәй)', + be_by: 'Беларуская (Беларусь)', + bg_bg: 'Български (България)', + hal_ua: 'Галицка (Галичина, Вкраїна)', + ky_kg: 'Кыргызча (Кыргызстан)', + mk_mk: 'Македонски (Северна Македонија)', + mn_mn: 'Монгол (Монгол Улс)', + ry_ua: 'Руснацькый (Пудкарпатя, Украина)', + ru_ru: 'Русский (Россия)', + rpr: 'Русскій дореформенный (Россійская имперія)', + sah_sah: 'Сахалыы (Cаха Сирэ)', + sr_sp: 'Српски (Србија)', + tt_ru: 'Татарча (Татарстан, Рәсәй)', + uk_ua: 'Українська (Україна)', + cv_cu: 'Чӑвашла (Чӑваш Ен, Раҫҫей)', + kk_kz: 'Қазақша (Қазақстан)', + hy_am: 'Հայերեն (Հայաստան)', + yi_de: 'ייִדיש (אשכנזיש יידן)', + he_il: 'עברית (ישראל)', + ar_sa: 'العربية (العالم العربي)', + zlm_arab: 'بهاس ملايو (مليسيا)', + fa_ir: 'فارسی (ايران)', + hi_in: 'हिंदी (भारत)', + ta_in: 'தமிழ் (இந்தியா)', + kn_in: 'ಕನ್ನಡ (ಭಾರತ)', + th_th: 'ไทย (ประเทศไทย)', + lo_la: 'ລາວ (ປະເທດລາວ)', + ka_ge: 'ქართული (საქართველო)', + lzh: '文言 (華夏)', + ja_jp: '日本語 (日本)', + zh_cn: '简体中文 (中国大陆)', + zh_tw: '繁體中文 (台灣)', + zh_hk: '繁體中文 (香港特別行政區)', + ko_kr: '한국어 (대한민국)', + got_de: '𐌲𐌿𐍄𐍂𐌰𐌶𐌳𐌰 (𐌲𐌿𐍄𐌸𐌹𐌿𐌳𐌰)', +} + +export const minecraftLanguageOptions: ComboboxOption[] = Object.entries(languageNames) + .map(([value, label]) => ({ value, label, searchTerms: [value] })) + .sort((a, b) => a.label.localeCompare(b.label)) diff --git a/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/row.vue b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/row.vue index 049afab5c1..3c82fe7483 100644 --- a/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/row.vue +++ b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/row.vue @@ -1,6 +1,7 @@ diff --git a/apps/app-frontend/src/pages/instance/components/settings-modal/java-settings.vue b/apps/app-frontend/src/pages/instance/components/settings-modal/java-settings.vue index a660b09eaf..c94f3b01a3 100644 --- a/apps/app-frontend/src/pages/instance/components/settings-modal/java-settings.vue +++ b/apps/app-frontend/src/pages/instance/components/settings-modal/java-settings.vue @@ -228,6 +228,8 @@ const messages = defineMessages({ :step="64" :snap-points="snapPoints" :snap-range="512" + min-label="512 MB" + :max-label="`${Number((maxMemory / 1024).toFixed(1))} GB`" unit="MB" /> diff --git a/apps/app-frontend/src/pages/instance/content/index.vue b/apps/app-frontend/src/pages/instance/content/index.vue index 04e2d2df4d..347c4081b3 100644 --- a/apps/app-frontend/src/pages/instance/content/index.vue +++ b/apps/app-frontend/src/pages/instance/content/index.vue @@ -1,6 +1,6 @@