andrewwda commited on
Commit
c09349d
·
verified ·
1 Parent(s): 3f13721

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +28 -398
templates/index.html CHANGED
@@ -2,7 +2,7 @@
2
  <html lang="id">
3
  <head>
4
  <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes, viewport-fit=cover">
6
  <meta name="theme-color" content="#0a0c15">
7
  <meta name="mobile-web-app-capable" content="yes">
8
  <meta name="apple-mobile-web-app-capable" content="yes">
@@ -16,12 +16,16 @@
16
  font-family: 'Segoe UI', 'Poppins', 'Inter', system-ui, -apple-system, sans-serif;
17
  }
18
 
19
- body {
20
- background: #0a0c15;
21
- overflow: hidden;
22
- height: 100dvh;
23
  width: 100%;
24
- /* TAMBAHAN UNTUK ANDROID */
 
 
 
 
 
25
  -webkit-tap-highlight-color: transparent;
26
  touch-action: pan-x pan-y;
27
  }
@@ -32,9 +36,9 @@
32
  .app {
33
  display: flex;
34
  flex-direction: column;
35
- height: 100vh;
36
- min-height: 100dvh;
37
  width: 100%;
 
38
  }
39
 
40
  /* =========================
@@ -51,7 +55,7 @@
51
  position: fixed;
52
  left: -320px;
53
  top: 0;
54
- height: 100vh;
55
  z-index: 999;
56
  transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1);
57
  border-right: 1px solid rgba(0, 255, 255, 0.15);
@@ -83,7 +87,6 @@
83
  box-shadow: 0 0 15px rgba(0, 212, 255, 0.4);
84
  }
85
 
86
- /* GAMBAR LOGO UNTUK SIDEBAR */
87
  .sidebar-logo-img {
88
  width: 55px;
89
  height: 55px;
@@ -154,7 +157,9 @@
154
  .overlay {
155
  position: fixed;
156
  width: 100%;
157
- height: 100vh;
 
 
158
  background: rgba(0, 0, 0, 0.6);
159
  backdrop-filter: blur(3px);
160
  z-index: 998;
@@ -172,15 +177,16 @@
172
  display: flex;
173
  flex-direction: column;
174
  width: 100%;
175
- height: 100dvh;
176
  overflow: hidden;
177
  background: #0a0c15;
178
- }
179
 
180
  /* =========================
181
  TOPBAR - NEO MASCULINE
182
  ========================= */
183
  .topbar {
 
184
  height: 80px;
185
  background: rgba(10, 12, 21, 0.95);
186
  backdrop-filter: blur(10px);
@@ -190,6 +196,7 @@
190
  color: #e8edff;
191
  border-bottom: 1px solid rgba(0, 212, 255, 0.3);
192
  box-shadow: 0 2px 20px rgba(0, 0, 0, 0.3);
 
193
  }
194
 
195
  .menu-btn {
@@ -200,13 +207,8 @@
200
  color: #00d4ff;
201
  }
202
 
203
- .menu-btn:hover {
204
- transform: scale(1.1);
205
- text-shadow: 0 0 8px #00d4ff;
206
- }
207
-
208
- /* LOGO AREA - DENGAN GAMBAR */
209
  .logo {
 
210
  width: 50px;
211
  height: 50px;
212
  border-radius: 14px;
@@ -226,11 +228,6 @@
226
  border-radius: 14px;
227
  }
228
 
229
- /* Fallback jika gambar tidak ada - pake icon keren */
230
- .logo-icon {
231
- font-size: 28px;
232
- }
233
-
234
  .title h1 {
235
  font-size: 24px;
236
  letter-spacing: -0.5px;
@@ -259,10 +256,9 @@
259
  CHAT AREA - GLASS
260
  ========================= */
261
  .chat-area {
262
- flex: 1;
263
  overflow-y: auto;
264
  padding: 15px;
265
- min-height: 0;
266
  background: linear-gradient(180deg, #0a0c15 0%, #0f111a 100%);
267
  -webkit-overflow-scrolling: touch;
268
  }
@@ -280,7 +276,7 @@
280
  }
281
 
282
  .message {
283
- max-width: 75%;
284
  padding: 14px 20px;
285
  border-radius: 20px;
286
  margin-bottom: 20px;
@@ -308,6 +304,7 @@
308
  color: #d0d9ff;
309
  border-bottom-left-radius: 6px;
310
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
 
311
  }
312
 
313
  .user {
@@ -323,6 +320,7 @@
323
  INPUT - CYBER
324
  ========================= */
325
  .input-area {
 
326
  display: flex;
327
  padding: 20px 30px;
328
  gap: 15px;
@@ -337,7 +335,7 @@
337
  background: rgba(18, 22, 40, 0.8);
338
  border-radius: 18px;
339
  padding: 16px 22px;
340
- font-size: 16px;
341
  outline: none;
342
  color: #e8edff;
343
  transition: all 0.2s;
@@ -353,6 +351,7 @@
353
  }
354
 
355
  button.send {
 
356
  border: none;
357
  background: linear-gradient(135deg, #00d4ff, #0099ff);
358
  color: #0a0c15;
@@ -364,373 +363,4 @@
364
  transition: 0.2s;
365
  display: flex;
366
  align-items: center;
367
- gap: 8px;
368
- }
369
-
370
- button.send:hover {
371
- transform: scale(1.02);
372
- box-shadow: 0 0 15px rgba(0, 212, 255, 0.5);
373
- }
374
-
375
- /* =========================
376
- RESPONSIVE UNTUK ANDROID
377
- ========================= */
378
- @media (max-width: 768px) {
379
- .sidebar {
380
- width: 85%;
381
- }
382
- .message {
383
- max-width: 90%;
384
- font-size: 15px;
385
- }
386
- .topbar {
387
- padding: 0 20px;
388
- }
389
- .input-area {
390
- padding: 15px 20px;
391
- }
392
- button.send {
393
- padding: 0 24px;
394
- }
395
- }
396
-
397
- /* TAMBAHAN KHUSUS UNTUK ANDROID */
398
- @media (max-width: 480px) {
399
- .topbar {
400
- height: 65px;
401
- padding: 0 15px;
402
- }
403
- .menu-btn {
404
- font-size: 24px;
405
- margin-right: 12px;
406
- }
407
- .logo {
408
- width: 40px;
409
- height: 40px;
410
- }
411
- .title h1 {
412
- font-size: 18px;
413
- }
414
- .title p {
415
- font-size: 10px;
416
- }
417
- .chat-area {
418
- padding: 15px;
419
- }
420
- .message {
421
- padding: 10px 14px;
422
- font-size: 14px;
423
- max-width: 95%;
424
- }
425
- .input-area {
426
- padding: 10px 15px;
427
- gap: 10px;
428
- }
429
- input {
430
- padding: 12px 16px;
431
- font-size: 14px;
432
- }
433
- button.send {
434
- padding: 0 18px;
435
- font-size: 14px;
436
- }
437
- .sidebar {
438
- width: 80%;
439
- padding: 20px 15px;
440
- }
441
- .sidebar-logo {
442
- width: 45px;
443
- height: 45px;
444
- font-size: 24px;
445
- }
446
- .sidebar h2 {
447
- font-size: 22px;
448
- }
449
- .new-chat {
450
- padding: 12px;
451
- font-size: 14px;
452
- }
453
- .history-item {
454
- padding: 12px 15px;
455
- font-size: 13px;
456
- }
457
- }
458
-
459
- /* TAMBAHAN UNTUK LANDSCAPE MODE ANDROID */
460
- @media (max-width: 900px) and (orientation: landscape) {
461
- .topbar {
462
- height: 55px;
463
- }
464
- .chat-area {
465
- padding: 10px 20px;
466
- }
467
- .message {
468
- margin-bottom: 10px;
469
- }
470
- .input-area {
471
- padding: 8px 15px;
472
- }
473
- input {
474
- padding: 10px 16px;
475
- }
476
- button.send {
477
- padding: 0 20px;
478
- }
479
- }
480
- </style>
481
- </head>
482
- <body>
483
-
484
- <div class="overlay" id="overlay" onclick="closeSidebar()"></div>
485
-
486
- <div class="app">
487
-
488
- <!-- SIDEBAR -->
489
- <div class="sidebar" id="sidebar">
490
- <div class="sidebar-header">
491
- <div class="sidebar-logo" id="sidebarLogo">
492
- <!-- Logo akan diisi JS -->
493
- 🐱‍👤
494
- </div>
495
- <div>
496
- <h2>ChibiCat</h2>
497
- <p>Neo Intelligence</p>
498
- </div>
499
- </div>
500
- <button class="new-chat" onclick="createNewChat()">+ New Chat</button>
501
- <div class="chat-history" id="chatHistory"></div>
502
- </div>
503
-
504
- <!-- MAIN -->
505
- <div class="main">
506
- <!-- TOPBAR -->
507
- <div class="topbar">
508
- <div class="menu-btn" onclick="openSidebar()">☰</div>
509
- <div class="logo" id="mainLogo">
510
- <!-- Logo akan diisi JS -->
511
- 🐱‍👤
512
- </div>
513
- <div class="title">
514
- <h1>ChibiCat AI</h1>
515
- <p>Online | Neo Mode</p>
516
- </div>
517
- </div>
518
-
519
- <!-- CHAT AREA -->
520
- <div class="chat-area" id="chatArea">
521
- <div class="message bot">
522
- <span style="font-weight: bold;">⚡ ChibiCat Neo</span><br>
523
- Halo bro! Ada yang bisa gue bantu? 🔥😎
524
- </div>
525
- </div>
526
-
527
- <!-- INPUT -->
528
- <div class="input-area">
529
- <input type="text" id="messageInput" placeholder="Ketik pesan bro..." />
530
- <button class="send" onclick="sendMessage()">
531
- <span></span> Kirim
532
- </button>
533
- </div>
534
- </div>
535
- </div>
536
-
537
- <script>
538
- let currentChatId = null
539
-
540
- // =========================================
541
- // KONFIGURASI LOGO
542
- // =========================================
543
- // Pilih salah satu mode logo:
544
- // mode: "emoji" = pake emoji keren
545
- // mode: "image" = pake gambar dari URL
546
- // mode: "svg" = pake karakter ASCII keren
547
-
548
- const LOGO_CONFIG = {
549
- mode: "image", // "emoji", "image", atau "svg"
550
- emoji: "🐱‍🚀", // emoji untuk mode emoji
551
- imageUrl: "/static/logo.png", // cyber cat image
552
- imageUrl2: "https://cdn-icons-png.flaticon.com/512/1998/1998592.png", // alternative robot cat
553
- svgIcon: "⚡🐱⚡" // untuk mode svg/ascii
554
- }
555
-
556
- function initLogos() {
557
- const sidebarLogo = document.getElementById("sidebarLogo")
558
- const mainLogo = document.getElementById("mainLogo")
559
-
560
- if (LOGO_CONFIG.mode === "emoji") {
561
- // Mode Emoji - simple tapi keren
562
- sidebarLogo.innerHTML = LOGO_CONFIG.emoji
563
- sidebarLogo.style.fontSize = "32px"
564
- sidebarLogo.style.background = "linear-gradient(135deg, #00d4ff, #0099ff)"
565
-
566
- mainLogo.innerHTML = LOGO_CONFIG.emoji
567
- mainLogo.style.fontSize = "28px"
568
- mainLogo.style.background = "linear-gradient(135deg, #00d4ff, #0099ff)"
569
-
570
- } else if (LOGO_CONFIG.mode === "image") {
571
- // Mode Gambar - lebih profesional
572
- sidebarLogo.innerHTML = `<img src="${LOGO_CONFIG.imageUrl}" class="sidebar-logo-img" style="width:100%;height:100%;border-radius:16px;object-fit:cover;" onerror="this.src='${LOGO_CONFIG.imageUrl2}'">`
573
- sidebarLogo.style.background = "transparent"
574
- sidebarLogo.style.padding = "0"
575
- sidebarLogo.style.boxShadow = "0 0 15px rgba(0,212,255,0.4)"
576
-
577
- mainLogo.innerHTML = `<img src="${LOGO_CONFIG.imageUrl}" class="logo-img" style="width:100%;height:100%;border-radius:14px;object-fit:cover;" onerror="this.src='${LOGO_CONFIG.imageUrl2}'">`
578
- mainLogo.style.background = "transparent"
579
- mainLogo.style.padding = "0"
580
-
581
- } else {
582
- // Mode SVG/ASCII - modern tech look
583
- sidebarLogo.innerHTML = LOGO_CONFIG.svgIcon
584
- sidebarLogo.style.fontSize = "28px"
585
- sidebarLogo.style.fontWeight = "bold"
586
- sidebarLogo.style.letterSpacing = "2px"
587
-
588
- mainLogo.innerHTML = LOGO_CONFIG.svgIcon
589
- mainLogo.style.fontSize = "24px"
590
- mainLogo.style.fontWeight = "bold"
591
- }
592
- }
593
-
594
- function openSidebar() {
595
- document.getElementById("sidebar").classList.add("active")
596
- document.getElementById("overlay").classList.add("active")
597
- }
598
-
599
- function closeSidebar() {
600
- document.getElementById("sidebar").classList.remove("active")
601
- document.getElementById("overlay").classList.remove("active")
602
- }
603
-
604
- async function createNewChat() {
605
- const response = await fetch("/new_chat", { method: "POST" })
606
- const data = await response.json()
607
- currentChatId = data.chat_id
608
- document.getElementById("chatArea").innerHTML = `
609
- <div class="message bot">
610
- <span style="font-weight: bold;">⚡ ChibiCat Neo</span><br>
611
- Halo bro! Ada yang bisa gue bantu? 🔥😎
612
- </div>
613
- `
614
- loadChats()
615
- closeSidebar()
616
- }
617
-
618
- async function loadChats() {
619
- const response = await fetch("/get_chats")
620
- const chats = await response.json()
621
- const history = document.getElementById("chatHistory")
622
- history.innerHTML = ""
623
- chats.forEach(chat => {
624
- history.innerHTML += `
625
- <div class="history-item" onclick="loadChat('${chat.chat_id}')">
626
- 💬 ${chat.title}
627
- </div>
628
- `
629
- })
630
- }
631
-
632
- async function loadChat(chatId) {
633
- currentChatId = chatId
634
- const response = await fetch(`/load_chat/${chatId}`)
635
- const messages = await response.json()
636
- const chatArea = document.getElementById("chatArea")
637
- chatArea.innerHTML = ""
638
- messages.forEach(msg => {
639
- const role = msg.role === "user" ? "user" : "bot"
640
- chatArea.innerHTML += `<div class="message ${role}">${msg.content}</div>`
641
- })
642
- closeSidebar()
643
- }
644
-
645
- async function sendMessage() {
646
- const input = document.getElementById("messageInput")
647
- const message = input.value.trim()
648
- if (message === "") return
649
-
650
- const chatArea = document.getElementById("chatArea")
651
-
652
- chatArea.innerHTML += `<div class="message user">${escapeHtml(message)}</div>`
653
- input.value = ""
654
- chatArea.scrollTop = chatArea.scrollHeight
655
-
656
- try {
657
- const response = await fetch("/chat", {
658
- method: "POST",
659
- headers: { "Content-Type": "application/json" },
660
- body: JSON.stringify({ message: message })
661
- })
662
- const data = await response.json()
663
- chatArea.innerHTML += `<div class="message bot">${escapeHtml(data.reply)}</div>`
664
- chatArea.scrollTop = chatArea.scrollHeight
665
- loadChats()
666
- } catch (error) {
667
- chatArea.innerHTML += `<div class="message bot">⚠️ Server error, coba lagi bro 😭</div>`
668
- }
669
- }
670
-
671
- // TAMBAHAN: Fungsi untuk menghindari XSS dan support emoji di Android
672
- function escapeHtml(text) {
673
- const div = document.createElement('div')
674
- div.textContent = text
675
- return div.innerHTML
676
- }
677
-
678
- // TAMBAHAN: Fix untuk keyboard Android
679
- function fixAndroidKeyboard() {
680
- const input = document.getElementById("messageInput")
681
- if (input) {
682
- input.addEventListener("focus", function() {
683
- setTimeout(() => {
684
- document.querySelector('.chat-area').scrollTop = document.querySelector('.chat-area').scrollHeight
685
- }, 300)
686
- })
687
- }
688
- }
689
-
690
- // TAMBAHAN: Deteksi Android dan tambah kelas khusus
691
- function detectAndroid() {
692
- const userAgent = navigator.userAgent.toLowerCase()
693
- const isAndroid = userAgent.indexOf("android") > -1
694
-
695
- if (isAndroid) {
696
- document.body.classList.add("android-device")
697
- console.log("✅ Android device detected - optimized layout")
698
- }
699
- }
700
-
701
- document.getElementById("messageInput").addEventListener("keypress", function(e) {
702
- if (e.key === "Enter") sendMessage()
703
- })
704
-
705
- // TAMBAHAN: Swipe gesture untuk Android (geser kanan buka sidebar)
706
- let touchStartX = 0
707
- let touchEndX = 0
708
-
709
- document.addEventListener('touchstart', function(e) {
710
- touchStartX = e.changedTouches[0].screenX
711
- }, false)
712
-
713
- document.addEventListener('touchend', function(e) {
714
- touchEndX = e.changedTouches[0].screenX
715
- const swipeDistance = touchEndX - touchStartX
716
-
717
- // Geser kanan lebih dari 50px untuk buka sidebar
718
- if (swipeDistance > 50 && touchStartX < 50) {
719
- openSidebar()
720
- }
721
-
722
- // Geser kiri lebih dari 50px untuk tutup sidebar
723
- if (swipeDistance < -50) {
724
- closeSidebar()
725
- }
726
- }, false)
727
-
728
- // Inisialisasi logo saat halaman load
729
- initLogos()
730
- loadChats()
731
- detectAndroid()
732
- fixAndroidKeyboard()
733
- </script>
734
-
735
- </body>
736
- </html>
 
2
  <html lang="id">
3
  <head>
4
  <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
6
  <meta name="theme-color" content="#0a0c15">
7
  <meta name="mobile-web-app-capable" content="yes">
8
  <meta name="apple-mobile-web-app-capable" content="yes">
 
16
  font-family: 'Segoe UI', 'Poppins', 'Inter', system-ui, -apple-system, sans-serif;
17
  }
18
 
19
+ /* FIX 2: Set html dan body ke 100% mutlak dengan background supaya tidak ada background putih yang bocor */
20
+ html, body {
21
+ height: 100%;
 
22
  width: 100%;
23
+ background-color: #0a0c15;
24
+ overflow: hidden;
25
+ }
26
+
27
+ body {
28
+ height: 100dvh; /* Tetap pertahankan dvh untuk browser modern */
29
  -webkit-tap-highlight-color: transparent;
30
  touch-action: pan-x pan-y;
31
  }
 
36
  .app {
37
  display: flex;
38
  flex-direction: column;
39
+ height: 100%;
 
40
  width: 100%;
41
+ position: relative;
42
  }
43
 
44
  /* =========================
 
55
  position: fixed;
56
  left: -320px;
57
  top: 0;
58
+ height: 100%;
59
  z-index: 999;
60
  transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1);
61
  border-right: 1px solid rgba(0, 255, 255, 0.15);
 
87
  box-shadow: 0 0 15px rgba(0, 212, 255, 0.4);
88
  }
89
 
 
90
  .sidebar-logo-img {
91
  width: 55px;
92
  height: 55px;
 
157
  .overlay {
158
  position: fixed;
159
  width: 100%;
160
+ height: 100%;
161
+ top: 0;
162
+ left: 0;
163
  background: rgba(0, 0, 0, 0.6);
164
  backdrop-filter: blur(3px);
165
  z-index: 998;
 
177
  display: flex;
178
  flex-direction: column;
179
  width: 100%;
180
+ height: 100%; /* FIX 3: Pastikan .main selalu 100% mengikuti parent */
181
  overflow: hidden;
182
  background: #0a0c15;
183
+ }
184
 
185
  /* =========================
186
  TOPBAR - NEO MASCULINE
187
  ========================= */
188
  .topbar {
189
+ flex-shrink: 0; /* FIX 4: Kunci flex supaya topbar tidak ikutan tertekan/mengecil */
190
  height: 80px;
191
  background: rgba(10, 12, 21, 0.95);
192
  backdrop-filter: blur(10px);
 
196
  color: #e8edff;
197
  border-bottom: 1px solid rgba(0, 212, 255, 0.3);
198
  box-shadow: 0 2px 20px rgba(0, 0, 0, 0.3);
199
+ z-index: 10;
200
  }
201
 
202
  .menu-btn {
 
207
  color: #00d4ff;
208
  }
209
 
 
 
 
 
 
 
210
  .logo {
211
+ flex-shrink: 0;
212
  width: 50px;
213
  height: 50px;
214
  border-radius: 14px;
 
228
  border-radius: 14px;
229
  }
230
 
 
 
 
 
 
231
  .title h1 {
232
  font-size: 24px;
233
  letter-spacing: -0.5px;
 
256
  CHAT AREA - GLASS
257
  ========================= */
258
  .chat-area {
259
+ flex: 1 1 0%; /* FIX 5: Aturan flex terbaik untuk scroll-area mobile */
260
  overflow-y: auto;
261
  padding: 15px;
 
262
  background: linear-gradient(180deg, #0a0c15 0%, #0f111a 100%);
263
  -webkit-overflow-scrolling: touch;
264
  }
 
276
  }
277
 
278
  .message {
279
+ max-width: 85%;
280
  padding: 14px 20px;
281
  border-radius: 20px;
282
  margin-bottom: 20px;
 
304
  color: #d0d9ff;
305
  border-bottom-left-radius: 6px;
306
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
307
+ align-self: flex-start;
308
  }
309
 
310
  .user {
 
320
  INPUT - CYBER
321
  ========================= */
322
  .input-area {
323
+ flex-shrink: 0; /* FIX 6: Kunci flex supaya input area selalu di bawah & dimensinya tetap */
324
  display: flex;
325
  padding: 20px 30px;
326
  gap: 15px;
 
335
  background: rgba(18, 22, 40, 0.8);
336
  border-radius: 18px;
337
  padding: 16px 22px;
338
+ font-size: 16px; /* Mencegah auto-zoom di iOS */
339
  outline: none;
340
  color: #e8edff;
341
  transition: all 0.2s;
 
351
  }
352
 
353
  button.send {
354
+ flex-shrink: 0;
355
  border: none;
356
  background: linear-gradient(135deg, #00d4ff, #0099ff);
357
  color: #0a0c15;
 
363
  transition: 0.2s;
364
  display: flex;
365
  align-items: center;
366
+ gap: 8px;