Interiors with TG (updated) Fix MID
This commit is contained in:
198
src/Game.js
198
src/Game.js
@@ -106,6 +106,10 @@ function Game({ avatarUrl, gender }) {
|
|||||||
const [activeChat, setActiveChat] = useState(null);
|
const [activeChat, setActiveChat] = useState(null);
|
||||||
// Добавьте этот код в начало компонента Game, рядом с другими состояниями
|
// Добавьте этот код в начало компонента Game, рядом с другими состояниями
|
||||||
const [telegramContacts, setTelegramContacts] = useState([]);
|
const [telegramContacts, setTelegramContacts] = useState([]);
|
||||||
|
const [tgLoading, setTgLoading] = useState(false);
|
||||||
|
const [tgError, setTgError] = useState(null);
|
||||||
|
const [sysTime, setSysTime] = useState(new Date());
|
||||||
|
const isPhoneNarrow = true; // экран виртуального телефона — всегда узкий
|
||||||
|
|
||||||
const [isIframeOpen, setIsIframeOpen] = useState(false);
|
const [isIframeOpen, setIsIframeOpen] = useState(false);
|
||||||
const [iframeUrl, setIframeUrl] = useState('');
|
const [iframeUrl, setIframeUrl] = useState('');
|
||||||
@@ -188,7 +192,9 @@ function Game({ avatarUrl, gender }) {
|
|||||||
setAppsHidden(true);
|
setAppsHidden(true);
|
||||||
setActiveApp(appName);
|
setActiveApp(appName);
|
||||||
if (appName === "Telegram") {
|
if (appName === "Telegram") {
|
||||||
loadTelegramContacts(); // Загрузка контактов при открытии
|
setTgError(null);
|
||||||
|
setTgLoading(true);
|
||||||
|
loadTelegramContacts().finally(() => setTgLoading(false));
|
||||||
}
|
}
|
||||||
if (appName === "Chrome") {
|
if (appName === "Chrome") {
|
||||||
loadQuestsProgress();
|
loadQuestsProgress();
|
||||||
@@ -1322,17 +1328,23 @@ function Game({ avatarUrl, gender }) {
|
|||||||
async function loadTelegramContacts() {
|
async function loadTelegramContacts() {
|
||||||
const token = localStorage.getItem('token');
|
const token = localStorage.getItem('token');
|
||||||
try {
|
try {
|
||||||
|
setTgError(null);
|
||||||
const res = await fetch('/api/users', {
|
const res = await fetch('/api/users', {
|
||||||
headers: { Authorization: `Bearer ${token}` }
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
|
credentials: 'include',
|
||||||
|
cache: 'no-cache'
|
||||||
});
|
});
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
setTelegramContacts(data);
|
setTelegramContacts(data);
|
||||||
} else {
|
} else {
|
||||||
console.error('Ошибка загрузки контактов Telegram');
|
const txt = await res.text().catch(()=> '');
|
||||||
|
console.error('Ошибка загрузки контактов Telegram', res.status, txt);
|
||||||
|
setTgError('Не удалось загрузить контакты');
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Ошибка сети:', err);
|
console.error('Ошибка сети:', err);
|
||||||
|
setTgError('Проблема сети');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5519,127 +5531,69 @@ useEffect(() => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{activeApp === "Telegram" && (
|
{activeApp === "Telegram" && (
|
||||||
<div style={{ width: "100%", height: "100%", display: "flex", flexDirection: "column" }}>
|
<div style={{ width: '100%', height: '100%', display: 'flex', flexDirection: 'column', background: '#fff' }}>
|
||||||
<div style={{ width: "100%", height: "10%", backgroundColor: "#0088cc", display: "flex", alignItems: "center", justifyContent: "center" }}>
|
{/* Заголовок приложения */}
|
||||||
<div style={{ fontSize: "150%", color: "white" }}>Shipgram Messenger</div>
|
<div style={{ padding: '8px 12px', background: '#0088cc', color: '#fff', fontWeight: 700, textAlign: 'center' }}>Shipgram</div>
|
||||||
|
{/* Контент */}
|
||||||
|
<div style={{ flex: 1, display: 'flex', minHeight: 0 }}>
|
||||||
|
{/* Список контактов */}
|
||||||
|
<div style={{ width: isPhoneNarrow ? (activeChat ? '0%' : '100%') : '30%', display: isPhoneNarrow && activeChat ? 'none' : 'block', borderRight: '1px solid #ddd', overflowY: 'auto', background: '#fff' }}>
|
||||||
|
<div style={{ padding: 10, fontWeight: 600, borderBottom: '1px solid #eee' }}>Контакты</div>
|
||||||
|
{tgLoading && (
|
||||||
|
<div style={{ padding: 12, color: '#666' }}>Загрузка…</div>
|
||||||
|
)}
|
||||||
|
{tgError && (
|
||||||
|
<div style={{ padding: 12, color: '#b91c1c' }}>{tgError}</div>
|
||||||
|
)}
|
||||||
|
{!tgLoading && !tgError && telegramContacts.length === 0 && (
|
||||||
|
<div style={{ padding: 12, color: '#666' }}>Контакты не найдены</div>
|
||||||
|
)}
|
||||||
|
{telegramContacts.map((user) => (
|
||||||
|
<div key={user.id} onClick={() => setActiveChat(user)} style={{ padding: '10px 12px', display: 'flex', alignItems: 'center', gap: 8, cursor: 'pointer', color: '#111' }}>
|
||||||
|
<div style={{ width: 28, height: 28, borderRadius: 14, background: '#e5e7eb', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 12 }}>
|
||||||
|
{user.firstName?.[0]}{user.lastName?.[0]}
|
||||||
</div>
|
</div>
|
||||||
|
<div style={{ overflow: 'hidden' }}>
|
||||||
<div style={{ width: "100%", height: "90%", display: "flex" }}>
|
<div style={{ whiteSpace: 'nowrap', textOverflow: 'ellipsis', overflow: 'hidden' }}>{user.firstName} {user.lastName}</div>
|
||||||
<div style={{ width: "30%", height: "100%", borderRight: "1px solid #ddd", overflowY: "auto" }}>
|
<div style={{ fontSize: 12, color: '#6b7280' }}>Онлайн</div>
|
||||||
<div style={{ padding: "10px", fontWeight: "bold", borderBottom: "1px solid #ddd" }}>Contacts</div>
|
|
||||||
<div id="user-list" style={{ overflowY: "auto" }}>
|
|
||||||
{telegramContacts.length === 0 && (
|
|
||||||
<div style={{ padding: 10, textAlign: "center" }}>
|
|
||||||
{telegramContacts.length === 0
|
|
||||||
? "Загрузка контактов..."
|
|
||||||
: "Контакты не найдены"}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{telegramContacts.map((user, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
style={{
|
|
||||||
padding: "10px",
|
|
||||||
borderBottom: "1px solid #eee",
|
|
||||||
cursor: "pointer",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center"
|
|
||||||
}}
|
|
||||||
onClick={() => setActiveChat(user)}
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
{user.firstName} {user.lastName}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style={{ width: "70%", height: "100%" }}>
|
|
||||||
{activeChat && (
|
|
||||||
<div style={{ padding: "10px" }}>
|
|
||||||
<h3>Чат с {activeChat.firstName} {activeChat.lastName}</h3>
|
|
||||||
{/* Контейнер сообщений с прокруткой */}
|
|
||||||
<div
|
|
||||||
id="chatContainer"
|
|
||||||
style={{
|
|
||||||
flex: 1,
|
|
||||||
border: "1px solid #ddd",
|
|
||||||
padding: "10px",
|
|
||||||
overflowY: "auto",
|
|
||||||
marginBottom: "10px"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{messages.length === 0 ? (
|
|
||||||
<p style={{ textAlign: 'center', color: '#888' }}>Нет сообщений</p>
|
|
||||||
) : (
|
|
||||||
messages.map((msg) => (
|
|
||||||
<div
|
|
||||||
key={msg.id}
|
|
||||||
style={{
|
|
||||||
textAlign: msg.sender_id === userProfile?.id ? 'right' : 'left',
|
|
||||||
margin: '10px 0'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{
|
|
||||||
display: 'inline-block',
|
|
||||||
padding: '8px 12px',
|
|
||||||
borderRadius: '12px',
|
|
||||||
background: msg.sender_id === userProfile?.id ? '#0084ff' : '#e5e5ea',
|
|
||||||
color: msg.sender_id === userProfile?.id ? '#fff' : '#000',
|
|
||||||
maxWidth: '80%'
|
|
||||||
}}>
|
|
||||||
{msg.message}
|
|
||||||
</div>
|
|
||||||
<div style={{
|
|
||||||
fontSize: '0.8em',
|
|
||||||
color: '#666',
|
|
||||||
marginTop: '4px'
|
|
||||||
}}>
|
|
||||||
{new Date(msg.created_at).toLocaleTimeString()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Поле ввода и кнопка отправки */}
|
|
||||||
<div style={{ display: 'flex' }}>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value={newMessage}
|
|
||||||
onChange={(e) => setNewMessage(e.target.value)}
|
|
||||||
placeholder="Введите сообщение..."
|
|
||||||
style={{
|
|
||||||
flex: 1,
|
|
||||||
padding: '8px',
|
|
||||||
borderRadius: '20px',
|
|
||||||
border: '1px solid #ddd'
|
|
||||||
}}
|
|
||||||
onKeyDown={(e) => {
|
|
||||||
if (e.key === 'Enter') sendMessage();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
onClick={sendMessage}
|
|
||||||
style={{
|
|
||||||
marginLeft: '8px',
|
|
||||||
padding: '8px 16px',
|
|
||||||
background: '#0084ff',
|
|
||||||
color: 'white',
|
|
||||||
border: 'none',
|
|
||||||
borderRadius: '20px',
|
|
||||||
cursor: 'pointer'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Отправить
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
))}
|
||||||
|
</div>
|
||||||
|
{/* Область чата */}
|
||||||
|
<div style={{ flex: 1, display: isPhoneNarrow && !activeChat ? 'none' : 'flex', flexDirection: 'column', background: '#fff' }}>
|
||||||
|
{activeChat && (
|
||||||
|
<>
|
||||||
|
<div style={{ padding: '8px 12px', borderBottom: '1px solid #eee', display: 'flex', alignItems: 'center', gap: 8 }}>
|
||||||
|
{isPhoneNarrow && (
|
||||||
|
<button onClick={() => setActiveChat(null)} style={{ border: 'none', background: 'transparent', fontSize: 16, cursor: 'pointer' }}>←</button>
|
||||||
|
)}
|
||||||
|
<span style={{ fontWeight: 600 }}>{activeChat.firstName} {activeChat.lastName}</span>
|
||||||
|
</div>
|
||||||
|
<div id="chatContainer" style={{ flex: 1, overflowY: 'auto', padding: 10, background: '#fafafa' }}>
|
||||||
|
{messages.length === 0 ? (
|
||||||
|
<p style={{ textAlign: 'center', color: '#666' }}>Нет сообщений</p>
|
||||||
|
) : (
|
||||||
|
messages.map(msg => (
|
||||||
|
<div key={msg.id} style={{ display: 'flex', justifyContent: (msg.sender_id === userProfile?.id) ? 'flex-end' : 'flex-start', margin: '8px 0' }}>
|
||||||
|
<div style={{ maxWidth: '75%', background: (msg.sender_id === userProfile?.id) ? '#0084ff' : '#e5e5ea', color: (msg.sender_id === userProfile?.id) ? '#fff' : '#000', padding: '8px 12px', borderRadius: 12 }}>{msg.message}</div>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div style={{ padding: 8, display: 'flex', gap: 8, borderTop: '1px solid #eee', background: '#fff' }}>
|
||||||
|
<input type="text" value={newMessage} onChange={(e) => setNewMessage(e.target.value)} placeholder="Сообщение" onKeyDown={(e) => { if (e.key === 'Enter') sendMessage(); }} style={{ flex: 1, padding: '10px 12px', borderRadius: 12, border: '1px solid #ddd' }} />
|
||||||
|
<button onClick={sendMessage} style={{ padding: '10px 14px', background: '#0084ff', color: '#fff', border: 'none', borderRadius: 12, cursor: 'pointer' }}>Отправить</button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{!activeChat && (
|
||||||
|
<div style={{ margin: 'auto', color: '#666' }}>Выберите контакт</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user