Veu3 / index.html
Hamed744's picture
Update index.html
2acdf6b verified
raw
history blame
16.1 kB
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>هوشان - نسخه اصلاح شده نهایی</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
@custom-variant dark (&:is(.dark *));
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--radius-lg: var(--radius);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.145 0 0);
--border: oklch(0.922 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0.145 0 0); /* Added for icon color */
}
:root {
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
}
.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--popover: oklch(0.205 0 0);
--popover-foreground: oklch(0.985 0 0);
--border: oklch(1 0 0 / 10%);
--card: oklch(0.205 0 0);
--card-foreground: oklch(0.985 0 0); /* Added for icon color */
}
@layer base {
* { @apply border-border outline-ring/50; }
body { @apply bg-background text-foreground; overflow-x: hidden; margin:0; padding:0; font-family: sans-serif; } /* Basic reset */
}
/* Notification Popover */
.notification-popover-wrapper {
position: fixed; top: 1rem; left: 50%; transform: translateX(-50%);
z-index: 100; width: calc(100% - 2rem); max-width: 28rem;
display: flex; justify-content: center; pointer-events: none;
}
.popover-content {
width: 100%; border-radius: var(--radius-md, 0.5rem); border-width: 1px;
border-color: var(--border); background-color: var(--popover);
color: var(--popover-foreground);
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
outline: none; transition: opacity 0.3s ease-out, transform 0.4s cubic-bezier(0.68, -0.55, 0.27, 1.55);
opacity: 0; transform: translateY(-30px) scale(0.95); /* Start further up for drop */
pointer-events: none;
visibility: hidden; /* Ensure hidden when opacity is 0 */
}
.popover-content.open {
opacity: 1; transform: translateY(0) scale(1); pointer-events: auto; visibility: visible;
}
.notification-popover-text-content {
background-color: #eff6ff; /* bg-blue-50 */
font-size: 0.875rem; line-height: 1.5rem; direction: rtl;
padding: 1rem; border-radius: inherit;
}
/* Header controls */
.header-controls {
display: flex; padding: 1rem; justify-content: space-between;
align-items: center; width: 100%; position: absolute;
top: 0; left: 0; z-index: 10;
}
.header-button {
display: flex; align-items: center; justify-content: center;
padding: 0.5rem; border-radius: var(--radius-lg, 0.625rem);
background-color: #e5e7eb; /* bg-gray-200 */
cursor: pointer;
color: var(--foreground); /* Ensure icon inherits text color */
}
.header-button svg { opacity: 0.6; } /* Slightly less transparent */
@keyframes ping { 75%, 100% { transform: scale(2); opacity: 0; } }
.animate-ping { animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; }
#large-logo-container.flex { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; position: absolute; top: 0; left: 0; }
#small-logo-container.flex { display: flex; align-items: center; justify-content: center; }
.footer-controls {
width: 100%; display: flex; gap: 1rem; position: absolute;
bottom: 0; padding: 2rem 3rem; align-items: center;
}
.footer-controls.layout-default { justify-content: space-between; }
.footer-controls.layout-with-small-logo { justify-content: space-around; }
.control-button-wrapper {
position: relative; display: flex; align-items: center; justify-content: center;
}
.camera-switch-icon {
position: absolute;
bottom: calc(100% + 10px); /* Positioned 10px above the camera button */
left: 50%;
transform: translateX(-50%) translateY(10px) scale(0.7); /* Initial: below, small, hidden */
background-color: var(--card);
color: var(--card-foreground); /* For SVG stroke */
border-radius: 50%;
padding: 10px; /* Increased padding */
box-shadow: 0 4px 8px rgba(0,0,0,0.1), 0 1px 3px rgba(0,0,0,0.08); /* Softer shadow */
cursor: pointer;
z-index: 5;
transition: opacity 0.25s cubic-bezier(0.4, 0, 0.2, 1), transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
opacity: 0;
pointer-events: none;
}
.camera-switch-icon.visible {
opacity: 1;
transform: translateX(-50%) translateY(0) scale(1); /* Animate to final position */
pointer-events: auto;
}
.camera-switch-icon svg {
width: 24px; /* Consistent size */
height: 24px;
}
.control-button {
height: 80px; width: 80px; border-radius: 9999px;
padding: 0; display: flex; align-items: center; justify-content: center;
border-width: 1px;
box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -1px rgba(0,0,0,0.06);
cursor: pointer;
}
.cam-button-color { background-color: #E0ECFF; } /* Left button */
.mic-button-color { background-color: #fecdd3; } /* Right button */
</style>
<script>
tailwind.config = {
darkMode: 'class',
theme: {
extend: {
colors: { /* ... */ }, borderRadius: { /* ... */ }, inset: { /* ... */ },
keyframes: {
'popover-drop-in': {
'0%': { opacity: '0', transform: 'translateY(-30px) scale(0.95)' },
'70%': { opacity: '1', transform: 'translateY(5px) scale(1.02)' },
'100%': { opacity: '1', transform: 'translateY(0) scale(1)' },
},
'popover-lift-out': {
'0%': { opacity: '1', transform: 'translateY(0) scale(1)' },
'100%': { opacity: '0', transform: 'translateY(-30px) scale(0.95)' },
}
},
animation: {
'popover-open-top-center': 'popover-drop-in 0.4s cubic-bezier(0.68, -0.55, 0.27, 1.55) forwards',
'popover-close-top-center': 'popover-lift-out 0.3s ease-in forwards',
}
}
}
}
</script>
</head>
<body class="antialiased bg-slate-50">
<div class="w-full flex flex-col items-center justify-center min-h-[90dvh] md:min-h-screen">
<div class="max-w-3xl w-full flex flex-col items-center justify-center h-full relative">
<!-- Header - Button order: Notification (L), Back (R) -->
<div class="header-controls">
<div id="notification-trigger-container">
<button id="notification-button" aria-label="Notifications" class="header-button">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line></svg>
</button>
</div>
<div>
<div class="header-button" onclick="alert('Back clicked')">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m15 18-6-6 6-6"></path></svg>
</div>
</div>
</div>
<div id="notification-popover-wrapper" class="notification-popover-wrapper">
<div id="notification-popover" class="popover-content"> <!-- initially-hidden removed, JS handles initial state -->
<div class="notification-popover-text-content">
مدل‌های هوش مصنوعی می‌توانند اشتباه کنند، صحت اطلاعات مهم را بررسی کنید و از وارد کردن اطلاعات حساس بپرهیزید.
</div>
</div>
</div>
<div class="w-full flex flex-col items-center justify-center h-[90dvh] bg-slate-50 top-0 left-0 relative">
<video id="video-feed" autoplay playsinline class="absolute top-0 left-0 w-full h-full object-cover scale-x-[-1] hidden"></video>
<div id="large-logo-container" class="hidden"></div>
<div id="footer-controls" class="footer-controls layout-default">
<!-- Camera Button Wrapper (Now on the Left in RTL) -->
<div class="control-button-wrapper">
<div id="cam-switch-icon" class="camera-switch-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
<path d="M11 19H4a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2h5"/>
<path d="M13 5h7a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2h-5"/>
<line x1="12" x2="12" y1="1" y2="23"/>
<polyline points="8 13 12 17 16 13"/>
<polyline points="16 11 12 7 8 11"/>
</svg>
</div>
<div id="cam-button" class="control-button cam-button-color"></div>
</div>
<div id="small-logo-container" class="hidden"></div>
<!-- Mic Button (Now on the Right in RTL) -->
<div id="mic-button" class="control-button mic-button-color"></div>
</div>
</div>
</div>
</div>
<!-- SVG Icon Definitions -->
<div style="display: none;">
<svg id="svg-pauseIcon">...</svg><svg id="svg-microphoneIcon">...</svg><svg id="svg-cameraIcon">...</svg><svg id="svg-stopCamIcon">...</svg><svg id="svg-humanIcon">...</svg>
</div>
<script>
const videoFeed = document.getElementById('video-feed');
const largeLogoContainer = document.getElementById('large-logo-container');
const smallLogoContainer = document.getElementById('small-logo-container');
const micButton = document.getElementById('mic-button'); // Right
const camButton = document.getElementById('cam-button'); // Left
const camSwitchIcon = document.getElementById('cam-switch-icon');
const footerControls = document.getElementById('footer-controls');
const notificationButton = document.getElementById('notification-button'); // Left header
const notificationPopover = document.getElementById('notification-popover');
const pauseIconSVG = document.getElementById('svg-pauseIcon').cloneNode(true);
const microphoneIconSVG = document.getElementById('svg-microphoneIcon').cloneNode(true);
const cameraIconSVG = document.getElementById('svg-cameraIcon').cloneNode(true);
const stopCamIconSVG = document.getElementById('svg-stopCamIcon').cloneNode(true);
let isMicActive = false;
let isCamActive = false;
let isNotificationOpen = false;
function createLogoHTML(isMini, isHumanActive) { /* ... same as before ... */ } // Assuming AI icon isn't used in these states
function updateUI() {
videoFeed.classList.toggle('hidden', !isCamActive);
largeLogoContainer.classList.toggle('hidden', !(!isCamActive && isMicActive));
largeLogoContainer.classList.toggle('flex', !isCamActive && isMicActive);
if(!isCamActive && isMicActive) largeLogoContainer.innerHTML = createLogoHTML(false, true);
smallLogoContainer.classList.toggle('hidden', !isCamActive);
smallLogoContainer.classList.toggle('flex', isCamActive);
if(isCamActive) smallLogoContainer.innerHTML = createLogoHTML(true, true);
footerControls.classList.toggle('layout-default', !isCamActive);
footerControls.classList.toggle('layout-with-small-logo', isCamActive);
camSwitchIcon.classList.toggle('visible', isCamActive);
camButton.innerHTML = '';
camButton.appendChild(isCamActive ? stopCamIconSVG.cloneNode(true) : cameraIconSVG.cloneNode(true));
micButton.innerHTML = '';
micButton.appendChild(isMicActive ? pauseIconSVG.cloneNode(true) : microphoneIconSVG.cloneNode(true));
// Notification Popover
if (isNotificationOpen) {
notificationPopover.style.display = 'block'; // Make it visible before animation
requestAnimationFrame(() => { // Ensure display:block is processed
notificationPopover.classList.remove('animate-popover-close-top-center');
notificationPopover.classList.add('open', 'animate-popover-open-top-center');
});
} else {
if (notificationPopover.classList.contains('open')) {
notificationPopover.classList.remove('animate-popover-open-top-center');
notificationPopover.classList.add('animate-popover-close-top-center');
setTimeout(() => {
if (!isNotificationOpen) {
notificationPopover.classList.remove('open');
notificationPopover.style.display = 'none'; // Hide after animation
}
}, 300); // Match close animation duration (0.3s)
} else {
notificationPopover.style.display = 'none'; // Ensure it's hidden if never opened
notificationPopover.classList.remove('open');
}
}
}
notificationButton.addEventListener('click', (event) => {
event.stopPropagation();
isNotificationOpen = !isNotificationOpen;
updateUI();
});
document.addEventListener('click', (event) => {
if (isNotificationOpen && !notificationPopover.contains(event.target) && event.target !== notificationButton) {
isNotificationOpen = false;
updateUI();
}
});
camButton.addEventListener('click', () => { isCamActive = !isCamActive; updateUI(); });
micButton.addEventListener('click', () => { isMicActive = !isMicActive; updateUI(); });
camSwitchIcon.addEventListener('click', (e) => {
e.stopPropagation(); alert('Camera switch clicked!');
});
// Initial call to set up the UI correctly, ensuring popover is hidden.
notificationPopover.style.opacity = '0';
notificationPopover.style.transform = 'translateY(-30px) scale(0.95)';
notificationPopover.style.visibility = 'hidden';
notificationPopover.style.display = 'none'; // Start fully hidden
updateUI();
</script>
</body>
</html>