feat(每日充值活动): 根据手机系统类型使用不同的展示方案
This commit is contained in:
parent
e67b130afc
commit
f236293dfb
@ -10,13 +10,34 @@ import {
|
|||||||
// ==================== 工具函数 ====================
|
// ==================== 工具函数 ====================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检测是否为设备(Android、ios)系统
|
* 检测是否为移动设备(Android、iOS)系统
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
export function android() {
|
export function android() {
|
||||||
return /Android|iPad|iPhone|iPod/.test(navigator.userAgent)
|
return /Android|iPad|iPhone|iPod/.test(navigator.userAgent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测是否为 Android 设备
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
export function isAndroidDevice() {
|
||||||
|
if (typeof navigator === 'undefined') return false
|
||||||
|
return /Android/i.test(navigator.userAgent || '')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测是否为 iOS 设备
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
export function isIosDevice() {
|
||||||
|
if (typeof navigator === 'undefined') return false
|
||||||
|
const userAgent = navigator.userAgent || ''
|
||||||
|
const isIosUserAgent = /iPad|iPhone|iPod/i.test(userAgent)
|
||||||
|
const isIPadOS = /Macintosh/i.test(userAgent) && navigator.maxTouchPoints > 1
|
||||||
|
return isIosUserAgent || isIPadOS
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检测是否在APP环境中
|
* 检测是否在APP环境中
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
@ -289,6 +310,21 @@ export function gotoAppPage(pageName) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通知 APP 调用 VAP 播放
|
||||||
|
*/
|
||||||
|
export function notifyAppPlayVap(sourceUrl) {
|
||||||
|
if (!sourceUrl) return
|
||||||
|
try {
|
||||||
|
const message = `play_vap:${sourceUrl}`
|
||||||
|
infoLog(message)
|
||||||
|
// 直接使用Flutter通道
|
||||||
|
window.FlutterPageControl.postMessage(message)
|
||||||
|
} catch (error) {
|
||||||
|
errorLog('通知APP调用VAP失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打开app组件
|
* 打开app组件
|
||||||
*/
|
*/
|
||||||
|
|||||||
119
src/views/Activities/DailyRecharge/components/vapBg.vue
Normal file
119
src/views/Activities/DailyRecharge/components/vapBg.vue
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
<template>
|
||||||
|
<div class="active-game-page">
|
||||||
|
<video
|
||||||
|
v-if="!useVapPlayer"
|
||||||
|
ref="nativeVideoRef"
|
||||||
|
class="native-background-video"
|
||||||
|
:src="resolvedSrc"
|
||||||
|
autoplay
|
||||||
|
muted
|
||||||
|
loop
|
||||||
|
playsinline
|
||||||
|
webkit-playsinline
|
||||||
|
x5-playsinline
|
||||||
|
preload="auto"
|
||||||
|
></video>
|
||||||
|
<VapMp4Player
|
||||||
|
v-else
|
||||||
|
v-model="backgroundVisible"
|
||||||
|
class="vap-background"
|
||||||
|
:src="src"
|
||||||
|
mode="inline"
|
||||||
|
fit="cover"
|
||||||
|
:loop="true"
|
||||||
|
:mute="true"
|
||||||
|
:auto-close="false"
|
||||||
|
:show-status="false"
|
||||||
|
@error="handleVapError"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { computed, nextTick, onMounted, ref, watch } from 'vue'
|
||||||
|
import { showError } from '@/utils/toast.js'
|
||||||
|
import VapMp4Player from '@/components/VapMp4Player.vue'
|
||||||
|
import { preloadVapConfig } from '@/utils/vapMp4Config.js'
|
||||||
|
import { resolveProtectedAssetUrl } from '@/utils/protectedAssets.js'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
src: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const backgroundVisible = ref(true)
|
||||||
|
const nativeVideoRef = ref(null)
|
||||||
|
const useVapPlayer = ref(false)
|
||||||
|
const resolvedSrc = computed(() => resolveProtectedAssetUrl(props.src))
|
||||||
|
|
||||||
|
async function ensureNativeVideoPlayback() {
|
||||||
|
await nextTick()
|
||||||
|
|
||||||
|
const video = nativeVideoRef.value
|
||||||
|
if (!video) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
video.muted = true
|
||||||
|
video.defaultMuted = true
|
||||||
|
video.playsInline = true
|
||||||
|
video.setAttribute('playsinline', '')
|
||||||
|
video.setAttribute('webkit-playsinline', '')
|
||||||
|
video.setAttribute('x5-playsinline', '')
|
||||||
|
|
||||||
|
try {
|
||||||
|
await video.play()
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Native background video autoplay failed:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function resolvePlaybackMode() {
|
||||||
|
useVapPlayer.value = false
|
||||||
|
|
||||||
|
if (!resolvedSrc.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ensureNativeVideoPlayback()
|
||||||
|
|
||||||
|
const vapConfig = await preloadVapConfig(resolvedSrc.value)
|
||||||
|
if (vapConfig) {
|
||||||
|
useVapPlayer.value = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleVapError(error) {
|
||||||
|
console.error('VAP playback failed:', error)
|
||||||
|
useVapPlayer.value = false
|
||||||
|
ensureNativeVideoPlayback()
|
||||||
|
|
||||||
|
if (!error?.message?.includes('VAP config')) {
|
||||||
|
showError(error?.message || 'VAP playback failed')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
resolvePlaybackMode()
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(resolvedSrc, () => {
|
||||||
|
resolvePlaybackMode()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.active-game-page {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.native-background-video {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -15,12 +15,14 @@
|
|||||||
<div class="active-game-shell scroll">
|
<div class="active-game-shell scroll">
|
||||||
<div class="active-game-stage">
|
<div class="active-game-stage">
|
||||||
<!-- 头部背景图 -->
|
<!-- 头部背景图 -->
|
||||||
<img
|
<VapBg
|
||||||
v-smart-img.noFade
|
v-if="isAndroidDevice"
|
||||||
:src="imageUrl('bg2')"
|
class="vap-background-layer vap-background-vap-layer"
|
||||||
alt=""
|
:src="bgVapUrl"
|
||||||
class="vap-background-layer"
|
|
||||||
/>
|
/>
|
||||||
|
<img v-else v-smart-img.noFade :src="imageUrl('bg2')" alt="" class="vap-background-layer" />
|
||||||
|
|
||||||
|
<!-- 背景层 -->
|
||||||
<div class="page-background-layer">
|
<div class="page-background-layer">
|
||||||
<BackgroundLayer
|
<BackgroundLayer
|
||||||
:useCanvas="true"
|
:useCanvas="true"
|
||||||
@ -325,36 +327,35 @@ justify-content: flex-start;
|
|||||||
<div
|
<div
|
||||||
class="reward-showcase-vap-wrap"
|
class="reward-showcase-vap-wrap"
|
||||||
:key="mainRewardRenderKey"
|
:key="mainRewardRenderKey"
|
||||||
:class="{ 'reward-showcase-vap-wrap-playable': mainReward?.sourceUrl }"
|
:class="{
|
||||||
@click="playMainRewardPreview"
|
'reward-showcase-vap-wrap-playable': isIosDevice && mainReward?.sourceUrl,
|
||||||
|
}"
|
||||||
|
@click="handleMainRewardPreviewClick"
|
||||||
>
|
>
|
||||||
<VapMp4Player
|
<VapMp4Player
|
||||||
v-if="mainReward.sourceUrl && rewardPreviewPlaying"
|
v-if="isAndroidDevice && mainReward.sourceUrl"
|
||||||
:model-value="rewardPreviewPlaying"
|
:model-value="true"
|
||||||
:src="mainReward.sourceUrl"
|
:src="mainReward.sourceUrl"
|
||||||
mode="overlay"
|
mode="inline"
|
||||||
fit="contain"
|
fit="contain"
|
||||||
:loop="true"
|
:loop="true"
|
||||||
:mute="true"
|
:mute="true"
|
||||||
:auto-close="false"
|
:auto-close="false"
|
||||||
:show-close="true"
|
|
||||||
:show-status="false"
|
:show-status="false"
|
||||||
@update:modelValue="rewardPreviewPlaying = $event"
|
|
||||||
@close="rewardPreviewPlaying = false"
|
|
||||||
@error="handleRewardVapError"
|
@error="handleRewardVapError"
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
v-if="!mainReward.sourceUrl || !rewardPreviewPlaying"
|
v-else
|
||||||
:src="mainReward.cover || ''"
|
:src="mainReward.cover || ''"
|
||||||
alt=""
|
alt=""
|
||||||
style="display: block; width: 90%; object-fit: contain"
|
style="display: block; width: 90%; object-fit: contain"
|
||||||
@error="(e) => handleRewardImageError(e, mainReward.type)"
|
@error="(e) => handleRewardImageError(e, mainReward.type)"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
v-if="mainReward.sourceUrl && !rewardPreviewPlaying"
|
v-if="isIosDevice && mainReward.sourceUrl"
|
||||||
type="button"
|
type="button"
|
||||||
class="reward-showcase-play-button"
|
class="reward-showcase-play-button"
|
||||||
@click.stop="playMainRewardPreview"
|
@click.stop="handleMainRewardPreviewClick"
|
||||||
>
|
>
|
||||||
<span class="reward-showcase-play-icon"></span>
|
<span class="reward-showcase-play-icon"></span>
|
||||||
</button>
|
</button>
|
||||||
@ -425,11 +426,7 @@ justify-content: flex-start;
|
|||||||
class="reward-extra-scroll-wrapper"
|
class="reward-extra-scroll-wrapper"
|
||||||
:class="{ 'reward-extra-scroll-wrapper-rtl': isRtlLayout }"
|
:class="{ 'reward-extra-scroll-wrapper-rtl': isRtlLayout }"
|
||||||
>
|
>
|
||||||
<div
|
<div v-for="value in 2" :key="value" class="reward-extra-scroll-content">
|
||||||
v-for="value in 2"
|
|
||||||
:key="value"
|
|
||||||
class="reward-extra-scroll-content"
|
|
||||||
>
|
|
||||||
{{ getRewardDisplayText(reward) }}
|
{{ getRewardDisplayText(reward) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -511,11 +508,16 @@ justify-content: flex-start;
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
import { computed, defineAsyncComponent, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { setDocumentDirection } from '@/locales/i18n'
|
import { setDocumentDirection } from '@/locales/i18n'
|
||||||
import { connectToApp } from '@/utils/appConnector.js'
|
import { connectToApp } from '@/utils/appConnector.js'
|
||||||
import { getPngUrl } from '@/config/imagePaths.js'
|
import {
|
||||||
|
isAndroidDevice as detectAndroidDevice,
|
||||||
|
isIosDevice as detectIosDevice,
|
||||||
|
notifyAppPlayVap,
|
||||||
|
} from '@/utils/appBridge.js'
|
||||||
|
import { getMp4Url, getPngUrl } from '@/config/imagePaths.js'
|
||||||
import { preloadImages } from '@/utils/image/imagePreloader.js'
|
import { preloadImages } from '@/utils/image/imagePreloader.js'
|
||||||
import { useLangStore } from '@/stores/lang'
|
import { useLangStore } from '@/stores/lang'
|
||||||
import { showError } from '@/utils/toast.js'
|
import { showError } from '@/utils/toast.js'
|
||||||
@ -534,7 +536,9 @@ import { useThrottle } from '@/utils/useDebounce.js'
|
|||||||
import BackgroundLayer from '@/components/BackgroundLayer.vue'
|
import BackgroundLayer from '@/components/BackgroundLayer.vue'
|
||||||
import itemCenter from '@/components/itemCenter.vue'
|
import itemCenter from '@/components/itemCenter.vue'
|
||||||
import maskLayer from '@/components/MaskLayer.vue'
|
import maskLayer from '@/components/MaskLayer.vue'
|
||||||
import VapMp4Player from '@/components/VapMp4Player.vue'
|
|
||||||
|
const VapMp4Player = defineAsyncComponent(() => import('@/components/VapMp4Player.vue'))
|
||||||
|
const VapBg = defineAsyncComponent(() => import('./components/vapBg.vue'))
|
||||||
|
|
||||||
const isLoading = ref(true)
|
const isLoading = ref(true)
|
||||||
|
|
||||||
@ -547,10 +551,74 @@ const currentLangType = computed(() => {
|
|||||||
const isRtlLayout = computed(() => {
|
const isRtlLayout = computed(() => {
|
||||||
return currentLangType.value === 'ar'
|
return currentLangType.value === 'ar'
|
||||||
})
|
})
|
||||||
|
const DEVICE_SIMULATION_STORAGE_KEY = 'daily-recharge-device-simulation'
|
||||||
|
const DEVICE_SIMULATION_MODES = ['auto', 'android', 'ios']
|
||||||
|
const normalizeDeviceSimulationMode = (mode) => {
|
||||||
|
return DEVICE_SIMULATION_MODES.includes(mode) ? mode : 'auto'
|
||||||
|
}
|
||||||
|
const getDeviceSimulationQueryMode = () => {
|
||||||
|
if (typeof window === 'undefined') {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchMode = new URLSearchParams(window.location.search).get('dailyRechargeDevice')
|
||||||
|
if (searchMode) {
|
||||||
|
return searchMode
|
||||||
|
}
|
||||||
|
|
||||||
|
const hashQueryIndex = window.location.hash.indexOf('?')
|
||||||
|
if (hashQueryIndex === -1) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
return new URLSearchParams(window.location.hash.slice(hashQueryIndex + 1)).get(
|
||||||
|
'dailyRechargeDevice',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const getInitialDeviceSimulationMode = () => {
|
||||||
|
if (!import.meta.env.DEV || typeof window === 'undefined') {
|
||||||
|
return 'auto'
|
||||||
|
}
|
||||||
|
|
||||||
|
const queryMode = getDeviceSimulationQueryMode()
|
||||||
|
const storageMode = window.localStorage.getItem(DEVICE_SIMULATION_STORAGE_KEY)
|
||||||
|
return normalizeDeviceSimulationMode(queryMode || storageMode || 'auto')
|
||||||
|
}
|
||||||
|
const simulatedDeviceMode = ref(getInitialDeviceSimulationMode())
|
||||||
|
const isAndroidDevice = computed(() => {
|
||||||
|
if (import.meta.env.DEV && simulatedDeviceMode.value === 'android') {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (import.meta.env.DEV && simulatedDeviceMode.value === 'ios') {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return detectAndroidDevice()
|
||||||
|
})
|
||||||
|
const isIosDevice = computed(() => {
|
||||||
|
if (import.meta.env.DEV && simulatedDeviceMode.value === 'ios') {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (import.meta.env.DEV && simulatedDeviceMode.value === 'android') {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return detectIosDevice()
|
||||||
|
})
|
||||||
|
const setSimulatedDeviceMode = (mode = 'auto') => {
|
||||||
|
if (!import.meta.env.DEV) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
simulatedDeviceMode.value = normalizeDeviceSimulationMode(mode)
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
window.localStorage.setItem(DEVICE_SIMULATION_STORAGE_KEY, simulatedDeviceMode.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
locale.value && setDocumentDirection(locale.value)
|
locale.value && setDocumentDirection(locale.value)
|
||||||
|
|
||||||
const imageUrl = (filename) => getPngUrl('Activities/DailyRecharge/', filename)
|
const imageUrl = (filename) => getPngUrl('Activities/DailyRecharge/', filename)
|
||||||
|
const mp4Url = (filename) => getMp4Url('Activities/DailyRecharge/', filename)
|
||||||
|
const bgVapUrl = mp4Url('bg')
|
||||||
const CHEST_PROGRESS_GAP_VW = 2
|
const CHEST_PROGRESS_GAP_VW = 2
|
||||||
const CHEST_PROGRESS_ITEM_WIDTH_VW = 14
|
const CHEST_PROGRESS_ITEM_WIDTH_VW = 14
|
||||||
const CHEST_PROGRESS_FIRST_CENTER_VW = CHEST_PROGRESS_GAP_VW + CHEST_PROGRESS_ITEM_WIDTH_VW / 2
|
const CHEST_PROGRESS_FIRST_CENTER_VW = CHEST_PROGRESS_GAP_VW + CHEST_PROGRESS_ITEM_WIDTH_VW / 2
|
||||||
@ -713,8 +781,8 @@ const rewardGridList = computed(() => {
|
|||||||
const mainRewardRenderKey = computed(() => {
|
const mainRewardRenderKey = computed(() => {
|
||||||
return mainReward.value ? getRewardRenderKey(mainReward.value, 0) : 'empty-main-reward'
|
return mainReward.value ? getRewardRenderKey(mainReward.value, 0) : 'empty-main-reward'
|
||||||
})
|
})
|
||||||
const rewardPreviewPlaying = ref(false)
|
|
||||||
const rewardVapPreloadElements = new Map()
|
const rewardVapPreloadElements = new Map()
|
||||||
|
const criticalVapPreloadElements = new Map()
|
||||||
let rewardVapPreloadTimer = null
|
let rewardVapPreloadTimer = null
|
||||||
let rewardVapPreloadIdleCallbackId = null
|
let rewardVapPreloadIdleCallbackId = null
|
||||||
let rewardVapPreloadStarted = false
|
let rewardVapPreloadStarted = false
|
||||||
@ -749,7 +817,7 @@ const getRewardVapUrls = (rewardTopList) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const preloadRewardVap = (sourceUrl) => {
|
const preloadRewardVap = (sourceUrl) => {
|
||||||
if (!sourceUrl || rewardVapPreloadElements.has(sourceUrl)) {
|
if (!isAndroidDevice.value || !sourceUrl || rewardVapPreloadElements.has(sourceUrl)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -785,8 +853,39 @@ const preloadRewardVaps = (rewardTopList) => {
|
|||||||
getRewardVapUrls(rewardTopList).forEach(preloadRewardVap)
|
getRewardVapUrls(rewardTopList).forEach(preloadRewardVap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const preloadCriticalVap = (sourceUrl) => {
|
||||||
|
if (!isAndroidDevice.value || !sourceUrl) {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolvedSourceUrl = resolveProtectedAssetUrl(sourceUrl)
|
||||||
|
const configPromise = preloadVapConfig(resolvedSourceUrl)
|
||||||
|
|
||||||
|
if (criticalVapPreloadElements.has(resolvedSourceUrl) || typeof document === 'undefined') {
|
||||||
|
return configPromise
|
||||||
|
}
|
||||||
|
|
||||||
|
const preloadVideo = document.createElement('video')
|
||||||
|
preloadVideo.preload = 'auto'
|
||||||
|
preloadVideo.muted = true
|
||||||
|
preloadVideo.playsInline = true
|
||||||
|
preloadVideo.src = resolvedSourceUrl
|
||||||
|
preloadVideo.style.position = 'fixed'
|
||||||
|
preloadVideo.style.left = '-9999px'
|
||||||
|
preloadVideo.style.top = '-9999px'
|
||||||
|
preloadVideo.style.width = '1px'
|
||||||
|
preloadVideo.style.height = '1px'
|
||||||
|
preloadVideo.style.opacity = '0'
|
||||||
|
preloadVideo.style.pointerEvents = 'none'
|
||||||
|
document.body.appendChild(preloadVideo)
|
||||||
|
preloadVideo.load()
|
||||||
|
criticalVapPreloadElements.set(resolvedSourceUrl, preloadVideo)
|
||||||
|
|
||||||
|
return configPromise
|
||||||
|
}
|
||||||
|
|
||||||
const startRewardVapPreload = () => {
|
const startRewardVapPreload = () => {
|
||||||
if (rewardVapPreloadStarted || !activityRewards.value.length) {
|
if (!isAndroidDevice.value || rewardVapPreloadStarted || !activityRewards.value.length) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -795,7 +894,7 @@ const startRewardVapPreload = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const queueRewardVapPreload = () => {
|
const queueRewardVapPreload = () => {
|
||||||
if (rewardVapPreloadStarted || typeof window === 'undefined') {
|
if (!isAndroidDevice.value || rewardVapPreloadStarted || typeof window === 'undefined') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -912,22 +1011,19 @@ const openPopup = (type) => {
|
|||||||
|
|
||||||
const handleRewardVapError = (error) => {
|
const handleRewardVapError = (error) => {
|
||||||
console.error('Reward VAP playback failed:', error)
|
console.error('Reward VAP playback failed:', error)
|
||||||
rewardPreviewPlaying.value = false
|
|
||||||
showError(error?.message || t('active_game_vap_playback_failed'))
|
showError(error?.message || t('active_game_vap_playback_failed'))
|
||||||
}
|
}
|
||||||
|
|
||||||
const playMainRewardPreview = () => {
|
const handleMainRewardPreviewClick = () => {
|
||||||
if (!mainReward.value?.sourceUrl) {
|
if (!mainReward.value?.sourceUrl) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rewardPreviewPlaying.value = true
|
if (isIosDevice.value) {
|
||||||
|
notifyAppPlayVap(mainReward.value.sourceUrl)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(mainRewardRenderKey, () => {
|
|
||||||
rewardPreviewPlaying.value = false
|
|
||||||
})
|
|
||||||
|
|
||||||
const claimTask1Reward = useThrottle(async () => {
|
const claimTask1Reward = useThrottle(async () => {
|
||||||
if (!canClaimTask1Reward.value) {
|
if (!canClaimTask1Reward.value) {
|
||||||
return
|
return
|
||||||
@ -1017,9 +1113,7 @@ const preloadCriticalImages = async () => {
|
|||||||
imageUrl(getImgName('ruleTitle')),
|
imageUrl(getImgName('ruleTitle')),
|
||||||
]
|
]
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([preloadImages(criticalImages), preloadCriticalVap(bgVapUrl)])
|
||||||
preloadImages(criticalImages),
|
|
||||||
])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const completePreloading = async () => {
|
const completePreloading = async () => {
|
||||||
@ -1068,10 +1162,18 @@ const connectToAppHandler = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
if (import.meta.env.DEV && typeof window !== 'undefined') {
|
||||||
|
window.__setDailyRechargeDevice = setSimulatedDeviceMode
|
||||||
|
window.__dailyRechargeDeviceMode = simulatedDeviceMode
|
||||||
|
}
|
||||||
connectToAppHandler()
|
connectToAppHandler()
|
||||||
})
|
})
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
|
if (import.meta.env.DEV && typeof window !== 'undefined') {
|
||||||
|
delete window.__setDailyRechargeDevice
|
||||||
|
delete window.__dailyRechargeDeviceMode
|
||||||
|
}
|
||||||
if (connectToAppFallbackTimer !== null && typeof window !== 'undefined') {
|
if (connectToAppFallbackTimer !== null && typeof window !== 'undefined') {
|
||||||
window.clearTimeout(connectToAppFallbackTimer)
|
window.clearTimeout(connectToAppFallbackTimer)
|
||||||
connectToAppFallbackTimer = null
|
connectToAppFallbackTimer = null
|
||||||
@ -1095,6 +1197,13 @@ onBeforeUnmount(() => {
|
|||||||
video.parentNode && video.parentNode.removeChild(video)
|
video.parentNode && video.parentNode.removeChild(video)
|
||||||
})
|
})
|
||||||
rewardVapPreloadElements.clear()
|
rewardVapPreloadElements.clear()
|
||||||
|
criticalVapPreloadElements.forEach((video) => {
|
||||||
|
video.pause()
|
||||||
|
video.removeAttribute('src')
|
||||||
|
video.load()
|
||||||
|
video.parentNode && video.parentNode.removeChild(video)
|
||||||
|
})
|
||||||
|
criticalVapPreloadElements.clear()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -1144,9 +1253,14 @@ onBeforeUnmount(() => {
|
|||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
object-fit: cover;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vap-background-vap-layer {
|
||||||
|
height: 150vw;
|
||||||
|
}
|
||||||
|
|
||||||
.page-background-layer {
|
.page-background-layer {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 120vw;
|
top: 120vw;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user