1405/04/10-fix bug iphone show
This commit is contained in:
+12
@@ -112,6 +112,7 @@ import {
|
|||||||
import { useDraggableFloatingButton } from '@/utils/useDraggableFloatingButton'
|
import { useDraggableFloatingButton } from '@/utils/useDraggableFloatingButton'
|
||||||
import AppCreditLink from '@/components/AppCreditLink.vue'
|
import AppCreditLink from '@/components/AppCreditLink.vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
|
import { recoverMobileViewportAfterAuth } from '@/layouts/composables/useMobileScrollReset'
|
||||||
|
|
||||||
const VersionUpdateModal = defineAsyncComponent(
|
const VersionUpdateModal = defineAsyncComponent(
|
||||||
() => import('@/modules/version/VersionUpdateModal.vue')
|
() => import('@/modules/version/VersionUpdateModal.vue')
|
||||||
@@ -251,6 +252,17 @@ watch(showSplash, (visible) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => route.name,
|
||||||
|
(toName, fromName) => {
|
||||||
|
if (isDesktop.value) return
|
||||||
|
if (fromName === 'login' || toName === 'home') {
|
||||||
|
recoverMobileViewportAfterAuth()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ flush: 'post' },
|
||||||
|
)
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { useUserStore } from '@/store/userStore'
|
|||||||
import { getToken } from '@/utils'
|
import { getToken } from '@/utils'
|
||||||
import '@/utils/useDateTime'
|
import '@/utils/useDateTime'
|
||||||
import { initPriceRealtimeChannel } from '@/utils/priceSocket'
|
import { initPriceRealtimeChannel } from '@/utils/priceSocket'
|
||||||
|
import { initMobileScrollRestoration } from '@/layouts/composables/useMobileScrollReset'
|
||||||
|
|
||||||
type BootWindow = Window & {
|
type BootWindow = Window & {
|
||||||
__BOOT_TIMEOUT__?: number
|
__BOOT_TIMEOUT__?: number
|
||||||
@@ -122,6 +123,7 @@ export async function bootstrapApp() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setupRouterGuards()
|
setupRouterGuards()
|
||||||
|
initMobileScrollRestoration()
|
||||||
|
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { useFundUserStore } from '@/store/fundStore'
|
|||||||
import type { NavigationGuardNext } from 'vue-router'
|
import type { NavigationGuardNext } from 'vue-router'
|
||||||
import { useAuthStore } from '@/store/useAuthStore'
|
import { useAuthStore } from '@/store/useAuthStore'
|
||||||
import { getConfigApp } from '@/utils/config'
|
import { getConfigApp } from '@/utils/config'
|
||||||
import { getFingerPosition, setFingerPosition } from '@/app/authBoot'
|
import { recoverMobileViewportAfterAuth } from '@/layouts/composables/useMobileScrollReset'
|
||||||
|
|
||||||
const PUBLIC_ROUTE_NAMES = ['login', '404', 'educate', 'aboutUs'] as const
|
const PUBLIC_ROUTE_NAMES = ['login', '404', 'educate', 'aboutUs'] as const
|
||||||
|
|
||||||
@@ -119,6 +119,13 @@ export function setupRouterGuards() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
router.afterEach((to, from) => {
|
||||||
|
if (document.documentElement.classList.contains('app-layout--desktop')) return
|
||||||
|
if (from.name === 'login') {
|
||||||
|
recoverMobileViewportAfterAuth()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
watch(currentRoute, async () => (userStore.userInfo ? '' : await start()))
|
watch(currentRoute, async () => (userStore.userInfo ? '' : await start()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,125 @@
|
|||||||
|
import { nextTick } from 'vue'
|
||||||
|
import router from '@/router'
|
||||||
|
|
||||||
|
let recoveryTimers: ReturnType<typeof setTimeout>[] = []
|
||||||
|
|
||||||
|
function clearRecoveryTimers() {
|
||||||
|
recoveryTimers.forEach(clearTimeout)
|
||||||
|
recoveryTimers = []
|
||||||
|
}
|
||||||
|
|
||||||
|
function blurFocusedField() {
|
||||||
|
const active = document.activeElement
|
||||||
|
if (active instanceof HTMLElement && active !== document.body) {
|
||||||
|
active.blur()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearBodyScrollLock() {
|
||||||
|
document.body.classList.remove('van-overflow-hidden')
|
||||||
|
document.body.style.removeProperty('position')
|
||||||
|
document.body.style.removeProperty('top')
|
||||||
|
document.body.style.removeProperty('left')
|
||||||
|
document.body.style.removeProperty('right')
|
||||||
|
document.body.style.removeProperty('width')
|
||||||
|
document.body.style.removeProperty('height')
|
||||||
|
document.body.style.removeProperty('min-height')
|
||||||
|
document.body.style.removeProperty('overflow')
|
||||||
|
document.body.style.removeProperty('transform')
|
||||||
|
document.documentElement.style.removeProperty('overflow')
|
||||||
|
document.documentElement.style.removeProperty('height')
|
||||||
|
document.documentElement.style.removeProperty('transform')
|
||||||
|
|
||||||
|
const appRoot = document.getElementById('app')
|
||||||
|
if (appRoot) {
|
||||||
|
appRoot.style.removeProperty('position')
|
||||||
|
appRoot.style.removeProperty('top')
|
||||||
|
appRoot.style.removeProperty('height')
|
||||||
|
appRoot.style.removeProperty('min-height')
|
||||||
|
appRoot.style.removeProperty('overflow')
|
||||||
|
appRoot.style.removeProperty('transform')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetAllScrollPositions() {
|
||||||
|
window.scrollTo(0, 0)
|
||||||
|
document.documentElement.scrollTop = 0
|
||||||
|
document.body.scrollTop = 0
|
||||||
|
|
||||||
|
document
|
||||||
|
.querySelectorAll('.main-with-bottom-chrome-inner, .login-page, .login-page-root')
|
||||||
|
.forEach((node) => {
|
||||||
|
if (node instanceof HTMLElement) {
|
||||||
|
node.scrollTop = 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function kickViewportReflow() {
|
||||||
|
window.dispatchEvent(new Event('resize'))
|
||||||
|
|
||||||
|
if (window.visualViewport) {
|
||||||
|
window.scrollTo(0, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function runViewportRecovery() {
|
||||||
|
clearBodyScrollLock()
|
||||||
|
resetAllScrollPositions()
|
||||||
|
kickViewportReflow()
|
||||||
|
}
|
||||||
|
|
||||||
|
function scheduleViewportRecovery() {
|
||||||
|
clearRecoveryTimers()
|
||||||
|
runViewportRecovery()
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
runViewportRecovery()
|
||||||
|
|
||||||
|
for (const delay of [50, 150, 300, 500]) {
|
||||||
|
recoveryTimers.push(window.setTimeout(runViewportRecovery, delay))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Reset scroll offsets after navigation — fixes iOS safe-area drift. */
|
||||||
|
export function resetMobileAppScroll() {
|
||||||
|
runViewportRecovery()
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
requestAnimationFrame(runViewportRecovery)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function dismissMobileKeyboard() {
|
||||||
|
blurFocusedField()
|
||||||
|
await new Promise((resolve) => window.setTimeout(resolve, 120))
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function prepareMobileViewportForAppShell() {
|
||||||
|
blurFocusedField()
|
||||||
|
resetAllScrollPositions()
|
||||||
|
await dismissMobileKeyboard()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Full recovery after auth — runs after home shell is mounted. */
|
||||||
|
export function recoverMobileViewportAfterAuth() {
|
||||||
|
scheduleViewportRecovery()
|
||||||
|
}
|
||||||
|
|
||||||
|
export const resetMobileAppScrollAfterLogin = recoverMobileViewportAfterAuth
|
||||||
|
|
||||||
|
export async function completeLoginNavigation() {
|
||||||
|
await prepareMobileViewportForAppShell()
|
||||||
|
await router.push({ name: 'home' })
|
||||||
|
await router.isReady()
|
||||||
|
recoverMobileViewportAfterAuth()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function initMobileScrollRestoration() {
|
||||||
|
if (typeof history !== 'undefined' && 'scrollRestoration' in history) {
|
||||||
|
history.scrollRestoration = 'manual'
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="mobile-app-layout">
|
||||||
<div :class="['main-with-bottom-chrome', { 'main-with-bottom-chrome--no-nav': hideMenu }]">
|
<div :class="['main-with-bottom-chrome', { 'main-with-bottom-chrome--no-nav': hideMenu }]">
|
||||||
<router-view v-slot="{ Component, route }">
|
<router-view v-slot="{ Component, route: activeRoute }">
|
||||||
<transition :name="route.meta.transition || 'fade'">
|
<transition :name="activeRoute.meta.transition || 'fade'">
|
||||||
<component :is="Component" class="main-with-bottom-chrome-inner" />
|
<component :is="Component" :key="activeRoute.fullPath" class="main-with-bottom-chrome-inner" />
|
||||||
</transition>
|
</transition>
|
||||||
</router-view>
|
</router-view>
|
||||||
</div>
|
</div>
|
||||||
@@ -19,13 +19,16 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed } from 'vue'
|
import { computed, onMounted, watch } from 'vue'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
import { useConfigStore } from '@/store/configStore'
|
import { useConfigStore } from '@/store/configStore'
|
||||||
import { getProjectMobileNavLogo, isBoursecuProject } from '@/utils/config'
|
import { getProjectMobileNavLogo, isBoursecuProject } from '@/utils/config'
|
||||||
import { useAppNavigation } from '../composables/useAppNavigation'
|
import { useAppNavigation } from '../composables/useAppNavigation'
|
||||||
|
import { recoverMobileViewportAfterAuth, resetMobileAppScroll } from '../composables/useMobileScrollReset'
|
||||||
import MobileBottomNav from './MobileBottomNav.vue'
|
import MobileBottomNav from './MobileBottomNav.vue'
|
||||||
|
|
||||||
const config = useConfigStore()
|
const config = useConfigStore()
|
||||||
|
const route = useRoute()
|
||||||
const isBoursecu = isBoursecuProject()
|
const isBoursecu = isBoursecuProject()
|
||||||
const navLogo = computed(() => getProjectMobileNavLogo(config.config?.avatar))
|
const navLogo = computed(() => getProjectMobileNavLogo(config.config?.avatar))
|
||||||
|
|
||||||
@@ -34,6 +37,19 @@ const {
|
|||||||
navItemClass,
|
navItemClass,
|
||||||
navigateTo,
|
navigateTo,
|
||||||
} = useAppNavigation()
|
} = useAppNavigation()
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => route.fullPath,
|
||||||
|
() => {
|
||||||
|
resetMobileAppScroll()
|
||||||
|
},
|
||||||
|
{ flush: 'post' },
|
||||||
|
)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
resetMobileAppScroll()
|
||||||
|
recoverMobileViewportAfterAuth()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" src="./mobile-layout.less"></style>
|
<style lang="less" src="./mobile-layout.less"></style>
|
||||||
|
|||||||
@@ -131,8 +131,16 @@
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mobile-app-layout {
|
||||||
|
height: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
.main-with-bottom-chrome {
|
.main-with-bottom-chrome {
|
||||||
height: calc(100vh - var(--app-bottom-chrome-height, 108px));
|
height: calc(100dvh - var(--app-bottom-chrome-height, 108px));
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -148,7 +156,11 @@
|
|||||||
overscroll-behavior-y: contain;
|
overscroll-behavior-y: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.main-with-bottom-chrome-inner--contained {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.main-with-bottom-chrome--no-nav,
|
.main-with-bottom-chrome--no-nav,
|
||||||
.main-with-bottom-chrome--no-nav .main-with-bottom-chrome-inner {
|
.main-with-bottom-chrome--no-nav .main-with-bottom-chrome-inner {
|
||||||
height: calc(100vh - var(--app-credit-footer-offset, 28px));
|
height: calc(100dvh - var(--app-credit-footer-offset, 28px));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,33 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
html:not(.app-layout--desktop) {
|
html:not(.app-layout--desktop) {
|
||||||
|
html,
|
||||||
|
body,
|
||||||
|
#app {
|
||||||
|
min-height: 0;
|
||||||
|
height: 100dvh;
|
||||||
|
max-height: 100dvh;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
overscroll-behavior: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktopConfig,
|
||||||
|
.app-main {
|
||||||
|
min-height: 0;
|
||||||
|
height: 100dvh;
|
||||||
|
max-height: 100dvh;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-main > * {
|
||||||
|
height: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
/* Teleport to body — dock bar must span viewport, not shrink to content */
|
/* Teleport to body — dock bar must span viewport, not shrink to content */
|
||||||
.app-dock-add-bar,
|
.app-dock-add-bar,
|
||||||
.wallet-card-slider {
|
.wallet-card-slider {
|
||||||
|
|||||||
@@ -107,17 +107,54 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mobile-info-page__header {
|
||||||
|
z-index: 1999;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decorative page background — fixed to viewport, never scrolls on iOS */
|
||||||
|
.mobile-page-bg,
|
||||||
.mobile-info-page__bg {
|
.mobile-info-page__bg {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
position: absolute;
|
position: fixed;
|
||||||
inset: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: var(--app-bottom-chrome-height, 108px);
|
||||||
|
overflow: hidden;
|
||||||
|
max-width: 100vw;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-page-bg--no-nav,
|
||||||
|
.mobile-info-page__bg {
|
||||||
|
bottom: var(--app-credit-footer-offset, 28px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-page-bg--cover {
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
html:not(.app-layout--desktop) {
|
||||||
|
@media screen and (min-width: 426px) and (max-width: 767.98px) {
|
||||||
|
.mobile-page-bg,
|
||||||
|
.mobile-info-page__bg {
|
||||||
|
width: 426px;
|
||||||
|
max-width: 426px;
|
||||||
|
left: 50%;
|
||||||
|
right: auto;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,10 +189,6 @@
|
|||||||
z-index: 1998;
|
z-index: 1998;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-info-page__header {
|
|
||||||
z-index: 1999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mobile-content-box {
|
.mobile-content-box {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="relative">
|
||||||
<MobilePageHeader title="آدرس ها" show-back />
|
<div class="mobile-page-bg" aria-hidden="true">
|
||||||
<div>
|
<img :src="img" alt="" />
|
||||||
<img :src="img" alt="" class="mt-2 w-full absolute bottom-0" />
|
|
||||||
</div>
|
</div>
|
||||||
|
<MobilePageHeader title="آدرس ها" show-back />
|
||||||
|
|
||||||
<div
|
<div
|
||||||
:class="loading ? 'h-screen' : ''"
|
:class="loading ? 'h-screen' : ''"
|
||||||
class="px-3 mpage-content pb-2 overflow-y-scroll mpage-scroll"
|
class="relative z-1 px-3 mpage-content pb-2 overflow-y-scroll mpage-scroll"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-if="isBazretalaProject()"
|
v-if="isBazretalaProject()"
|
||||||
|
|||||||
@@ -40,7 +40,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'
|
import { computed, nextTick, onActivated, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
import { useUserStore } from '@/store/userStore'
|
import { useUserStore } from '@/store/userStore'
|
||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
import Icon from '@/components/BasicPacks/BasicIcon.vue'
|
import Icon from '@/components/BasicPacks/BasicIcon.vue'
|
||||||
@@ -48,6 +49,7 @@ import { getProjectMobileNavLogo, isBoursecuProject } from '@/utils/config'
|
|||||||
|
|
||||||
const headerRef = ref<HTMLElement | null>(null)
|
const headerRef = ref<HTMLElement | null>(null)
|
||||||
const isHeaderScrolled = ref(false)
|
const isHeaderScrolled = ref(false)
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const projectLogo = computed(() => getProjectMobileNavLogo())
|
const projectLogo = computed(() => getProjectMobileNavLogo())
|
||||||
@@ -158,6 +160,21 @@ onMounted(async () => {
|
|||||||
requestAnimationFrame(() => setupScrollTracking())
|
requestAnimationFrame(() => setupScrollTracking())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
onActivated(() => {
|
||||||
|
isHeaderScrolled.value = false
|
||||||
|
setupScrollTracking()
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => route.fullPath,
|
||||||
|
() => {
|
||||||
|
if (route.name === 'home') {
|
||||||
|
isHeaderScrolled.value = false
|
||||||
|
nextTick(() => setupScrollTracking())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
teardownScrollTracking()
|
teardownScrollTracking()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import BalanceSheet from './components/BalanceSheet.vue'
|
|||||||
import ShareModal from './components/ShareModal.vue'
|
import ShareModal from './components/ShareModal.vue'
|
||||||
import HomePageShell from './shell/HomePageShell.vue'
|
import HomePageShell from './shell/HomePageShell.vue'
|
||||||
import { useHomePage } from './composables/useHomePage'
|
import { useHomePage } from './composables/useHomePage'
|
||||||
|
import { onMounted } from 'vue'
|
||||||
|
import { recoverMobileViewportAfterAuth } from '@/layouts/composables/useMobileScrollReset'
|
||||||
|
|
||||||
const {
|
const {
|
||||||
userStore,
|
userStore,
|
||||||
@@ -37,6 +39,10 @@ const {
|
|||||||
goldVal,
|
goldVal,
|
||||||
logout,
|
logout,
|
||||||
} = useHomePage()
|
} = useHomePage()
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
recoverMobileViewportAfterAuth()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="products-page-root">
|
<div class="products-page-root main-with-bottom-chrome-inner--contained">
|
||||||
<ResponsiveViewPair>
|
<ResponsiveViewPair>
|
||||||
<template #mobile>
|
<template #mobile>
|
||||||
<MobileProductsView />
|
<MobileProductsView />
|
||||||
@@ -104,16 +104,9 @@ const {
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.products-page-root {
|
.products-page-root {
|
||||||
min-height: 100%;
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
min-height: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style lang="less">
|
|
||||||
.products-page-root.main-with-bottom-chrome-inner {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="products-mobile-root">
|
<div class="products-mobile-root">
|
||||||
<div class="products-mobile-root__bg" aria-hidden="true">
|
<div class="mobile-page-bg" aria-hidden="true">
|
||||||
<img :src="img" alt="" />
|
<img :src="img" alt="" />
|
||||||
</div>
|
</div>
|
||||||
<MobilePageHeader title="خرید و فروش" />
|
<MobilePageHeader title="خرید و فروش" />
|
||||||
@@ -86,20 +86,6 @@ const storeClosedMessage = computed(() => getStoreClosedMessage())
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.products-mobile-root__bg {
|
|
||||||
pointer-events: none;
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
z-index: 0;
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.products-mobile-root__chrome {
|
.products-mobile-root__chrome {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="relative">
|
||||||
<div class="absolute inset-0 bg-cover bg-center opacity-60 pointer-events-none"></div>
|
<div
|
||||||
|
class="mobile-page-bg mobile-page-bg--cover opacity-60"
|
||||||
|
aria-hidden="true"
|
||||||
|
:style="{ backgroundImage: `url(${img})` }"
|
||||||
|
></div>
|
||||||
<MobilePageHeader title="تراکنش ها">
|
<MobilePageHeader title="تراکنش ها">
|
||||||
<template #trailing>
|
<template #trailing>
|
||||||
<BasicIcon icon="vuesax-linear:filter" @click="showFilter = true" />
|
<BasicIcon icon="vuesax-linear:filter" @click="showFilter = true" />
|
||||||
@@ -8,7 +12,7 @@
|
|||||||
</MobilePageHeader>
|
</MobilePageHeader>
|
||||||
|
|
||||||
<!-- <div ref="el" :class="loading ? 'h-screen' : ''" class="px-3 mpage-content pb-10">-->
|
<!-- <div ref="el" :class="loading ? 'h-screen' : ''" class="px-3 mpage-content pb-10">-->
|
||||||
<div ref="el" class="transactions-page-body px-3 pt-16 pb-24">
|
<div ref="el" class="transactions-page-body relative z-1 px-3 mpage-content pb-24">
|
||||||
<list-anim v-if="!loading">
|
<list-anim v-if="!loading">
|
||||||
<Item v-for="item in items" :key="item.id" :item="item" />
|
<Item v-for="item in items" :key="item.id" :item="item" />
|
||||||
<div :ref="bindMobileObserver" v-show="!loading" class="w-full opacity-0 relative">
|
<div :ref="bindMobileObserver" v-show="!loading" class="w-full opacity-0 relative">
|
||||||
@@ -52,6 +56,7 @@ import BaseDatePicker from '@/components/BasicPacks/BaseDatePicker/src/BaseDateP
|
|||||||
import ListAnim from '@/components/ListAnim.vue'
|
import ListAnim from '@/components/ListAnim.vue'
|
||||||
import TransactionSkeleton from '@/components/TransactionSkeleton.vue'
|
import TransactionSkeleton from '@/components/TransactionSkeleton.vue'
|
||||||
import { DotLottieVue } from '@lottiefiles/dotlottie-vue'
|
import { DotLottieVue } from '@lottiefiles/dotlottie-vue'
|
||||||
|
import img from '@/assets/img/user_ly1.svg'
|
||||||
import { useTransactionsPageContext } from './composables/useTransactionsPage'
|
import { useTransactionsPageContext } from './composables/useTransactionsPage'
|
||||||
|
|
||||||
const el = ref<HTMLElement | null>(null)
|
const el = ref<HTMLElement | null>(null)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mobile-user-view">
|
<div class="mobile-user-view">
|
||||||
<div class="mobile-user-view__bg" aria-hidden="true">
|
<div class="mobile-page-bg" aria-hidden="true">
|
||||||
<img :src="img" alt="" />
|
<img :src="img" alt="" />
|
||||||
</div>
|
</div>
|
||||||
<MobilePageHeader title="اطلاعات حساب کاربری" show-back />
|
<MobilePageHeader title="اطلاعات حساب کاربری" show-back />
|
||||||
@@ -114,20 +114,6 @@ const {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-user-view__bg {
|
|
||||||
pointer-events: none;
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
z-index: 0;
|
|
||||||
|
|
||||||
img {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mobile-user-view__scroll {
|
.mobile-user-view__scroll {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="relative">
|
||||||
<div class="absolute inset-0 bg-cover bg-center opacity-60" :style="{ backgroundImage: `url(${img})` }"></div>
|
<div
|
||||||
|
class="mobile-page-bg mobile-page-bg--cover opacity-60"
|
||||||
|
aria-hidden="true"
|
||||||
|
:style="{ backgroundImage: `url(${img})` }"
|
||||||
|
></div>
|
||||||
<MobilePageHeader title="کیف پول" />
|
<MobilePageHeader title="کیف پول" />
|
||||||
<div class="mpage-subheader wrap-fix flex justify-evenly">
|
<div class="mpage-subheader wrap-fix flex justify-evenly">
|
||||||
<div class="flex justify-evenly w-full px-2 h-11 items-center bg-gray-50 relative rounded">
|
<div class="flex justify-evenly w-full px-2 h-11 items-center bg-gray-50 relative rounded">
|
||||||
|
|||||||
@@ -377,6 +377,7 @@ import { useWalletStore } from '@/store/walletStore'
|
|||||||
import { useSettingsStore } from '@/store/settingsStore'
|
import { useSettingsStore } from '@/store/settingsStore'
|
||||||
import { syncPriceRealtimeChannel } from '@/utils/priceSocket'
|
import { syncPriceRealtimeChannel } from '@/utils/priceSocket'
|
||||||
import { setTruth } from '@/app/authBoot'
|
import { setTruth } from '@/app/authBoot'
|
||||||
|
import { completeLoginNavigation } from '@/layouts/composables/useMobileScrollReset'
|
||||||
import {useConfigStore} from "@/store/configStore";
|
import {useConfigStore} from "@/store/configStore";
|
||||||
import {
|
import {
|
||||||
getConfigApp,
|
getConfigApp,
|
||||||
@@ -488,7 +489,7 @@ async function login(accessToken: string | undefined) {
|
|||||||
/* if (userStore.userInfo?.type === (URLUserType() === 'customer' ? 1 : 2)) {*/
|
/* if (userStore.userInfo?.type === (URLUserType() === 'customer' ? 1 : 2)) {*/
|
||||||
await walletStore.getMyWallet()
|
await walletStore.getMyWallet()
|
||||||
setTruth()
|
setTruth()
|
||||||
await router.push({ name: 'home' })
|
await completeLoginNavigation()
|
||||||
/* } else {
|
/* } else {
|
||||||
removeToken()
|
removeToken()
|
||||||
userStore.removeInformation()
|
userStore.removeInformation()
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { useUserStore } from '@/store/userStore'
|
|||||||
import { useWalletStore } from '@/store/walletStore'
|
import { useWalletStore } from '@/store/walletStore'
|
||||||
import { useSettingsStore } from '@/store/settingsStore'
|
import { useSettingsStore } from '@/store/settingsStore'
|
||||||
import { setTruth } from '@/app/authBoot'
|
import { setTruth } from '@/app/authBoot'
|
||||||
|
import { completeLoginNavigation } from '@/layouts/composables/useMobileScrollReset'
|
||||||
|
|
||||||
export function useLoginForm() {
|
export function useLoginForm() {
|
||||||
const { time, onFinish, reset } = useCountdownTimer('00:02:00', 'mm:ss')
|
const { time, onFinish, reset } = useCountdownTimer('00:02:00', 'mm:ss')
|
||||||
@@ -55,7 +56,7 @@ export function useLoginForm() {
|
|||||||
const fingerPrint = await authenticateWithFingerprint()
|
const fingerPrint = await authenticateWithFingerprint()
|
||||||
if (fingerPrint) {
|
if (fingerPrint) {
|
||||||
setTruth()
|
setTruth()
|
||||||
await router.push({ name: 'home' })
|
await completeLoginNavigation()
|
||||||
} else {
|
} else {
|
||||||
message.error('خطا در اعتبارسنجی')
|
message.error('خطا در اعتبارسنجی')
|
||||||
}
|
}
|
||||||
@@ -75,7 +76,7 @@ export function useLoginForm() {
|
|||||||
await userStore.getMyInfo()
|
await userStore.getMyInfo()
|
||||||
await walletStore.getMyWallet()
|
await walletStore.getMyWallet()
|
||||||
setTruth()
|
setTruth()
|
||||||
await router.push({ name: 'home' })
|
await completeLoginNavigation()
|
||||||
}
|
}
|
||||||
|
|
||||||
function getcode() {
|
function getcode() {
|
||||||
|
|||||||
@@ -78,11 +78,18 @@ const isGaroosi = computed(() => config.config?.name === 'garoosi')
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
.login-page-root {
|
.login-page-root {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 100vh;
|
height: 100%;
|
||||||
|
max-height: 100dvh;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-page {
|
.login-page {
|
||||||
min-height: calc(100vh - var(--app-credit-footer-offset, 28px));
|
height: 100%;
|
||||||
|
max-height: calc(100dvh - var(--app-credit-footer-offset, 28px));
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
overscroll-behavior: contain;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-page__content {
|
.login-page__content {
|
||||||
|
|||||||
@@ -32,6 +32,10 @@ const isBoursecu = isBoursecuProject()
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.login-page {
|
.login-page {
|
||||||
min-height: calc(100vh - var(--app-credit-footer-offset, 28px));
|
min-height: calc(100dvh - var(--app-credit-footer-offset, 28px));
|
||||||
|
max-height: calc(100dvh - var(--app-credit-footer-offset, 28px));
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
overscroll-behavior: contain;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user