code-slicer commited on
Commit
3e0c8a2
Β·
verified Β·
1 Parent(s): a5a3c1b

Update css.py

Browse files
Files changed (1) hide show
  1. css.py +35 -20
css.py CHANGED
@@ -4,40 +4,58 @@ import re
4
  import uuid
5
  import pandas as pd
6
  import time
 
7
 
8
  # ────────────────── 말풍선 생성 ν•¨μˆ˜
9
  # 색상 μ •μ˜
10
  PRIMARY_USER = "#e2f6e8"
11
  PRIMARY_BOT = "#f6f6f6"
12
 
 
 
 
 
 
 
 
 
 
 
13
  def render_message(
14
  message: str,
15
  sender: str = "bot",
16
  chips: list[str] | None = None,
17
  key: str | None = None,
18
  *,
19
- animated: bool = False, # ← μΆ”κ°€: νƒ€μž 효과 ON/OFF
20
- speed_cps: int = 40, # ← μΆ”κ°€: μ΄ˆλ‹Ή κΈ€μž 수
21
- by_word: bool = False, # ← μΆ”κ°€: 단어 λ‹¨μœ„ 좜λ ₯
22
  ) -> str | None:
23
- """
24
- - `message` : ν‘œμ‹œν•  ν…μŠ€νŠΈ (HTML ν—ˆμš©)
25
- - `sender` : "user" | "bot"
26
- - `chips` : λ²„νŠΌ ν˜•νƒœλ‘œ 보여 쀄 λ¬Έμžμ—΄ 리슀트
27
- - return : μ‚¬μš©μžκ°€ ν΄λ¦­ν•œ μΉ©(λ¬Έμžμ—΄) λ˜λŠ” None
28
- """
29
- color = PRIMARY_USER if sender == "user" else PRIMARY_BOT
30
  align = "right" if sender == "user" else "left"
 
 
 
31
  message = str(message).rstrip()
 
 
 
 
 
32
 
33
  # 곡톡 풍선 래퍼
34
  def _wrap(html_inner: str) -> str:
35
  return (
36
  f'''<div style="text-align:{align}; margin:6px 0;">'''
37
- f'''<p style="font-size:13px;"></p>'''
38
- f'''<span style="background:{color}; padding:10px 14px; border-radius:12px;'''
39
- f'''display:inline-block; max-width:80%; font-size:13px; line-height:1.45;'''
40
- f'''word-break:break-word;">{html_inner}</span></div>'''
41
  )
42
 
43
  if not animated:
@@ -45,24 +63,21 @@ def render_message(
45
  else:
46
  ph = st.empty()
47
  buf = ""
48
-
49
- # νƒœκ·ΈλŠ” μ¦‰μ‹œ μΆ”κ°€, ν…μŠ€νŠΈλ§Œ 점진 좜λ ₯(νƒœκ·Έ 반쯀 잘렀 λ³΄μ΄λŠ” ν˜„μƒ μ΅œμ†Œν™”)
50
  segments = re.split(r'(<[^>]+>)', message)
51
  delay = max(0.005, 1.0 / max(1, speed_cps))
52
-
53
  for seg in segments:
54
  if not seg:
55
  continue
56
  if seg.startswith("<") and seg.endswith(">"):
57
- # νƒœκ·ΈλŠ” ꡬ쑰 μœ μ§€ μœ„ν•΄ ν•œ λ²ˆμ— μΆ”κ°€
58
  buf += seg
59
  ph.markdown(_wrap(buf), unsafe_allow_html=True)
60
  else:
61
- if by_word:
62
  for w in seg.split(" "):
63
  buf = (buf + " " + w).strip()
64
  ph.markdown(_wrap(buf), unsafe_allow_html=True)
65
- time.sleep(delay * 5) # 단어 λ‹¨μœ„λŠ” 쑰금 더 μ—¬μœ 
66
  else:
67
  for ch in seg:
68
  buf += ch
 
4
  import uuid
5
  import pandas as pd
6
  import time
7
+ from datetime import datetime # νƒ€μž„μŠ€νƒ¬ν”„μš©
8
 
9
  # ────────────────── 말풍선 생성 ν•¨μˆ˜
10
  # 색상 μ •μ˜
11
  PRIMARY_USER = "#e2f6e8"
12
  PRIMARY_BOT = "#f6f6f6"
13
 
14
+ # β‘’ 말풍선 ν…Œλ§ˆ νŒ”λ ˆνŠΈ & 헬퍼
15
+ THEMES = {
16
+ "민트": {"user": "#DCFCE7", "bot": "#E0F2FE"},
17
+ "라벀더": {"user": "#EDE9FE", "bot": "#E9D5FF"},
18
+ "λͺ¨λ…Έ": {"user": "#EFEFEF", "bot": "#F5F5F5"},
19
+ }
20
+ def _get_colors():
21
+ theme = st.session_state.get("bubble_theme", "민트")
22
+ return THEMES.get(theme, THEMES["민트"])
23
+
24
  def render_message(
25
  message: str,
26
  sender: str = "bot",
27
  chips: list[str] | None = None,
28
  key: str | None = None,
29
  *,
30
+ animated: bool = False, # νƒ€μž 효과 ON/OFF
31
+ speed_cps: int = 40, # μ΄ˆλ‹Ή κΈ€μž 수
32
+ by_word: bool = False, # 단어 λ‹¨μœ„ 좜λ ₯
33
  ) -> str | None:
34
+ import re, time
35
+ # β‘’ ν…Œλ§ˆ/콀팩트 κ°’ 읽기
36
+ palette = _get_colors()
37
+ dense = st.session_state.get("dense_mode", False)
38
+ show_time = st.session_state.get("show_time", False) and sender == "bot" # β‘£ λ΄‡λ§Œ μ‹œκ°„ ν‘œμ‹œ
39
+
40
+ color = palette["user"] if sender == "user" else palette["bot"]
41
  align = "right" if sender == "user" else "left"
42
+ pad = "6px 10px" if dense else "10px 14px" # β‘’ 콀팩트 λͺ¨λ“œ νŒ¨λ”©
43
+ fsz = "12px" if dense else "13px" # β‘’ 콀팩트 λͺ¨λ“œ 폰트
44
+
45
  message = str(message).rstrip()
46
+ # β‘£ νƒ€μž„μŠ€νƒ¬ν”„ HTML
47
+ ts_html = (
48
+ f'<div style="font-size:11px;color:#888;margin-top:4px;">{datetime.now().strftime("%H:%M")}</div>'
49
+ if show_time else ""
50
+ )
51
 
52
  # 곡톡 풍선 래퍼
53
  def _wrap(html_inner: str) -> str:
54
  return (
55
  f'''<div style="text-align:{align}; margin:6px 0;">'''
56
+ f'''<span style="background:{color}; padding:{pad}; border-radius:12px;'''
57
+ f'''display:inline-block; max-width:80%; font-size:{fsz}; line-height:1.45;'''
58
+ f'''word-break:break-word;">{html_inner}{ts_html}</span></div>'''
 
59
  )
60
 
61
  if not animated:
 
63
  else:
64
  ph = st.empty()
65
  buf = ""
66
+ # νƒœκ·ΈλŠ” μ¦‰μ‹œ, ν…μŠ€νŠΈλ§Œ 점진 좜λ ₯(νƒœκ·Έ 깨짐 λ°©μ§€)
 
67
  segments = re.split(r'(<[^>]+>)', message)
68
  delay = max(0.005, 1.0 / max(1, speed_cps))
 
69
  for seg in segments:
70
  if not seg:
71
  continue
72
  if seg.startswith("<") and seg.endswith(">"):
 
73
  buf += seg
74
  ph.markdown(_wrap(buf), unsafe_allow_html=True)
75
  else:
76
+ if by_word or st.session_state.get("type_by_word", False):
77
  for w in seg.split(" "):
78
  buf = (buf + " " + w).strip()
79
  ph.markdown(_wrap(buf), unsafe_allow_html=True)
80
+ time.sleep(delay * 5)
81
  else:
82
  for ch in seg:
83
  buf += ch