[Service] New UI

This commit is contained in:
2026-09-13 21:12:44 -07:00
parent e473d00f4f
commit 1b1ca16fdd
45 changed files with 2726 additions and 205 deletions
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#FF2A3038" />
<corners android:radius="10dp" />
</shape>
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true">
<shape android:shape="rectangle">
<solid android:color="@color/pc_red_soft" />
<corners android:radius="10dp" />
<stroke android:width="2dp" android:color="@color/pc_red" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="@color/pc_red_soft" />
<corners android:radius="10dp" />
</shape>
</item>
</selector>
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true">
<shape android:shape="rectangle">
<solid android:color="@color/pc_blue" />
<corners android:radius="10dp" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="@color/pc_blue" />
<corners android:radius="10dp" />
</shape>
</item>
</selector>
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true">
<shape android:shape="rectangle">
<solid android:color="#FF3A414B" />
<corners android:radius="10dp" />
<stroke android:width="2dp" android:color="@color/pc_focus_outline" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="#FF3A414B" />
<corners android:radius="10dp" />
</shape>
</item>
</selector>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="@color/pc_card" />
<corners android:radius="16dp" />
</shape>
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true">
<shape android:shape="rectangle">
<solid android:color="@color/pc_card_inner_focus" />
<corners android:radius="12dp" />
<stroke android:width="1dp" android:color="@color/pc_stroke" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="@color/pc_card_inner" />
<corners android:radius="12dp" />
<stroke android:width="1dp" android:color="@color/pc_stroke" />
</shape>
</item>
</selector>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="@color/pc_green" />
<size android:width="8dp" android:height="8dp" />
</shape>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="@color/pc_blue" />
<size android:width="40dp" android:height="40dp" />
</shape>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="#3322C55E" />
<size android:width="40dp" android:height="40dp" />
</shape>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="#33FBBF24" />
<size android:width="40dp" android:height="40dp" />
</shape>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="@color/pc_blue" />
<corners android:radius="10dp" />
</shape>
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:state_selected="true">
<shape android:shape="rectangle">
<solid android:color="@color/pc_mode_selected" />
<corners android:radius="12dp" />
<stroke android:width="2dp" android:color="@color/pc_focus_outline" />
</shape>
</item>
<item android:state_focused="true">
<shape android:shape="rectangle">
<solid android:color="@color/pc_card_inner" />
<corners android:radius="12dp" />
<stroke android:width="2dp" android:color="@color/pc_focus_outline" />
</shape>
</item>
<item android:state_selected="true">
<shape android:shape="rectangle">
<solid android:color="@color/pc_mode_selected" />
<corners android:radius="12dp" />
<stroke android:width="1dp" android:color="@color/pc_stroke" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="@color/pc_card_inner" />
<corners android:radius="12dp" />
<stroke android:width="1dp" android:color="@color/pc_stroke" />
</shape>
</item>
</selector>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#FF102027" />
<size android:width="320dp" android:height="180dp" />
</shape>
Binary file not shown.
@@ -0,0 +1,451 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/pc_bg"
android:orientation="vertical"
android:padding="20dp">
<!-- Header -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingBottom="16dp">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="PortalCam"
android:textColor="@color/pc_text"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Camera Streaming"
android:textColor="@color/pc_text_secondary"
android:textSize="13sp" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/header_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="start"
android:orientation="horizontal">
<FrameLayout
android:layout_width="16dp"
android:layout_height="match_parent">
<View
android:id="@+id/header_streaming_dot"
android:layout_width="8dp"
android:layout_height="8dp"
android:layout_gravity="top|start"
android:layout_marginTop="4dp"
android:background="@drawable/pc_dot_green"
android:visibility="invisible" />
</FrameLayout>
<LinearLayout
android:id="@+id/header_status_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/header_streaming"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Idle"
android:textColor="@color/pc_text_secondary"
android:textSize="13sp"
android:textStyle="bold" />
<TextView
android:id="@+id/header_ready"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Ready"
android:textColor="@color/pc_text_secondary"
android:textSize="13sp" />
</LinearLayout>
</LinearLayout>
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_marginStart="28dp"
android:layout_marginEnd="28dp"
android:background="@color/pc_separator" />
</LinearLayout>
<TextView
android:id="@+id/header_clock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lineSpacingExtra="2dp"
android:textColor="@color/pc_text_secondary"
android:textSize="13sp" />
<TextView
android:id="@+id/header_overflow"
android:layout_width="44dp"
android:layout_height="44dp"
android:layout_marginStart="48dp"
android:background="@drawable/pc_btn_secondary"
android:focusable="true"
android:fontFamily="@font/lucide"
android:gravity="center"
android:includeFontPadding="false"
android:textColor="@color/pc_text"
android:textSize="20sp" />
</LinearLayout>
</LinearLayout>
<!-- Top cards row — height hugs mode list; card padding 14dp all sides. -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<!-- Mode -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:layout_weight="1"
android:background="@drawable/pc_card"
android:orientation="vertical"
android:padding="14dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="10dp"
android:text="Mode"
android:textColor="@color/pc_text"
android:textSize="15sp"
android:textStyle="bold" />
<LinearLayout
android:id="@+id/modes_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
</LinearLayout>
<!-- Mode Controls -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginEnd="12dp"
android:layout_weight="1.5"
android:background="@drawable/pc_card"
android:orientation="vertical"
android:padding="14dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="10dp"
android:text="Mode Controls"
android:textColor="@color/pc_text"
android:textSize="15sp"
android:textStyle="bold" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<LinearLayout
android:id="@+id/controls_empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/controls_empty_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/lucide"
android:includeFontPadding="false"
android:textColor="@color/pc_text_dim"
android:textSize="28sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="8dp"
android:text="No mode parameters"
android:textColor="@color/pc_text_secondary"
android:textSize="15sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="4dp"
android:text="This mode doesn't have any configurable settings."
android:textColor="@color/pc_text_dim"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/controls_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone" />
</FrameLayout>
</LinearLayout>
<!-- Live Stats -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1.5"
android:background="@drawable/pc_card"
android:orientation="vertical"
android:padding="14dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="10dp"
android:text="Live Stats"
android:textColor="@color/pc_text"
android:textSize="15sp"
android:textStyle="bold" />
<!-- Same rhythm as Mode: 52dp rows + 8dp gaps; row inset = 2× mode button L/R padding. -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="20dp"
android:paddingEnd="20dp">
<LinearLayout
android:id="@+id/stat_video_row"
android:layout_width="match_parent"
android:layout_height="52dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView android:id="@+id/stat_video_icon" android:layout_width="36dp" android:layout_height="36dp" android:fontFamily="@font/lucide" android:gravity="center" android:includeFontPadding="false" android:textColor="@color/pc_text_secondary" android:textSize="36sp" />
<TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:paddingStart="12dp" android:text="Active video" android:textColor="@color/pc_text_secondary" android:textSize="18sp" />
<TextView android:id="@+id/stat_video" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="0" android:textColor="@color/pc_text_secondary" android:textSize="18sp" android:textStyle="bold" />
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="8dp">
<include
layout="@layout/pc_separator_h"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_gravity="center_vertical" />
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="52dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView android:id="@+id/stat_audio_icon" android:layout_width="36dp" android:layout_height="36dp" android:fontFamily="@font/lucide" android:gravity="center" android:includeFontPadding="false" android:textColor="@color/pc_text_secondary" android:textSize="36sp" />
<TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:paddingStart="12dp" android:text="Active audio" android:textColor="@color/pc_text_secondary" android:textSize="18sp" />
<TextView android:id="@+id/stat_audio" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="0" android:textColor="@color/pc_text_secondary" android:textSize="18sp" android:textStyle="bold" />
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="8dp">
<include
layout="@layout/pc_separator_h"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_gravity="center_vertical" />
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="52dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView android:id="@+id/stat_video_bw_icon" android:layout_width="36dp" android:layout_height="36dp" android:fontFamily="@font/lucide" android:gravity="center" android:includeFontPadding="false" android:textColor="@color/pc_text_secondary" android:textSize="36sp" />
<TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:paddingStart="12dp" android:text="Uplink video" android:textColor="@color/pc_text_secondary" android:textSize="18sp" />
<TextView android:id="@+id/stat_video_bw" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="0 bit/s" android:textColor="@color/pc_text_secondary" android:textSize="18sp" android:textStyle="bold" />
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="8dp">
<include
layout="@layout/pc_separator_h"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_gravity="center_vertical" />
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="52dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView android:id="@+id/stat_audio_bw_icon" android:layout_width="36dp" android:layout_height="36dp" android:fontFamily="@font/lucide" android:gravity="center" android:includeFontPadding="false" android:textColor="@color/pc_text_secondary" android:textSize="36sp" />
<TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:paddingStart="12dp" android:text="Uplink audio" android:textColor="@color/pc_text_secondary" android:textSize="18sp" />
<TextView android:id="@+id/stat_audio_bw" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="0 bit/s" android:textColor="@color/pc_text_secondary" android:textSize="18sp" android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<!-- Clients card -->
<LinearLayout
android:id="@+id/clients_host"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="12dp"
android:layout_weight="1"
android:background="@drawable/pc_card"
android:orientation="vertical"
android:padding="14dp">
<LinearLayout
android:id="@+id/clients_pane"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingBottom="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Clients"
android:textColor="@color/pc_text"
android:textSize="15sp"
android:textStyle="bold" />
<TextView
android:id="@+id/clients_badge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:background="@drawable/pc_badge"
android:paddingStart="8dp"
android:paddingTop="2dp"
android:paddingEnd="8dp"
android:paddingBottom="2dp"
android:text="0"
android:textColor="@color/pc_text"
android:textSize="12sp" />
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1" />
<LinearLayout
android:id="@+id/btn_revoke_all"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:background="@drawable/pc_btn_danger"
android:focusable="true"
android:gravity="center_vertical"
android:nextFocusRight="@id/btn_revoke_all"
android:orientation="horizontal"
android:paddingStart="14dp"
android:paddingEnd="14dp">
<TextView
android:id="@+id/btn_revoke_all_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/lucide"
android:includeFontPadding="false"
android:textColor="@color/pc_red"
android:textSize="14sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="8dp"
android:text="Revoke all"
android:textColor="@color/pc_red"
android:textSize="13sp" />
</LinearLayout>
</LinearLayout>
<ScrollView
android:id="@+id/clients_scroll"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:focusable="false">
<LinearLayout
android:id="@+id/clients_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
</ScrollView>
</LinearLayout>
<LinearLayout
android:id="@+id/client_detail"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="gone">
<TextView
android:id="@+id/detail_body"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:textColor="@color/pc_text"
android:textSize="16sp" />
<Button
android:id="@+id/btn_revoke_one"
android:layout_width="wrap_content"
android:layout_height="44dp"
android:background="@drawable/pc_btn_danger"
android:focusable="true"
android:paddingStart="18dp"
android:paddingEnd="18dp"
android:text="Revoke client"
android:textColor="@color/pc_red" />
</LinearLayout>
<LinearLayout
android:id="@+id/log_overlay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="gone">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="8dp"
android:text="Logs"
android:textColor="@color/pc_text"
android:textSize="15sp"
android:textStyle="bold" />
<ScrollView
android:id="@+id/log_scroll"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:focusable="true">
<TextView
android:id="@+id/log_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/pc_text_secondary"
android:textSize="13sp" />
</ScrollView>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<FrameLayout
android:id="@+id/guided_step_overlay"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Fixed mode: D-pad cross (placement) + vertical zoom stack on the right. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="horizontal">
<!-- Zoom stack -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="28dp"
android:gravity="center_horizontal"
android:orientation="vertical">
<Button
android:id="@+id/fixed_zoom_in"
android:layout_width="64dp"
android:layout_height="48dp"
android:layout_marginBottom="4dp"
android:background="@drawable/pc_btn_secondary"
android:focusable="true"
android:fontFamily="@font/lucide"
android:gravity="center"
android:includeFontPadding="false"
android:nextFocusDown="@+id/fixed_zoom_out"
android:nextFocusRight="@+id/fixed_center"
android:nextFocusUp="@+id/header_overflow"
android:textAllCaps="false"
android:textColor="@color/pc_text"
android:textSize="20sp" />
<TextView
android:id="@+id/fixed_zoom_value"
android:layout_width="64dp"
android:layout_height="48dp"
android:layout_marginBottom="4dp"
android:focusable="false"
android:gravity="center"
android:text="1.0×"
android:textColor="@color/pc_text"
android:textSize="15sp"
android:textStyle="bold" />
<Button
android:id="@+id/fixed_zoom_out"
android:layout_width="64dp"
android:layout_height="48dp"
android:background="@drawable/pc_btn_secondary"
android:focusable="true"
android:fontFamily="@font/lucide"
android:gravity="center"
android:includeFontPadding="false"
android:nextFocusUp="@+id/fixed_zoom_in"
android:nextFocusRight="@+id/fixed_center"
android:textAllCaps="false"
android:textColor="@color/pc_text"
android:textSize="20sp" />
</LinearLayout>
<!-- Direction cross -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical">
<Button
android:id="@+id/fixed_up"
android:layout_width="56dp"
android:layout_height="48dp"
android:layout_marginBottom="4dp"
android:background="@drawable/pc_btn_secondary"
android:focusable="true"
android:nextFocusUp="@+id/header_overflow"
android:text="▲"
android:textAllCaps="false"
android:textColor="@color/pc_text"
android:textSize="16sp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<Button
android:id="@+id/fixed_left"
android:layout_width="56dp"
android:layout_height="48dp"
android:background="@drawable/pc_btn_secondary"
android:focusable="true"
android:nextFocusLeft="@+id/fixed_zoom_in"
android:text="◀"
android:textAllCaps="false"
android:textColor="@color/pc_text"
android:textSize="16sp" />
<Button
android:id="@+id/fixed_center"
android:layout_width="56dp"
android:layout_height="48dp"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"
android:background="@drawable/pc_btn_secondary"
android:focusable="true"
android:text="●"
android:textAllCaps="false"
android:textColor="@color/pc_text"
android:textSize="14sp" />
<Button
android:id="@+id/fixed_right"
android:layout_width="56dp"
android:layout_height="48dp"
android:background="@drawable/pc_btn_secondary"
android:focusable="true"
android:text="▶"
android:textAllCaps="false"
android:textColor="@color/pc_text"
android:textSize="16sp" />
</LinearLayout>
<Button
android:id="@+id/fixed_down"
android:layout_width="56dp"
android:layout_height="48dp"
android:background="@drawable/pc_btn_secondary"
android:focusable="true"
android:text="▼"
android:textAllCaps="false"
android:textColor="@color/pc_text"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>
@@ -0,0 +1,125 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/pc_card_inner"
android:focusable="true"
android:focusableInTouchMode="true"
android:gravity="center_vertical"
android:nextFocusRight="@+id/client_revoke"
android:orientation="horizontal"
android:padding="12dp">
<!-- Left: client info (equal weight keeps Paired At centered) -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/client_icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="@drawable/pc_icon_circle_green"
android:fontFamily="@font/lucide"
android:gravity="center"
android:includeFontPadding="false"
android:textColor="@color/pc_green"
android:textSize="18sp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:orientation="vertical">
<TextView
android:id="@+id/client_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/pc_text"
android:textSize="15sp"
android:textStyle="bold" />
<TextView
android:id="@+id/client_meta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textColor="@color/pc_text_secondary"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
<!-- Center: Paired At with separators on both sides -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="top"
android:orientation="horizontal">
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_marginEnd="28dp"
android:background="@color/pc_separator" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="start"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Paired At"
android:textColor="@color/pc_text_dim"
android:textSize="11sp" />
<TextView
android:id="@+id/client_paired_at"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/pc_text_secondary"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
<!-- Right: status + revoke (equal weight keeps center block centered) -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="end|center_vertical"
android:orientation="horizontal"
android:paddingStart="28dp">
<LinearLayout
android:id="@+id/client_connected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="gone">
<TextView
android:layout_width="8dp"
android:layout_height="8dp"
android:layout_marginEnd="6dp"
android:background="@drawable/pc_dot_green" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:text="Connected"
android:textColor="@color/pc_green"
android:textSize="13sp" />
</LinearLayout>
<Button
android:id="@+id/client_revoke"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:background="@drawable/pc_btn_danger"
android:focusable="true"
android:paddingStart="14dp"
android:paddingEnd="14dp"
android:text="Revoke"
android:textAllCaps="false"
android:textColor="@color/pc_red"
android:textSize="13sp" />
</LinearLayout>
</LinearLayout>
@@ -0,0 +1,122 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/pc_card_inner"
android:focusable="true"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="12dp">
<!-- Left: client info (equal weight keeps PIN centered) -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/pending_icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="@drawable/pc_icon_circle_yellow"
android:fontFamily="@font/lucide"
android:gravity="center"
android:includeFontPadding="false"
android:textColor="@color/pc_yellow"
android:textSize="18sp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Pairing request"
android:textColor="@color/pc_yellow"
android:textSize="11sp"
android:textStyle="bold" />
<TextView
android:id="@+id/pending_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="2dp"
android:textColor="@color/pc_text"
android:textSize="15sp"
android:textStyle="bold" />
<TextView
android:id="@+id/pending_meta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/pc_text_secondary"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
<!-- Center: PIN with separators; fixed value-row height for timer alignment -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="top"
android:orientation="horizontal">
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_marginEnd="28dp"
android:background="@color/pc_separator" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="start"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="PIN"
android:textColor="@color/pc_text_dim"
android:textSize="11sp" />
<TextView
android:id="@+id/pending_pin"
android:layout_width="wrap_content"
android:layout_height="28dp"
android:fontFamily="monospace"
android:gravity="center_vertical"
android:includeFontPadding="false"
android:textColor="@color/pc_text"
android:textSize="22sp"
android:textStyle="bold" />
</LinearLayout>
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_marginStart="28dp"
android:background="@color/pc_separator" />
</LinearLayout>
<!-- Right: label tops with PIN; timer centered on PIN value row -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="start"
android:orientation="vertical"
android:paddingStart="28dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Expires in"
android:textColor="@color/pc_text_dim"
android:textSize="11sp" />
<TextView
android:id="@+id/pending_expires"
android:layout_width="wrap_content"
android:layout_height="28dp"
android:fontFamily="monospace"
android:gravity="center_vertical"
android:includeFontPadding="false"
android:textColor="@color/pc_yellow"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_margin="4dp"
android:background="@drawable/pc_btn_secondary"
android:focusable="true"
android:textColor="@color/pc_text"
android:textSize="14sp" />
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/pc_mode_item"
android:focusable="true"
android:focusableInTouchMode="true"
android:gravity="center_vertical"
android:minHeight="52dp"
android:orientation="horizontal"
android:paddingStart="10dp"
android:paddingTop="8dp"
android:paddingEnd="10dp"
android:paddingBottom="8dp">
<TextView
android:id="@+id/mode_icon"
android:layout_width="36dp"
android:layout_height="36dp"
android:background="@null"
android:fontFamily="@font/lucide"
android:gravity="center"
android:includeFontPadding="false"
android:textColor="@color/pc_text_secondary"
android:textSize="36sp" />
<TextView
android:id="@+id/mode_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_weight="1"
android:textColor="@color/pc_text_secondary"
android:textSize="18sp" />
<TextView
android:id="@+id/mode_check"
android:layout_width="36dp"
android:layout_height="36dp"
android:fontFamily="@font/lucide"
android:gravity="center"
android:includeFontPadding="false"
android:textColor="@color/pc_text"
android:textSize="18sp"
android:visibility="gone" />
</LinearLayout>
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/lb_basic_card_bg_color"
android:focusable="true"
android:focusableInTouchMode="true"
android:orientation="vertical"
android:paddingStart="16dp"
android:paddingTop="12dp"
android:paddingEnd="16dp"
android:paddingBottom="12dp">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.Leanback.ImageCardView.Title" />
<TextView
android:id="@+id/subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="2dp"
android:textAppearance="@style/TextAppearance.Leanback.ImageCardView.Content" />
</LinearLayout>
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingTop="8dp"
android:paddingBottom="8dp">
<TextView
android:id="@+id/stat_icon"
android:layout_width="28dp"
android:layout_height="28dp"
android:gravity="center"
android:text="●"
android:textColor="@color/pc_text_secondary"
android:textSize="12sp" />
<TextView
android:id="@+id/stat_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingStart="8dp"
android:textColor="@color/pc_text_secondary"
android:textSize="13sp" />
<TextView
android:id="@+id/stat_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/pc_text"
android:textSize="14sp"
android:textStyle="bold" />
</LinearLayout>
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Reusable 1px horizontal separator (white @ 20%). Include with: <include layout="@layout/pc_separator_h" /> -->
<View xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/PcSeparatorHorizontal" />
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="pc_bg">#FF121418</color>
<color name="pc_card">#FF1C2025</color>
<color name="pc_card_inner">#FF252A31</color>
<color name="pc_card_inner_focus">#FF2E343C</color>
<color name="pc_stroke">#FF2A3038</color>
<color name="pc_blue">#FF2B7DE9</color>
<color name="pc_blue_soft">#332B7DE9</color>
<color name="pc_focus_outline">#FF8FC6F8</color>
<color name="pc_mode_selected">#FF1465B2</color>
<color name="pc_yellow">#FFFBBF24</color>
<color name="pc_red">#FFEF4444</color>
<color name="pc_red_soft">#33EF4444</color>
<color name="pc_green">#FF22C55E</color>
<color name="pc_green_soft">#3322C55E</color>
<color name="pc_text">#FFFFFFFF</color>
<color name="pc_text_secondary">#FF9CA3AF</color>
<color name="pc_text_dim">#FF6B7280</color>
<!-- Horizontal rule: 1px white @ 60% opacity -->
<color name="pc_separator">#33FFFFFF</color>
</resources>
+19 -1
View File
@@ -1 +1,19 @@
<resources><style name="AppTheme" parent="android:style/Theme.Material.NoActionBar"><item name="android:fontFamily">sans</item><item name="android:colorAccent">#80cbc4</item></style></resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="Theme.Leanback">
<item name="android:windowBackground">@color/pc_bg</item>
<item name="android:colorPrimary">@color/pc_blue</item>
<item name="android:colorAccent">@color/pc_blue</item>
<item name="defaultBrandColor">@color/pc_blue</item>
<item name="android:windowContentTransitions">true</item>
<item name="android:windowAllowEnterTransitionOverlap">true</item>
<item name="android:windowAllowReturnTransitionOverlap">true</item>
</style>
<!-- 1px white @ 20% — use on a View, or via @layout/pc_separator_h -->
<style name="PcSeparatorHorizontal">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">1px</item>
<item name="android:background">@color/pc_separator</item>
</style>
</resources>