Spaces:
Sleeping
Sleeping
Update pages/draw_page.py
Browse files- pages/draw_page.py +157 -17
pages/draw_page.py
CHANGED
|
@@ -6,30 +6,166 @@ import io
|
|
| 6 |
import base64
|
| 7 |
from datetime import datetime
|
| 8 |
|
| 9 |
-
# ---
|
| 10 |
THEMES = {
|
| 11 |
"boy": {
|
| 12 |
"primary_background": "#D0E4FF",
|
| 13 |
-
"secondary_background": "#
|
| 14 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
}
|
| 16 |
}
|
| 17 |
|
| 18 |
-
theme
|
| 19 |
-
|
| 20 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
<style>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
.stApp {{
|
| 23 |
-
background-color:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
}}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
.stButton>button {{
|
| 26 |
-
background-color:
|
| 27 |
-
color: white;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
}}
|
| 29 |
</style>
|
| 30 |
-
""",
|
| 31 |
-
|
| 32 |
-
|
|
|
|
|
|
|
| 33 |
|
| 34 |
# ---------------------- Initialize Session State ----------------------
|
| 35 |
if "saved_drawings" not in st.session_state:
|
|
@@ -65,6 +201,7 @@ def draw_page():
|
|
| 65 |
|
| 66 |
# Save drawing if user clicks
|
| 67 |
if st.button("💾 Save Drawing"):
|
|
|
|
| 68 |
if canvas_result.image_data is not None and canvas_result.image_data.sum() > 0:
|
| 69 |
drawing_data = {
|
| 70 |
"image": canvas_result.image_data,
|
|
@@ -79,18 +216,21 @@ def draw_page():
|
|
| 79 |
|
| 80 |
# Show saved drawings
|
| 81 |
if st.session_state.saved_drawings:
|
| 82 |
-
st.subheader("🖼 Your Saved Drawings")
|
| 83 |
for i, saved in enumerate(st.session_state.saved_drawings):
|
| 84 |
-
st.markdown(f"*Drawing {i + 1} - {saved['timestamp']}*")
|
| 85 |
st.image(saved["image"])
|
| 86 |
|
| 87 |
# Clear saved drawings with confirmation
|
| 88 |
-
with st.expander("⚠ Clear All Drawings", expanded=False):
|
| 89 |
confirm_clear = st.checkbox("Yes, delete all my drawings", key="clear_confirm_checkbox")
|
| 90 |
-
if confirm_clear and st.button("🗑 Clear All My Saved Drawings"):
|
| 91 |
st.session_state.saved_drawings = []
|
| 92 |
st.success("All drawings deleted.")
|
|
|
|
|
|
|
|
|
|
| 93 |
|
| 94 |
# ---------------------- Run the page ----------------------
|
| 95 |
-
if
|
| 96 |
draw_page()
|
|
|
|
| 6 |
import base64
|
| 7 |
from datetime import datetime
|
| 8 |
|
| 9 |
+
# --- THEME DEFINITIONS (IMPORTANT: COPY THIS BLOCK TO ALL FILES IN THE 'PAGES' FOLDER) ---
|
| 10 |
THEMES = {
|
| 11 |
"boy": {
|
| 12 |
"primary_background": "#D0E4FF",
|
| 13 |
+
"secondary_background": "#A7D2FF",
|
| 14 |
+
"text_color": "#202060",
|
| 15 |
+
"accent_color": "#E53935",
|
| 16 |
+
"hero_image": "https://placehold.co/400x300/e53935/ffffff?text=Spiderman+Theme",
|
| 17 |
+
"welcome_message": "Ready for an adventure, {name}!"
|
| 18 |
+
},
|
| 19 |
+
"girl": {
|
| 20 |
+
"primary_background": "#FFEBFB",
|
| 21 |
+
"secondary_background": "#F5C7F7",
|
| 22 |
+
"text_color": "#7B1FA2",
|
| 23 |
+
"accent_color": "#EC407A",
|
| 24 |
+
"hero_image": "https://placehold.co/400x300/EC407A/ffffff?text=Gwen+Stacy+Theme",
|
| 25 |
+
"welcome_message": "Hello, {name}! Let's make today amazing!"
|
| 26 |
+
},
|
| 27 |
+
"neutral": {
|
| 28 |
+
"primary_background": "#E0FFE0",
|
| 29 |
+
"secondary_background": "#C9F0C9",
|
| 30 |
+
"text_color": "#33691E",
|
| 31 |
+
"accent_color": "#8BC34A",
|
| 32 |
+
"hero_image": "https://placehold.co/400x300/8BC34A/ffffff?text=HappyTrails+Theme",
|
| 33 |
+
"welcome_message": "Welcome to HappyTrails, {name}!"
|
| 34 |
}
|
| 35 |
}
|
| 36 |
|
| 37 |
+
# Function to apply the selected theme via custom CSS (IMPORTANT: COPY THIS BLOCK TO ALL FILES IN THE 'PAGES' FOLDER)
|
| 38 |
+
def apply_theme():
|
| 39 |
+
# Ensure user_profile exists in session state before accessing
|
| 40 |
+
if "user_profile" not in st.session_state:
|
| 41 |
+
st.session_state.user_profile = {"gender": "neutral"} # Default to neutral if not set
|
| 42 |
+
|
| 43 |
+
selected_gender = st.session_state.user_profile.get("gender", "neutral")
|
| 44 |
+
theme = THEMES.get(selected_gender, THEMES["neutral"])
|
| 45 |
+
|
| 46 |
+
st.markdown(f"""
|
| 47 |
<style>
|
| 48 |
+
:root {{
|
| 49 |
+
--primary-background: {theme["primary_background"]};
|
| 50 |
+
--secondary-background: {theme["secondary_background"]};
|
| 51 |
+
--text-color: {theme["text_color"]};
|
| 52 |
+
--accent-color: {theme["accent_color"]};
|
| 53 |
+
/* Define RGB values for rgba colors (useful for chat bubbles) */
|
| 54 |
+
--accent-color-rgb: {int(theme["accent_color"][1:3], 16)}, {int(theme["accent_color"][3:5], 16)}, {int(theme["accent_color"][5:7], 16)};
|
| 55 |
+
--secondary-background-rgb: {int(theme["secondary_background"][1:3], 16)}, {int(theme["secondary_background"][3:5], 16)}, {int(theme["secondary_background"][5:7], 16)};
|
| 56 |
+
}}
|
| 57 |
+
|
| 58 |
+
/* Apply theme colors using CSS variables */
|
| 59 |
.stApp {{
|
| 60 |
+
background-color: var(--primary-background);
|
| 61 |
+
color: var(--text-color); /* Fallback for general text */
|
| 62 |
+
}}
|
| 63 |
+
/* Target common Streamlit components for text color */
|
| 64 |
+
div, p, span, li, ul, ol, strong, em,
|
| 65 |
+
.st-emotion-cache-nahz7x, /* General text in st.write, st.markdown */
|
| 66 |
+
.st-emotion-cache-1f8796m, /* Text inside info/warning/success boxes */
|
| 67 |
+
.st-emotion-cache-1m6a05l, /* Streamlit headers/titles */
|
| 68 |
+
.st-emotion-cache-jny0p5, /* Text input and text area labels */
|
| 69 |
+
.st-emotion-cache-vk3360, /* Radio/checkbox labels */
|
| 70 |
+
.st-emotion-cache-1k1q0z8 /* Selectbox labels */
|
| 71 |
+
{{
|
| 72 |
+
color: var(--text-color) !important; /* Use !important to ensure override */
|
| 73 |
+
}}
|
| 74 |
+
|
| 75 |
+
.st-emotion-cache-1jm6gvd {{ /* Targeted for the main content area background */
|
| 76 |
+
background-color: var(--secondary-background);
|
| 77 |
}}
|
| 78 |
+
/* Headings color */
|
| 79 |
+
h1, h2, h3, h4, h5, h6 {{
|
| 80 |
+
color: var(--text-color) !important; /* Use !important for headings */
|
| 81 |
+
}}
|
| 82 |
+
/* Button styling */
|
| 83 |
.stButton>button {{
|
| 84 |
+
background-color: var(--accent-color);
|
| 85 |
+
color: white !important; /* Force white text on buttons */
|
| 86 |
+
border-radius: 8px;
|
| 87 |
+
border: none;
|
| 88 |
+
padding: 10px 20px;
|
| 89 |
+
font-weight: bold;
|
| 90 |
+
box-shadow: 2px 2px 5px rgba(0,0,0,0.2);
|
| 91 |
+
}}
|
| 92 |
+
.stButton>button:hover {{
|
| 93 |
+
background-color: #FF7043; /* A slightly different accent on hover */
|
| 94 |
+
transform: translateY(-2px);
|
| 95 |
+
box_shadow: 3px 3px 6px rgba(0,0,0,0.3);
|
| 96 |
+
}}
|
| 97 |
+
/* Label colors for various input widgets */
|
| 98 |
+
.stRadio > label, .stSelectbox > label, .stSlider > label, .stTextInput > label, .stTextArea > label, .stFileUploader > label {{
|
| 99 |
+
color: var(--text-color) !important;
|
| 100 |
+
}}
|
| 101 |
+
/* Markdown text color - important for general text */
|
| 102 |
+
.stMarkdown {{
|
| 103 |
+
color: var(--text-color) !important;
|
| 104 |
+
}}
|
| 105 |
+
.stRadio div[role="radiogroup"] {{
|
| 106 |
+
background-color: var(--secondary-background);
|
| 107 |
+
padding: 10px;
|
| 108 |
+
border-radius: 8px;
|
| 109 |
+
}}
|
| 110 |
+
.stSelectbox div[data-baseweb="select"] {{
|
| 111 |
+
background-color: var(--secondary-background);
|
| 112 |
+
border-radius: 8px;
|
| 113 |
+
}}
|
| 114 |
+
|
| 115 |
+
/* Specific styles for info/warning/success/error boxes to ensure text visibility */
|
| 116 |
+
.st-emotion-cache-1f8796m[data-baseweb="alert"] {{ /* general alert box container */
|
| 117 |
+
color: var(--text-color) !important; /* Text color inside alert boxes */
|
| 118 |
+
border-left-width: 5px;
|
| 119 |
+
border-left-style: solid;
|
| 120 |
+
border-radius: 8px;
|
| 121 |
+
padding: 1rem;
|
| 122 |
+
margin-bottom: 1rem;
|
| 123 |
+
}}
|
| 124 |
+
.st-emotion-cache-1f8796m[data-baseweb="alert"][kind="info"] {{
|
| 125 |
+
background-color: rgba(0, 123, 255, 0.1);
|
| 126 |
+
border-left-color: #007bff;
|
| 127 |
+
}}
|
| 128 |
+
.st-emotion-cache-1f8796m[data-baseweb="alert"][kind="success"] {{
|
| 129 |
+
background-color: rgba(40, 167, 69, 0.1);
|
| 130 |
+
border-left-color: #28a745;
|
| 131 |
+
}}
|
| 132 |
+
.st-emotion-cache-1f8796m[data-baseweb="alert"][kind="warning"] {{
|
| 133 |
+
background-color: rgba(255, 193, 7, 0.1);
|
| 134 |
+
border-left-color: #ffc107;
|
| 135 |
+
}}
|
| 136 |
+
.st-emotion-cache-1f8796m[data-baseweb="alert"][kind="error"] {{
|
| 137 |
+
background-color: rgba(220, 53, 69, 0.1);
|
| 138 |
+
border-left-color: #dc3545;
|
| 139 |
+
}}
|
| 140 |
+
/* For Streamlit's chat messages to ensure readability */
|
| 141 |
+
.stChatMessage {{
|
| 142 |
+
background-color: var(--secondary-background) !important; /* Chat bubble background */
|
| 143 |
+
color: var(--text-color) !important; /* Chat text color */
|
| 144 |
+
border-radius: 12px;
|
| 145 |
+
padding: 10px 15px;
|
| 146 |
+
margin-bottom: 8px;
|
| 147 |
+
}}
|
| 148 |
+
.stChatMessage.st-user {{ /* User's message */
|
| 149 |
+
background-color: rgba(var(--accent-color-rgb), 0.1) !important; /* Lighter accent for user */
|
| 150 |
+
color: var(--text-color) !important;
|
| 151 |
+
}}
|
| 152 |
+
.stChatMessage.st-assistant {{ /* Assistant's message */
|
| 153 |
+
background-color: rgba(var(--secondary-background-rgb), 0.8) !important; /* Secondary background for assistant */
|
| 154 |
+
color: var(--text-color) !important;
|
| 155 |
+
}}
|
| 156 |
+
|
| 157 |
+
/* === CRITICAL FIX FOR SVG ICONS === */
|
| 158 |
+
/* Target the SVG elements directly and ensure fill color is from theme */
|
| 159 |
+
svg {{
|
| 160 |
+
fill: currentColor !important; /* Use currentColor to inherit from parent text color */
|
| 161 |
+
stroke: currentColor !important; /* Also set stroke for outlines */
|
| 162 |
}}
|
| 163 |
</style>
|
| 164 |
+
""", unsafe_allow_html=True)
|
| 165 |
+
|
| 166 |
+
# --- Apply Theme ---
|
| 167 |
+
apply_theme()
|
| 168 |
+
|
| 169 |
|
| 170 |
# ---------------------- Initialize Session State ----------------------
|
| 171 |
if "saved_drawings" not in st.session_state:
|
|
|
|
| 201 |
|
| 202 |
# Save drawing if user clicks
|
| 203 |
if st.button("💾 Save Drawing"):
|
| 204 |
+
# Check if the canvas image data exists and is not entirely transparent/empty
|
| 205 |
if canvas_result.image_data is not None and canvas_result.image_data.sum() > 0:
|
| 206 |
drawing_data = {
|
| 207 |
"image": canvas_result.image_data,
|
|
|
|
| 216 |
|
| 217 |
# Show saved drawings
|
| 218 |
if st.session_state.saved_drawings:
|
| 219 |
+
st.subheader("🖼️ Your Saved Drawings")
|
| 220 |
for i, saved in enumerate(st.session_state.saved_drawings):
|
| 221 |
+
st.markdown(f"**Drawing {i + 1} - {saved['timestamp']}**")
|
| 222 |
st.image(saved["image"])
|
| 223 |
|
| 224 |
# Clear saved drawings with confirmation
|
| 225 |
+
with st.expander("⚠️ Clear All Drawings", expanded=False):
|
| 226 |
confirm_clear = st.checkbox("Yes, delete all my drawings", key="clear_confirm_checkbox")
|
| 227 |
+
if confirm_clear and st.button("🗑️ Clear All My Saved Drawings"):
|
| 228 |
st.session_state.saved_drawings = []
|
| 229 |
st.success("All drawings deleted.")
|
| 230 |
+
# Uncheck the confirmation box after clearing
|
| 231 |
+
st.session_state.clear_confirm_checkbox = False
|
| 232 |
+
|
| 233 |
|
| 234 |
# ---------------------- Run the page ----------------------
|
| 235 |
+
if __name__ == "__main__":
|
| 236 |
draw_page()
|