Hello – I’m trying to build an app that cycles through multiple upcoming calendar events. I have things mostly working except for when the event has a long title. I am trying to use Marquee to vertically scroll the title, and while this works too, any time I get to a scrolling title then the app stops progressing through the list of events and just stays on the scrolling event title until what I believe to be the app cycle timing resets it (I am only testing locally on my computer so far). If i set Root allow_full_animation to True then once I get to a Marquee scroll it never moves forward to another event at all, I guess cause it’s stuck thinking it’s still trying to complete an animation.
Here’s the related code, appreciate any guidance!
def build_events_frame(now, users_tz, events_chunk):
# Get date information
month = get_month_name(now, users_tz)
weekday = get_weekday_name(now, users_tz)
day = get_day_of_month(now, users_tz)
# Top section
top_section = render.Box(
width = 64,
height = 8,
child= render.Row(
main_align = "start",
cross_align = "center",
expanded = True,
children = [
render.Image(src=CALENDAR_ICON, width = 7, height = 8),
render.Box(width=2),
render.Text(
font = main_font,
content = weekday.upper(),
color = color_font,
offset = -1,
),
render.Box(width = 1),
render.Text(
font = main_font,
content = month.upper(),
color = color_font,
offset = -1,
),
render.Box(width = 1),
render.Text(
font = main_font,
content = day,
color = color_font,
offset = -1,
),
],
),
)
# Middle section
# Event details
event = events_chunk[0]
event_start = event["start"]
event_name = event["name"]
minutes_until_start = event["detail"]["minutesUntilStart"]
# Determine color and time display
if minutes_until_start <= 5:
if minutes_until_start > 1:
color = "#ff5000"
time_display = "in {} min".format(minutes_until_start)
elif minutes_until_start == 1:
color = "#ff5000"
time_display = "in 1 min"
else:
color = "#9000ff"
time_display = "now"
else:
color = "#ff78e9"
time_display = get_time_display(event_start, users_tz)
# Event name widgets
event_name_wrapped = render.WrappedText(
content = event_name.upper(),
color = "#ffffff",
font = main_font,
width = 64,
linespacing = 0,
align = "left",
)
event_name_widget = render.Marquee(
child = event_name_wrapped,
width = 64,
height = 16,
align = "end",
scroll_direction = "vertical",
)
# Middle section with event name
middle_section = render.Box(
width = 64,
height = 16, # Fixed height
child = render.Column(
main_align = "end",
cross_align = "start",
expanded = True,
children = [
event_name_widget,
],
),
)
# Bottom section with event time
bottom_section = render.Box(
width = 64,
height = 8, # Fixed height
child= render.Row(
main_align = "start",
cross_align = "center",
expanded = True,
children = [
render.Text(
content = time_display,
color = color_font,
font = small_font,
offset = 0,
),
],
),
)
# Combine the sections
content = render.Column(
main_align = "start",
cross_align = "start",
children = [
top_section,
middle_section,
bottom_section,
],
)
# Return the frame content
return content
def main():
# Configuration settings
timezone = DEFAULT_TIMEZONE
ics_urls = DEFAULT_ICS_URLS
max_events = DEFAULT_MAX_EVENTS
users_tz = timezone
now = time.now().in_location(users_tz).unix
all_events = []
for url in ics_urls:
ics_response = http.get(url)
if ics_response.status_code != 200:
continue
ics_content = ics_response.body()
events = parse_ics(ics_content, users_tz)
all_events.extend(events)
if len(all_events) == 0:
print("no events found")
return [build_calendar_frame(now, users_tz)]
# Sort events by start time
all_events_sorted = sorted(all_events, key=get_event_start)
upcoming_events = all_events_sorted[:max_events]
# Define frame timing
frame_delay = 100
event_display_duration = 3750
frames_per_event = event_display_duration // frame_delay
frames = []
for event in upcoming_events:
# Generate multiple frames for each event
for _ in range(frames_per_event):
frame_content = build_events_frame(now, users_tz, [event])
frame = render.Root(
delay = frame_delay,
child = frame_content,
)
frames.append(frame)
return frames