Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ rand = "=0.8.5" # Locked on 0.8 until argon2 and p256 update to 0.9
rand_chacha = "=0.3.1" # Locked on 0.3 until we can update rand to 0.9
rdkafka = { version = "0.36.2", features = ["cmake-build"] }
redis = "1.4.1"
reflink-copy = "0.1.30"
regex = "1.12.2"
reqwest = { version = "0.12.24", default-features = false }
rgb = "0.8.52"
Expand All @@ -174,6 +175,7 @@ rustls = "0.23.32"
rustrict = { version = "0.7.39", default-features = false, features = ["censor"] }
rusty-money = "0.4.1"
scalar_api_reference = { version = "0.2.2", default-features = false }
same-file = "1.0.6"
secrecy = "0.10.3"
sentry = { version = "0.45.0", default-features = false, features = [
"backtrace",
Expand Down
1 change: 1 addition & 0 deletions apps/app-frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"floating-vue": "^5.2.2",
"fuse.js": "^6.6.2",
"intl-messageformat": "^10.7.7",
"motion-v": "2.2.1",
"ofetch": "^1.3.4",
"overlayscrollbars": "^2.15.1",
"posthog-js": "^1.158.2",
Expand Down
17 changes: 9 additions & 8 deletions apps/app-frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2288,15 +2288,16 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
<ServerStackIcon />
</NavButton>
<suspense>
<QuickInstanceSwitcher />
<QuickInstanceSwitcher>
<NavButton
v-tooltip.right="formatMessage(messages.createNewInstance)"
:to="() => installationModal?.show()"
:disabled="offline"
>
<PlusIcon />
</NavButton>
</QuickInstanceSwitcher>
</suspense>
<NavButton
v-tooltip.right="formatMessage(messages.createNewInstance)"
:to="() => installationModal?.show()"
:disabled="offline"
>
<PlusIcon />
</NavButton>
<NavButton
v-tooltip.right="formatMessage(commonMessages.settingsLabel)"
:to="() => appSettingsModal?.show()"
Expand Down
101 changes: 18 additions & 83 deletions apps/app-frontend/src/components/ui/AppActionBar.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<template>
<div class="flex gap-2 items-center">
<DownloadManager />
<div v-if="downloadState.total > 0 || hasActiveLoadingBars" class="relative">
<IconButton
v-tooltip="downloadToggleLabel"
Expand Down Expand Up @@ -132,9 +133,9 @@ import {
TerminalSquareIcon,
UnplugIcon,
} from '@modrinth/assets'
import { IconButton } from '@modrinth/ui'
import {
defineMessages,
IconButton,
injectNotificationManager,
injectPopupNotificationManager,
type PopupNotificationProgressItem,
Expand All @@ -147,10 +148,9 @@ import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'

import AppUpdateButton from '@/components/ui/app-update-button/index.vue'
import { useInstallJobNotifications } from '@/composables/browse/install-job-notifications'
import DownloadManager from '@/components/ui/download-manager/index.vue'
import { useAppEvent } from '@/composables/use-app-event'
import { trackEvent } from '@/helpers/analytics'
import { toError } from '@/helpers/errors'
import { get_many as getInstances } from '@/helpers/instance'
import { get_all as getRunningProcesses, kill as killProcess } from '@/helpers/process'
import type { LoadingBar } from '@/helpers/state'
Expand Down Expand Up @@ -325,7 +325,6 @@ function goToTerminal(instanceId?: string) {
const currentLoadingBars = ref<LoadingBar[]>([])
const currentLoadingBarIconUrls = ref<Record<string, string | null>>({})
const notificationId = ref<string | number | null>(null)
const terminalNotificationIds = new Map<string, string | number>()
const dismissed = ref(false)

function getLoadingBarKey(loadingBar: LoadingBar): string {
Expand Down Expand Up @@ -373,79 +372,28 @@ function removeNotification(): void {
notificationId.value = null
}

function syncTerminalNotifications(): void {
const terminalNotifications = installJobNotifications.terminalNotifications.value
const currentJobIds = new Set(terminalNotifications.map((notification) => notification.id))

for (const terminal of terminalNotifications) {
const popupId = terminalNotificationIds.get(terminal.id)
let notification = popupId
? popupNotificationManager
.getNotifications()
.find(
(candidate): candidate is PopupNotificationStandard =>
candidate.id === popupId && candidate.contentType === 'standard',
)
: undefined

if (!notification) {
notification = popupNotificationManager.addPopupNotification({
contentType: 'standard',
title: terminal.title,
text: terminal.text,
type: terminal.type,
buttons: terminal.buttons,
onDismiss: terminal.onDismiss,
autoCloseMs: null,
})
terminalNotificationIds.set(terminal.id, notification.id)
continue
}

notification.title = terminal.title
notification.text = terminal.text
notification.type = terminal.type
notification.buttons = terminal.buttons
notification.onDismiss = terminal.onDismiss
}

for (const [jobId, popupId] of terminalNotificationIds) {
if (!currentJobIds.has(jobId)) {
popupNotificationManager.removeNotification(popupId)
terminalNotificationIds.delete(jobId)
}
}
}

function buildDownloadItems(): PopupNotificationProgressItem[] {
return [
...installJobNotifications.progressItems.value,
...currentLoadingBars.value.map<PopupNotificationProgressItem>((bar) => ({
id: getLoadingBarKey(bar),
title: bar.title ?? '',
text: getLoadingText(bar),
iconUrl: currentLoadingBarIconUrls.value[getLoadingBarKey(bar)] ?? null,
progress: getLoadingProgress(bar),
waiting: !bar.total || bar.total <= 0,
progressType: bar.bar_type?.type === 'pack_import' ? 'bytes' : 'percentage',
progressCurrent: bar.current,
progressTotal: bar.total,
})),
]
return currentLoadingBars.value.map((bar) => ({
id: getLoadingBarKey(bar),
title: bar.title ?? '',
text: getLoadingText(bar),
iconUrl: currentLoadingBarIconUrls.value[getLoadingBarKey(bar)] ?? null,
progress: getLoadingProgress(bar),
waiting: !bar.total || bar.total <= 0,
progressType: bar.bar_type?.type === 'pack_import' ? 'bytes' : 'percentage',
progressCurrent: bar.current,
progressTotal: bar.total,
}))
}

const hasActiveLoadingBars = computed(
() => currentLoadingBars.value.length > 0 || installJobNotifications.active.value,
)
const hasActiveLoadingBars = computed(() => currentLoadingBars.value.length > 0)

function updateNotification(resummon = false): void {
syncTerminalNotifications()

if (resummon) {
dismissed.value = false
}

if (currentLoadingBars.value.length === 0 && !installJobNotifications.active.value) {
if (currentLoadingBars.value.length === 0) {
removeNotification()
dismissed.value = false
return
Expand All @@ -464,19 +412,15 @@ function updateNotification(resummon = false): void {
const progressItems = buildDownloadItems()

if (notif) {
notif.title = installJobNotifications.active.value
? installJobNotifications.title.value
: formatMessage(messages.downloads)
notif.title = formatMessage(messages.downloads)
notif.text = undefined
notif.progressItems = progressItems
notif.progress = undefined
notif.waiting = undefined
} else {
const notification = popupNotificationManager.addPopupNotification({
contentType: 'standard',
title: installJobNotifications.active.value
? installJobNotifications.title.value
: formatMessage(messages.downloads),
title: formatMessage(messages.downloads),
type: 'download',
autoCloseMs: null,
progressItems,
Expand Down Expand Up @@ -556,12 +500,6 @@ async function refreshLoadingBars() {
updateNotification()
}

const installJobNotifications = await useInstallJobNotifications({
router,
handleError: (error) => handleError(toError(error)),
onChange: updateNotification,
})

await refreshLoadingBars()

useAppEvent('loading', async () => {
Expand All @@ -578,11 +516,8 @@ function selectProcess(process: RunningProcess) {

onBeforeUnmount(() => {
removeNotification()
terminalNotificationIds.forEach((id) => popupNotificationManager.removeNotification(id))
terminalNotificationIds.clear()
dismissed.value = false
window.removeEventListener('offline', handleOffline)
window.removeEventListener('online', handleOnline)
installJobNotifications.dispose()
})
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const runningInstances = ref([])
const { formatMessage } = useVIntl()

const container = ref()
const footer = ref()
let resizeObserver
const maxAuto = ref(0)
const allInstances = computed(() =>
Expand Down Expand Up @@ -74,9 +75,10 @@ const updateMaxAuto = () => {
const rem = Number.parseFloat(getComputedStyle(document.documentElement).fontSize)
const dividerHeight = rem + 1
const gap = rem / 4
const footerHeight = (footer.value?.clientHeight ?? 0) + gap
maxAuto.value = Math.max(
0,
Math.floor((container.value.clientHeight - 2 * dividerHeight - gap) / (3 * rem + gap)),
Math.floor((container.value.clientHeight - footerHeight - 2 * dividerHeight - gap) / (3 * rem + gap)),
)
}

Expand Down Expand Up @@ -165,6 +167,7 @@ useAppEvent('process', checkProcesses)
onMounted(() => {
resizeObserver = new ResizeObserver(updateMaxAuto)
resizeObserver.observe(container.value)
resizeObserver.observe(footer.value)
updateMaxAuto()
checkProcesses()
})
Expand Down Expand Up @@ -325,6 +328,9 @@ function openContextMenu(event, instance) {
"
></div>
</div>
<div ref="footer" class="flex shrink-0 flex-col items-center">
<slot />
</div>
</div>
</template>

Expand Down
Loading
Loading