diff --git a/selfdrive/ui/layouts/home.py b/selfdrive/ui/layouts/home.py index 1a1f69afe1..72d96bd40b 100644 --- a/selfdrive/ui/layouts/home.py +++ b/selfdrive/ui/layouts/home.py @@ -4,6 +4,7 @@ from collections.abc import Callable from enum import IntEnum from openpilot.common.params import Params from openpilot.selfdrive.ui.widgets.offroad_alerts import UpdateAlert, OffroadAlert +from openpilot.selfdrive.ui.widgets.prime import PrimeAdWidget from openpilot.system.ui.lib.text_measure import measure_text_cached from openpilot.system.ui.lib.label import gui_label from openpilot.system.ui.lib.application import gui_app, FontWeight, DEFAULT_TEXT_COLOR, Widget @@ -47,6 +48,8 @@ class HomeLayout(Widget): self.update_notif_rect = rl.Rectangle(0, 0, 200, HEADER_HEIGHT - 10) self.alert_notif_rect = rl.Rectangle(0, 0, 220, HEADER_HEIGHT - 10) + self._prime_ad_widget = PrimeAdWidget() + self._setup_callbacks() def _setup_callbacks(self): @@ -171,7 +174,7 @@ class HomeLayout(Widget): def _render_left_column(self): rl.draw_rectangle_rounded(self.left_column_rect, 0.02, 10, PRIME_BG_COLOR) - gui_label(self.left_column_rect, "Prime Widget", 48, alignment=rl.GuiTextAlignment.TEXT_ALIGN_CENTER) + self._prime_ad_widget.render(self.left_column_rect) def _render_right_column(self): widget_height = (self.right_column_rect.height - SPACING) // 2 diff --git a/selfdrive/ui/widgets/prime.py b/selfdrive/ui/widgets/prime.py new file mode 100644 index 0000000000..3ab6362952 --- /dev/null +++ b/selfdrive/ui/widgets/prime.py @@ -0,0 +1,38 @@ +import pyray as rl +from openpilot.system.ui.lib.application import gui_app, Widget, FontWeight +from openpilot.system.ui.lib.label import gui_label +from openpilot.system.ui.lib.wrap_text import wrap_text +from openpilot.system.ui.lib.text_measure import measure_text_cached + + +class PrimeAdWidget(Widget): + """Advertisement widget for non-Prime users.""" + + def __init__(self): + super().__init__() + + def _render(self, rect): + # Layout + x, y = rect.x + 80, rect.y + 90 + w = rect.width - 160 + + # Title + gui_label(rl.Rectangle(x, y, w, 90), "Upgrade Now", 75, font_weight=FontWeight.BOLD) + + # Description with wrapping + desc_y = y + 140 + font = gui_app.font(FontWeight.LIGHT) + wrapped_text = "\n".join(wrap_text(font, "Become a comma prime member at connect.comma.ai", 56, w)) + text_size = measure_text_cached(font, wrapped_text, 56) + rl.draw_text_ex(font, wrapped_text, rl.Vector2(x, desc_y), 56, 0, rl.Color(255, 255, 255, 255)) + + # Features section + features_y = desc_y + text_size.y + 50 + gui_label(rl.Rectangle(x, features_y, w, 50), "PRIME FEATURES:", 41, font_weight=FontWeight.BOLD) + + # Feature list + features = ["Remote access", "24/7 LTE connectivity", "1 year of drive storage", "Remote snapshots"] + for i, feature in enumerate(features): + item_y = features_y + 80 + i * 65 + gui_label(rl.Rectangle(x, item_y, 50, 60), "✓", 50, color=rl.Color(70, 91, 234, 255)) + gui_label(rl.Rectangle(x + 60, item_y, w - 60, 60), feature, 50) diff --git a/system/ui/lib/application.py b/system/ui/lib/application.py index f051d9f10a..72b408be53 100644 --- a/system/ui/lib/application.py +++ b/system/ui/lib/application.py @@ -252,7 +252,7 @@ class GuiApplication: for layout in KEYBOARD_LAYOUTS.values(): all_chars.update(key for row in layout for key in row) all_chars = "".join(all_chars) - all_chars += "-" + all_chars += "-✓" codepoint_count = rl.ffi.new("int *", 1) codepoints = rl.load_codepoints(all_chars, codepoint_count)