diff --git a/.github/instructions/i18n-convert.instructions.md b/.github/instructions/i18n-convert.instructions.md index 91786f4fe3..aa1f5a53f3 100644 --- a/.github/instructions/i18n-convert.instructions.md +++ b/.github/instructions/i18n-convert.instructions.md @@ -33,24 +33,24 @@ Please follow these rules precisely: "By creating an account, you agree to our Terms and Privacy Policy." - Render rich-text messages with `` from `@modrinth/ui` using named slots: - - + + - For simple emphasis: `'Welcome to Modrinth!'` with a slot: - For more complex child handling, use `normalizeChildren` from `@modrinth/ui`: 5. Formatting in templates diff --git a/AGENTS.md b/AGENTS.md index c962748cbc..4e46b24039 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -70,12 +70,14 @@ Each project may have its own file with detailed instructions: ## Code Guidelines ### Comments + - DO NOT use "heading" comments like: `=== Helper methods ===`. - Use doc comments, but avoid inline comments unless ABSOLUTELY necessary for clarity. Code should aim to be self documenting! ## Bash Guidelines ### Output handling + - DO NOT pipe output through `head`, `tail`, `less`, or `more` - NEVER use `| head -n X` or `| tail -n X` to truncate output - IMPORTANT: Run commands directly without pipes when possible @@ -83,6 +85,7 @@ Each project may have its own file with detailed instructions: - ALWAYS read the full output — never pipe through filters ### General + - Do not create new non-source code files (e.g. Bash scripts, SQL scripts) unless explicitly prompted to - For Frontend, when doing lint checks, only use the `prepr` commands, do not use `typecheck` or `tsc` etc. - Types in `@modrinth/utils` are considered highly outdated, if a component needs them, check if you can switch said component to use types from `packages/api-client` diff --git a/apps/app/capabilities/plugins.json b/apps/app/capabilities/plugins.json index 875968d902..65d1441028 100644 --- a/apps/app/capabilities/plugins.json +++ b/apps/app/capabilities/plugins.json @@ -2,9 +2,7 @@ "identifier": "plugins", "description": "", "local": true, - "windows": [ - "main" - ], + "windows": ["main"], "permissions": [ "dialog:allow-open", "dialog:allow-confirm", diff --git a/apps/daedalus_client/Cargo.toml b/apps/daedalus_client/Cargo.toml index 080fab4f3e..7296a32249 100644 --- a/apps/daedalus_client/Cargo.toml +++ b/apps/daedalus_client/Cargo.toml @@ -21,11 +21,7 @@ futures = { workspace = true } indexmap = { workspace = true, features = ["serde"] } itertools = { workspace = true } quick-xml = { workspace = true } -reqwest = { workspace = true, features = [ - "json", - "rustls-tls-native-roots", - "stream", -] } +reqwest = { workspace = true, features = ["json", "rustls-tls-native-roots", "stream"] } rust-s3 = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } diff --git a/apps/docs/src/styles/modrinth.css b/apps/docs/src/styles/modrinth.css index 4f149c26a7..b61c7fbe4c 100644 --- a/apps/docs/src/styles/modrinth.css +++ b/apps/docs/src/styles/modrinth.css @@ -2,8 +2,9 @@ ::backdrop, :root[data-theme='light'], [data-theme='light'] ::backdrop { - --sl-font-system: Inter, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Roboto, - Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; + --sl-font-system: + Inter, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Roboto, Cantarell, + Fira Sans, Droid Sans, Helvetica Neue, sans-serif; --sl-color-white: var(--color-contrast); /* “white” */ --sl-color-gray-1: var(--color-base); diff --git a/apps/frontend/src/pages/settings/billing/index.vue b/apps/frontend/src/pages/settings/billing/index.vue index a993e5246e..d4309189f1 100644 --- a/apps/frontend/src/pages/settings/billing/index.vue +++ b/apps/frontend/src/pages/settings/billing/index.vue @@ -291,7 +291,9 @@ v-bind="subscription.serverInfo" :pending-change="getPendingChange(subscription)" :cancellation-date="getCancellationDate(subscription)" - :on-download-backup="getBackupDownloadForServer(subscription.serverInfo)" + :on-download-world=" + getWorldDownload(subscription.serverInfo.server_id, serverFullList) + " />

@@ -508,11 +510,7 @@ {{ formatMessage(messages.upgrade) }}

-
- +
- +
+ + +
@@ -95,17 +106,27 @@ :description="formatMessage(messages.emptyDescription)" > (() => [ const client = injectModrinthClient() const queryClient = useQueryClient() const { server, worldId, busyReasons } = injectModrinthServerContext() +const { downloadWorldFiles } = useServerWorldDownload() +const isDownloadingFiles = ref(false) + +async function downloadFiles() { + const node = server.value.node + const currentWorldId = worldId.value + if (!node || !currentWorldId || isDownloadingFiles.value) return + + isDownloadingFiles.value = true + try { + await downloadWorldFiles(node.instance, currentWorldId) + } finally { + isDownloadingFiles.value = false + } +} const props = defineProps<{ isServerRunning: boolean diff --git a/packages/ui/src/layouts/wrapped/hosting/manage/index.vue b/packages/ui/src/layouts/wrapped/hosting/manage/index.vue index 061d7c2e1c..ba1891ca23 100644 --- a/packages/ui/src/layouts/wrapped/hosting/manage/index.vue +++ b/packages/ui/src/layouts/wrapped/hosting/manage/index.vue @@ -188,7 +188,7 @@ :cancellation-date="serverBillingMap.get(server.server_id)?.cancellationDate" :is-provisioning="serverBillingMap.get(server.server_id)?.isProvisioning" :on-resubscribe="serverBillingMap.get(server.server_id)?.onResubscribe" - :on-download-backup="serverBillingMap.get(server.server_id)?.onDownloadBackup" + :on-download-world="getWorldDownload(server.server_id, serverFullList)" />
@@ -238,16 +238,18 @@ import { HammerIcon, LoaderCircleIcon, PlusIcon, SearchIcon } from '@modrinth/as import { CopyCode, defineMessages, + hasAvailableWorldDownload, injectAuth, injectModrinthClient, injectNotificationManager, Input, IntlFormatted, + isWithinServerResubscribeWindow, ModrinthServersPurchaseModal, ResubscribeModal, ServerListEmpty, ServersGuestPlanModal, - useServerBackupDownload, + useServerWorldDownload, useVIntl, } from '@modrinth/ui' import { useQuery, useQueryClient } from '@tanstack/vue-query' @@ -561,14 +563,14 @@ function sortServers(array: Archon.Servers.v0.Server[]): Archon.Servers.v0.Serve }) } -// files expire 30 days after cancellation -function filesExpired(server: Archon.Servers.v0.Server): boolean { - if (server.status !== 'suspended' || server.suspension_reason !== 'cancelled') return false +function shouldShowServer(server: Archon.Servers.v0.Server): boolean { + if (server.status !== 'suspended' || server.suspension_reason !== 'cancelled') return true const cancellationDate = serverBillingMap.value.get(server.server_id)?.cancellationDate - if (!cancellationDate) return false - const cancellation = new Date(cancellationDate) - const thirtyDaysLater = new Date(cancellation.getTime() + 30 * 24 * 60 * 60 * 1000) - return new Date() > thirtyDaysLater + if (!cancellationDate || !serverFullList.value) return true + return ( + isWithinServerResubscribeWindow(cancellationDate) || + hasAvailableWorldDownload(server.server_id, serverFullList.value) + ) } function isServerOwnedByCurrentUser(server: Archon.Servers.v0.Server): boolean { @@ -586,11 +588,13 @@ function getServerOwner(server: Archon.Servers.v0.Server): ServerListingOwner | } const ownedServerList = computed(() => - serverList.value.filter((server) => !filesExpired(server) && isServerOwnedByCurrentUser(server)), + serverList.value.filter( + (server) => shouldShowServer(server) && isServerOwnedByCurrentUser(server), + ), ) const sharedServerList = computed(() => serverList.value - .filter((server) => !filesExpired(server) && !isServerOwnedByCurrentUser(server)) + .filter((server) => shouldShowServer(server) && !isServerOwnedByCurrentUser(server)) .map((server) => ({ ...server, owner: getServerOwner(server), @@ -636,7 +640,7 @@ watch(serverResponse, (response) => { const { addNotification } = injectNotificationManager() const queryClient = useQueryClient() -const { getLatestBackupDownload } = useServerBackupDownload() +const { getWorldDownload } = useServerWorldDownload() function handlePurchaseSuccess() { startNewServerPolling(serverResponse.value?.servers ?? []) @@ -776,7 +780,6 @@ type ServerBillingInfo = { cancellationDate?: string | null isProvisioning?: boolean onResubscribe?: () => void - onDownloadBackup?: (() => void) | null } type ResubscribeRequest = { @@ -928,12 +931,12 @@ const serverBillingMap = computed(() => { (charge?.status === 'processing' || charge?.status === 'open'), } - info.onDownloadBackup = getLatestBackupDownload(serverId, serverFullList.value) - if (charge?.status === 'cancelled') { info.cancellationDate = charge.due - info.onResubscribe = () => openResubscribeModal(serverId, sub, charge) + if (isWithinServerResubscribeWindow(charge.due)) { + info.onResubscribe = () => openResubscribeModal(serverId, sub, charge) + } } map.set(serverId, info) diff --git a/packages/ui/src/locales/de-CH/index.json b/packages/ui/src/locales/de-CH/index.json index 52c5297b3c..43507c9aff 100644 --- a/packages/ui/src/locales/de-CH/index.json +++ b/packages/ui/src/locales/de-CH/index.json @@ -5153,9 +5153,6 @@ "servers.listing.copy-id-label": { "defaultMessage": "ID kopieren" }, - "servers.listing.download-latest-backup-tooltip": { - "defaultMessage": "Neueste Sicherung herunterladen" - }, "servers.listing.manage-billing-label": { "defaultMessage": "Abrechnung verwalten" }, diff --git a/packages/ui/src/locales/de-DE/index.json b/packages/ui/src/locales/de-DE/index.json index 63a10cf572..a69c6f5f49 100644 --- a/packages/ui/src/locales/de-DE/index.json +++ b/packages/ui/src/locales/de-DE/index.json @@ -5153,9 +5153,6 @@ "servers.listing.copy-id-label": { "defaultMessage": "ID kopieren" }, - "servers.listing.download-latest-backup-tooltip": { - "defaultMessage": "Neueste Sicherung herunterladen" - }, "servers.listing.manage-billing-label": { "defaultMessage": "Abrechnung verwalten" }, diff --git a/packages/ui/src/locales/en-US/index.json b/packages/ui/src/locales/en-US/index.json index 363460f362..5207c916bf 100644 --- a/packages/ui/src/locales/en-US/index.json +++ b/packages/ui/src/locales/en-US/index.json @@ -206,6 +206,9 @@ "button.download": { "defaultMessage": "Download" }, + "button.download-files": { + "defaultMessage": "Download files" + }, "button.downloading": { "defaultMessage": "Downloading" }, @@ -5162,6 +5165,18 @@ "servers.busy.installing": { "defaultMessage": "Server is installing" }, + "servers.download.failed.description": { + "defaultMessage": "An error occurred while trying to download the world's files." + }, + "servers.download.failed.title": { + "defaultMessage": "Download failed" + }, + "servers.download.unavailable.description": { + "defaultMessage": "This world's files cannot currently be downloaded." + }, + "servers.download.unavailable.title": { + "defaultMessage": "Download unavailable" + }, "servers.files.zip-created": { "defaultMessage": "ZIP created" }, @@ -5315,9 +5330,6 @@ "servers.listing.copy-id-label": { "defaultMessage": "Copy ID" }, - "servers.listing.download-latest-backup-tooltip": { - "defaultMessage": "Download latest backup" - }, "servers.listing.manage-billing-label": { "defaultMessage": "Manage billing" }, diff --git a/packages/ui/src/locales/es-419/index.json b/packages/ui/src/locales/es-419/index.json index 54d0d15df1..34b7cf5076 100644 --- a/packages/ui/src/locales/es-419/index.json +++ b/packages/ui/src/locales/es-419/index.json @@ -5153,9 +5153,6 @@ "servers.listing.copy-id-label": { "defaultMessage": "Copiar ID" }, - "servers.listing.download-latest-backup-tooltip": { - "defaultMessage": "Descargar el respaldo más reciente" - }, "servers.listing.manage-billing-label": { "defaultMessage": "Gestionar facturación" }, diff --git a/packages/ui/src/locales/es-ES/index.json b/packages/ui/src/locales/es-ES/index.json index 6d6cfc540a..21f3e22449 100644 --- a/packages/ui/src/locales/es-ES/index.json +++ b/packages/ui/src/locales/es-ES/index.json @@ -4952,9 +4952,6 @@ "servers.listing.copy-id-label": { "defaultMessage": "Copiar ID" }, - "servers.listing.download-latest-backup-tooltip": { - "defaultMessage": "Descargar último respaldo" - }, "servers.listing.manage-billing-label": { "defaultMessage": "Gestiona facturaciones" }, diff --git a/packages/ui/src/locales/fr-FR/index.json b/packages/ui/src/locales/fr-FR/index.json index 05ab48ec5d..abe70d6922 100644 --- a/packages/ui/src/locales/fr-FR/index.json +++ b/packages/ui/src/locales/fr-FR/index.json @@ -4832,9 +4832,6 @@ "servers.listing.copy-id-label": { "defaultMessage": "Copier l'ID" }, - "servers.listing.download-latest-backup-tooltip": { - "defaultMessage": "Télécharger la dernière sauvegarde" - }, "servers.listing.manage-billing-label": { "defaultMessage": "Gérer la facturation" }, diff --git a/packages/ui/src/locales/hu-HU/index.json b/packages/ui/src/locales/hu-HU/index.json index 991c9ab56e..8f063652ef 100644 --- a/packages/ui/src/locales/hu-HU/index.json +++ b/packages/ui/src/locales/hu-HU/index.json @@ -4175,9 +4175,6 @@ "servers.listing.copy-id-label": { "defaultMessage": "Azonosító másolása" }, - "servers.listing.download-latest-backup-tooltip": { - "defaultMessage": "A legfrissebb biztonsági mentés letöltése" - }, "servers.listing.manage-billing-label": { "defaultMessage": "Számlázás kezelése" }, diff --git a/packages/ui/src/locales/it-IT/index.json b/packages/ui/src/locales/it-IT/index.json index aa9af79e61..85e8d69ebc 100644 --- a/packages/ui/src/locales/it-IT/index.json +++ b/packages/ui/src/locales/it-IT/index.json @@ -5096,9 +5096,6 @@ "servers.listing.copy-id-label": { "defaultMessage": "Copia ID" }, - "servers.listing.download-latest-backup-tooltip": { - "defaultMessage": "Scarica l'ultimo backup" - }, "servers.listing.manage-billing-label": { "defaultMessage": "Gestione fatturazione" }, diff --git a/packages/ui/src/locales/ja-JP/index.json b/packages/ui/src/locales/ja-JP/index.json index 5cd0e61468..801ba1f6ea 100644 --- a/packages/ui/src/locales/ja-JP/index.json +++ b/packages/ui/src/locales/ja-JP/index.json @@ -4487,9 +4487,6 @@ "servers.listing.copy-id-label": { "defaultMessage": "IDをコピー" }, - "servers.listing.download-latest-backup-tooltip": { - "defaultMessage": "最新のバックアップをダウンロード" - }, "servers.listing.manage-billing-label": { "defaultMessage": "請求設定" }, diff --git a/packages/ui/src/locales/ko-KR/index.json b/packages/ui/src/locales/ko-KR/index.json index f7ad1e4ae6..440a78e538 100644 --- a/packages/ui/src/locales/ko-KR/index.json +++ b/packages/ui/src/locales/ko-KR/index.json @@ -4820,9 +4820,6 @@ "servers.listing.copy-id-label": { "defaultMessage": "신분증 복사" }, - "servers.listing.download-latest-backup-tooltip": { - "defaultMessage": "최신 백업 다운로드" - }, "servers.listing.manage-billing-label": { "defaultMessage": "청구 관리" }, diff --git a/packages/ui/src/locales/ms-MY/index.json b/packages/ui/src/locales/ms-MY/index.json index 46b9247e74..afe5cd4d20 100644 --- a/packages/ui/src/locales/ms-MY/index.json +++ b/packages/ui/src/locales/ms-MY/index.json @@ -3905,9 +3905,6 @@ "servers.listing.copy-id-label": { "defaultMessage": "Salin ID" }, - "servers.listing.download-latest-backup-tooltip": { - "defaultMessage": "Muat turun sandaran terkini" - }, "servers.listing.manage-billing-label": { "defaultMessage": "Urus pengebilan" }, diff --git a/packages/ui/src/locales/nl-NL/index.json b/packages/ui/src/locales/nl-NL/index.json index b7ca9ce76b..03c5cc115a 100644 --- a/packages/ui/src/locales/nl-NL/index.json +++ b/packages/ui/src/locales/nl-NL/index.json @@ -4625,9 +4625,6 @@ "servers.listing.copy-id-label": { "defaultMessage": "Kopieer ID" }, - "servers.listing.download-latest-backup-tooltip": { - "defaultMessage": "Laatste back-up downloaden" - }, "servers.listing.manage-billing-label": { "defaultMessage": "Facturering beheren" }, diff --git a/packages/ui/src/locales/pl-PL/index.json b/packages/ui/src/locales/pl-PL/index.json index e56694e4a5..ecb1a186ab 100644 --- a/packages/ui/src/locales/pl-PL/index.json +++ b/packages/ui/src/locales/pl-PL/index.json @@ -4970,9 +4970,6 @@ "servers.listing.copy-id-label": { "defaultMessage": "Kopiuj ID" }, - "servers.listing.download-latest-backup-tooltip": { - "defaultMessage": "Pobierz najnowszy backup" - }, "servers.listing.manage-billing-label": { "defaultMessage": "Zarządzaj rozliczaniem" }, diff --git a/packages/ui/src/locales/pt-BR/index.json b/packages/ui/src/locales/pt-BR/index.json index ab7cbb2e9c..d84ee7d9d4 100644 --- a/packages/ui/src/locales/pt-BR/index.json +++ b/packages/ui/src/locales/pt-BR/index.json @@ -4967,9 +4967,6 @@ "servers.listing.copy-id-label": { "defaultMessage": "Copiar ID" }, - "servers.listing.download-latest-backup-tooltip": { - "defaultMessage": "Baixe a cópia de segurança mais recente" - }, "servers.listing.manage-billing-label": { "defaultMessage": "Gerenciar cobrança" }, diff --git a/packages/ui/src/locales/ru-RU/index.json b/packages/ui/src/locales/ru-RU/index.json index 5c29afac38..bb4601f509 100644 --- a/packages/ui/src/locales/ru-RU/index.json +++ b/packages/ui/src/locales/ru-RU/index.json @@ -5063,9 +5063,6 @@ "servers.listing.copy-id-label": { "defaultMessage": "Копировать ID" }, - "servers.listing.download-latest-backup-tooltip": { - "defaultMessage": "Скачать последнюю резервную копию" - }, "servers.listing.manage-billing-label": { "defaultMessage": "Управление платежами" }, diff --git a/packages/ui/src/locales/sr-CS/index.json b/packages/ui/src/locales/sr-CS/index.json index cb69a7a63f..8f3974545f 100644 --- a/packages/ui/src/locales/sr-CS/index.json +++ b/packages/ui/src/locales/sr-CS/index.json @@ -4400,9 +4400,6 @@ "servers.listing.copy-id-label": { "defaultMessage": "Kopiraj ID" }, - "servers.listing.download-latest-backup-tooltip": { - "defaultMessage": "Instaliraj najnoviji backup" - }, "servers.listing.manage-billing-label": { "defaultMessage": "Upravljaj naplatom" }, diff --git a/packages/ui/src/locales/sv-SE/index.json b/packages/ui/src/locales/sv-SE/index.json index ed05c880f8..d9b40071b4 100644 --- a/packages/ui/src/locales/sv-SE/index.json +++ b/packages/ui/src/locales/sv-SE/index.json @@ -4649,9 +4649,6 @@ "servers.listing.copy-id-label": { "defaultMessage": "Kopiera ID" }, - "servers.listing.download-latest-backup-tooltip": { - "defaultMessage": "Ladda ner senaste säkerhetskopian" - }, "servers.listing.manage-billing-label": { "defaultMessage": "Hantera användarfakturering" }, diff --git a/packages/ui/src/locales/tr-TR/index.json b/packages/ui/src/locales/tr-TR/index.json index 7c8b997e38..16502fc5c7 100644 --- a/packages/ui/src/locales/tr-TR/index.json +++ b/packages/ui/src/locales/tr-TR/index.json @@ -4913,9 +4913,6 @@ "servers.listing.copy-id-label": { "defaultMessage": "ID'yi Kopyala" }, - "servers.listing.download-latest-backup-tooltip": { - "defaultMessage": "Son yedeği indirin" - }, "servers.listing.manage-billing-label": { "defaultMessage": "Faturalandırmayı yönetin" }, diff --git a/packages/ui/src/locales/uk-UA/index.json b/packages/ui/src/locales/uk-UA/index.json index 7f598a4ff6..6070e4fca9 100644 --- a/packages/ui/src/locales/uk-UA/index.json +++ b/packages/ui/src/locales/uk-UA/index.json @@ -4931,9 +4931,6 @@ "servers.listing.copy-id-label": { "defaultMessage": "Скопіювати ID" }, - "servers.listing.download-latest-backup-tooltip": { - "defaultMessage": "Завантажити останню резервну копію" - }, "servers.listing.manage-billing-label": { "defaultMessage": "Керування платежами" }, diff --git a/packages/ui/src/locales/vi-VN/index.json b/packages/ui/src/locales/vi-VN/index.json index aa5979c35b..eed81ec1d5 100644 --- a/packages/ui/src/locales/vi-VN/index.json +++ b/packages/ui/src/locales/vi-VN/index.json @@ -3908,9 +3908,6 @@ "servers.listing.copy-id-label": { "defaultMessage": "Sao chép ID" }, - "servers.listing.download-latest-backup-tooltip": { - "defaultMessage": "Tải bản sao lưu mới nhất" - }, "servers.listing.manage-billing-label": { "defaultMessage": "Quản lý giao dịch" }, diff --git a/packages/ui/src/locales/zh-CN/index.json b/packages/ui/src/locales/zh-CN/index.json index 4af7731dd8..c1596c6f62 100644 --- a/packages/ui/src/locales/zh-CN/index.json +++ b/packages/ui/src/locales/zh-CN/index.json @@ -5153,9 +5153,6 @@ "servers.listing.copy-id-label": { "defaultMessage": "复制 ID" }, - "servers.listing.download-latest-backup-tooltip": { - "defaultMessage": "下载最新备份" - }, "servers.listing.manage-billing-label": { "defaultMessage": "管理账单" }, diff --git a/packages/ui/src/locales/zh-TW/index.json b/packages/ui/src/locales/zh-TW/index.json index dbd709dd3b..9f5f79eaeb 100644 --- a/packages/ui/src/locales/zh-TW/index.json +++ b/packages/ui/src/locales/zh-TW/index.json @@ -5153,9 +5153,6 @@ "servers.listing.copy-id-label": { "defaultMessage": "複製 ID" }, - "servers.listing.download-latest-backup-tooltip": { - "defaultMessage": "下載最新備份" - }, "servers.listing.manage-billing-label": { "defaultMessage": "管理帳務" }, diff --git a/packages/ui/src/stories/servers/AuditLogTable.stories.ts b/packages/ui/src/stories/servers/AuditLogTable.stories.ts index 646b108703..84077ea442 100644 --- a/packages/ui/src/stories/servers/AuditLogTable.stories.ts +++ b/packages/ui/src/stories/servers/AuditLogTable.stories.ts @@ -93,6 +93,7 @@ const serverFullResponse: Archon.Servers.v1.ServerFull = { region: 'us-east', region_should_be_user_displayed: true, hostname: 'ashburn-01', + url_host: 'https://ashburn-01.example.com', is_decommissioned_node: false, }, }, @@ -102,6 +103,7 @@ const serverFullResponse: Archon.Servers.v1.ServerFull = { name: 'Create SMP', created_at: new Date(Date.now() - 90 * 24 * 60 * 60 * 1000).toISOString(), is_active: false, + download_method: { method_type: 'direct_node_download' }, backups: [], content: { modloader: 'fabric', @@ -120,6 +122,7 @@ const serverFullResponse: Archon.Servers.v1.ServerFull = { name: 'SMP Season 4', created_at: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString(), is_active: true, + download_method: { method_type: 'direct_node_download' }, backups: [ { id: backupId, diff --git a/packages/ui/src/stories/servers/ServerListing.stories.ts b/packages/ui/src/stories/servers/ServerListing.stories.ts index c890a6fba3..750622ed86 100644 --- a/packages/ui/src/stories/servers/ServerListing.stories.ts +++ b/packages/ui/src/stories/servers/ServerListing.stories.ts @@ -109,7 +109,7 @@ export const SetToCancel: Story = { name: 'Survival SMP', cancellationDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(), onResubscribe: () => alert('Resubscribe clicked'), - onDownloadBackup: () => alert('Download backup clicked'), + onDownloadWorld: () => alert('Download world clicked'), }, } @@ -121,19 +121,19 @@ export const SuspendedCancelled: Story = { suspension_reason: 'cancelled', cancellationDate: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(), onResubscribe: () => alert('Resubscribe clicked'), - onDownloadBackup: () => alert('Download backup clicked'), + onDownloadWorld: () => alert('Download world clicked'), }, } -export const SuspendedCancelledFilesExpired: Story = { +export const SuspendedCancelledAfterResubscribeWindow: Story = { args: { ...baseServer, - onDownloadBackup: null, + onDownloadWorld: () => alert('Download world clicked'), name: 'Old Event Server', status: 'suspended', suspension_reason: 'cancelled', cancellationDate: new Date(2025, 1, 17).toISOString(), - onResubscribe: () => alert('Resubscribe clicked'), + onResubscribe: null, }, } @@ -144,7 +144,7 @@ export const SuspendedPaymentFailed: Story = { status: 'suspended', suspension_reason: 'paymentfailed', cancellationDate: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(), - onDownloadBackup: () => alert('Download backup clicked'), + onDownloadWorld: () => alert('Download world clicked'), }, } @@ -154,7 +154,7 @@ export const SuspendedModerated: Story = { name: 'Banned Server', status: 'suspended', suspension_reason: 'moderated', - onDownloadBackup: () => alert('Download backup clicked'), + onDownloadWorld: () => alert('Download world clicked'), }, } @@ -163,6 +163,6 @@ export const SuspendedGeneric: Story = { ...baseServer, name: 'Server with other suspension reason', status: 'suspended', - onDownloadBackup: () => alert('Download backup clicked'), + onDownloadWorld: () => alert('Download world clicked'), }, } diff --git a/packages/ui/src/utils/common-messages.ts b/packages/ui/src/utils/common-messages.ts index 314863039e..d53deb76c5 100644 --- a/packages/ui/src/utils/common-messages.ts +++ b/packages/ui/src/utils/common-messages.ts @@ -124,6 +124,10 @@ export const commonMessages = defineMessages({ id: 'button.download', defaultMessage: 'Download', }, + downloadFilesButton: { + id: 'button.download-files', + defaultMessage: 'Download files', + }, downloadingButton: { id: 'button.downloading', defaultMessage: 'Downloading', diff --git a/packages/ui/src/utils/index.ts b/packages/ui/src/utils/index.ts index d92f045915..b636f5ae64 100644 --- a/packages/ui/src/utils/index.ts +++ b/packages/ui/src/utils/index.ts @@ -11,6 +11,7 @@ export * from './notices' export * from './project-types' export * from './savable' export * from './search' +export * from './server-billing' export * from './server-search' export * from './tag-messages' export * from './theme-color-transition' diff --git a/packages/ui/src/utils/server-billing.ts b/packages/ui/src/utils/server-billing.ts new file mode 100644 index 0000000000..ffff279d1b --- /dev/null +++ b/packages/ui/src/utils/server-billing.ts @@ -0,0 +1,12 @@ +const SERVER_RESUBSCRIBE_WINDOW_MS = 30 * 24 * 60 * 60 * 1000 + +export function isWithinServerResubscribeWindow( + cancellationDate: string | number | Date | null | undefined, +): boolean { + if (cancellationDate == null) return false + const cancellationTime = new Date(cancellationDate).getTime() + return ( + Number.isFinite(cancellationTime) && + Date.now() <= cancellationTime + SERVER_RESUBSCRIBE_WINDOW_MS + ) +} diff --git a/turbo.jsonc b/turbo.jsonc index fae1c8dca6..f7ab6d9c34 100644 --- a/turbo.jsonc +++ b/turbo.jsonc @@ -48,12 +48,7 @@ "BUILD_ENV", "PREVIEW" ], - "passThroughEnv": [ - "SCCACHE_*", - "RUSTC_WRAPPER", - "AWS_ACCESS_KEY_ID", - "AWS_SECRET_ACCESS_KEY" - ] + "passThroughEnv": ["SCCACHE_*", "RUSTC_WRAPPER", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"] }, "lint": { "env": [ @@ -65,12 +60,7 @@ "FORCE_COLOR", "NEXTEST_*" ], - "passThroughEnv": [ - "SCCACHE_*", - "RUSTC_WRAPPER", - "AWS_ACCESS_KEY_ID", - "AWS_SECRET_ACCESS_KEY" - ] + "passThroughEnv": ["SCCACHE_*", "RUSTC_WRAPPER", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"] }, "lint:ancillary": {}, "//#i18n:coverage": { @@ -110,12 +100,7 @@ "FORCE_COLOR", "NEXTEST_*" ], - "passThroughEnv": [ - "SCCACHE_*", - "RUSTC_WRAPPER", - "AWS_ACCESS_KEY_ID", - "AWS_SECRET_ACCESS_KEY" - ] + "passThroughEnv": ["SCCACHE_*", "RUSTC_WRAPPER", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"] }, "fix": {}, "fix:ancillary": {