diff --git a/apps/app-frontend/src/composables/intercom-positioning.ts b/apps/app-frontend/src/composables/intercom-positioning.ts index a188d26b5..5a348202b 100644 --- a/apps/app-frontend/src/composables/intercom-positioning.ts +++ b/apps/app-frontend/src/composables/intercom-positioning.ts @@ -36,18 +36,38 @@ export function useIntercomPositioning({ () => route.path.startsWith('/browse') || route.path.startsWith('/project'), ) const sidebarVisible = computed(() => sidebarToggled.value || forceSidebar.value) - const intercomBubbleHorizontalPadding = computed(() => + const defaultIntercomBubbleHorizontalPadding = computed(() => sidebarVisible.value ? APP_SIDEBAR_WIDTH + INTERCOM_BUBBLE_DEFAULT_PADDING : INTERCOM_BUBBLE_DEFAULT_PADDING, ) + const intercomBubbleRequestedHorizontalPadding = ref(null) + const intercomBubbleHorizontalPadding = computed( + () => + intercomBubbleRequestedHorizontalPadding.value ?? + defaultIntercomBubbleHorizontalPadding.value, + ) const intercomBubbleVerticalClearance = ref(null) const intercomBubblePosition = computed(() => ({ horizontalPadding: intercomBubbleHorizontalPadding.value, verticalPadding: intercomBubbleVerticalClearance.value ?? INTERCOM_BUBBLE_DEFAULT_PADDING, })) + const intercomBubbleHorizontalPaddingRequests = new Map() const intercomBubbleClearanceRequests = new Map() + function requestIntercomBubbleHorizontalPadding(id: symbol, padding: number | null) { + if (padding === null) { + intercomBubbleHorizontalPaddingRequests.delete(id) + } else { + intercomBubbleHorizontalPaddingRequests.set(id, padding) + } + + intercomBubbleRequestedHorizontalPadding.value = + intercomBubbleHorizontalPaddingRequests.size > 0 + ? Math.max(...intercomBubbleHorizontalPaddingRequests.values()) + : null + } + function requestIntercomBubbleVerticalClearance(id: symbol, clearance: number | null) { if (clearance === null) { intercomBubbleClearanceRequests.delete(id) @@ -93,6 +113,7 @@ export function useIntercomPositioning({ intercomBubble: { width: ref(INTERCOM_BUBBLE_WIDTH), horizontalPadding: intercomBubbleHorizontalPadding, + requestHorizontalPadding: requestIntercomBubbleHorizontalPadding, requestVerticalClearance: requestIntercomBubbleVerticalClearance, }, }, diff --git a/packages/ui/src/layouts/shared/console/layout.vue b/packages/ui/src/layouts/shared/console/layout.vue index 3ed874bf2..ec28059e5 100644 --- a/packages/ui/src/layouts/shared/console/layout.vue +++ b/packages/ui/src/layouts/shared/console/layout.vue @@ -108,6 +108,7 @@ import NewModal from '#ui/components/modal/NewModal.vue' import ShareModal from '#ui/components/modal/ShareModal.vue' import { injectModrinthClient } from '#ui/providers' import { injectModalBehavior } from '#ui/providers/modal-behavior' +import { injectPageContext } from '#ui/providers/page-context' import { injectNotificationManager } from '#ui/providers/web-notifications.ts' import ConsoleActionButtons from './components/ConsoleActionButtons.vue' @@ -127,6 +128,7 @@ import type { LogLevel, LogLine } from './types' const ctx = injectConsoleManager() const client = injectModrinthClient() const modalBehavior = injectModalBehavior() +const pageContext = injectPageContext(null) const { addNotification } = injectNotificationManager() const crashHeader = computed(() => { @@ -149,6 +151,9 @@ const deleteModal = ref | null>(null) const isDeleting = ref(false) const searchQuery = ref('') const isFullscreen = ref(false) +const fullscreenBodyClass = 'modrinth-console-fullscreen-active' +const fullscreenIntercomPadding = 20 +const fullscreenIntercomPaddingRequestId = Symbol('console-fullscreen') const isApp = typeof window !== 'undefined' && !!(window as Record).__TAURI_INTERNALS__ const isSharing = ref(false) @@ -187,6 +192,11 @@ function buildCombinedPredicate(): ((line: LogLine) => boolean) | null { onBeforeUnmount(() => { if (isFullscreen.value) { document.body.style.overflow = '' + document.body.classList.remove(fullscreenBodyClass) + pageContext?.intercomBubble?.requestHorizontalPadding?.( + fullscreenIntercomPaddingRequestId, + null, + ) modalBehavior?.onHide?.() } }) @@ -266,9 +276,19 @@ function toggleFullscreen() { isFullscreen.value = !isFullscreen.value if (isFullscreen.value) { document.body.style.overflow = 'hidden' + document.body.classList.add(fullscreenBodyClass) + pageContext?.intercomBubble?.requestHorizontalPadding?.( + fullscreenIntercomPaddingRequestId, + fullscreenIntercomPadding, + ) modalBehavior?.onShow?.() } else { document.body.style.overflow = '' + document.body.classList.remove(fullscreenBodyClass) + pageContext?.intercomBubble?.requestHorizontalPadding?.( + fullscreenIntercomPaddingRequestId, + null, + ) modalBehavior?.onHide?.() } nextTick(() => { @@ -396,3 +416,17 @@ async function handleShare() { } } + + diff --git a/packages/ui/src/providers/page-context.ts b/packages/ui/src/providers/page-context.ts index 6c0ca196a..32ffc248d 100644 --- a/packages/ui/src/providers/page-context.ts +++ b/packages/ui/src/providers/page-context.ts @@ -13,6 +13,7 @@ export interface PageContext { intercomBubble?: { width: Ref | ComputedRef horizontalPadding: Ref | ComputedRef + requestHorizontalPadding?: (id: symbol, padding: number | null) => void requestVerticalClearance: (id: symbol, clearance: number | null) => void } featureFlags?: {