2026-01-24 22:59:20 +00:00
|
|
|
import { ref, computed, onMounted, onBeforeUnmount } from 'vue'
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Composable for mobile back button positioning
|
feat: cloud native file browser, settings Claude auth, deploy hardening
- Add native Cloud file browser with FileBrowser API integration
- Add cloud store, filebrowser-client, useAudioPlayer, useFileType composables
- Add Cloud components: FileGrid, FileCard, FileCardGrid, CloudToolbar
- Add Claude authentication section to Settings with OAuth status check
- Harden deploy script to preserve /aiui/ and claude-login.html
- Add nginx proxies for btcpay, homeassistant, filebrowser (HTTPS block)
- Add app configs for filebrowser, searxng, penpot in package.rs
- Update goal progress tracking with app aliases
- Improve mobile back button composable with ResizeObserver
- Update various views with cloud integration and UI refinements
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 23:05:01 +00:00
|
|
|
* Ensures back buttons are always 8px above the mobile tab bar
|
2026-01-24 22:59:20 +00:00
|
|
|
* Uses ResizeObserver to reactively update when tab bar height changes
|
|
|
|
|
*/
|
|
|
|
|
export function useMobileBackButton() {
|
|
|
|
|
const tabBarHeight = ref<number>(72) // Default fallback height
|
|
|
|
|
|
|
|
|
|
// Computed property for bottom position - always 16px above tab bar
|
|
|
|
|
const bottomPosition = computed(() => {
|
feat: cloud native file browser, settings Claude auth, deploy hardening
- Add native Cloud file browser with FileBrowser API integration
- Add cloud store, filebrowser-client, useAudioPlayer, useFileType composables
- Add Cloud components: FileGrid, FileCard, FileCardGrid, CloudToolbar
- Add Claude authentication section to Settings with OAuth status check
- Harden deploy script to preserve /aiui/ and claude-login.html
- Add nginx proxies for btcpay, homeassistant, filebrowser (HTTPS block)
- Add app configs for filebrowser, searxng, penpot in package.rs
- Update goal progress tracking with app aliases
- Improve mobile back button composable with ResizeObserver
- Update various views with cloud integration and UI refinements
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 23:05:01 +00:00
|
|
|
return `${tabBarHeight.value + 8}px`
|
2026-01-24 22:59:20 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Computed property for Tailwind class (for use in class bindings)
|
|
|
|
|
const bottomClass = computed(() => {
|
|
|
|
|
// Use Tailwind arbitrary value with the computed height
|
feat: cloud native file browser, settings Claude auth, deploy hardening
- Add native Cloud file browser with FileBrowser API integration
- Add cloud store, filebrowser-client, useAudioPlayer, useFileType composables
- Add Cloud components: FileGrid, FileCard, FileCardGrid, CloudToolbar
- Add Claude authentication section to Settings with OAuth status check
- Harden deploy script to preserve /aiui/ and claude-login.html
- Add nginx proxies for btcpay, homeassistant, filebrowser (HTTPS block)
- Add app configs for filebrowser, searxng, penpot in package.rs
- Update goal progress tracking with app aliases
- Improve mobile back button composable with ResizeObserver
- Update various views with cloud integration and UI refinements
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 23:05:01 +00:00
|
|
|
return `bottom-[${tabBarHeight.value + 8}px]`
|
2026-01-24 22:59:20 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
let resizeObserver: ResizeObserver | null = null
|
|
|
|
|
let mutationObserver: MutationObserver | null = null
|
|
|
|
|
let intervalId: ReturnType<typeof setInterval> | null = null
|
|
|
|
|
|
|
|
|
|
function updateTabBarHeight() {
|
|
|
|
|
if (typeof window === 'undefined') return
|
|
|
|
|
|
|
|
|
|
// Try to find the mobile tab bar element
|
|
|
|
|
const tabBar = document.querySelector('[data-mobile-tab-bar]') as HTMLElement
|
|
|
|
|
if (tabBar) {
|
|
|
|
|
tabBarHeight.value = tabBar.offsetHeight
|
|
|
|
|
} else {
|
|
|
|
|
// Fallback: read from CSS variable if available
|
|
|
|
|
const cssVar = getComputedStyle(document.documentElement)
|
|
|
|
|
.getPropertyValue('--mobile-tab-bar-height')
|
|
|
|
|
.trim()
|
|
|
|
|
|
|
|
|
|
if (cssVar) {
|
|
|
|
|
const height = parseFloat(cssVar)
|
|
|
|
|
if (!isNaN(height)) {
|
|
|
|
|
tabBarHeight.value = height
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
// Initial update
|
|
|
|
|
updateTabBarHeight()
|
|
|
|
|
|
|
|
|
|
// Watch for CSS variable changes
|
|
|
|
|
mutationObserver = new MutationObserver(() => {
|
|
|
|
|
updateTabBarHeight()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
mutationObserver.observe(document.documentElement, {
|
|
|
|
|
attributes: true,
|
|
|
|
|
attributeFilter: ['style'],
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Watch for tab bar size changes
|
|
|
|
|
const tabBar = document.querySelector('[data-mobile-tab-bar]') as HTMLElement
|
|
|
|
|
if (tabBar && 'ResizeObserver' in window) {
|
|
|
|
|
resizeObserver = new ResizeObserver(() => {
|
|
|
|
|
updateTabBarHeight()
|
|
|
|
|
})
|
|
|
|
|
resizeObserver.observe(tabBar)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Also listen to window resize as fallback
|
|
|
|
|
window.addEventListener('resize', updateTabBarHeight)
|
|
|
|
|
|
|
|
|
|
// Periodic check to ensure we're always in sync (safety net)
|
|
|
|
|
intervalId = setInterval(() => {
|
|
|
|
|
updateTabBarHeight()
|
|
|
|
|
}, 1000)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
onBeforeUnmount(() => {
|
|
|
|
|
if (mutationObserver) {
|
|
|
|
|
mutationObserver.disconnect()
|
|
|
|
|
}
|
|
|
|
|
if (resizeObserver) {
|
|
|
|
|
resizeObserver.disconnect()
|
|
|
|
|
}
|
|
|
|
|
if (intervalId) {
|
|
|
|
|
clearInterval(intervalId)
|
|
|
|
|
}
|
|
|
|
|
window.removeEventListener('resize', updateTabBarHeight)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
bottomPosition,
|
|
|
|
|
bottomClass,
|
|
|
|
|
tabBarHeight,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|