This commit is contained in:
Calum H. (IMB11)
2026-07-31 14:07:21 +01:00
parent e1774217c6
commit 501757b9d9
27 changed files with 68 additions and 132 deletions
@@ -14,11 +14,11 @@
</template>
<template #cell-actions="{ row }">
<div class="flex items-center justify-end">
<Button v-if="currentSelected.path === row.path" class="!shadow-none" disabled>
<Button v-if="currentSelected.path === row.path" disabled>
<CheckIcon aria-hidden="true" />
{{ formatMessage(messages.selected) }}
</Button>
<Button v-else class="!shadow-none" @click="setJavaInstall(row)">
<Button v-else @click="setJavaInstall(row)">
<PlusIcon aria-hidden="true" />
{{ formatMessage(messages.select) }}
</Button>
@@ -32,7 +32,7 @@
</Table>
<div class="flex justify-end">
<Button type="outlined"
class="!shadow-none !border-surface-4 !border"
class="!border-surface-4 !border"
@click="$refs.detectJavaModal.hide()"
>
<XIcon aria-hidden="true" />
@@ -27,7 +27,7 @@
: undefined
"
:aria-label="formatMessage(messages.testJavaInstallation)"
class="!shadow-none !text-[var(--legacy-button-color,var(--color-base))] [&>svg]:!text-[var(--legacy-button-color,var(--color-primary))]"
class="!text-[var(--legacy-button-color,var(--color-base))] [&>svg]:!text-[var(--legacy-button-color,var(--color-primary))]"
:disabled="testingJava || props.disabled"
@click="runTest(props.modelValue?.path)"
@mouseenter="!props.disabled && (hoveringTest = true)"
@@ -65,7 +65,6 @@
v-tooltip="
testingJavaSuccess === true ? formatMessage(messages.alreadyInstalled) : undefined
"
class="!shadow-none"
:disabled="props.disabled || installingJava || testingJavaSuccess === true"
@click="reinstallJava"
>
@@ -76,11 +75,11 @@
: formatMessage(messages.installRecommended)
}}
</Button>
<Button class="!shadow-none" :disabled="props.disabled" @click="autoDetect">
<Button :disabled="props.disabled" @click="autoDetect">
<SearchIcon />
{{ formatMessage(messages.detect) }}
</Button>
<Button class="!shadow-none" :disabled="props.disabled" @click="handleJavaFileInput()">
<Button :disabled="props.disabled" @click="handleJavaFileInput()">
<FolderSearchIcon />
{{ formatMessage(messages.browse) }}
</Button>
@@ -350,7 +350,7 @@ const messages = defineMessages({
v-tooltip="installing ? formatMessage(messages.duplicateButtonTooltipInstalling) : null"
aria-labelledby="duplicate-instance-label"
:disabled="installing"
class="w-max !shadow-none"
class="w-max"
@click="duplicateInstance"
>
<CopyIcon /> {{ formatMessage(messages.duplicateButton) }}
@@ -380,7 +380,7 @@ const messages = defineMessages({
class="w-full max-w-[300px]"
@submit="() => addCategory"
/>
<Button class="w-fit !shadow-none" @click="() => addCategory()">
<Button class="w-fit" @click="() => addCategory()">
<PlusIcon /> {{ formatMessage(messages.libraryGroupsCreate) }}
</Button>
</div>
@@ -414,7 +414,7 @@ const messages = defineMessages({
<Button type="colored" color="red"
aria-labelledby="delete-instance-label"
:disabled="removing"
class="w-fit !shadow-none"
class="w-fit"
@click="deleteConfirmModal.show()"
>
<SpinnerIcon v-if="removing" class="animate-spin" />
@@ -21,11 +21,11 @@
<div class="flex flex-col gap-6 px-6 pb-6">
<div class="flex justify-end gap-2">
<ButtonLink class="w-full !shadow-none" href="https://support.modrinth.com" @click="modal?.hide()">
<ButtonLink class="w-full" href="https://support.modrinth.com" @click="modal?.hide()">
<MessagesSquareIcon />
{{ formatMessage(messages.getSupport) }}
</ButtonLink>
<Button type="colored" color="brand" class="w-full !shadow-none" :disabled="loadingSignIn" @click="signIn">
<Button type="colored" color="brand" class="w-full" :disabled="loadingSignIn" @click="signIn">
<SpinnerIcon v-if="loadingSignIn" class="animate-spin" />
<svg
v-else
@@ -19,7 +19,7 @@
<div class="flex flex-col gap-6">
<div class="grid grid-cols-1 gap-2 sm:grid-cols-2">
<Button class="w-full !shadow-none" native-type="button" @click="authenticate('sign-up')">
<Button class="w-full" native-type="button" @click="authenticate('sign-up')">
<UserPlusIcon aria-hidden="true" />
{{ formatMessage(messages.createAccountButton) }}
</Button>
@@ -70,7 +70,7 @@
{{ formatMessage(messages.cancelButton) }}
</Button>
<Button
class="w-full !shadow-none"
class="w-full"
native-type="button"
:disabled="reopeningBrowser"
@click="reopenBrowser"
@@ -78,7 +78,7 @@ watch(
{{ formatMessage(messages.adsConsentTitle) }}
</h2>
<div class="mt-2 flex flex-col gap-2.5 items-start">
<Button class="!shadow-none" @click="manageAdsPreferences">
<Button @click="manageAdsPreferences">
<Settings2Icon aria-hidden="true" />
{{ formatMessage(messages.adsConsentManage) }}
</Button>
@@ -22,7 +22,7 @@
<div class="flex flex-col gap-4 w-full min-h-[20rem]">
<section v-if="mode === 'edit' && canEditTextureAndModel">
<h2 class="text-base font-semibold mb-2">{{ formatMessage(messages.textureSection) }}</h2>
<Button class="!shadow-none" @click="openTextureFileBrowser">
<Button @click="openTextureFileBrowser">
<UploadIcon /> {{ formatMessage(messages.replaceTextureButton) }}
</Button>
<input
@@ -15,7 +15,7 @@
<Button type="quiet" @click="modal?.hide()">
{{ formatMessage(analyticsChartMessages.cancelButton) }}
</Button>
<Button type="colored" color="orange" class="!shadow-none" @click="confirm">
<Button type="colored" color="orange" @click="confirm">
{{ formatMessage(analyticsChartMessages.showAll) }}
</Button>
</div>
@@ -32,7 +32,7 @@
@focusin="selectSearchInputText"
/>
<TeleportOverflowMenu label="More options"
class="!shadow-none !w-auto !px-2.5 !rounded-xl"
class="!w-auto !px-2.5 !rounded-xl"
:options="csvExportOptions"
:disabled="isDataLoading || filteredRows.length === 0"
>
@@ -50,7 +50,6 @@
<template v-if="showDependencyDownloadActions" #actions>
<div class="flex flex-wrap justify-end gap-2 p-2">
<Button
class="!shadow-none"
:disabled="!!downloadingActionType || !dependencyDownloadFilesLoaded"
@click="downloadSelectedVersionZip"
>
@@ -80,7 +79,6 @@
{{ formatMessage(messages.downloadWithDependencies) }}
</SplitButton>
<Button type="colored" color="brand" v-else
class="!shadow-none"
:disabled="!!downloadingActionType || !dependencyDownloadFilesLoaded"
@click="downloadFilesWithDependencies"
>
@@ -41,7 +41,7 @@
<section class="grid grid-cols-1 gap-2.5 sm:grid-cols-2">
<ButtonLink v-for="provider in oauthProviders" :key="provider.id"
class="relative w-full !justify-center overflow-visible !shadow-none"
class="relative w-full !justify-center overflow-visible"
:class="{
'!border !border-[var(--color-green)]': lastSignInProvider === provider.id,
}"
@@ -61,7 +61,7 @@
</span>
</ButtonLink>
<Button
class="relative w-full !justify-center overflow-visible !shadow-none sm:col-span-2"
class="relative w-full !justify-center overflow-visible sm:col-span-2"
:class="{ '!border !border-[var(--color-green)]': lastSignInProvider === 'passkey' }"
role="button"
tabindex="0"
@@ -7,7 +7,6 @@
</div>
<section class="flex flex-col gap-2.5">
<ButtonLink
class="!shadow-none"
:href="getAuthUrl('google', redirectTarget)"
@click="onOAuthProviderClick('google')"
>
@@ -15,7 +14,6 @@
<span>{{ formatMessage(messages.continueWithProvider, { provider: 'Google' }) }}</span>
</ButtonLink>
<ButtonLink
class="!shadow-none"
:href="getAuthUrl('microsoft', redirectTarget)"
@click="onOAuthProviderClick('microsoft')"
>
@@ -23,7 +21,6 @@
<span>{{ formatMessage(messages.continueWithProvider, { provider: 'Microsoft' }) }}</span>
</ButtonLink>
<ButtonLink
class="!shadow-none"
:href="getAuthUrl('discord', redirectTarget)"
@click="onOAuthProviderClick('discord')"
>
@@ -32,7 +29,6 @@
</ButtonLink>
<template v-if="showOtherOptions">
<ButtonLink
class="!shadow-none"
:href="getAuthUrl('github', redirectTarget)"
@click="onOAuthProviderClick('github')"
>
@@ -40,7 +36,6 @@
<span>{{ formatMessage(messages.continueWithProvider, { provider: 'GitHub' }) }}</span>
</ButtonLink>
<ButtonLink
class="!shadow-none"
:href="getAuthUrl('gitlab', redirectTarget)"
@click="onOAuthProviderClick('gitlab')"
>
@@ -48,7 +43,6 @@
<span>{{ formatMessage(messages.continueWithProvider, { provider: 'GitLab' }) }}</span>
</ButtonLink>
<ButtonLink
class="!shadow-none"
:href="getAuthUrl('steam', redirectTarget)"
@click="onOAuthProviderClick('steam')"
>
@@ -25,7 +25,7 @@
</div>
<div v-if="!hideRemove" class="flex shrink-0 items-center justify-end gap-1">
<Button aria-label="Remove file" class="-mr-2 !shadow-none" @click="emitRemove">
<Button aria-label="Remove file" class="-mr-2" @click="emitRemove">
<XIcon aria-hidden="true" />
</Button>
</div>
@@ -26,7 +26,7 @@
</div>
<div class="flex shrink-0 items-center justify-end gap-1">
<Button type="quiet" aria-label="Add dependency" class="!shadow-none" @click="emitAddSuggestion">
<Button type="quiet" aria-label="Add dependency" @click="emitAddSuggestion">
<PlusIcon aria-hidden="true" />
</Button>
</div>
@@ -27,7 +27,7 @@
</div>
</template>
<Button v-if="onRemove" aria-label="Remove file" class="!shadow-none" @click="onRemove">
<Button v-if="onRemove" aria-label="Remove file" @click="onRemove">
<XIcon aria-hidden="true" />
</Button>
<Button v-if="isPrimary"
@@ -37,7 +37,6 @@
: 'Replace primary file'
"
aria-label="Change primary file"
class="!shadow-none"
:disabled="editingVersion"
@click="primaryFileInput?.click()"
>
@@ -30,7 +30,6 @@
<Button
v-tooltip="'Replace file'"
aria-label="Replace file"
class="!shadow-none"
@click="fileInput?.click()"
>
<ArrowLeftRightIcon aria-hidden="true" />
@@ -86,7 +86,6 @@
:type="rightButtonConfig.color && rightButtonConfig.color !== 'standard' ? 'colored' : 'base'"
:color="rightButtonConfig.color === 'standard' ? undefined : rightButtonConfig.color"
v-tooltip="rightButtonConfig.tooltip"
class="!shadow-none"
:class="rightButtonConfig.buttonClass"
:disabled="rightButtonConfig.disabled || rightButtonConfig.loading"
@click="rightButtonConfig.onClick"
@@ -70,12 +70,12 @@
<!-- Add launcher path -->
<div v-if="!showAddPath">
<Button class="w-full !shadow-none" @click="showAddPath = true">
<Button class="w-full" @click="showAddPath = true">
{{ formatMessage(messages.addLauncherPath) }}
</Button>
</div>
<div v-else class="flex items-center gap-2">
<IconButton label="Browse for launcher path" class="!shadow-none" @click="browseForLauncherPath">
<IconButton label="Browse for launcher path" @click="browseForLauncherPath">
<FolderSearchIcon />
</IconButton>
<StyledInput
@@ -83,7 +83,7 @@
:placeholder="formatMessage(messages.launcherPathPlaceholder)"
class="flex-1"
/>
<Button class="!shadow-none" :disabled="!newLauncherPath.trim()" @click="addLauncherPath">
<Button :disabled="!newLauncherPath.trim()" @click="addLauncherPath">
{{ formatMessage(messages.add) }}
</Button>
</div>
@@ -31,7 +31,7 @@
wrapper-class="max-w-[20rem]"
/>
<div class="flex gap-2 justify-end">
<Button class="!shadow-none" @click="hide()">
<Button @click="hide()">
<XIcon />
Cancel
</Button>
@@ -89,7 +89,7 @@
<template v-if="item.buttons?.length">
<div class="col-span-2 flex flex-wrap gap-1.5 pt-1">
<Button :type="(button.color) && (button.color) !== 'standard' ? 'colored' : 'base'" :color="(button.color) && (button.color) !== 'standard' ? ((button.color) === 'medal-promo' ? 'medal_promotion' : (button.color)) : undefined" v-for="(button, buttonIndex) in item.buttons"
:key="buttonIndex" class="!shadow-none" @click="handleButtonClick(item, button)">
:key="buttonIndex" @click="handleButtonClick(item, button)">
<component :is="button.icon" v-if="button.icon" />
{{ button.label }}
</Button>
@@ -141,7 +141,7 @@
/>
<div v-if="item.buttons?.length" class="flex gap-1.5">
<Button :type="(btn.color || (idx === 0 ? 'brand' : undefined)) && (btn.color || (idx === 0 ? 'brand' : undefined)) !== 'standard' ? 'colored' : 'base'" :color="(btn.color || (idx === 0 ? 'brand' : undefined)) && (btn.color || (idx === 0 ? 'brand' : undefined)) !== 'standard' ? ((btn.color || (idx === 0 ? 'brand' : undefined)) === 'medal-promo' ? 'medal_promotion' : (btn.color || (idx === 0 ? 'brand' : undefined))) : undefined" v-for="(btn, idx) in item.buttons"
:key="idx" class="!shadow-none" @click="handleButtonClick(item.id, btn)">
:key="idx" @click="handleButtonClick(item.id, btn)">
<component :is="btn.icon" v-if="btn.icon" />
{{ btn.label }}
</Button>
@@ -132,7 +132,7 @@
class="col-start-1 col-end-3 row-start-3 mt-2 flex min-w-0 flex-wrap items-center gap-2"
>
<Button :type="(action.color || (index === 0 ? 'brand' : undefined)) && (action.color || (index === 0 ? 'brand' : undefined)) !== 'standard' ? 'colored' : 'base'" :color="(action.color || (index === 0 ? 'brand' : undefined)) && (action.color || (index === 0 ? 'brand' : undefined)) !== 'standard' ? ((action.color || (index === 0 ? 'brand' : undefined)) === 'medal-promo' ? 'medal_promotion' : (action.color || (index === 0 ? 'brand' : undefined))) : undefined" v-for="(action, index) in actions"
:key="index" class="!shadow-none" @click="$emit('action', index)">
:key="index" @click="$emit('action', index)">
<component :is="action.icon" v-if="action.icon" />
{{ action.label }}
</Button>
@@ -102,7 +102,7 @@
</div>
<Button
native-type="button"
class="!h-10 w-full !justify-between !px-4 text-left !shadow-none"
class="!h-10 w-full !justify-between !px-4 text-left"
@click="copyInviteLink"
>
<span class="min-w-0 truncate text-base font-semibold text-primary">
@@ -18,7 +18,6 @@
? formatMessage(messages.backupInProgress)
: undefined
"
class="!shadow-none"
:disabled="
!canManageBackups || backup.isBackingUp.value || backup.externalBackupInProgress.value
"
@@ -699,7 +699,6 @@ const messages = defineMessages({
<div>
<Button type="colored" color="orange"
v-tooltip="ctx.isBusy.value ? ctx.busyMessage?.value : undefined"
class="!shadow-none"
:disabled="ctx.isBusy.value"
@click="handleShowUnlinkModal"
>
@@ -731,7 +730,6 @@ const messages = defineMessages({
<div>
<Button type="colored" color="red"
v-tooltip="ctx.isBusy.value ? ctx.busyMessage?.value : undefined"
class="!shadow-none"
:disabled="ctx.isBusy.value"
@click="handleShowReinstallModal"
>
@@ -918,7 +916,6 @@ const messages = defineMessages({
<div class="flex flex-wrap gap-2">
<Button type="colored" color="brand"
v-tooltip="ctx.isBusy.value ? ctx.busyMessage?.value : undefined"
class="!shadow-none"
:disabled="
!form.isValid.value ||
!form.hasChanges.value ||
@@ -963,7 +960,6 @@ const messages = defineMessages({
<div class="flex flex-wrap gap-2">
<Button type="colored" color="orange"
v-tooltip="ctx.isBusy.value ? ctx.busyMessage?.value : undefined"
class="!shadow-none"
:disabled="ctx.isBusy.value"
@click="handleStartEditing"
>
@@ -22,82 +22,54 @@
<div class="flex flex-col gap-2.5 rounded-2xl bg-surface-2 p-4">
<span class="text-lg font-semibold text-contrast">Server Address</span>
<div
<Button
native-type="button"
v-tooltip="sftpCopyTooltip('Copy SFTP server address')"
class="copy-field hover:bg-button-bg-hover"
:class="{ 'opacity-60': !canWriteFiles }"
class="!h-10 w-full !justify-between !px-4 text-left"
:disabled="!canWriteFiles"
@click="copyToClipboard('Server address', server?.sftp_host)"
>
<span class="cursor-pointer font-semibold text-primary">
<span class="min-w-0 truncate text-base font-semibold text-primary">
{{ server?.sftp_host }}
</span>
<div class="grid h-10 w-10 place-content-center">
<CopyIcon class="h-5 w-5" />
</div>
</div>
<ClipboardCopyIcon class="size-5 shrink-0 text-secondary" aria-hidden="true" />
</Button>
<div class="flex flex-col gap-2 sm:mt-0 sm:flex-row">
<div class="flex w-full flex-col justify-center gap-2">
<span class="text-lg font-semibold text-contrast">Username</span>
<div
<Button
native-type="button"
v-tooltip="sftpCopyTooltip('Copy SFTP username')"
class="copy-field hover:bg-button-bg-hover"
:class="{ 'opacity-60': !canWriteFiles }"
class="!h-10 w-full !justify-between !px-4 text-left"
:disabled="!canWriteFiles"
@click="copyToClipboard('Username', server?.sftp_username)"
>
<div class="truncate font-semibold">
<span class="min-w-0 truncate text-base font-semibold text-primary">
{{ server?.sftp_username }}
</div>
<div class="grid h-10 w-9 place-content-center">
<CopyIcon class="h-5 w-5" />
</div>
</div>
</span>
<ClipboardCopyIcon
class="size-5 shrink-0 text-secondary"
aria-hidden="true"
/>
</Button>
</div>
<div class="flex w-full flex-col justify-center gap-2">
<span class="text-lg font-semibold text-contrast">Password</span>
<div
class="copy-field-has-button [&:hover:not(:has(button:hover))]:bg-button-bg-hover"
:class="{ 'opacity-60': !canWriteFiles }"
<Button
native-type="button"
v-tooltip="sftpCopyTooltip('Copy SFTP password')"
class="!h-10 w-full !justify-between !px-4 text-left"
:disabled="!canWriteFiles"
@click="copyToClipboard('Password', server?.sftp_password)"
>
<div class="flex items-center gap-1.5 h-full w-full">
<div
v-tooltip="sftpCopyTooltip('Copy SFTP Password')"
class="h-full flex justify-between grow items-center"
>
<div class="truncate font-semibold">
{{
showPassword
? server?.sftp_password
: '*'.repeat(server?.sftp_password?.length ?? 0)
}}
</div>
<CopyIcon class="h-5 w-5" />
</div>
<IconButton type="quiet" :label="
canWriteFiles
? showPassword
? 'Hide password'
: 'Show password'
: permissionDeniedMessage
"
v-tooltip="
canWriteFiles
? showPassword
? 'Hide password'
: 'Show password'
: permissionDeniedMessage
"
class="hover:bg-button-bg-hover grid h-10 w-10 place-content-center rounded-lg"
:disabled="!canWriteFiles"
@click.stop="togglePasswordVisibility"
>
<!-- look into doing stop propagation here -->
<EyeIcon v-if="showPassword" class="h-5 w-5" />
<EyeOffIcon v-else class="h-5 w-5" />
</IconButton>
</div>
</div>
<span class="min-w-0 truncate text-base font-semibold text-primary">
{{ '*'.repeat(server?.sftp_password?.length ?? 0) }}
</span>
<ClipboardCopyIcon
class="size-5 shrink-0 text-secondary"
aria-hidden="true"
/>
</Button>
</div>
</div>
</div>
@@ -157,6 +129,7 @@
:options="displayedJavaVersions"
:display-value="javaVersionLabel ?? 'Java Version'"
:disabled="isStartupLoading || !canUseAdvancedSettings"
trigger-type="base"
>
<template #dropdown-footer>
<button
@@ -194,6 +167,7 @@
:options="JRE_VENDORS"
:display-value="jreVendorLabel ?? 'Runtime'"
:disabled="isStartupLoading || !canUseAdvancedSettings"
trigger-type="base"
/>
<div
v-if="isStartupLoading"
@@ -217,10 +191,10 @@
</template>
<script setup lang="ts">
import { Button, ButtonLink, IconButton } from '#ui/components/base/buttons'
import { Button, ButtonLink } from '#ui/components/base/buttons'
import type { Archon } from '@modrinth/api-client'
import {
CopyIcon,
ClipboardCopyIcon,
ExternalIcon,
EyeIcon,
EyeOffIcon,
@@ -245,8 +219,6 @@ const client = injectModrinthClient()
const queryClient = useQueryClient()
const { canUseAdvancedSettings, canWriteFiles, permissionDeniedMessage } = useServerPermissions()
// SFTP state
const showPassword = ref(false)
const sftpUrl = computed(() => `sftp://${server.value?.sftp_username}@${server.value?.sftp_host}`)
const advancedActionTooltip = computed(() =>
canUseAdvancedSettings.value ? undefined : permissionDeniedMessage.value,
@@ -282,11 +254,6 @@ const { data: startupData, isLoading: isStartupLoading } = useQuery({
enabled: computed(() => worldId.value !== null),
})
function togglePasswordVisibility() {
if (!canWriteFiles.value) return
showPassword.value = !showPassword.value
}
const JAVA_VERSIONS = [
{ value: 8, label: 'Java 8' },
{ value: 11, label: 'Java 11' },
@@ -428,15 +395,3 @@ function resetToDefault() {
startupCommand.value = defaultStartupCommand.value
}
</script>
<style scoped>
.copy-field {
@apply flex h-10 cursor-pointer items-center justify-between gap-2 rounded-lg bg-button-bg px-3 pr-1.5 transition-all;
@apply hover:brightness-125 active:scale-95;
}
.copy-field-has-button {
@apply flex h-10 cursor-pointer items-center justify-between gap-2 rounded-lg bg-button-bg px-3 pr-1.5 transition-all;
@apply [&:hover:not(:has(button:hover))]:brightness-125 [&:active:not(:has(button:active))]:scale-95;
}
</style>
@@ -24,7 +24,6 @@
<div>
<Button type="colored" color="red"
v-tooltip="resetServerDisabledTooltip"
class="!shadow-none"
:disabled="resetServerDisabled"
@click="showResetServerModal"
>
@@ -57,10 +56,9 @@
{{ formatMessage(messages.supportOptionsTitle) }}
</span>
<div>
<Button type="colored" color="red"
v-tooltip="supportResetToOnboardingTooltip"
class="!shadow-none"
:disabled="supportResetToOnboardingDisabled"
<Button type="colored" color="red"
v-tooltip="supportResetToOnboardingTooltip"
:disabled="supportResetToOnboardingDisabled"
@click="showResetToOnboardingModal"
>
<RotateCounterClockwiseIcon class="size-5" />