fix: phần code build android
This commit is contained in:
Vendored
+28
-28
@@ -1,27 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||
<script src="https://accounts.google.com/gsi/client" async defer></script>
|
||||
<title>Travel Planner</title>
|
||||
|
||||
<!-- Open Graph Meta Tags for Social Media Sharing -->
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="https://yotrip.labz.io.vn" />
|
||||
<meta property="og:title" content="Travel Planner - Lên kế hoạch chuyến đi của bạn" />
|
||||
<meta property="og:description" content="Khám phá những hành trình tuyệt vời và chia sẻ khoảnh khắc đẹp với cộng đồng du lịch." />
|
||||
<meta property="og:image" content="https://yotrip.labz.io.vn/background.avif" />
|
||||
<meta property="og:image:width" content="1200" />
|
||||
<meta property="og:image:height" content="630" />
|
||||
|
||||
<!-- Twitter Card Meta Tags -->
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content="Travel Planner - Lên kế hoạch chuyến đi của bạn" />
|
||||
<meta name="twitter:description" content="Khám phá những hành trình tuyệt vời và chia sẻ khoảnh khắc đẹp với cộng đồng du lịch." />
|
||||
<meta name="twitter:image" content="https://yotrip.labz.io.vn/background.avif" />
|
||||
<script type="module" crossorigin src="/assets/index-CRdl2V_E.js"></script>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||
<script src="https://accounts.google.com/gsi/client" async defer></script>
|
||||
<title>Travel Planner</title>
|
||||
|
||||
<!-- Open Graph Meta Tags for Social Media Sharing -->
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="https://yotrip.labz.io.vn" />
|
||||
<meta property="og:title" content="Travel Planner - Lên kế hoạch chuyến đi của bạn" />
|
||||
<meta property="og:description" content="Khám phá những hành trình tuyệt vời và chia sẻ khoảnh khắc đẹp với cộng đồng du lịch." />
|
||||
<meta property="og:image" content="https://yotrip.labz.io.vn/background.avif" />
|
||||
<meta property="og:image:width" content="1200" />
|
||||
<meta property="og:image:height" content="630" />
|
||||
|
||||
<!-- Twitter Card Meta Tags -->
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content="Travel Planner - Lên kế hoạch chuyến đi của bạn" />
|
||||
<meta name="twitter:description" content="Khám phá những hành trình tuyệt vời và chia sẻ khoảnh khắc đẹp với cộng đồng du lịch." />
|
||||
<meta name="twitter:image" content="https://yotrip.labz.io.vn/background.avif" />
|
||||
<script type="module" crossorigin src="/assets/index--uaaEHqB.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-Cyuzqnbw.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/vendor-others-VIU5qAPG.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/vendor-editor-DOXkNaRS.js">
|
||||
@@ -31,8 +31,8 @@
|
||||
<link rel="stylesheet" crossorigin href="/assets/vendor-maps-CcXJxNtP.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/vendor-react-CuSj0z1j.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-BsXBn1-b.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
</body>
|
||||
@@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
|
||||
import { X, Send, MessageSquare, User, Loader2, Trash2 } from 'lucide-react';
|
||||
import { io } from 'socket.io-client';
|
||||
import { Capacitor } from '@capacitor/core';
|
||||
import { BACKEND_URL } from '@/utils/backendEndpoint';
|
||||
import { useTourStore } from '@/store/useTourStore';
|
||||
import { ConfirmModal } from './ConfirmModal';
|
||||
|
||||
@@ -71,7 +72,7 @@ export const CommentModal: React.FC<CommentModalProps> = ({ isOpen, onClose, loc
|
||||
|
||||
// Lắng nghe bình luận mới qua Proxy (không cần hardcode URL)
|
||||
const socket = Capacitor.isNativePlatform()
|
||||
? io(import.meta.env.VITE_BACKEND_URL || 'https://yotrip.labz.io.vn')
|
||||
? io(BACKEND_URL)
|
||||
: io();
|
||||
socket.emit('joinTour', 'global'); // Hoặc logic join cụ thể
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, { useState, useEffect, useRef } from 'react';
|
||||
import { X, Send, MessageSquare, User, Loader2, Calendar, MapPin, Download, Edit, Heart, Trash2 } from 'lucide-react';
|
||||
import { io } from 'socket.io-client';
|
||||
import { Capacitor } from '@capacitor/core';
|
||||
import { BACKEND_URL } from '@/utils/backendEndpoint';
|
||||
import { CoordinateSelectModal } from './CoordinateSelectModal';
|
||||
import { useTranslation } from '../hooks/useTranslation';
|
||||
import { useConfirm } from '../hooks/useConfirm';
|
||||
@@ -248,7 +249,7 @@ export const PublicPhotoModal: React.FC<PublicPhotoModalProps> = ({
|
||||
fetchComments();
|
||||
|
||||
const socket = Capacitor.isNativePlatform()
|
||||
? io(import.meta.env.VITE_BACKEND_URL || 'https://yotrip.labz.io.vn')
|
||||
? io(BACKEND_URL)
|
||||
: io();
|
||||
socket.emit('joinPhoto', photo.id);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, { useState, useEffect, useRef } from 'react';
|
||||
import { io, Socket } from 'socket.io-client';
|
||||
import { Capacitor } from '@capacitor/core';
|
||||
import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';
|
||||
import { BACKEND_URL } from '@/utils/backendEndpoint';
|
||||
import { Send, MessageSquare, Loader2, Image as ImageIcon, MapPin, Download, X } from 'lucide-react';
|
||||
import { useNotification } from '@/hooks/useNotification';
|
||||
|
||||
@@ -182,7 +183,7 @@ export const TourChat: React.FC<TourChatProps> = ({ tourId, embedded = false })
|
||||
// Connect to socket and listen for tour messages
|
||||
useEffect(() => {
|
||||
const socket = Capacitor.isNativePlatform()
|
||||
? io(import.meta.env.VITE_BACKEND_URL || 'https://yotrip.labz.io.vn')
|
||||
? io(BACKEND_URL)
|
||||
: io();
|
||||
socketRef.current = socket;
|
||||
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
<<<<<<< Updated upstream
|
||||
=======
|
||||
import { io, Socket } from 'socket.io-client';
|
||||
import { Capacitor } from '@capacitor/core';
|
||||
import { BACKEND_URL } from '@/utils/backendEndpoint';
|
||||
>>>>>>> Stashed changes
|
||||
import {
|
||||
Compass,
|
||||
Users,
|
||||
@@ -97,6 +103,7 @@ export const MemberDashboard: React.FC<MemberDashboardProps> = ({
|
||||
const [chatMessages, setChatMessages] = useState<any[]>([]);
|
||||
const [newMessage, setNewMessage] = useState('');
|
||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
||||
const socketRef = useRef<Socket | null>(null);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
@@ -530,14 +537,32 @@ export const MemberDashboard: React.FC<MemberDashboardProps> = ({
|
||||
muteNotificationsRef.current = muteNotifications;
|
||||
});
|
||||
|
||||
// Socket connection for realtime messaging - changed to listen to global socket events
|
||||
// Socket connection for realtime messaging
|
||||
useEffect(() => {
|
||||
if (!user?.id) return;
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
const handleMessageReceived = (e: Event) => {
|
||||
const message = (e as CustomEvent).detail;
|
||||
// If we are actively chatting with the sender of this message
|
||||
if (activeChatUser && (message.senderId === activeChatUser.id || message.receiverId === activeChatUser.id)) {
|
||||
=======
|
||||
// Connect to WebSocket: absolute URL on native, relative (Vite proxy) on web
|
||||
const socket = Capacitor.isNativePlatform()
|
||||
? io(BACKEND_URL)
|
||||
: io();
|
||||
socketRef.current = socket;
|
||||
|
||||
socket.on('connect', () => {
|
||||
console.log('[WS] MemberDashboard connected:', socket.id);
|
||||
socket.emit('joinUser', user.id);
|
||||
});
|
||||
|
||||
const handleMessageReceived = (message: any) => {
|
||||
// Check against window-global activeChatUserId so stale closure doesn't block updates
|
||||
const activeChatUserId = (window as any).activeChatUserId;
|
||||
if (activeChatUserId && (message.senderId === activeChatUserId || message.receiverId === activeChatUserId)) {
|
||||
>>>>>>> Stashed changes
|
||||
setChatMessages(prev => [...prev, message]);
|
||||
} else {
|
||||
// Add to unread states
|
||||
@@ -548,31 +573,24 @@ export const MemberDashboard: React.FC<MemberDashboardProps> = ({
|
||||
}
|
||||
};
|
||||
|
||||
const handleConnectionAccepted = () => {
|
||||
socket.on('messageReceived', handleMessageReceived);
|
||||
|
||||
socket.on('connectionAccepted', () => {
|
||||
fetchConnectionsRef.current();
|
||||
};
|
||||
});
|
||||
|
||||
const handleTourMessageNotification = (e: Event) => {
|
||||
const data = (e as CustomEvent).detail;
|
||||
socket.on('tourMessageNotification', (data: any) => {
|
||||
setUnreadTourChats(prev => prev.includes(data.tourId) ? prev : [...prev, data.tourId]);
|
||||
};
|
||||
});
|
||||
|
||||
const handleJoinRequestAccepted = () => {
|
||||
socket.on('joinRequestAccepted', () => {
|
||||
fetchPublicToursRef.current();
|
||||
};
|
||||
|
||||
window.addEventListener('app:messageReceived', handleMessageReceived);
|
||||
window.addEventListener('app:connectionAccepted', handleConnectionAccepted);
|
||||
window.addEventListener('app:tourMessageNotification', handleTourMessageNotification);
|
||||
window.addEventListener('app:joinRequestAccepted', handleJoinRequestAccepted);
|
||||
});
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('app:messageReceived', handleMessageReceived);
|
||||
window.removeEventListener('app:connectionAccepted', handleConnectionAccepted);
|
||||
window.removeEventListener('app:tourMessageNotification', handleTourMessageNotification);
|
||||
window.removeEventListener('app:joinRequestAccepted', handleJoinRequestAccepted);
|
||||
socket.disconnect();
|
||||
};
|
||||
}, [user?.id, activeChatUser]);
|
||||
}, [user?.id]);
|
||||
|
||||
// Autoscroll chat to bottom
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useState, useEffect, useMemo, useRef } from 'react';
|
||||
import { io } from 'socket.io-client';
|
||||
import { Capacitor } from '@capacitor/core';
|
||||
import { BACKEND_URL } from '@/utils/backendEndpoint';
|
||||
import { jsPDF } from 'jspdf';
|
||||
import autoTable from 'jspdf-autotable';
|
||||
import { robotoBase64, robotoBoldBase64 } from '../utils/pdfFont';
|
||||
@@ -1573,7 +1574,7 @@ export const TourDetailPage = ({
|
||||
if (!currentTour) return;
|
||||
|
||||
const socket = Capacitor.isNativePlatform()
|
||||
? io(import.meta.env.VITE_BACKEND_URL || 'https://yotrip.labz.io.vn')
|
||||
? io(BACKEND_URL)
|
||||
: io(); // Kết nối qua Proxy của Vite (cùng origin)
|
||||
|
||||
socket.on('connect', () => {
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Smart runtime backend URL resolver.
|
||||
*
|
||||
* Eliminates the need to manually update `.env` files when switching between:
|
||||
* - Docker/Linux Production Web Server → uses window.location.origin
|
||||
* - Android APK (Capacitor WebView) → forces absolute production domain
|
||||
*
|
||||
* Priority order:
|
||||
* 1. Explicit VITE_BACKEND_URL env variable (if set at build time)
|
||||
* 2. Android/Capacitor app detection → https://yotrip.labz.io.vn
|
||||
* 3. Production web server → window.location.origin
|
||||
*/
|
||||
|
||||
const PRODUCTION_DOMAIN = 'https://yotrip.labz.io.vn';
|
||||
|
||||
const resolveBackendEndpoint = (): string => {
|
||||
// 1. Honour explicit build-time env override first
|
||||
const envUrl = import.meta.env.VITE_BACKEND_URL as string | undefined;
|
||||
if (envUrl) {
|
||||
return envUrl;
|
||||
}
|
||||
|
||||
const origin = window.location.origin;
|
||||
const userAgent = navigator.userAgent.toLowerCase();
|
||||
|
||||
// 2. Detect Android APK / Capacitor WebView environment
|
||||
// These shells run on local/file:// origins, not the production domain.
|
||||
const isAndroidApp =
|
||||
origin.startsWith('http://localhost') ||
|
||||
origin.startsWith('capacitor://') ||
|
||||
origin.startsWith('file://') ||
|
||||
(userAgent.includes('android') && !origin.includes('yotrip.labz.io.vn'));
|
||||
|
||||
if (isAndroidApp) {
|
||||
console.log('[Backend] 📱 Android/Capacitor environment detected — using production domain.');
|
||||
return PRODUCTION_DOMAIN;
|
||||
}
|
||||
|
||||
// 3. Web production server: the origin IS the backend (same Docker host)
|
||||
return origin;
|
||||
};
|
||||
|
||||
/** Resolved backend base URL for the current runtime environment. */
|
||||
export const BACKEND_URL: string = resolveBackendEndpoint();
|
||||
|
||||
console.log(`[Backend] 🌐 Active endpoint: ${BACKEND_URL}`);
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Capacitor } from '@capacitor/core';
|
||||
import { GoogleAuth } from '@codetrix-studio/capacitor-google-auth';
|
||||
import { LocalNotifications } from '@capacitor/local-notifications';
|
||||
import { BACKEND_URL } from './backendEndpoint';
|
||||
|
||||
function rewriteUrls(obj: any, backendUrl: string): any {
|
||||
if (obj === null || obj === undefined) return obj;
|
||||
@@ -47,7 +48,7 @@ if (Capacitor.isNativePlatform()) {
|
||||
console.error('[LocalNotifications] Failed to request permissions:', e);
|
||||
}
|
||||
|
||||
const backendUrl = import.meta.env.VITE_BACKEND_URL || 'https://yotrip.labz.io.vn';
|
||||
const backendUrl = BACKEND_URL;
|
||||
|
||||
const originalFetch = window.fetch;
|
||||
window.fetch = async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {
|
||||
|
||||
Reference in New Issue
Block a user