| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>AI Chat Assistant</title> |
| <style> |
| :root { |
| --primary-color: #2dd4bf; |
| --secondary-color: #1e293b; |
| --bg-color: #0f172a; |
| --text-primary: #f8fafc; |
| --text-secondary: #94a3b8; |
| --accent-color: #818cf8; |
| --border-color: #334155; |
| --hover-color: #1e293b; |
| --gradient-1: linear-gradient(135deg, #2dd4bf20, #818cf820); |
| --gradient-2: linear-gradient(45deg, #2dd4bf, #818cf8); |
| --glow-shadow: 0 0 20px rgba(45, 212, 191, 0.2); |
| --message-user-bg: linear-gradient(135deg, #2dd4bf, #818cf8); |
| --message-ai-bg: rgba(30, 41, 59, 0.5); |
| --message-user-gradient: linear-gradient(135deg, #2563eb, #1d4ed8); |
| --message-user-text: #ffffff; |
| --message-user-shadow: 0 4px 15px rgba(45, 212, 191, 0.2); |
| } |
| |
| body { |
| font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; |
| margin: 0; |
| padding: 0; |
| background-color: var(--bg-color); |
| color: var(--text-primary); |
| display: grid; |
| grid-template-columns: 260px 1fr; |
| min-height: 100vh; |
| background: var(--bg-color); |
| background-image: |
| radial-gradient(circle at 10% 20%, rgba(0, 255, 170, 0.05) 0%, transparent 20%), |
| radial-gradient(circle at 90% 80%, rgba(0, 200, 255, 0.05) 0%, transparent 20%); |
| transition: all 0.3s ease; |
| } |
| |
| |
| .sidebar { |
| background-color: var(--secondary-color); |
| backdrop-filter: blur(10px); |
| border-right: 1px solid rgba(255, 255, 255, 0.1); |
| padding: 16px; |
| display: flex; |
| flex-direction: column; |
| gap: 16px; |
| animation: slideIn 0.5s ease; |
| } |
| |
| .new-chat-btn { |
| background: var(--message-user-bg); |
| color: white; |
| border: none; |
| padding: 12px; |
| border-radius: 12px; |
| cursor: pointer; |
| font-weight: 600; |
| transition: all 0.3s ease; |
| box-shadow: var(--message-user-shadow); |
| display: flex; |
| align-items: center; |
| gap: 8px; |
| } |
| |
| .new-chat-btn:hover { |
| transform: translateY(-2px); |
| box-shadow: 0 6px 20px rgba(45, 212, 191, 0.3); |
| background: var(--accent-color); |
| } |
| |
| .chat-list { |
| flex-grow: 1; |
| overflow-y: auto; |
| } |
| |
| .chat-item { |
| padding: 10px; |
| border-radius: 6px; |
| cursor: pointer; |
| display: flex; |
| align-items: center; |
| justify-content: space-between; |
| color: var(--text-secondary); |
| transition: all 0.3s ease; |
| background: transparent; |
| border: 1px solid transparent; |
| } |
| |
| .chat-item:hover { |
| background: var(--hover-color); |
| border-color: var(--primary-color); |
| transform: translateX(5px); |
| } |
| |
| .chat-item.active { |
| background: var(--hover-color); |
| border-left: 2px solid var(--primary-color); |
| } |
| |
| .delete-chat { |
| opacity: 0; |
| transition: opacity 0.2s ease; |
| color: var(--text-secondary); |
| background: none; |
| border: none; |
| cursor: pointer; |
| padding: 4px; |
| } |
| |
| .chat-item:hover .delete-chat { |
| opacity: 1; |
| } |
| |
| |
| .main-container { |
| display: flex; |
| flex-direction: column; |
| height: 100vh; |
| } |
| |
| .chat-header { |
| padding: 16px; |
| border-bottom: 1px solid var(--border-color); |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| position: relative; |
| background: rgba(26, 31, 44, 0.8); |
| backdrop-filter: blur(10px); |
| border-bottom: 1px solid rgba(255, 255, 255, 0.1); |
| } |
| |
| .chat-title { |
| font-size: 1.1rem; |
| color: var(--primary-color); |
| margin: 0; |
| text-align: center; |
| font-weight: 500; |
| max-width: 60%; |
| overflow: hidden; |
| text-overflow: ellipsis; |
| white-space: nowrap; |
| text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); |
| letter-spacing: 0.5px; |
| } |
| |
| .chat-messages { |
| flex-grow: 1; |
| overflow-y: auto; |
| padding: 20px; |
| scroll-behavior: smooth; |
| height: calc(100vh - 140px); |
| font-size: 16px !important; |
| } |
| |
| .message { |
| max-width: 80%; |
| padding: 12px 16px; |
| margin-bottom: 16px; |
| font-size: 16px !important; |
| line-height: 1.5; |
| border-radius: 18px; |
| position: relative; |
| display: inline-flex; |
| gap: 12px; |
| align-items: flex-start; |
| width: fit-content; |
| } |
| |
| .message.user-message { |
| margin-left: auto; |
| background: linear-gradient(135deg, #2dd4bf, #0ea5e9); |
| border-bottom-right-radius: 4px; |
| flex-direction: row-reverse; |
| box-shadow: 0 2px 8px rgba(45, 212, 191, 0.2); |
| float: right; |
| clear: both; |
| } |
| |
| .message.ai-message { |
| margin-right: auto; |
| background: var(--secondary-color); |
| border-bottom-left-radius: 4px; |
| box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); |
| float: left; |
| clear: both; |
| } |
| |
| .avatar { |
| width: 32px; |
| height: 32px; |
| border-radius: 50%; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| font-weight: 600; |
| font-size: 14px; |
| flex-shrink: 0; |
| margin-top: 4px; |
| } |
| |
| .user-avatar { |
| background: white; |
| color: var(--primary-color); |
| box-shadow: 0 2px 8px rgba(45, 212, 191, 0.2); |
| } |
| |
| .ai-avatar { |
| background: white; |
| color: var(--secondary-color); |
| box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); |
| } |
| |
| .message-content { |
| font-size: 16px !important; |
| line-height: 1.5; |
| padding: 0 4px; |
| word-wrap: break-word; |
| white-space: pre-wrap; |
| } |
| |
| .user-message .message-content { |
| color: white; |
| text-align: left; |
| } |
| |
| .ai-message .message-content { |
| color: var(--text-primary); |
| } |
| |
| |
| .input-container { |
| padding: 20px; |
| border-top: 1px solid var(--border-color); |
| max-width: 900px; |
| margin: 0 auto; |
| width: calc(100% - 40px); |
| position: relative; |
| } |
| |
| .input-wrapper { |
| display: flex; |
| gap: 12px; |
| background: var(--message-ai-bg); |
| border: 1px solid rgba(45, 212, 191, 0.2); |
| padding: 12px 16px; |
| border-radius: 12px; |
| transition: all 0.3s ease; |
| } |
| |
| .input-wrapper:focus-within { |
| border-color: var(--primary-color); |
| box-shadow: 0 0 15px rgba(45, 212, 191, 0.2); |
| } |
| |
| #user-input { |
| flex-grow: 1; |
| padding: 8px 0; |
| border: none; |
| background: transparent; |
| font-size: 16px; |
| color: var(--text-primary); |
| outline: none; |
| resize: none; |
| min-height: 24px; |
| max-height: 200px; |
| line-height: 1.5; |
| } |
| |
| .send-button { |
| background: var(--message-user-bg); |
| border: none; |
| border-radius: 8px; |
| width: 32px; |
| height: 32px; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| cursor: pointer; |
| transition: all 0.3s ease; |
| padding: 0; |
| margin: auto 0; |
| box-shadow: var(--message-user-shadow); |
| } |
| |
| .send-button:hover { |
| transform: translateY(-2px) scale(1.05); |
| box-shadow: 0 6px 20px rgba(45, 212, 191, 0.3); |
| background: var(--accent-color); |
| } |
| |
| .send-button:active { |
| transform: translateY(0); |
| } |
| |
| .send-button svg { |
| width: 16px; |
| height: 16px; |
| stroke: white; |
| } |
| |
| .send-button.disabled { |
| background-color: var(--text-secondary); |
| cursor: not-allowed; |
| opacity: 0.5; |
| } |
| |
| |
| |
| |
| .message .code-block { |
| position: relative; |
| background: #1e1e1e; |
| border-radius: 8px; |
| margin: 12px 0; |
| font-family: 'Fira Code', 'Consolas', monospace; |
| border: 1px solid rgba(255, 255, 255, 0.1); |
| } |
| |
| .code-block pre { |
| margin: 0; |
| padding: 16px; |
| padding-top: 32px; |
| overflow-x: auto; |
| color: #e0e0e0; |
| font-size: 14px; |
| line-height: 1.5; |
| } |
| |
| .code-block .copy-button { |
| position: absolute; |
| top: 8px; |
| right: 8px; |
| background: rgba(255, 255, 255, 0.1); |
| color: #fff; |
| border: none; |
| border-radius: 4px; |
| padding: 4px 8px; |
| font-size: 12px; |
| cursor: pointer; |
| display: flex; |
| align-items: center; |
| gap: 4px; |
| transition: all 0.2s ease; |
| opacity: 0; |
| } |
| |
| .code-block:hover .copy-button { |
| opacity: 1; |
| } |
| |
| .code-block .copy-button:hover { |
| background: rgba(255, 255, 255, 0.2); |
| } |
| |
| .code-block .copy-button svg { |
| width: 14px; |
| height: 14px; |
| } |
| |
| .code-block .language-label { |
| position: absolute; |
| top: 8px; |
| left: 8px; |
| color: #888; |
| font-size: 12px; |
| font-family: 'Inter', sans-serif; |
| } |
| |
| |
| .code-block .keyword { color: #569CD6; } |
| .code-block .string { color: #CE9178; } |
| .code-block .comment { color: #6A9955; } |
| .code-block .number { color: #B5CEA8; } |
| .code-block .function { color: #DCDCAA; } |
| .code-block .operator { color: #D4D4D4; } |
| .code-block .class { color: #4EC9B0; } |
| .code-block .property { color: #9CDCFE; } |
| |
| |
| .thinking { |
| display: flex; |
| align-items: center; |
| gap: 12px; |
| } |
| |
| .loading-dots { |
| display: flex; |
| gap: 4px; |
| } |
| |
| .loading-dots span { |
| width: 8px; |
| height: 8px; |
| border-radius: 50%; |
| background: var(--primary-color); |
| animation: pulse 1.5s infinite ease-in-out; |
| } |
| |
| .loading-dots span:nth-child(2) { animation-delay: 0.2s; } |
| .loading-dots span:nth-child(3) { animation-delay: 0.4s; } |
| |
| @keyframes pulse { |
| 0%, 100% { transform: scale(0.5); opacity: 0.5; } |
| 50% { transform: scale(1); opacity: 1; } |
| } |
| |
| |
| ::-webkit-scrollbar { |
| width: 6px; |
| } |
| |
| ::-webkit-scrollbar-track { |
| background: transparent; |
| } |
| |
| ::-webkit-scrollbar-thumb { |
| background: var(--primary-color); |
| border-radius: 3px; |
| } |
| |
| |
| @keyframes slideIn { |
| from { |
| transform: translateX(-100%); |
| opacity: 0; |
| } |
| to { |
| transform: translateX(0); |
| opacity: 1; |
| } |
| } |
| |
| @keyframes messageSlide { |
| from { |
| transform: translateY(20px); |
| opacity: 0; |
| } |
| to { |
| transform: translateY(0); |
| opacity: 1; |
| } |
| } |
| |
| |
| .message { |
| position: relative; |
| overflow: hidden; |
| } |
| |
| .message.user-message::after { |
| content: ''; |
| position: absolute; |
| top: 0; |
| left: 0; |
| right: 0; |
| bottom: 0; |
| background: linear-gradient( |
| 45deg, |
| transparent, |
| rgba(45, 212, 191, 0.1), |
| transparent |
| ); |
| animation: shine 2s infinite; |
| } |
| |
| @keyframes shine { |
| 0% { |
| transform: translateX(-100%) translateY(-100%); |
| } |
| 50%, 100% { |
| transform: translateX(100%) translateY(100%); |
| } |
| } |
| |
| |
| .avatar:hover { |
| transform: scale(1.05); |
| transition: transform 0.2s ease; |
| } |
| |
| |
| .scroll-button { |
| position: fixed; |
| right: 30px; |
| width: 45px; |
| height: 45px; |
| border-radius: 50%; |
| background: #2dd4bf; |
| color: white; |
| border: none; |
| cursor: pointer; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| opacity: 0; |
| visibility: hidden; |
| transition: opacity 0.3s; |
| box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); |
| } |
| |
| .scroll-button.visible { |
| opacity: 1; |
| visibility: visible; |
| } |
| |
| .scroll-top-button { |
| bottom: 100px; |
| } |
| |
| .scroll-bottom-button { |
| bottom: 40px; |
| } |
| |
| |
| .scroll-button::after { |
| content: ''; |
| position: absolute; |
| width: 100%; |
| height: 100%; |
| border-radius: 50%; |
| background: inherit; |
| filter: blur(8px); |
| opacity: 0; |
| transition: opacity 0.3s ease; |
| z-index: -1; |
| } |
| |
| .scroll-button:hover::after { |
| opacity: 0.5; |
| } |
| |
| |
| .chat-messages { |
| scroll-behavior: smooth; |
| } |
| |
| |
| @keyframes messageAppear { |
| from { |
| opacity: 0; |
| transform: translateY(10px); |
| } |
| to { |
| opacity: 1; |
| transform: translateY(0); |
| } |
| } |
| |
| .message { |
| animation: messageAppear 0.3s ease-out; |
| } |
| |
| |
| .chat-messages::after { |
| content: ''; |
| display: table; |
| clear: both; |
| } |
| |
| |
| @media (max-width: 768px) { |
| body { |
| grid-template-columns: 1fr; |
| } |
| |
| .sidebar { |
| position: fixed; |
| left: -100%; |
| top: 0; |
| bottom: 0; |
| width: 280px; |
| z-index: 1000; |
| transition: left 0.3s ease; |
| padding: 12px; |
| background: var(--secondary-color); |
| backdrop-filter: blur(10px); |
| box-shadow: none; |
| } |
| |
| .sidebar.active { |
| left: 0; |
| box-shadow: 0 0 20px rgba(0, 0, 0, 0.3); |
| } |
| |
| .menu-button { |
| position: fixed; |
| left: 15px; |
| top: 15px; |
| z-index: 1001; |
| background: var(--primary-color); |
| border: none; |
| border-radius: 8px; |
| width: 36px; |
| height: 36px; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| cursor: pointer; |
| color: white; |
| } |
| |
| .chat-header { |
| padding: 15px 70px; |
| height: 50px; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| } |
| |
| .chat-title { |
| font-size: 16px; |
| max-width: 80%; |
| } |
| |
| .main-container { |
| padding-top: 0; |
| height: 100vh; |
| margin-left: 0; |
| width: 100%; |
| position: relative; |
| z-index: 1; |
| } |
| |
| .message { |
| max-width: 90%; |
| padding: 10px 12px; |
| } |
| |
| .input-container { |
| padding: 12px; |
| width: calc(100% - 24px); |
| } |
| |
| .scroll-button { |
| right: 10px; |
| width: 40px; |
| height: 40px; |
| } |
| |
| |
| .code-block { |
| max-width: 100%; |
| overflow-x: auto; |
| } |
| |
| .code-block pre { |
| padding: 12px; |
| font-size: 12px; |
| } |
| |
| .chat-list { |
| padding-bottom: 20px; |
| height: calc(100vh - 80px); |
| overflow-y: auto; |
| } |
| |
| .chat-item { |
| padding: 12px 10px; |
| font-size: 14px; |
| margin-bottom: 4px; |
| } |
| |
| .chat-item span { |
| max-width: 200px; |
| overflow: hidden; |
| text-overflow: ellipsis; |
| white-space: nowrap; |
| } |
| |
| |
| .new-chat-btn { |
| margin: 0 0 12px 0; |
| width: calc(100% - 24px); |
| padding: 12px; |
| font-size: 14px; |
| } |
| } |
| |
| |
| .overlay { |
| display: none; |
| position: fixed; |
| top: 0; |
| left: 0; |
| right: 0; |
| bottom: 0; |
| background: rgba(0, 0, 0, 0.5); |
| z-index: 999; |
| } |
| |
| .overlay.active { |
| display: block; |
| } |
| |
| |
| body { |
| background: linear-gradient(135deg, #0f172a 0%, #1e1b4b 100%); |
| position: relative; |
| overflow: hidden; |
| } |
| |
| |
| .background-effects { |
| position: fixed; |
| top: 0; |
| left: 0; |
| right: 0; |
| bottom: 0; |
| z-index: 0; |
| pointer-events: none; |
| } |
| |
| .background-effects::before, |
| .background-effects::after { |
| content: ''; |
| position: absolute; |
| width: 300px; |
| height: 300px; |
| border-radius: 50%; |
| filter: blur(100px); |
| opacity: 0.15; |
| animation: floatAround 20s infinite ease-in-out; |
| } |
| |
| .background-effects::before { |
| background: #00ffaa; |
| top: -150px; |
| left: -150px; |
| } |
| |
| .background-effects::after { |
| background: #00c8ff; |
| bottom: -150px; |
| right: -150px; |
| animation-delay: -10s; |
| } |
| |
| @keyframes floatAround { |
| 0%, 100% { transform: translate(0, 0); } |
| 25% { transform: translate(100px, 100px); } |
| 50% { transform: translate(0, 200px); } |
| 75% { transform: translate(-100px, 100px); } |
| } |
| |
| |
| .welcome-message { |
| background: rgba(255, 255, 255, 0.05); |
| border-radius: 12px; |
| padding: 20px; |
| margin: 10px 20px 24px 20px; |
| backdrop-filter: blur(10px); |
| border: 1px solid rgba(255, 255, 255, 0.1); |
| animation: fadeIn 0.5s ease-out; |
| max-width: calc(100% - 40px); |
| } |
| |
| .welcome-message h3 { |
| color: var(--primary-color); |
| margin: 0 0 12px 0; |
| font-size: 1.2rem; |
| } |
| |
| .welcome-message p { |
| margin: 0 0 16px 0; |
| line-height: 1.5; |
| font-size: 0.95rem; |
| } |
| |
| .quick-actions { |
| display: flex; |
| gap: 8px; |
| flex-wrap: wrap; |
| margin-top: 16px; |
| } |
| |
| .quick-action-btn { |
| background: rgba(255, 255, 255, 0.1); |
| border: none; |
| padding: 8px 16px; |
| border-radius: 20px; |
| color: var(--text-primary); |
| cursor: pointer; |
| transition: all 0.3s ease; |
| font-size: 14px; |
| white-space: nowrap; |
| position: relative; |
| overflow: hidden; |
| } |
| |
| .quick-action-btn:hover { |
| background: var(--primary-color); |
| transform: translateY(-2px); |
| box-shadow: 0 4px 12px rgba(45, 212, 191, 0.3); |
| } |
| |
| .quick-action-btn:active { |
| transform: translateY(0); |
| } |
| |
| |
| .quick-action-btn::after { |
| content: ''; |
| position: absolute; |
| width: 100%; |
| height: 100%; |
| top: 0; |
| left: 0; |
| pointer-events: none; |
| background-image: radial-gradient(circle, #fff 10%, transparent 10.01%); |
| background-repeat: no-repeat; |
| background-position: 50%; |
| transform: scale(10, 10); |
| opacity: 0; |
| transition: transform .5s, opacity 1s; |
| } |
| |
| .quick-action-btn:active::after { |
| transform: scale(0, 0); |
| opacity: .3; |
| transition: 0s; |
| } |
| |
| |
| .quick-action-btn:hover::before { |
| content: ''; |
| position: absolute; |
| top: 0; |
| left: 0; |
| right: 0; |
| bottom: 0; |
| border-radius: 20px; |
| background: var(--primary-color); |
| z-index: -1; |
| filter: blur(8px); |
| opacity: 0.5; |
| transition: opacity 0.3s ease; |
| } |
| |
| |
| @media (max-width: 768px) { |
| .quick-action-btn { |
| padding: 10px 16px; |
| } |
| |
| .quick-action-btn:active { |
| background: var(--primary-color); |
| transform: scale(0.98); |
| } |
| } |
| |
| |
| @media (max-width: 768px) { |
| .welcome-message { |
| margin: 10px 10px 20px 10px; |
| padding: 15px; |
| max-width: calc(100% - 20px); |
| } |
| |
| .welcome-message h3 { |
| font-size: 1.1rem; |
| margin-bottom: 10px; |
| } |
| |
| .welcome-message p { |
| font-size: 0.9rem; |
| margin-bottom: 12px; |
| } |
| |
| .quick-actions { |
| gap: 6px; |
| margin-top: 12px; |
| } |
| |
| .quick-action-btn { |
| padding: 6px 12px; |
| font-size: 13px; |
| flex: 1 1 calc(50% - 6px); |
| text-align: center; |
| min-width: calc(50% - 6px); |
| max-width: calc(50% - 6px); |
| } |
| } |
| |
| |
| @keyframes fadeIn { |
| from { |
| opacity: 0; |
| transform: translateY(10px); |
| } |
| to { |
| opacity: 1; |
| transform: translateY(0); |
| } |
| } |
| |
| |
| .input-container { |
| position: relative; |
| backdrop-filter: blur(10px); |
| } |
| |
| .input-wrapper { |
| position: relative; |
| } |
| |
| .input-actions { |
| position: absolute; |
| right: 50px; |
| top: 50%; |
| transform: translateY(-50%); |
| display: flex; |
| gap: 8px; |
| } |
| |
| .input-action-btn { |
| background: none; |
| border: none; |
| color: var(--text-secondary); |
| cursor: pointer; |
| padding: 4px; |
| transition: all 0.2s ease; |
| } |
| |
| .input-action-btn:hover { |
| color: var(--primary-color); |
| } |
| |
| |
| .settings-button { |
| position: absolute; |
| right: 20px; |
| top: 50%; |
| transform: translateY(-50%); |
| width: 40px; |
| height: 40px; |
| border-radius: 10px; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| cursor: pointer; |
| color: var(--text-secondary); |
| transition: all 0.3s ease; |
| background: rgba(255, 255, 255, 0.1); |
| } |
| |
| .settings-button:hover { |
| background: var(--primary-color); |
| color: white; |
| transform: translateY(-50%) scale(1.05); |
| } |
| |
| |
| .settings-modal { |
| display: none; |
| position: fixed; |
| top: 0; |
| left: 0; |
| right: 0; |
| bottom: 0; |
| background: rgba(0, 0, 0, 0.5); |
| z-index: 1000; |
| backdrop-filter: blur(5px); |
| } |
| |
| .settings-modal.active { |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| } |
| |
| .settings-content { |
| background: var(--secondary-color); |
| border-radius: 12px; |
| width: 90%; |
| max-width: 500px; |
| position: relative; |
| animation: modalSlide 0.3s ease; |
| } |
| |
| .settings-header { |
| padding: 20px; |
| border-bottom: 1px solid var(--border-color); |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| } |
| |
| .settings-header h2 { |
| margin: 0; |
| color: var(--text-primary); |
| } |
| |
| .close-settings { |
| background: none; |
| border: none; |
| color: var(--text-secondary); |
| font-size: 24px; |
| cursor: pointer; |
| padding: 0; |
| } |
| |
| .settings-body { |
| padding: 20px; |
| } |
| |
| .settings-section { |
| margin-bottom: 24px; |
| } |
| |
| .settings-section h3 { |
| margin: 0 0 12px 0; |
| color: var(--text-primary); |
| } |
| |
| .theme-options { |
| display: flex; |
| gap: 8px; |
| } |
| |
| .theme-btn { |
| padding: 8px 16px; |
| border-radius: 8px; |
| border: 1px solid var(--border-color); |
| background: transparent; |
| color: var(--text-primary); |
| cursor: pointer; |
| transition: all 0.3s ease; |
| } |
| |
| .theme-btn.active { |
| background: var(--primary-color); |
| border-color: var(--primary-color); |
| } |
| |
| .language-select { |
| width: 100%; |
| padding: 8px; |
| border-radius: 8px; |
| background: var(--bg-color); |
| color: var(--text-primary); |
| border: 1px solid var(--border-color); |
| } |
| |
| @keyframes modalSlide { |
| from { |
| opacity: 0; |
| transform: translateY(20px); |
| } |
| to { |
| opacity: 1; |
| transform: translateY(0); |
| } |
| } |
| |
| |
| @media (max-width: 768px) { |
| .settings-button { |
| right: 15px; |
| width: 36px; |
| height: 36px; |
| } |
| |
| .settings-content { |
| width: 95%; |
| margin: 20px; |
| } |
| } |
| |
| |
| .landing-page { |
| position: fixed; |
| top: 0; |
| left: 0; |
| width: 100%; |
| height: 100%; |
| background: linear-gradient(135deg, #0f172a 0%, #1e1b4b 100%); |
| z-index: 9999; |
| overflow-y: auto; |
| transition: opacity 0.5s ease, transform 0.5s ease; |
| -webkit-overflow-scrolling: touch; |
| } |
| |
| .landing-page.hidden { |
| opacity: 0; |
| transform: translateY(-20px); |
| pointer-events: none; |
| } |
| |
| .landing-container { |
| max-width: 1200px; |
| margin: 0 auto; |
| padding: 40px 20px; |
| } |
| |
| .hero-section { |
| text-align: center; |
| padding: 60px 0; |
| animation: fadeIn 1s ease-out; |
| } |
| |
| .hero-title { |
| font-size: 3.5rem; |
| margin-bottom: 20px; |
| background: linear-gradient(135deg, #2dd4bf, #818cf8); |
| -webkit-background-clip: text; |
| background-clip: text; |
| -webkit-text-fill-color: transparent; |
| } |
| |
| .hero-subtitle { |
| font-size: 1.2rem; |
| color: var(--text-secondary); |
| margin-bottom: 40px; |
| } |
| |
| .features-grid { |
| display: grid; |
| grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); |
| gap: 30px; |
| padding: 40px 0; |
| } |
| |
| .feature-card { |
| background: rgba(255, 255, 255, 0.05); |
| border-radius: 15px; |
| padding: 30px; |
| backdrop-filter: blur(10px); |
| border: 1px solid rgba(255, 255, 255, 0.1); |
| transition: transform 0.3s ease; |
| } |
| |
| .feature-card:hover { |
| transform: translateY(-5px); |
| } |
| |
| .feature-icon { |
| font-size: 2rem; |
| margin-bottom: 20px; |
| color: var(--primary-color); |
| } |
| |
| .feature-title { |
| font-size: 1.5rem; |
| margin-bottom: 15px; |
| color: var(--primary-color); |
| } |
| |
| .feature-description { |
| color: var(--text-secondary); |
| } |
| |
| .cta-button { |
| display: inline-block; |
| background: linear-gradient(135deg, #2dd4bf, #818cf8); |
| color: white; |
| padding: 15px 40px; |
| border-radius: 30px; |
| text-decoration: none; |
| font-weight: 600; |
| font-size: 1.1rem; |
| transition: all 0.3s ease; |
| border: none; |
| cursor: pointer; |
| margin-top: 40px; |
| } |
| |
| .cta-button:hover { |
| transform: translateY(-2px); |
| box-shadow: 0 10px 20px rgba(45, 212, 191, 0.2); |
| } |
| |
| |
| @media (max-width: 768px) { |
| .hero-title { |
| font-size: 2.5rem; |
| } |
| |
| .hero-subtitle { |
| font-size: 1rem; |
| padding: 0 20px; |
| } |
| |
| .features-grid { |
| grid-template-columns: 1fr; |
| padding: 20px; |
| } |
| |
| .feature-card { |
| padding: 20px; |
| } |
| } |
| |
| |
| .landing-page { |
| position: fixed; |
| top: 0; |
| left: 0; |
| width: 100%; |
| height: 100%; |
| background: linear-gradient(135deg, #0f172a 0%, #1e1b4b 100%); |
| z-index: 9999; |
| overflow-y: auto; |
| transition: opacity 0.5s ease, transform 0.5s ease; |
| -webkit-overflow-scrolling: touch; |
| } |
| |
| |
| @media (max-width: 768px) { |
| .landing-container { |
| padding: 20px 15px; |
| } |
| |
| .hero-section { |
| padding: 40px 0; |
| } |
| |
| .hero-title { |
| font-size: 2.2rem; |
| padding: 0 10px; |
| margin-bottom: 15px; |
| } |
| |
| .hero-subtitle { |
| font-size: 1rem; |
| padding: 0 15px; |
| margin-bottom: 30px; |
| } |
| |
| .features-grid { |
| grid-template-columns: 1fr; |
| gap: 15px; |
| padding: 20px 0; |
| } |
| |
| .feature-card { |
| padding: 20px; |
| margin: 0 10px; |
| } |
| |
| .feature-title { |
| font-size: 1.2rem; |
| } |
| |
| .feature-description { |
| font-size: 0.9rem; |
| } |
| |
| .cta-button { |
| padding: 12px 30px; |
| font-size: 1rem; |
| margin-top: 30px; |
| width: 80%; |
| max-width: 300px; |
| } |
| } |
| |
| |
| @media (max-width: 380px) { |
| .hero-title { |
| font-size: 1.8rem; |
| } |
| |
| .feature-card { |
| padding: 15px; |
| } |
| |
| .cta-button { |
| padding: 10px 25px; |
| font-size: 0.9rem; |
| } |
| } |
| |
| |
| @media (max-width: 768px) { |
| body { |
| grid-template-columns: 1fr; |
| } |
| |
| .main-container { |
| width: 100%; |
| height: 100vh; |
| position: relative; |
| overflow: hidden; |
| } |
| |
| .chat-messages { |
| height: calc(100vh - 180px); |
| padding: 10px; |
| overflow-y: auto; |
| -webkit-overflow-scrolling: touch; |
| position: relative; |
| margin-bottom: 60px; |
| } |
| |
| .welcome-message { |
| position: relative; |
| width: calc(100% - 20px); |
| margin: 10px auto; |
| z-index: 1; |
| } |
| |
| .input-container { |
| position: fixed; |
| bottom: 0; |
| left: 0; |
| right: 0; |
| background: var(--bg-color); |
| padding: 10px; |
| border-top: 1px solid var(--border-color); |
| z-index: 100; |
| width: 100%; |
| max-width: 100%; |
| margin: 0; |
| box-sizing: border-box; |
| } |
| |
| .input-wrapper { |
| max-width: 100%; |
| margin: 0; |
| } |
| |
| #user-input { |
| font-size: 16px; |
| padding: 8px; |
| } |
| |
| .message { |
| max-width: 85%; |
| margin-bottom: 10px; |
| } |
| |
| |
| .scroll-button { |
| width: 36px; |
| height: 36px; |
| right: 10px; |
| z-index: 101; |
| } |
| |
| .scroll-top-button { |
| bottom: 80px; |
| } |
| |
| .scroll-bottom-button { |
| bottom: 130px; |
| } |
| |
| |
| .chat-header { |
| padding: 10px; |
| height: auto; |
| z-index: 99; |
| } |
| |
| |
| .quick-actions { |
| display: grid; |
| grid-template-columns: repeat(2, 1fr); |
| gap: 8px; |
| padding: 0 5px; |
| } |
| |
| .quick-action-btn { |
| width: 100%; |
| padding: 8px; |
| font-size: 14px; |
| text-align: center; |
| white-space: normal; |
| } |
| } |
| |
| |
| @media (max-width: 380px) { |
| .chat-messages { |
| height: calc(100vh - 160px); |
| } |
| |
| .message { |
| max-width: 90%; |
| padding: 8px 12px; |
| } |
| |
| .input-container { |
| padding: 8px; |
| } |
| } |
| </style> |
| </head> |
| <body> |
| <div class="landing-page" id="landing-page"> |
| <div class="landing-container"> |
| <section class="hero-section"> |
| <h1 class="hero-title">Welcome to Rxple AI</h1> |
| <p class="hero-subtitle">Experience the future of AI-powered conversations with our advanced chatbot</p> |
| </section> |
|
|
| <div class="features-grid"> |
| <div class="feature-card"> |
| <div class="feature-icon">🤖</div> |
| <h3 class="feature-title">Advanced AI Technology</h3> |
| <p class="feature-description"> |
| Powered by state-of-the-art language models, our AI understands context and provides accurate, relevant responses. |
| </p> |
| </div> |
|
|
| <div class="feature-card"> |
| <div class="feature-icon">💡</div> |
| <h3 class="feature-title">Smart Assistance</h3> |
| <p class="feature-description"> |
| Get help with coding, writing, analysis, and more. Our AI adapts to your needs and learning style. |
| </p> |
| </div> |
|
|
| <div class="feature-card"> |
| <div class="feature-icon">🔒</div> |
| <h3 class="feature-title">Secure & Private</h3> |
| <p class="feature-description"> |
| Your conversations are private and secure. We prioritize your data protection and privacy. |
| </p> |
| </div> |
|
|
| <div class="feature-card"> |
| <div class="feature-icon">⚡</div> |
| <h3 class="feature-title">Real-time Responses</h3> |
| <p class="feature-description"> |
| Get instant answers to your questions with our lightning-fast response system. |
| </p> |
| </div> |
|
|
| <div class="feature-card"> |
| <div class="feature-icon">📱</div> |
| <h3 class="feature-title">Mobile Friendly</h3> |
| <p class="feature-description"> |
| Access our AI assistant from any device with a seamless, responsive design. |
| </p> |
| </div> |
|
|
| <div class="feature-card"> |
| <div class="feature-icon">🔄</div> |
| <h3 class="feature-title">Continuous Learning</h3> |
| <p class="feature-description"> |
| Our AI constantly improves and updates its knowledge to provide better assistance. |
| </p> |
| </div> |
| </div> |
|
|
| <section class="hero-section"> |
| <button class="cta-button" onclick="startChat()">Start Chatting with AI</button> |
| </section> |
| </div> |
| </div> |
|
|
| <aside class="sidebar"> |
| <button class="new-chat-btn" onclick="createNewChat()"> |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| <line x1="12" y1="5" x2="12" y2="19"></line> |
| <line x1="5" y1="12" x2="19" y2="12"></line> |
| </svg> |
| New Chat |
| </button> |
| <div class="chat-list" id="chat-list"> |
| |
| </div> |
| </aside> |
|
|
| <main class="main-container"> |
| <div class="chat-header"> |
| <div class="settings-button" id="settings-button" title="Settings"> |
| <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| <path d="M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/> |
| <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/> |
| </svg> |
| </div> |
| <h1 class="chat-title" id="current-chat-title">New Chat</h1> |
| </div> |
| <div class="chat-messages" id="chat-messages"></div> |
|
|
| <button id="scroll-top" class="scroll-button scroll-top-button" title="Scroll to top"> |
| <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| <path d="M18 15l-6-6-6 6"/> |
| </svg> |
| </button> |
|
|
| <button id="scroll-bottom" class="scroll-button scroll-bottom-button" title="Scroll to bottom"> |
| <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| <path d="M6 9l6 6 6-6"/> |
| </svg> |
| </button> |
|
|
| <div class="input-container"> |
| <div class="input-wrapper"> |
| <input |
| type="text" |
| id="user-input" |
| placeholder="Send a message..." |
| autocomplete="off" |
| autofocus |
| > |
| <button class="send-button" id="send-button" onclick="sendMessage()"> |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| <path d="M22 2L11 13M22 2L15 22L11 13L2 9L22 2Z"></path> |
| </svg> |
| </button> |
| </div> |
| </div> |
| </main> |
|
|
| <button class="menu-button" id="menu-button" style="display: none;"> |
| <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| <line x1="3" y1="12" x2="21" y2="12"></line> |
| <line x1="3" y1="6" x2="21" y2="6"></line> |
| <line x1="3" y1="18" x2="21" y2="18"></line> |
| </svg> |
| </button> |
|
|
| <div class="overlay" id="overlay"></div> |
|
|
| <div class="background-effects"></div> |
|
|
| <div class="welcome-message"> |
| <h3>👋 Welcome to AI Chat Assistant</h3> |
| <p>I'm here to help you with any questions or tasks. Here are some things I can do:</p> |
| <div class="quick-actions"> |
| <button class="quick-action-btn" onclick="sendQuickAction('Tell me a joke')">Tell me a joke</button> |
| <button class="quick-action-btn" onclick="sendQuickAction('Write a poem')">Write a poem</button> |
| <button class="quick-action-btn" onclick="sendQuickAction('Explain quantum physics')">Explain quantum physics</button> |
| <button class="quick-action-btn" onclick="sendQuickAction('Help with coding')">Help with coding</button> |
| </div> |
| </div> |
|
|
| <div class="settings-modal" id="settings-modal"> |
| <div class="settings-content"> |
| <div class="settings-header"> |
| <h2>Settings</h2> |
| <button class="close-settings">×</button> |
| </div> |
| <div class="settings-body"> |
| <div class="settings-section"> |
| <h3>Theme</h3> |
| <div class="theme-options"> |
| <button class="theme-btn active" data-theme="dark">Dark</button> |
| <button class="theme-btn" data-theme="light">Light</button> |
| <button class="theme-btn" data-theme="system">System</button> |
| </div> |
| </div> |
| <div class="settings-section"> |
| <h3>Language</h3> |
| <select class="language-select"> |
| <option value="en">English</option> |
| <option value="es">Español</option> |
| <option value="fr">Français</option> |
| </select> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| <script> |
| |
| const MISTRAL_API_KEY = 'UgKksYvcKnoxvJ13q5UBjL3AdU8Mu1DQ'; |
| const chatMessages = document.getElementById('chat-messages'); |
| const userInput = document.getElementById('user-input'); |
| const sendButton = document.getElementById('send-button'); |
| const scrollTopBtn = document.getElementById('scroll-top'); |
| const scrollBottomBtn = document.getElementById('scroll-bottom'); |
| let lastScrollTop = 0; |
| let scrollCount = 0; |
| let scrollTimeout; |
| let chats = []; |
| let currentChatId = null; |
| |
| |
| document.addEventListener('DOMContentLoaded', () => { |
| initializeScrollButtons(); |
| |
| |
| if (chats.length === 0) { |
| createNewChat(); |
| } |
| |
| |
| userInput.addEventListener('keypress', (e) => { |
| if (e.key === 'Enter' && !e.shiftKey) { |
| e.preventDefault(); |
| sendMessage(); |
| } |
| }); |
| |
| userInput.addEventListener('input', () => { |
| const isEmpty = userInput.value.trim() === ''; |
| sendButton.classList.toggle('disabled', isEmpty); |
| }); |
| |
| |
| sendButton.classList.add('disabled'); |
| }); |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function addMessage(text, sender, save = true) { |
| const messageDiv = document.createElement('div'); |
| messageDiv.className = `message ${sender}-message`; |
| |
| const avatar = document.createElement('div'); |
| avatar.className = `avatar ${sender}-avatar`; |
| avatar.textContent = sender === 'user' ? 'U' : 'AI'; |
| |
| const content = document.createElement('div'); |
| content.className = 'message-content'; |
| |
| if (text === 'Thinking...') { |
| content.innerHTML = ` |
| <div class="thinking"> |
| <span>Thinking</span> |
| <div class="loading-dots"> |
| <span></span> |
| <span></span> |
| <span></span> |
| </div> |
| </div>`; |
| } else { |
| content.innerHTML = formatMessage(text); |
| |
| |
| content.querySelectorAll('.copy-button').forEach(button => { |
| button.addEventListener('click', handleCopyClick); |
| }); |
| } |
| |
| messageDiv.appendChild(avatar); |
| messageDiv.appendChild(content); |
| |
| const id = Date.now(); |
| messageDiv.id = `message-${id}`; |
| |
| chatMessages.appendChild(messageDiv); |
| |
| |
| if (save && currentChatId) { |
| const chat = chats.find(c => c.id === currentChatId); |
| if (chat) { |
| chat.messages.push({ content: text, sender }); |
| |
| if (chat.title === 'New Chat' && sender === 'user') { |
| const title = text.slice(0, 30) + (text.length > 30 ? '...' : ''); |
| updateChatTitle(title); |
| } |
| } |
| } |
| |
| |
| const shouldScroll = chatMessages.scrollTop + chatMessages.clientHeight >= chatMessages.scrollHeight - 100; |
| |
| |
| setTimeout(() => { |
| if (shouldScroll) { |
| chatMessages.scrollTo({ |
| top: chatMessages.scrollHeight, |
| behavior: 'smooth' |
| }); |
| } |
| handleScroll(); |
| }, 100); |
| |
| |
| setTimeout(() => { |
| chatMessages.scrollTop = chatMessages.scrollHeight; |
| }, 100); |
| |
| return id; |
| } |
| |
| function formatMessage(text) { |
| const codeBlockRegex = /```(\w*)\n([\s\S]*?)```/g; |
| let formattedText = text; |
| |
| |
| formattedText = formattedText.replace(codeBlockRegex, (match, language, code) => { |
| const highlightedCode = highlightSyntax(code.trim(), language); |
| return ` |
| <div class="code-block" data-language="${language || 'plaintext'}"> |
| <span class="language-label">${language || 'plaintext'}</span> |
| <pre><code>${highlightedCode}</code></pre> |
| <button class="copy-button" data-code="${encodeURIComponent(code.trim())}"> |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| <path d="M8 4v12a2 2 0 002 2h8a2 2 0 002-2V7.242a2 2 0 00-.602-1.43L16.083 2.57A2 2 0 0014.685 2H10a2 2 0 00-2 2z"/> |
| <path d="M16 18v2a2 2 0 01-2 2H6a2 2 0 01-2-2V9a2 2 0 012-2h2"/> |
| </svg> |
| Copy |
| </button> |
| </div> |
| `; |
| }); |
| |
| return formattedText; |
| } |
| |
| function highlightSyntax(code, language) { |
| |
| return code |
| .replace(/&/g, '&') |
| .replace(/</g, '<') |
| .replace(/>/g, '>') |
| |
| .replace(/\b(function|const|let|var|if|else|return|class|import|export|default|new|this|for|while|break|continue)\b/g, '<span class="keyword">$1</span>') |
| |
| .replace(/(".*?"|'.*?'|`.*?`)/g, '<span class="string">$1</span>') |
| |
| .replace(/(\/\/.*|\/\*[\s\S]*?\*\/)/g, '<span class="comment">$1</span>') |
| |
| .replace(/\b(\d+)\b/g, '<span class="number">$1</span>') |
| |
| .replace(/(\w+)\(/g, '<span class="function">$1</span>(') |
| |
| .replace(/\b([A-Z]\w*)\b/g, '<span class="class">$1</span>') |
| |
| .replace(/\.(\w+)\b/g, '.<span class="property">$1</span>'); |
| } |
| |
| function handleCopyClick(event) { |
| const button = event.target.closest('.copy-button'); |
| if (!button) return; |
| |
| const code = decodeURIComponent(button.dataset.code); |
| |
| navigator.clipboard.writeText(code).then(() => { |
| const originalText = button.innerHTML; |
| button.innerHTML = ` |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| <path d="M20 6L9 17l-5-5"/> |
| </svg> |
| Copied! |
| `; |
| button.style.background = '#10B981'; |
| |
| setTimeout(() => { |
| button.innerHTML = originalText; |
| button.style.background = ''; |
| }, 2000); |
| }).catch(err => { |
| console.error('Failed to copy:', err); |
| button.textContent = 'Failed'; |
| }); |
| } |
| |
| async function sendMessage() { |
| const message = userInput.value.trim(); |
| if (!message) return; |
| |
| try { |
| addMessage(message, 'user'); |
| userInput.value = ''; |
| scrollToBottom(true); |
| |
| const loadingId = addMessage('Thinking...', 'ai'); |
| scrollToBottom(true); |
| |
| const response = await fetch('https://api.mistral.ai/v1/chat/completions', { |
| method: 'POST', |
| headers: { |
| 'Content-Type': 'application/json', |
| 'Authorization': `Bearer ${MISTRAL_API_KEY}`, |
| 'Accept': 'application/json' |
| }, |
| body: JSON.stringify({ |
| model: "mistral-small", |
| messages: [ |
| { |
| role: "system", |
| content: "You are a helpful AI assistant. Provide clear and concise responses." |
| }, |
| { |
| role: "user", |
| content: message |
| } |
| ], |
| max_tokens: 1000, |
| temperature: 0.7 |
| }) |
| }); |
| |
| if (!response.ok) { |
| const errorData = await response.json().catch(() => ({})); |
| throw new Error( |
| `API Error (${response.status}): ${errorData.error?.message || 'Unknown error'}` |
| ); |
| } |
| |
| const data = await response.json(); |
| removeMessage(loadingId); |
| |
| if (data.choices && data.choices[0] && data.choices[0].message) { |
| removeMessage(loadingId); |
| addMessage(data.choices[0].message.content, 'ai'); |
| scrollToBottom(); |
| } else { |
| console.error('Unexpected API response:', data); |
| addMessage('Sorry, I received an unexpected response format.', 'ai'); |
| scrollToBottom(); |
| } |
| } catch (error) { |
| console.error('Error details:', error); |
| removeMessage(loadingId); |
| addMessage(`Sorry, I encountered an error: ${error.message}`, 'ai'); |
| scrollToBottom(); |
| } finally { |
| userInput.disabled = false; |
| sendButton.classList.remove('disabled'); |
| userInput.focus(); |
| } |
| } |
| |
| function removeMessage(id) { |
| const message = document.getElementById(`message-${id}`); |
| if (message) { |
| message.remove(); |
| } |
| } |
| |
| function initializeScrollButtons() { |
| const scrollTopBtn = document.getElementById('scroll-top'); |
| const scrollBottomBtn = document.getElementById('scroll-bottom'); |
| const chatMessages = document.getElementById('chat-messages'); |
| |
| chatMessages.addEventListener('scroll', () => { |
| |
| if (chatMessages.scrollTop > 500) { |
| scrollTopBtn.classList.add('visible'); |
| } else { |
| scrollTopBtn.classList.remove('visible'); |
| } |
| |
| |
| const isAtBottom = chatMessages.scrollHeight - chatMessages.scrollTop - chatMessages.clientHeight < 100; |
| if (!isAtBottom) { |
| scrollBottomBtn.classList.add('visible'); |
| } else { |
| scrollBottomBtn.classList.remove('visible'); |
| } |
| }); |
| |
| |
| scrollTopBtn.addEventListener('click', () => { |
| chatMessages.scrollTo({ top: 0, behavior: 'smooth' }); |
| }); |
| |
| |
| scrollBottomBtn.addEventListener('click', () => { |
| chatMessages.scrollTo({ top: chatMessages.scrollHeight, behavior: 'smooth' }); |
| }); |
| } |
| |
| function handleScroll() { |
| const scrollTop = chatMessages.scrollTop; |
| const scrollHeight = chatMessages.scrollHeight; |
| const clientHeight = chatMessages.clientHeight; |
| |
| if (scrollTop > 100) { |
| scrollTopBtn.classList.add('visible'); |
| } else { |
| scrollTopBtn.classList.remove('visible'); |
| } |
| |
| if (scrollTop < lastScrollTop) { |
| scrollCount++; |
| if (scrollCount >= 2) { |
| scrollBottomBtn.classList.add('visible'); |
| } |
| } else { |
| scrollCount = 0; |
| scrollBottomBtn.classList.remove('visible'); |
| } |
| |
| clearTimeout(scrollTimeout); |
| scrollTimeout = setTimeout(() => { |
| scrollCount = 0; |
| }, 1000); |
| |
| lastScrollTop = scrollTop; |
| |
| if (scrollHeight - scrollTop - clientHeight < 20) { |
| scrollBottomBtn.classList.remove('visible'); |
| } |
| } |
| |
| function scrollToTop() { |
| chatMessages.scrollTo({ |
| top: 0, |
| behavior: 'smooth' |
| }); |
| } |
| |
| function scrollToBottom(immediate = false) { |
| const chatMessages = document.getElementById('chat-messages'); |
| if (chatMessages) { |
| const scrollOptions = { |
| top: chatMessages.scrollHeight, |
| behavior: immediate ? 'auto' : 'smooth' |
| }; |
| |
| |
| if (chatMessages.scrollTo) { |
| chatMessages.scrollTo(scrollOptions); |
| } else { |
| chatMessages.scrollTop = chatMessages.scrollHeight; |
| } |
| } |
| } |
| |
| |
| createNewChat(); |
| |
| function createNewChat() { |
| const chatId = Date.now(); |
| const chat = { |
| id: chatId, |
| title: 'New Chat', |
| messages: [] |
| }; |
| |
| chats.push(chat); |
| currentChatId = chatId; |
| |
| |
| clearMessages(); |
| |
| |
| updateChatList(); |
| updateChatTitle('New Chat'); |
| |
| |
| const welcomeMessage = document.createElement('div'); |
| welcomeMessage.className = 'welcome-message'; |
| welcomeMessage.innerHTML = ` |
| <h3>👋 Welcome to Rxple AI Chat Assistant</h3> |
| <p>I'm here to help you with any questions or tasks. Here are some things I can do:</p> |
| <div class="quick-actions"> |
| <button class="quick-action-btn" onclick="sendQuickAction('Tell me a joke')">Tell me a joke</button> |
| <button class="quick-action-btn" onclick="sendQuickAction('Write a poem')">Write a poem</button> |
| <button class="quick-action-btn" onclick="sendQuickAction('Explain quantum physics')">Explain quantum physics</button> |
| <button class="quick-action-btn" onclick="sendQuickAction('Help with coding')">Help with coding</button> |
| </div> |
| `; |
| chatMessages.appendChild(welcomeMessage); |
| } |
| |
| function updateChatList() { |
| const chatList = document.getElementById('chat-list'); |
| chatList.innerHTML = ''; |
| |
| chats.forEach(chat => { |
| const chatItem = document.createElement('div'); |
| chatItem.className = `chat-item ${chat.id === currentChatId ? 'active' : ''}`; |
| chatItem.innerHTML = ` |
| <span>${chat.title}</span> |
| <button class="delete-chat" onclick="deleteChat(${chat.id})"> |
| <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| <path d="M3 6h18"></path> |
| <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"></path> |
| <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path> |
| </svg> |
| </button> |
| `; |
| chatItem.onclick = (e) => { |
| if (!e.target.closest('.delete-chat')) { |
| switchChat(chat.id); |
| } |
| }; |
| chatList.appendChild(chatItem); |
| }); |
| } |
| |
| function deleteChat(chatId) { |
| if (confirm('Are you sure you want to delete this chat?')) { |
| chats = chats.filter(chat => chat.id !== chatId); |
| if (currentChatId === chatId) { |
| if (chats.length > 0) { |
| switchChat(chats[0].id); |
| } else { |
| createNewChat(); |
| } |
| } |
| updateChatList(); |
| } |
| } |
| |
| function switchChat(chatId) { |
| currentChatId = chatId; |
| const chat = chats.find(c => c.id === chatId); |
| clearMessages(); |
| chat.messages.forEach(msg => { |
| addMessage(msg.content, msg.sender, false); |
| }); |
| updateChatTitle(chat.title); |
| updateChatList(); |
| } |
| |
| function updateChatTitle(title) { |
| document.getElementById('current-chat-title').textContent = title; |
| if (currentChatId) { |
| const chat = chats.find(c => c.id === currentChatId); |
| if (chat) { |
| chat.title = title; |
| updateChatList(); |
| } |
| } |
| } |
| |
| function clearMessages() { |
| chatMessages.innerHTML = ''; |
| } |
| |
| |
| const menuButton = document.getElementById('menu-button'); |
| const sidebar = document.querySelector('.sidebar'); |
| const overlay = document.getElementById('overlay'); |
| |
| function checkScreenSize() { |
| if (window.innerWidth <= 768) { |
| menuButton.style.display = 'flex'; |
| menuButton.style.opacity = sidebar.classList.contains('active') ? '0' : '1'; |
| } else { |
| menuButton.style.display = 'none'; |
| menuButton.style.opacity = '1'; |
| sidebar.classList.remove('active'); |
| overlay.classList.remove('active'); |
| } |
| } |
| |
| menuButton.addEventListener('click', () => { |
| sidebar.classList.toggle('active'); |
| overlay.classList.toggle('active'); |
| |
| menuButton.style.opacity = sidebar.classList.contains('active') ? '0' : '1'; |
| }); |
| |
| overlay.addEventListener('click', () => { |
| sidebar.classList.remove('active'); |
| overlay.classList.remove('active'); |
| |
| menuButton.style.opacity = '1'; |
| }); |
| |
| |
| window.addEventListener('load', checkScreenSize); |
| window.addEventListener('resize', checkScreenSize); |
| |
| |
| document.addEventListener('click', (e) => { |
| if (window.innerWidth <= 768 && |
| !e.target.closest('.sidebar') && |
| !e.target.closest('.menu-button') && |
| sidebar.classList.contains('active')) { |
| sidebar.classList.remove('active'); |
| overlay.classList.remove('active'); |
| } |
| }); |
| |
| |
| function updateScrollButtonPositions() { |
| const inputHeight = document.querySelector('.input-container').offsetHeight; |
| const scrollTopBtn = document.getElementById('scroll-top'); |
| const scrollBottomBtn = document.getElementById('scroll-bottom'); |
| |
| if (window.innerWidth <= 768) { |
| scrollBottomBtn.style.bottom = `${inputHeight + 20}px`; |
| scrollTopBtn.style.bottom = `${inputHeight + 80}px`; |
| } else { |
| scrollBottomBtn.style.bottom = '40px'; |
| scrollTopBtn.style.bottom = '100px'; |
| } |
| } |
| |
| |
| window.addEventListener('load', updateScrollButtonPositions); |
| window.addEventListener('resize', updateScrollButtonPositions); |
| |
| |
| const style = document.createElement('style'); |
| style.textContent = ` |
| .menu-button { |
| transition: opacity 0.3s ease; |
| } |
| `; |
| document.head.appendChild(style); |
| |
| function sendQuickAction(text) { |
| userInput.value = text; |
| sendMessage(); |
| } |
| |
| |
| const settingsButton = document.getElementById('settings-button'); |
| const settingsModal = document.getElementById('settings-modal'); |
| const closeSettings = document.querySelector('.close-settings'); |
| |
| settingsButton.addEventListener('click', () => { |
| settingsModal.classList.add('active'); |
| }); |
| |
| closeSettings.addEventListener('click', () => { |
| settingsModal.classList.remove('active'); |
| }); |
| |
| |
| settingsModal.addEventListener('click', (e) => { |
| if (e.target === settingsModal) { |
| settingsModal.classList.remove('active'); |
| } |
| }); |
| |
| |
| const themeButtons = document.querySelectorAll('.theme-btn'); |
| themeButtons.forEach(button => { |
| button.addEventListener('click', () => { |
| themeButtons.forEach(btn => btn.classList.remove('active')); |
| button.classList.add('active'); |
| |
| }); |
| }); |
| |
| function startChat() { |
| document.getElementById('landing-page').classList.add('hidden'); |
| |
| } |
| |
| |
| function setMobileHeight() { |
| const vh = window.innerHeight * 0.01; |
| document.documentElement.style.setProperty('--vh', `${vh}px`); |
| } |
| |
| window.addEventListener('load', setMobileHeight); |
| window.addEventListener('resize', setMobileHeight); |
| </script> |
| </body> |
| </html> |
|
|