"; // 例如:const API_BASE_URL = "https://survival-api.abc123.workers.dev"; let currentUser = null; let customHabits = []; let checkData = {}; let selectedDate = new Date(); let currentDisplayYear = new Date().getFullYear(); let currentDisplayMonth = new Date().getMonth(); const COMMON_ICONS = ["🌅", "🌙", "🏃", "🧘", "💧", "📚", "🥗", "🚶", "🏋️", "🧠", "🎯", "💪", "🚿", "🧹", "✍️", "🎵", "🏊", "🚴", "🧃", "☕️", "🍎", "💤", "🌟", "🌍", "🏕️", "🎒", "⛰️", "🌸", "🍃", "🦋", "🐚", "🎨"]; // ==================== 云端API调用函数 ==================== async function callAPI(endpoint, data) { try { const response = await fetch(`${API_BASE_URL}${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }); return await response.json(); } catch (error) { console.error('API调用失败:', error); return { success: false, message: '网络错误,请检查网络连接' }; } } async function callGetAPI(endpoint, params) { try { const url = new URL(`${API_BASE_URL}${endpoint}`); Object.keys(params).forEach(key => url.searchParams.append(key, params[key])); const response = await fetch(url); return await response.json(); } catch (error) { console.error('API调用失败:', error); return { success: false, message: '网络错误' }; } } // 注册 async function register(username, password, securityQuestion, securityAnswer) { return await callAPI('/api/register', { username, password, securityQuestion, securityAnswer }); } // 登录 async function login(username, password) { const result = await callAPI('/api/login', { username, password }); if (result.success) { currentUser = { username: username, token: result.token }; customHabits = result.user.habits; checkData = result.user.checkData; localStorage.setItem("cloud_last_user", username); localStorage.setItem("cloud_token", result.token); return { success: true }; } return result; } // 保存用户数据到云端 async function saveUserData() { if (!currentUser) return; await callAPI('/api/saveUserData', { username: currentUser.username, habits: customHabits, checkData: checkData }); } // 修改密码 async function changePassword(username, oldPassword, newPassword) { return await callAPI('/api/changePassword', { username, oldPassword, newPassword }); } // 验证安全问题 async function verifySecurity(username, answer) { return await callAPI('/api/verifySecurity', { username, answer }); } // 重置密码 async function resetPassword(username, newPassword) { return await callAPI('/api/resetPassword', { username, newPassword }); } // 退出登录 function logout() { if (currentUser) { saveUserData(); } currentUser = null; localStorage.removeItem("cloud_last_user"); localStorage.removeItem("cloud_token"); showSplashAndAuth(); } // ==================== 3D地球 ==================== function createHDRTexture() { const canvas = document.createElement('canvas'); canvas.width = 1024; canvas.height = 1024; const ctx = canvas.getContext('2d'); ctx.fillStyle = '#1a4d8c'; ctx.fillRect(0, 0, canvas.width, canvas.height); const gradient = ctx.createLinearGradient(0, 0, canvas.width, canvas.height); gradient.addColorStop(0, '#2a6bae'); gradient.addColorStop(1, '#0a3a6a'); ctx.fillStyle = gradient; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = '#6abe6a'; ctx.beginPath(); ctx.moveTo(180, 280); ctx.bezierCurveTo(160,260,140,270,130,290); ctx.fill(); ctx.beginPath(); ctx.moveTo(160, 180); ctx.bezierCurveTo(140,160,115,165,105,185); ctx.fill(); ctx.beginPath(); ctx.moveTo(550, 150); ctx.bezierCurveTo(520,130,490,135,475,150); ctx.fill(); ctx.beginPath(); ctx.moveTo(490, 330); ctx.bezierCurveTo(470,315,450,325,445,345); ctx.fill(); ctx.beginPath(); ctx.ellipse(780, 520, 40, 35, 0.2, 0, Math.PI*2); ctx.fill(); return new THREE.CanvasTexture(canvas); } function initHDREarth(containerId) { const container = document.getElementById(containerId); if (!container || container.innerHTML) return; const width = 48, height = 48; const scene = new THREE.Scene(); scene.background = null; const camera = new THREE.PerspectiveCamera(45, width/height, 0.1, 1000); camera.position.set(0, 0, 2.2); const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true }); renderer.setSize(width, height); renderer.setClearColor(0x000000, 0); container.innerHTML = ''; container.appendChild(renderer.domElement); renderer.domElement.classList.add('earth-canvas'); const texture = createHDRTexture(); const geometry = new THREE.SphereGeometry(0.88, 96, 96); const material = new THREE.MeshStandardMaterial({ map: texture, roughness: 0.3, metalness: 0.2, emissive: '#2266aa', emissiveIntensity: 0.25 }); const earth = new THREE.Mesh(geometry, material); scene.add(earth); const ambient = new THREE.AmbientLight(0x446688); scene.add(ambient); const light = new THREE.DirectionalLight(0xffeedd, 1.5); light.position.set(5,3,5); scene.add(light); let angle = 0; function animate() { requestAnimationFrame(animate); angle += 0.007; earth.rotation.y = angle; renderer.render(scene, camera); } animate(); } // ==================== 日历同步功能 ==================== function generateICS(eventTitle, startDate, notes = "", icon = "⏰") { const formatICSDate = (date) => new Date(date).toISOString().replace(/[-:]/g, '').split('.')[0] + 'Z'; const startUTC = new Date(startDate); const endUTC = new Date(startUTC.getTime() + 30 * 60000); return [ "BEGIN:VCALENDAR", "VERSION:2.0", "PRODID:-//Online Survival Diary//EN", "BEGIN:VEVENT", `SUMMARY:${icon} ${eventTitle}`, `DTSTART:${formatICSDate(startUTC)}`, `DTEND:${formatICSDate(endUTC)}`, `DESCRIPTION:${notes}\\n来自Online生存日记`, "BEGIN:VALARM", "TRIGGER:-PT15M", "ACTION:DISPLAY", "DESCRIPTION:提醒", "END:VALARM", "END:VEVENT", "END:VCALENDAR" ].join("\r\n"); } function syncAllToCalendar() { const habitsWithReminder = customHabits.filter(h => h.reminderTime && h.reminderTime.trim()); if (habitsWithReminder.length === 0) return alert("当前没有设置提醒时间的事项"); if (confirm(`将生成 ${habitsWithReminder.length} 个日历提醒文件`)) { habitsWithReminder.forEach((habit, index) => { const today = new Date(); const [hour, minute] = habit.reminderTime.split(':'); const remindDate = new Date(today); remindDate.setHours(parseInt(hour), parseInt(minute), 0, 0); const ics = generateICS(`${habit.name} 提醒`, remindDate, habit.remark || habit.name, habit.icon || '⏰'); const blob = new Blob([ics], { type: "text/calendar" }); const link = document.createElement("a"); link.href = URL.createObjectURL(blob); link.download = `reminder_${habit.name.replace(/\s/g, '_')}.ics`; document.body.appendChild(link); setTimeout(() => { link.click(); document.body.removeChild(link); URL.revokeObjectURL(link.href); }, index * 300); }); setTimeout(() => alert(`已生成 ${habitsWithReminder.length} 个日历文件`), habitsWithReminder.length * 300 + 100); } } function syncSelectedDateToCalendar() { if (!selectedDate) return alert("请先选择一个日期"); const habitsWithReminder = customHabits.filter(h => h.reminderTime && h.reminderTime.trim()); if (habitsWithReminder.length === 0) return alert("当前没有设置提醒时间的事项"); if (confirm(`将生成 ${habitsWithReminder.length} 个提醒文件`)) { habitsWithReminder.forEach((habit, index) => { const [hour, minute] = habit.reminderTime.split(':'); const remindDate = new Date(selectedDate); remindDate.setHours(parseInt(hour), parseInt(minute), 0, 0); const ics = generateICS(`${habit.name} 提醒`, remindDate, habit.remark || habit.name, habit.icon || '⏰'); const blob = new Blob([ics], { type: "text/calendar" }); const link = document.createElement("a"); link.href = URL.createObjectURL(blob); link.download = `reminder_${selectedDate.toISOString().slice(0,10)}_${habit.name.replace(/\s/g, '_')}.ics`; document.body.appendChild(link); setTimeout(() => { link.click(); document.body.removeChild(link); URL.revokeObjectURL(link.href); }, index * 300); }); setTimeout(() => alert(`已生成 ${habitsWithReminder.length} 个日历文件`), habitsWithReminder.length * 300 + 100); } } // ==================== 主应用逻辑 ==================== function formatYMD(date) { return `${date.getFullYear()}-${String(date.getMonth()+1).padStart(2,'0')}-${String(date.getDate()).padStart(2,'0')}`; } function getDayCheckObject(date) { const key = formatYMD(date); if (!checkData[key]) checkData[key] = {}; customHabits.forEach(h => { if (typeof checkData[key][h.id] !== 'boolean') checkData[key][h.id] = false; }); return checkData[key]; } function getProgressForDate(date) { const dayObj = getDayCheckObject(date); if (customHabits.length === 0) return 0; return customHabits.filter(h => dayObj[h.id]).length / customHabits.length; } async function toggleHabitStatus(date, habitId, completed) { const key = formatYMD(date); if (!checkData[key]) checkData[key] = {}; checkData[key][habitId] = completed; await saveUserData(); renderCalendar(); if (selectedDate && formatYMD(selectedDate) === formatYMD(date)) { renderHabitPanel(selectedDate); updateDailyProgress(selectedDate); } } function updateDailyProgress(date) { const percent = Math.round(getProgressForDate(date) * 100); const badge = document.getElementById("dailyProgressBadge"); if (badge) badge.innerText = `${percent}%`; } function renderCalendar() { const grid = document.getElementById("calendarGrid"); if (!grid) return; const year = currentDisplayYear, month = currentDisplayMonth; const firstDay = new Date(year, month, 1); let offset = (firstDay.getDay() === 0 ? 6 : firstDay.getDay() - 1); const daysInMonth = new Date(year, month + 1, 0).getDate(); const daysInPrevMonth = new Date(year, month, 0).getDate(); let cellsHtml = ''; for (let i = 0; i < 42; i++) { let cellDate, isCurrentMonth = true, dayNumber; if (i < offset) { dayNumber = daysInPrevMonth - (offset - i); const prevYear = month === 0 ? year - 1 : year; const prevMonth = month === 0 ? 11 : month - 1; cellDate = new Date(prevYear, prevMonth, dayNumber); isCurrentMonth = false; } else if (i >= offset + daysInMonth) { dayNumber = i - (offset + daysInMonth) + 1; const nextYear = month === 11 ? year + 1 : year; const nextMonth = month === 11 ? 0 : month + 1; cellDate = new Date(nextYear, nextMonth, dayNumber); isCurrentMonth = false; } else { dayNumber = i - offset + 1; cellDate = new Date(year, month, dayNumber); isCurrentMonth = true; } const isToday = cellDate.toDateString() === new Date().toDateString(); const progress = getProgressForDate(cellDate); const percent = Math.round(progress * 100); let progressClass = '', progressText = ''; if (progress === 1) { progressClass = 'progress-complete'; progressText = '✓'; } else if (progress > 0) { progressClass = 'progress-partial'; progressText = `${percent}%`; } else { progressClass = 'progress-none'; progressText = '○'; } let extraClass = !isCurrentMonth ? "other-month" : ""; if (isToday) extraClass += " today"; cellsHtml += `
${dayNumber}
${progressText}
`; } grid.innerHTML = cellsHtml; document.querySelectorAll('.calendar-day').forEach(el => { el.addEventListener('click', () => { const [y, m, d] = el.getAttribute('data-date').split('-').map(Number); selectedDate = new Date(y, m, d); renderHabitPanel(selectedDate); updateDailyProgress(selectedDate); highlightSelectedDate(selectedDate); }); }); if (selectedDate) highlightSelectedDate(selectedDate); const monthDisplay = document.getElementById("monthYearDisplay"); if (monthDisplay) monthDisplay.innerText = `${year}年 ${month+1}月`; } function highlightSelectedDate(date) { document.querySelectorAll('.calendar-day').forEach(day => { day.style.border = ''; day.style.backgroundColor = ''; }); const target = document.querySelector(`.calendar-day[data-date="${date.getFullYear()}-${date.getMonth()}-${date.getDate()}"]`); if (target) { target.style.border = '2px solid #3b82f6'; target.style.backgroundColor = '#eef2ff'; } } function renderHabitPanel(date) { const container = document.getElementById("habitListContainer"); const dateBadge = document.querySelector(".date-badge"); if (!container || !dateBadge) return; if (!date) { container.innerHTML = '
点击日历选择日期
'; return; } dateBadge.innerHTML = `📅 ${date.getFullYear()}年${date.getMonth()+1}月${date.getDate()}日 ${['周日','周一','周二','周三','周四','周五','周六'][date.getDay()]}`; const dayData = getDayCheckObject(date); if (customHabits.length === 0) { container.innerHTML = '
✨ 点击下方添加生存事项
'; updateDailyProgress(date); return; } let habitsHtml = ''; customHabits.forEach(habit => { const isChecked = dayData[habit.id] === true; const btnClass = isChecked ? 'check-btn completed' : 'check-btn'; const btnText = isChecked ? '✓' : '○'; const remarkDisplay = habit.remark ? (habit.remark.length > 25 ? habit.remark.substring(0,22)+'...' : habit.remark) : ''; habitsHtml += `
${habit.icon || '📋'}${escapeHtml(habit.name)}
${remarkDisplay ? `📝 ${escapeHtml(remarkDisplay)}` : '无备注'}
`; }); container.innerHTML = habitsHtml; attachHabitEvents(date); updateDailyProgress(date); } function attachHabitEvents(date) { document.querySelectorAll('.check-btn').forEach(btn => { btn.addEventListener('click', async () => { const habitId = btn.getAttribute('data-id'); const currentlyChecked = btn.getAttribute('data-checked') === 'true'; await toggleHabitStatus(date, habitId, !currentlyChecked); }); }); document.querySelectorAll('.set-reminder-btn').forEach(btn => { btn.addEventListener('click', async () => { const habitId = btn.getAttribute('data-id'); const timeInput = document.querySelector(`.reminder-time-input[data-id="${habitId}"]`); const habit = customHabits.find(h => h.id === habitId); if (habit && timeInput.value) { habit.reminderTime = timeInput.value; await saveUserData(); alert(`已设置提醒 ${timeInput.value}`); } }); }); document.querySelectorAll('.delete-habit-btn').forEach(btn => { btn.addEventListener('click', async () => { const habitId = btn.getAttribute('data-id'); if (confirm('删除后历史打卡数据将不再显示?')) { const idx = customHabits.findIndex(h => h.id === habitId); if (idx !== -1) { customHabits.splice(idx, 1); for (let key in checkData) delete checkData[key][habitId]; await saveUserData(); renderCalendar(); renderHabitPanel(selectedDate); } } }); }); } function showAddHabitModal() { let selectedIcon = "🌍"; const modal = document.createElement('div'); modal.className = 'modal-overlay'; modal.innerHTML = `
✨ 添加生存事项
`; document.body.appendChild(modal); const iconGrid = modal.querySelector('#modalIconGrid'); COMMON_ICONS.forEach(icon => { const div = document.createElement('div'); div.className = 'icon-option'; div.textContent = icon; if (icon === selectedIcon) div.classList.add('selected'); div.addEventListener('click', () => { iconGrid.querySelectorAll('.icon-option').forEach(opt => opt.classList.remove('selected')); div.classList.add('selected'); selectedIcon = icon; }); iconGrid.appendChild(div); }); const nameInput = modal.querySelector('#modalHabitName'); const remarkInput = modal.querySelector('#modalHabitRemark'); modal.querySelector('#confirmModalBtn').addEventListener('click', async () => { const name = nameInput.value.trim(); if (!name) { alert("请输入事项名称"); return; } customHabits.push({ id: "habit_" + Date.now() + "_" + Math.random().toString(36).substr(2, 6), name: name, icon: selectedIcon, remark: remarkInput.value.trim() || "", reminderTime: "" }); await saveUserData(); renderCalendar(); renderHabitPanel(selectedDate); modal.remove(); }); modal.querySelector('#cancelModalBtn').addEventListener('click', () => modal.remove()); modal.addEventListener('click', (e) => { if (e.target === modal) modal.remove(); }); } // 个人中心页面 function renderProfilePage() { const totalDays = new Set(); let totalCheckins = 0; for (let key in checkData) { const dayData = checkData[key]; let hasAny = false; for (let hid in dayData) { if (dayData[hid] === true) { hasAny = true; totalCheckins++; } } if (hasAny) totalDays.add(key); } const habitStats = customHabits.map(habit => ({ ...habit, completedDays: Object.values(checkData).filter(day => day[habit.id] === true).length })); const maxCompleted = Math.max(...habitStats.map(h => h.completedDays), 1); const app = document.getElementById("app"); app.innerHTML = `
🌍
${escapeHtml(currentUser.username)}
${totalDays.size}
活跃打卡天数
${totalCheckins}
总打卡次数
📊 各事项打卡统计
`; const chartContainer = document.getElementById("barChartContainer"); if (habitStats.length === 0) { chartContainer.innerHTML = '
暂无打卡事项
'; } else { habitStats.forEach(habit => { const percent = maxCompleted > 0 ? (habit.completedDays / maxCompleted) * 100 : 0; chartContainer.innerHTML += `
${habit.icon || '📋'} ${escapeHtml(habit.name)}
${habit.completedDays > 0 ? habit.completedDays : ''}
${habit.completedDays} 天
`; }); } document.getElementById("backToHomeBtn").addEventListener("click", () => renderMainApp()); document.getElementById("changePasswordBtn").addEventListener("click", showChangePasswordModal); document.getElementById("exportDataBtn").addEventListener("click", () => { const exportObj = { username: currentUser.username, habits: customHabits, checkData: checkData }; const blob = new Blob([JSON.stringify(exportObj, null, 2)], { type: "application/json" }); const link = document.createElement("a"); link.href = URL.createObjectURL(blob); link.download = `survival_${currentUser.username}_backup.json`; link.click(); URL.revokeObjectURL(link.href); alert("数据已导出!"); }); document.getElementById("logoutConfirmBtn").addEventListener("click", () => { const confirmModal = document.createElement('div'); confirmModal.className = 'modal-overlay'; confirmModal.innerHTML = `
🚪
确认退出登录?
`; document.body.appendChild(confirmModal); confirmModal.querySelector("#cancelLogoutBtn").addEventListener("click", () => confirmModal.remove()); confirmModal.querySelector("#confirmLogoutBtn").addEventListener("click", () => { confirmModal.remove(); logout(); }); confirmModal.addEventListener("click", (e) => { if (e.target === confirmModal) confirmModal.remove(); }); }); } function showChangePasswordModal() { const modal = document.createElement('div'); modal.className = 'modal-overlay'; modal.innerHTML = `
🔐 修改密码
`; document.body.appendChild(modal); const oldPwd = modal.querySelector('#oldPwd'); const newPwd = modal.querySelector('#newPwd'); const confirmPwd = modal.querySelector('#confirmPwd'); const msgDiv = modal.querySelector('#pwdMsg'); modal.querySelector('#confirmPwdBtn').addEventListener('click', async () => { if (newPwd.value !== confirmPwd.value) { msgDiv.innerHTML = '
两次新密码不一致
'; return; } const result = await changePassword(currentUser.username, oldPwd.value, newPwd.value); if (result.success) { msgDiv.innerHTML = '
密码修改成功!请重新登录
'; setTimeout(() => { modal.remove(); logout(); }, 1500); } else { msgDiv.innerHTML = `
${result.message}
`; } }); modal.querySelector('#cancelPwdBtn').addEventListener('click', () => modal.remove()); modal.addEventListener('click', (e) => { if (e.target === modal) modal.remove(); }); } function renderMainApp() { const app = document.getElementById("app"); app.innerHTML = `

Online生存日记

📅 加载中
0%
`; initHDREarth("earthHDRContainer"); const today = new Date(); selectedDate = new Date(today.getFullYear(), today.getMonth(), today.getDate()); currentDisplayYear = today.getFullYear(); currentDisplayMonth = today.getMonth(); renderCalendar(); renderHabitPanel(selectedDate); document.getElementById("prevMonthBtn").addEventListener("click", () => { let m = currentDisplayMonth - 1, y = currentDisplayYear; if (m < 0) { m = 11; y--; } currentDisplayYear = y; currentDisplayMonth = m; renderCalendar(); }); document.getElementById("nextMonthBtn").addEventListener("click", () => { let m = currentDisplayMonth + 1, y = currentDisplayYear; if (m > 11) { m = 0; y++; } currentDisplayYear = y; currentDisplayMonth = m; renderCalendar(); }); document.getElementById("addHabitBtn").addEventListener("click", showAddHabitModal); document.getElementById("resetDayBtn").addEventListener("click", async () => { if (selectedDate) { const key = formatYMD(selectedDate); if (checkData[key]) customHabits.forEach(habit => { checkData[key][habit.id] = false; }); await saveUserData(); renderCalendar(); renderHabitPanel(selectedDate); } }); document.getElementById("profileBtn").addEventListener("click", () => renderProfilePage()); document.getElementById("syncTodayBtn").addEventListener("click", syncSelectedDateToCalendar); document.getElementById("syncAllBtn").addEventListener("click", syncAllToCalendar); } function renderAuthPage() { const app = document.getElementById("app"); app.innerHTML = `
Online生存日记
记录每一天,遇见更好的自己
`; document.getElementById("loginBtn").addEventListener("click", async () => { const username = document.getElementById("loginUsername").value.trim(); const password = document.getElementById("loginPassword").value; const result = await login(username, password); const msgDiv = document.getElementById("authMessage"); if (result.success) { renderMainApp(); } else { msgDiv.innerHTML = `
${result.message}
`; } }); document.getElementById("switchToRegister").addEventListener("click", (e) => { e.preventDefault(); const authForm = document.getElementById("authForm"); authForm.innerHTML = `
返回登录
`; document.getElementById("registerBtn").addEventListener("click", async () => { const username = document.getElementById("regUsername").value.trim(); const password = document.getElementById("regPassword").value; const confirm = document.getElementById("regConfirm").value; const securityQuestion = document.getElementById("securityQuestion").value.trim(); const securityAnswer = document.getElementById("securityAnswer").value.trim(); const msgDiv = document.getElementById("authMessage"); if (password !== confirm) { msgDiv.innerHTML = '
两次密码不一致
'; return; } const result = await register(username, password, securityQuestion, securityAnswer); if (result.success) { msgDiv.innerHTML = '
注册成功!请登录
'; setTimeout(() => renderAuthPage(), 1500); } else { msgDiv.innerHTML = `
${result.message}
`; } }); document.getElementById("switchToLogin").addEventListener("click", (e) => { e.preventDefault(); renderAuthPage(); }); }); document.getElementById("forgotPasswordLink").addEventListener("click", (e) => { e.preventDefault(); const authForm = document.getElementById("authForm"); authForm.innerHTML = `
返回登录
`; document.getElementById("verifySecurityBtn").addEventListener("click", async () => { const username = document.getElementById("forgotUsername").value.trim(); const answer = document.getElementById("securityAnswerInput").value; const msgDiv = document.getElementById("authMessage"); const result = await verifySecurity(username, answer); if (result.success) { msgDiv.innerHTML = `
验证成功!请设置新密码
`; document.getElementById("resetPwdBtn").addEventListener("click", async () => { const newPwd = document.getElementById("newPassword").value; const confirmNew = document.getElementById("confirmNewPassword").value; if (newPwd !== confirmNew) { msgDiv.innerHTML = '
两次密码不一致
'; return; } const resetResult = await resetPassword(username, newPwd); if (resetResult.success) { msgDiv.innerHTML = '
密码重置成功!请登录
'; setTimeout(() => renderAuthPage(), 1500); } else { msgDiv.innerHTML = `
${resetResult.message}
`; } }); } else { msgDiv.innerHTML = `
${result.message}
`; } }); document.getElementById("backToLogin").addEventListener("click", (e) => { e.preventDefault(); renderAuthPage(); }); }); } function showSplashAndAuth() { const splash = document.createElement('div'); splash.className = 'splash-screen'; splash.innerHTML = `
🌍
Online生存日记
记录每一天,遇见更好的自己
`; document.body.appendChild(splash); setTimeout(() => { splash.classList.add('splash-hidden'); setTimeout(() => { splash.remove(); renderAuthPage(); }, 800); }, 1800); } function escapeHtml(str) { return str.replace(/[&<>]/g, m => ({'&':'&','<':'<','>':'>'}[m])); } // 启动应用 const lastUser = localStorage.getItem("cloud_last_user"); if (lastUser) { showSplashAndAuth(); } else { showSplashAndAuth(); }