View file zip0.ru/messages.php

File size: 11.44Kb
<?php
require_once 'db.php';

if (empty($_SESSION['user_id'])) {
    header('Location: login.php');
    exit;
}

$current_user_id = (int)$_SESSION['user_id'];

if (function_exists('is_banned') && is_banned($current_user_id)) {
    include 'header.php';
    echo '<p>Ваш аккаунт заблокирован. Обратитесь в поддержку.</p>';
    include 'footer.php';
    exit;
}

$companion_id = isset($_GET['user_id']) ? (int)$_GET['user_id'] : 0;
if ($companion_id <= 0 || $companion_id === $current_user_id) {
    header('Location: dialogs.php');
    exit;
}

// загружаем собеседника
$stmt = $mysqli->prepare("
    SELECT id, name, city, photo, is_banned
    FROM users
    WHERE id = ?
");
$stmt->bind_param('i', $companion_id);
$stmt->execute();
$companion = $stmt->get_result()->fetch_assoc();
$stmt->close();

if (!$companion || !empty($companion['is_banned'])) {
    include 'header.php';
    echo '<p>Профиль недоступен для общения.</p>';
    include 'footer.php';
    exit;
}

/* ========== обработка отправки сообщения (текст + голос) ========== */

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $text = trim($_POST['message'] ?? '');

    $type       = 'text';
    $voice_file = null;

    // если есть загруженный аудиофайл
    if (!empty($_FILES['voice']['name']) && $_FILES['voice']['error'] === UPLOAD_ERR_OK) {
        $tmp  = $_FILES['voice']['tmp_name'];
        $orig = $_FILES['voice']['name'];

        // расширение файла
        $ext = strtolower(pathinfo($orig, PATHINFO_EXTENSION));
        if ($ext === '') {
            $ext = 'webm';
        }

        // имя файла
        $voice_file = 'voice_' . $current_user_id . '_' . time() . '_' . mt_rand(1000,9999) . '.' . $ext;
        $target_dir  = __DIR__ . '/assets/voice';
        if (!is_dir($target_dir)) {
            @mkdir($target_dir, 0755, true);
        }
        $target_path = $target_dir . '/' . $voice_file;

        if (move_uploaded_file($tmp, $target_path)) {
            $type = 'voice'; // помечаем как голосовое
        } else {
            // не получилось сохранить файл — не используем голос
            $voice_file = null;
        }
    }

    // если нет ни текста, ни голосового — ничего не отправляем
    if (!($text === '' && $voice_file === null)) {
        $stmt = $mysqli->prepare("
            INSERT INTO messages (from_user_id, to_user_id, body, type, voice_file, created_at, is_read)
            VALUES (?, ?, ?, ?, ?, NOW(), 0)
        ");
        $stmt->bind_param('iisss', $current_user_id, $companion_id, $text, $type, $voice_file);
        $stmt->execute();
        $stmt->close();
    }

    header('Location: messages.php?user_id=' . $companion_id);
    exit;
}

/* ========== помечаем входящие как прочитанные ========== */
$stmt = $mysqli->prepare("
    UPDATE messages
    SET is_read = 1
    WHERE from_user_id = ? AND to_user_id = ? AND is_read = 0
");
$stmt->bind_param('ii', $companion_id, $current_user_id);
$stmt->execute();
$stmt->close();

/* ========== загружаем историю сообщений ========== */

$stmt = $mysqli->prepare("
    SELECT id, from_user_id, to_user_id, body, type, voice_file, created_at
    FROM messages
    WHERE (from_user_id = ? AND to_user_id = ?)
       OR (from_user_id = ? AND to_user_id = ?)
    ORDER BY created_at ASC, id ASC
");
$stmt->bind_param('iiii', $current_user_id, $companion_id, $companion_id, $current_user_id);
$stmt->execute();
$messages = $stmt->get_result();
$stmt->close();

include 'header.php';
?>

<style>
#record-btn {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    border: none;
    background: #ff4f8b;
    color: white;
    font-size: 22px;
    display:flex;
    align-items:center;
    justify-content:center;
    cursor:pointer;
    transition:0.2s;
}
#record-btn.recording {
    background: #d92020;
    box-shadow: 0 0 10px rgba(255,0,0,0.7);
}

.chat-page { margin-top: 18px; }

.chat-layout {
    display: grid;
    grid-template-columns: minmax(0,1.3fr);
    gap: 16px;
}

.chat-card {
    background:#ffffff;
    border-radius:22px;
    padding:16px 16px 12px;
    box-shadow:0 10px 30px rgba(0,0,0,0.06);
    display:flex;
    flex-direction:column;
    height:70vh;
    max-height:560px;
}

.chat-header{
    display:flex;
    align-items:center;
    gap:10px;
    padding-bottom:8px;
    border-bottom:1px solid rgba(0,0,0,0.04);
    margin-bottom:8px;
}
.chat-companion-avatar{
    width:42px;height:42px;border-radius:999px;object-fit:cover;
}
.chat-companion-avatar-placeholder{
    width:42px;height:42px;border-radius:999px;
    background:linear-gradient(135deg,#ffe5f0,#f5ebff);
    display:flex;align-items:center;justify-content:center;font-size:20px;
}
.chat-companion-name{font-size:15px;font-weight:600;}
.chat-companion-city{font-size:12px;color:#7b7287;}

.chat-messages{
    flex:1;
    overflow-y:auto;
    padding:8px 2px;
    display:flex;
    flex-direction:column;
    gap:6px;
}

.chat-message{
    max-width:75%;
    padding:8px 10px;
    border-radius:16px;
    font-size:13px;
}
.chat-message-in{
    align-self:flex-start;
    background:#fff1f6;
}
.chat-message-out{
    align-self:flex-end;
    background:#f3f0ff;
}
.chat-text{
    white-space:pre-wrap;
    word-wrap:break-word;
}
.chat-meta{
    font-size:10px;
    color:#a29ab4;
    margin-top:3px;
    text-align:right;
}

.chat-form{
    border-top:1px solid rgba(0,0,0,0.04);
    padding-top:8px;
    margin-top:4px;
}
.chat-input{
    width:100%;
    box-sizing:border-box;
}
.chat-form-row{margin-bottom:6px;}

@media (max-width:768px){
    .chat-layout{grid-template-columns:1fr;}
    .chat-card{
        margin:0 -4px 60px;
        border-radius:18px;
        height:calc(100vh - 180px);
        max-height:none;
    }
}
</style>

<div class="chat-page">
    <h1>Диалог</h1>

    <div class="chat-layout">
        <section class="chat-card">
            <div class="chat-header">
                <?php if ($companion['photo']): ?>
                    <img src="/assets/img/<?= htmlspecialchars($companion['photo']) ?>" class="chat-companion-avatar" alt="">
                <?php else: ?>
                    <div class="chat-companion-avatar-placeholder">🙂</div>
                <?php endif; ?>
                <div>
                    <div class="chat-companion-name">
                        <?= htmlspecialchars($companion['name'] ?: 'Без имени') ?>
                    </div>
                    <?php if (!empty($companion['city'])): ?>
                        <div class="chat-companion-city"><?= htmlspecialchars($companion['city']) ?></div>
                    <?php endif; ?>
                </div>
            </div>

            <div class="chat-messages" id="chat-messages">
                <?php if ($messages->num_rows === 0): ?>
                    <div style="font-size:13px;color:#7b7287;margin-top:8px;">
                        Здесь пока пусто. Напишите первое сообщение 🙂
                    </div>
                <?php else: ?>
                    <?php while ($msg = $messages->fetch_assoc()): ?>
                        <?php
                        $outgoing = ($msg['from_user_id'] == $current_user_id);
                        $cls = $outgoing ? 'chat-message chat-message-out' : 'chat-message chat-message-in';
                        ?>
                        <div class="<?= $cls ?>">
                            <div class="chat-text">
                                <?php if ($msg['type'] === 'voice' && !empty($msg['voice_file'])): ?>
                                    <div style="margin-bottom:4px;">🎙 Голосовое сообщение</div>
                                    <audio controls preload="none" style="width:220px;max-width:100%;">
                                        <source src="/assets/voice/<?= htmlspecialchars($msg['voice_file']) ?>">
                                        Ваш браузер не поддерживает воспроизведение аудио.
                                    </audio>
                                    <?php if ($msg['body'] !== ''): ?>
                                        <div style="margin-top:4px;">
                                            <?= nl2br(htmlspecialchars($msg['body'])) ?>
                                        </div>
                                    <?php endif; ?>
                                <?php else: ?>
                                    <?= nl2br(htmlspecialchars($msg['body'])) ?>
                                <?php endif; ?>
                            </div>
                            <div class="chat-meta">
                                <?= htmlspecialchars(date('d.m H:i', strtotime($msg['created_at']))) ?>
                            </div>
                        </div>
                    <?php endwhile; ?>
                <?php endif; ?>
            </div>

            <form method="post" enctype="multipart/form-data" class="chat-form">
                <div class="chat-form-row">
                    <input type="text" name="message"
                           placeholder="Напишите сообщение..."
                           class="chat-input">
                </div>
                <div class="chat-form-row" style="display:flex;align-items:center;justify-content:space-between;gap:10px;">
                    <button type="button" id="record-btn">🎙</button>
                    <label style="font-size:12px;color:#7b7287;cursor:pointer;">
                        Прикрепить голосовое
                        <input type="file" name="voice" id="voice-file" accept="audio/*" style="display:none;">
                    </label>
                    <button type="submit" class="btn-primary">Отправить</button>
                </div>
            </form>
        </section>
    </div>
</div>

<script>
let recorder;
let chunks = [];
let stream;

const recBtn = document.getElementById("record-btn");
const voiceInput = document.getElementById("voice-file");

// нажали кнопку 🎙
recBtn.onclick = async () => {

    // если запись уже идёт → останавливаем
    if (recBtn.classList.contains("recording")) {
        recorder.stop();
        recBtn.classList.remove("recording");
        recBtn.innerHTML = "🎙";
        return;
    }

    // запускаем запись
    try {
        stream = await navigator.mediaDevices.getUserMedia({ audio: true });
        recorder = new MediaRecorder(stream);
        chunks = [];

        recorder.ondataavailable = e => chunks.push(e.data);

        recorder.onstop = async () => {
            // создаём файл webm
            const blob = new Blob(chunks, { type: "audio/webm" });
            const file = new File([blob], "record.webm", { type: "audio/webm" });

            // помещаем файл в input[type=file]
            const dataTransfer = new DataTransfer();
            dataTransfer.items.add(file);
            voiceInput.files = dataTransfer.files;

            stream.getTracks().forEach(t => t.stop());
        };

        recorder.start();
        recBtn.classList.add("recording");
        recBtn.innerHTML = "⏺";

    } catch (err) {
        alert("Ошибка доступа к микрофону");
        console.log(err);
    }
};
</script>

<?php include 'footer.php'; ?>