diff --git a/src/config-loader.js b/src/config-loader.js index 788aae1..cbe5011 100644 --- a/src/config-loader.js +++ b/src/config-loader.js @@ -15,104 +15,157 @@ configReject = reject; }); - // API endpoint for config - you can change this URL - // You can also set it via a data attribute: - //const scriptTag = document.currentScript || document.querySelector('script[src*="config-loader.js"]'); - //const customUrl = scriptTag ? scriptTag.getAttribute('data-config-url') : null; - const CONFIG_URL = 'https://nerkh.gold/get_user' //customUrl || window.location.origin + '/api/config'; + const VERSION_URL = 'https://abshode-service.montgit.ir/server/get_version'; + const CONFIG_URLS = [ + 'https://nerkh.gold/get_user', + 'https://abshode-service.montgit.ir/server/get_user' + ]; + const CONFIG_SUCCESS_URL_KEY = 'CONFIG_Success_URL'; - // Timeout to ensure main.ts loads even if config fails (5 seconds) - const CONFIG_TIMEOUT = 5000; + // Timeout to ensure main.ts loads even if config fails + const CONFIG_TIMEOUT = 12000; let configTimeoutId; let mainScriptLoaded = false; - // Fetch config from server - async function loadConfig() { + function getProtocol() { + return window.location.protocol === 'https:' ? 'https:' : 'http:'; + } + + function sortConfigUrls(urls) { + const lastSuccessUrl = localStorage.getItem(CONFIG_SUCCESS_URL_KEY); + + return [...urls].sort((a, b) => { + if (a === lastSuccessUrl) return -1; + if (b === lastSuccessUrl) return 1; + return 0; + }); + } + + async function fetchJson(url, timeout = 3500) { + const controller = new AbortController(); + const timeoutId = window.setTimeout(() => controller.abort(), timeout); + try { - const response = await fetch(CONFIG_URL, { + const response = await fetch(url, { method: 'GET', headers: { - 'Accept': 'application/json', + Accept: 'application/json' }, - cache: 'no-cache' + cache: 'no-store', + signal: controller.signal }); if (!response.ok) { - throw new Error('Failed to fetch config: ' + response.status); + throw new Error('Request failed: ' + response.status); } - // Check if response is actually JSON - const contentType = response.headers.get('content-type'); - if (!contentType || !contentType.includes('application/json')) { + const contentType = response.headers.get('content-type') || ''; + + if (!contentType.includes('application/json')) { const text = await response.text(); throw new Error('Response is not JSON. Received: ' + text.substring(0, 100)); } - const config = await response.json(); + return await response.json(); + } finally { + window.clearTimeout(timeoutId); + } + } - // Store config in window object - window.__APP_CONFIG__ = config; - window.__CONFIG_READY__ = true; - if (config?.user?.name_fa) { - document.title = 'پنل مدیریت '+ '-'+config.user.name_fa; - } - // ---------- Dynamic Favicon ---------- - if (config?.user?.avatar) { - const faviconUrl = config.user.avatar; - - // remove existing favicon(s) - const existingIcons = document.querySelectorAll('link[rel*="icon"]'); - existingIcons.forEach(icon => icon.remove()); - - // create new favicon - const link = document.createElement('link'); - link.rel = 'icon'; - link.type = 'image/png'; // یا image/x-icon - link.href = faviconUrl + '?v=' + Date.now(); - - document.head.appendChild(link); - } - // Resolve the promise - if (configResolve) { - configResolve(config); - } - - // Dispatch custom event to notify that config is ready - window.dispatchEvent(new CustomEvent('configReady', { detail: config })); - - console.log('Config loaded successfully:', config); - - // Clear timeout if config loaded successfully - if (configTimeoutId) { - clearTimeout(configTimeoutId); - configTimeoutId = null; - } - - // Load main.ts after config is ready - loadMainScript(); + async function loadVersion() { + try { + await fetchJson(VERSION_URL, 3500); + console.log('Version loaded from:', VERSION_URL); } catch (error) { - console.warn('Config loader: Could not fetch config from', CONFIG_URL); + console.warn('Version check failed from', VERSION_URL, error); + } + } + + async function fetchConfig() { + const protocol = getProtocol(); + const urls = sortConfigUrls( + CONFIG_URLS.map((url) => url.replace(/^https?:/, protocol)) + ); + + for (let index = 0; index < urls.length; index++) { + const url = urls[index]; + const timeout = index === urls.length - 1 ? 5000 : 3500; + + try { + const config = await fetchJson(url, timeout); + + if (!config || typeof config !== 'object') { + throw new Error('Config response is invalid'); + } + + localStorage.setItem(CONFIG_SUCCESS_URL_KEY, url); + return { config, url }; + } catch (error) { + console.warn('Config failed from', url, error); + } + } + + throw new Error('Cannot load config from any server'); + } + + function applyConfig(config) { + window.__APP_CONFIG__ = config; + window.__CONFIG_READY__ = true; + + if (config?.user?.name_fa) { + document.title = 'پنل مدیریت ' + '-' + config.user.name_fa; + } + + if (config?.user?.avatar) { + const faviconUrl = config.user.avatar; + const existingIcons = document.querySelectorAll('link[rel*="icon"]'); + existingIcons.forEach((icon) => icon.remove()); + + const link = document.createElement('link'); + link.rel = 'icon'; + link.type = 'image/png'; + link.href = faviconUrl + '?v=' + Date.now(); + document.head.appendChild(link); + } + } + + function finishConfigLoad(config, error) { + if (configResolve) { + configResolve(config); + } + + if (error) { + window.dispatchEvent(new CustomEvent('configError', { detail: error })); + } else { + window.dispatchEvent(new CustomEvent('configReady', { detail: config })); + } + + if (configTimeoutId) { + clearTimeout(configTimeoutId); + configTimeoutId = null; + } + + loadMainScript(); + } + + // Fetch config from server + async function loadConfig() { + try { + await loadVersion(); + + const { config, url } = await fetchConfig(); + applyConfig(config); + + console.log('Config loaded successfully from', url, config); + finishConfigLoad(config); + } catch (error) { + console.warn('Config loader: Could not fetch config from any endpoint'); console.warn('Error details:', error.message); - console.warn('This is normal if the endpoint does not exist yet. App will continue with empty config.'); - // Set default empty config on error + console.warn('App will continue with empty config.'); + window.__APP_CONFIG__ = {}; window.__CONFIG_READY__ = true; - - // Resolve the promise even on error (with empty config) - if (configResolve) { - configResolve({}); - } - - window.dispatchEvent(new CustomEvent('configError', { detail: error })); - - // Clear timeout if error occurred - if (configTimeoutId) { - clearTimeout(configTimeoutId); - configTimeoutId = null; - } - - // Load main.ts even on error (with empty config) - loadMainScript(); + finishConfigLoad({}, error); } } diff --git a/src/pages/menuPages/withdraw/components/WithdrawMobileDetailSheet.vue b/src/pages/menuPages/withdraw/components/WithdrawMobileDetailSheet.vue index 2537c73..5b65d12 100644 --- a/src/pages/menuPages/withdraw/components/WithdrawMobileDetailSheet.vue +++ b/src/pages/menuPages/withdraw/components/WithdrawMobileDetailSheet.vue @@ -62,15 +62,28 @@ {{ row.sts_str || '-' }} +