File size: 6,074 Bytes
d925554
365db9f
d925554
 
 
 
 
7c52824
 
7695044
7c52824
7695044
d925554
 
2351502
a5f16fc
2351502
 
a5f16fc
 
 
 
7a5f7f3
a5f16fc
 
7a5f7f3
 
a5f16fc
2351502
 
 
 
 
 
 
 
 
 
 
 
7a5f7f3
 
2351502
 
 
7a5f7f3
 
 
 
 
 
 
 
 
 
 
 
2351502
 
 
 
d925554
 
a5f16fc
1ef93e4
 
 
 
 
 
 
 
 
 
d925554
7695044
d925554
a5f16fc
 
 
 
 
 
 
 
 
d925554
 
7695044
 
 
 
 
 
 
ed21b93
 
 
7695044
ed21b93
 
 
 
7695044
 
 
d925554
 
 
 
 
7695044
 
 
 
 
 
 
 
d925554
 
 
7695044
 
 
 
d925554
7695044
 
 
 
d925554
7695044
 
 
d925554
 
1ef93e4
d925554
a5f16fc
 
d925554
7695044
d925554
 
 
 
2351502
d925554
 
 
 
 
 
1ef93e4
 
 
 
d925554
 
 
7695044
d925554
1ef93e4
7a5f7f3
1ef93e4
 
d925554
7695044
a5f16fc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# app.py
import streamlit as st
import requests
from PIL import Image
from io import BytesIO
from colorthief import ColorThief
import random
import os

# -- API Keys from Hugging Face Secrets --
UNSPLASH_ACCESS_KEY = os.environ.get("UNSPLASH_ACCESS_KEY")
GOOGLE_FONTS_API_KEY = os.environ.get("GOOGLE_FONTS_API_KEY")

st.set_page_config(page_title="Moodboard AI", layout="wide")

# -- Init Session State --
if 'dark_mode' not in st.session_state:
    st.session_state.dark_mode = False
if 'generate' not in st.session_state:
    st.session_state.generate = False
if 'remix' not in st.session_state:
    st.session_state.remix = random.randint(1, 10000)

# -- Dark Mode Toggle (no forced rerun) --
dark_mode_toggle = st.toggle("πŸŒ™ Toggle Dark Mode", value=st.session_state.dark_mode, key="dark_toggle")
if dark_mode_toggle != st.session_state.dark_mode:
    st.session_state.dark_mode = dark_mode_toggle
    st.experimental_rerun()

# -- Apply Dark Mode Styling --
if st.session_state.dark_mode:
    st.markdown("""
        <style>
            body, .stApp {
                background-color: #121212;
                color: #f0f0f0;
            }
            h1, h2, h3, h4, h5, h6 {
                color: #ffffff !important;
            }
            .stTextInput > div > div > input,
            .stTextArea > div > textarea {
                background-color: #222222;
                color: #ffffff;
            }
            .stButton>button {
                background-color: #333333;
                color: #ffffff;
            }
        </style>
    """, unsafe_allow_html=True)
else:
    st.markdown("""
        <style>
            h1, h2, h3, h4, h5, h6 {
                color: #000000 !important;
            }
        </style>
    """, unsafe_allow_html=True)

# -- Title --
st.title("🎨 Moodboard AI – Smart Visual Inspiration Generator")

# -- API Status Display --
if UNSPLASH_ACCESS_KEY:
    st.success("βœ… Unsplash API key loaded successfully.")
else:
    st.warning("⚠️ Unsplash API key missing or not set in Hugging Face Secrets.")

if GOOGLE_FONTS_API_KEY:
    st.success("βœ… Google Fonts API key loaded successfully.")
else:
    st.warning("⚠️ Google Fonts API key missing or not set in Hugging Face Secrets.")

# -- Theme Input --
theme = st.text_input("Enter a theme or keyword (e.g. 'vintage tech', 'coastal minimalism'):", "futuristic tech").lower()

# -- Control Buttons --
col1, col2 = st.columns(2)
with col1:
    if st.button("πŸ” Remix Moodboard"):
        st.session_state.remix = random.randint(1, 10000)
        st.session_state.generate = True
with col2:
    if st.button("✨ Generate Moodboard"):
        st.session_state.generate = True

# -- Fetch Images from Unsplash --
def fetch_images_from_unsplash(query, count=5):
    if not UNSPLASH_ACCESS_KEY:
        st.error("🚫 Missing Unsplash API Key. Please add it to Hugging Face Secrets.")
        return []
    try:
        url = f"https://api.unsplash.com/search/photos?query={query}&per_page={count}&client_id={UNSPLASH_ACCESS_KEY}"
        response = requests.get(url)
        if response.status_code != 200:
            st.error(f"❌ Unsplash API Error: {response.status_code}")
            return []
        data = response.json()
        results = data.get('results', [])
        if not results:
            st.warning("⚠️ Unsplash API returned 0 results. Try a different keyword.")
        return [item['urls']['regular'] for item in results]
    except Exception as e:
        st.error(f"❌ Error fetching images: {e}")
        return []

# -- Extract Dominant Colors --
def extract_colors(image_urls):
    colors = []
    for url in image_urls[:3]:
        try:
            response = requests.get(url)
            img = BytesIO(response.content)
            ct = ColorThief(img)
            palette = ct.get_palette(color_count=3)
            colors.extend(palette)
        except:
            continue
    return colors[:5]

# -- Fetch Fonts from Google Fonts --
def fetch_google_fonts():
    if not GOOGLE_FONTS_API_KEY:
        st.error("🚫 Missing Google Fonts API Key. Please add it to Hugging Face Secrets.")
        return []
    try:
        url = f"https://www.googleapis.com/webfonts/v1/webfonts?sort=popularity&key={GOOGLE_FONTS_API_KEY}"
        res = requests.get(url)
        data = res.json()
        fonts = [item['family'] for item in data.get('items', [])]
        return random.sample(fonts, 3)
    except Exception as e:
        st.error(f"❌ Error fetching fonts: {e}")
        return []

# -- Show Moodboard --
if st.session_state.get("generate"):
    with st.spinner("Generating your moodboard..."):
        query = f"{theme} {st.session_state.remix}"
        image_urls = fetch_images_from_unsplash(query)
        if not image_urls:
            st.warning("No images found. Try another keyword or check your API key.")
        else:
            st.subheader("πŸ–ΌοΈ Image Suggestions")
            cols = st.columns(len(image_urls))
            for col, url in zip(cols, image_urls):
                col.image(url, use_container_width=True)

            st.subheader("🎨 Color Palette")
            palette = extract_colors(image_urls)
            color_cols = st.columns(len(palette))
            for col, rgb in zip(color_cols, palette):
                hex_color = '#%02x%02x%02x' % rgb
                col.markdown(
                    f"<div style='background-color:{hex_color};height:50px;width:100%;border-radius:5px'></div>",
                    unsafe_allow_html=True
                )
                col.write(hex_color)

            st.subheader("πŸ”€ Font Suggestions")
            fonts = fetch_google_fonts()
            for font in fonts:
                st.markdown(
                    f"<p style='font-family:{font};font-size:24px;color:{'#ffffff' if st.session_state.dark_mode else '#000000'}'>{font}</p>",
                    unsafe_allow_html=True
                )

            st.success("βœ… Moodboard ready! Right-click or screenshot to save.")
    st.session_state.generate = False  # Reset