fix: phần code build android
This commit is contained in:
@@ -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