this repo has no description

Added icons

+154 -61
+154 -61
components/WeeklySchedule.tsx
··· 8 8 headerColor: string; 9 9 dateRangeColor: string; 10 10 dayColor: string; 11 - eventBgColor: string; 11 + eventBgColors: { 12 + default: string; 13 + twitch: string; 14 + discord: string; 15 + }; 12 16 eventTextColor: string; 13 17 noEventColor: string; 14 18 backgroundImagePath: string; // Path to background image 15 - eventIconPath?: string; // Path to event SVG icon (optional) 19 + iconPaths: { 20 + discord: string; 21 + twitch: string; 22 + }; 16 23 } 17 24 18 25 // Default theme ··· 21 28 headerColor: "#ffffff", 22 29 dateRangeColor: "#ffffff", 23 30 dayColor: "#ffffff", 24 - eventBgColor: "#e6d195", //twitch: eebd37 discord: f3af52 31 + eventBgColors: { 32 + default: "#e6d195", 33 + twitch: "#eebd37", 34 + discord: "#f3af52", 35 + }, 25 36 eventTextColor: "#ffffff", 26 37 noEventColor: "#ffffff", 27 38 backgroundImagePath: "./static/background.png", 28 - eventIconPath: "./static/discord-icon.svg", 39 + iconPaths: { 40 + discord: "./static/discord-icon.svg", 41 + twitch: "./static/twitch-icon.svg", 42 + }, 29 43 }; 30 44 31 45 // Theme collection - can be expanded as needed ··· 36 50 headerColor: "#ffffff", 37 51 dateRangeColor: "#cccccc", 38 52 dayColor: "#ffffff", 39 - eventBgColor: "#333333", 53 + eventBgColors: { 54 + default: "#333333", 55 + twitch: "#333333", 56 + discord: "#333333", 57 + }, 40 58 eventTextColor: "#ffffff", 41 59 noEventColor: "#777777", 42 60 backgroundImagePath: "./static/background.png", 43 - eventIconPath: "./static/discord-icon.svg", 61 + iconPaths: { 62 + discord: "./static/discord-icon.svg", 63 + twitch: "./static/twitch-icon.svg", 64 + }, 44 65 }, 45 66 // Add more themes as needed 46 67 }; ··· 50 71 startDate: Date, 51 72 endDate: Date, 52 73 backgroundImageBase64?: string, 74 + iconBase64Map?: Record<string, string>, 53 75 theme: Theme = defaultTheme, 54 76 ) { 55 77 const days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]; ··· 58 80 const displayHeight = displayWidth / aspectRatio; 59 81 60 82 // Calculate relative positions 61 - const headerPosition = 0.10; 62 - const dateRangePosition = 0.15; 63 - const scheduleStartPosition = 0.21; 83 + const headerPosition = 0.08; 84 + const scheduleStartPosition = 0.212; 64 85 const scheduleHeight = 0.73; 65 86 66 87 // Format the date range ··· 68 89 const endDateFormatted = format(endDate, "dd.MM.", []); 69 90 const dateRangeText = `${startDateFormatted} - ${endDateFormatted}`; 70 91 92 + // Helper function to get event background color based on location 93 + const getEventBgColor = (event: Event | undefined) => { 94 + if (!event || !event.location) return theme.eventBgColors.default; 95 + 96 + const location = event.location.toLowerCase(); 97 + if (location === "twitch") return theme.eventBgColors.twitch; 98 + if (location === "discord") return theme.eventBgColors.discord; 99 + 100 + return theme.eventBgColors.default; 101 + }; 102 + 103 + // Helper function to get icon based on location 104 + const getEventIcon = (event: Event | undefined) => { 105 + if (!event || !event.location || !iconBase64Map) return null; 106 + 107 + const location = event.location.toLowerCase(); 108 + if (location === "twitch" && iconBase64Map.twitch) { 109 + return iconBase64Map.twitch; 110 + } 111 + if (location === "discord" && iconBase64Map.discord) { 112 + return iconBase64Map.discord; 113 + } 114 + 115 + return null; 116 + }; 117 + 71 118 return ( 72 119 <div 73 120 style={{ ··· 95 142 /> 96 143 )} 97 144 98 - {/* Header Title */} 145 + {/* Header */} 99 146 <div 147 + className="header" 100 148 style={{ 101 149 position: "absolute", 102 150 top: `${headerPosition * 100}%`, 103 - width: "79%", 104 - textAlign: "center", 105 - fontFamily: theme.fontFamily, 106 - fontSize: "24px", 107 - fontWeight: "bold", 108 - color: theme.headerColor, 151 + width: "100%", 152 + display: "flex", 153 + flexDirection: "column", 154 + alignItems: "center", 155 + justifyContent: "center", 109 156 }} 110 157 > 111 - Stream Schedule 112 - </div> 158 + {/* Title */} 159 + <div 160 + className="title" 161 + style={{ 162 + fontFamily: theme.fontFamily, 163 + fontSize: "32px", 164 + fontWeight: "bold", 165 + color: theme.headerColor, 166 + justifyContent: "center", 167 + width: "100%", 168 + marginBottom: "8px", 169 + }} 170 + > 171 + Stream Schedule 172 + </div> 113 173 114 - {/* Date Range */} 115 - <div 116 - style={{ 117 - position: "absolute", 118 - top: `${dateRangePosition * 100}%`, 119 - width: "79%", 120 - textAlign: "center", 121 - fontFamily: theme.fontFamily, 122 - fontSize: "18px", 123 - color: theme.dateRangeColor, 124 - }} 125 - > 126 - {dateRangeText} 174 + {/* Date Range */} 175 + <div 176 + className="week-range" 177 + style={{ 178 + fontFamily: theme.fontFamily, 179 + fontSize: "20px", 180 + color: theme.dateRangeColor, 181 + justifyContent: "center", 182 + width: "100%", 183 + }} 184 + > 185 + {dateRangeText} 186 + </div> 127 187 </div> 128 188 129 189 {/* Weekly Schedule */} 130 190 <div 191 + className="schedule" 131 192 style={{ 132 193 position: "absolute", 133 194 top: `${scheduleStartPosition * 100}%`, 134 - width: "79%", 195 + width: "80%", 135 196 height: `${scheduleHeight * 100}%`, 136 197 display: "flex", 137 198 flexDirection: "column", ··· 142 203 const event = events.find((e) => 143 204 format(e.start, "eee", []) === day 144 205 ); 206 + const hasEvent = !!event; 207 + const eventBgColor = getEventBgColor(event); 208 + const eventIcon = getEventIcon(event); 209 + 145 210 return ( 146 211 <div 147 212 key={index} 213 + className="event-box" 148 214 style={{ 149 215 display: "flex", 150 216 flexDirection: "row", ··· 152 218 justifyContent: "space-between", 153 219 width: "100%", 154 220 height: `${100 / days.length - 2}%`, 155 - backgroundColor: theme.eventBgColor, 221 + backgroundColor: eventBgColor, 156 222 padding: "10px", 157 - borderRadius: "10px", 223 + borderRadius: "15px", 158 224 marginBottom: "8px", 225 + fontSize: "1.3em", 159 226 fontFamily: theme.fontFamily, 227 + position: "relative", 160 228 }} 161 229 > 230 + {/* Location icon overlay */} 231 + {eventIcon && ( 232 + <img 233 + src={`data:image/svg+xml;base64,${eventIcon}`} 234 + style={{ 235 + position: "absolute", 236 + top: "-12px", 237 + left: "-12px", 238 + width: "30px", 239 + height: "30px", 240 + zIndex: 10, 241 + }} 242 + /> 243 + )} 244 + 162 245 <div 246 + className="weekday" 163 247 style={{ 164 248 fontWeight: "bold", 165 249 marginRight: "12px", 166 - textAlign: "left", 250 + justifyContent: "flex-start", 167 251 flex: "1", 168 - fontSize: "1.2em", 169 252 color: theme.dayColor, 170 253 }} 171 254 > 172 255 {day} 173 256 </div> 174 257 175 - {event && ( 176 - <> 177 - <div 178 - style={{ 179 - display: "flex", 180 - flexDirection: "column", 181 - textAlign: "center", 182 - flex: 2, 183 - marginRight: "12px", 184 - wordWrap: "break-word", 185 - fontSize: "1.2em", 186 - color: theme.eventTextColor, 187 - }} 188 - > 189 - <div>{event.summary}</div> 190 - </div> 191 - </> 192 - )} 258 + <div 259 + className="summary" 260 + style={{ 261 + display: "flex", 262 + flexDirection: "column", 263 + justifyContent: "center", 264 + flex: 2, 265 + marginRight: "12px", 266 + wordWrap: "break-word", 267 + color: theme.eventTextColor, 268 + }} 269 + > 270 + {hasEvent ? event.summary : "-"} 271 + </div> 193 272 194 273 <div 274 + className="time" 195 275 style={{ 196 276 display: "flex", 197 - textAlign: "right", 277 + justifyContent: "flex-end", 198 278 flex: "1", 199 279 whiteSpace: "nowrap", 200 - color: event 201 - ? theme.eventTextColor 202 - : theme.noEventColor, 203 - fontSize: "1.2em", 280 + color: theme.eventTextColor, 204 281 }} 205 282 > 206 - {event && format(event.start, "ha", [])} 207 - {!event && "No event"} 283 + {hasEvent ? format(event.start, "ha", []) : ""} 208 284 </div> 209 285 </div> 210 286 ); ··· 239 315 ); 240 316 } 241 317 318 + // Load icon images 319 + const iconBase64Map: Record<string, string> = {}; 320 + try { 321 + // Load Discord icon 322 + const discordIconData = await Deno.readFile(theme.iconPaths.discord); 323 + iconBase64Map.discord = encodeBase64(discordIconData); 324 + 325 + // Load Twitch icon 326 + const twitchIconData = await Deno.readFile(theme.iconPaths.twitch); 327 + iconBase64Map.twitch = encodeBase64(twitchIconData); 328 + } catch (error) { 329 + console.error( 330 + `Error loading icon images: ${(error as Error).message}`, 331 + ); 332 + } 333 + 242 334 const svg = await satori( 243 335 WeeklySchedule( 244 336 events, 245 337 startDate, 246 338 endDate, 247 339 backgroundImageBase64, 340 + iconBase64Map, 248 341 theme, 249 342 // deno-lint-ignore no-explicit-any 250 343 ) as any,