feat(android): scaffold kotlin app with settings screen and foreground service shell

This commit is contained in:
Dark-Avery
2026-03-16 19:45:57 +03:00
parent ec70188385
commit 47e5c6241d
22 changed files with 1110 additions and 0 deletions
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#1E88E5"
android:pathData="M54,10A44,44 0 1,1 10,54A44,44 0 0,1 54,10Z" />
<path
android:fillColor="#FFFFFF"
android:pathData="M33,34h42v10H59v30H49V44H33z" />
</vector>
@@ -0,0 +1,151 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dp">
<TextView
android:id="@+id/titleText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
android:textStyle="bold" />
<TextView
android:id="@+id/subtitleText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/subtitle"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium" />
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
app:cardCornerRadius="20dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="18dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/status_label"
android:textAppearance="@style/TextAppearance.Material3.LabelLarge" />
<TextView
android:id="@+id/statusValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:text="@string/status_stopped"
android:textAppearance="@style/TextAppearance.Material3.TitleMedium"
android:textStyle="bold" />
<TextView
android:id="@+id/serviceHint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@string/service_hint_idle"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:hint="@string/host_hint">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/hostInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:maxLines="1" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:hint="@string/port_hint">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/portInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:maxLines="1" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:hint="@string/dc_ip_hint">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/dcIpInput"
android:layout_width="match_parent"
android:layout_height="140dp"
android:gravity="top|start"
android:inputType="textMultiLine"
android:minLines="5" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/verboseSwitch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/verbose_label" />
<TextView
android:id="@+id/errorText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
android:textColor="?attr/colorError"
android:visibility="gone" />
<com.google.android.material.button.MaterialButton
android:id="@+id/saveButton"
style="@style/Widget.Material3.Button.OutlinedButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="18dp"
android:text="@string/save_button" />
<com.google.android.material.button.MaterialButton
android:id="@+id/startButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/start_button" />
<com.google.android.material.button.MaterialButton
android:id="@+id/stopButton"
style="@style/Widget.Material3.Button.OutlinedButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:enabled="false"
android:text="@string/stop_button" />
</LinearLayout>
</ScrollView>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="proxy_blue">#1E88E5</color>
<color name="proxy_navy">#0B1F33</color>
<color name="proxy_surface">#F4F8FC</color>
<color name="proxy_white">#FFFFFF</color>
</resources>
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">TG WS Proxy</string>
<string name="subtitle">Android shell for the local Telegram SOCKS5 proxy. The embedded Python runtime will be wired in the next commit.</string>
<string name="status_label">Foreground service</string>
<string name="status_running">Running</string>
<string name="status_stopped">Stopped</string>
<string name="service_hint_idle">The Android service shell is ready. Save settings, then start the service.</string>
<string name="service_hint_running">Foreground service active for %1$s:%2$d. Python proxy bootstrap will be connected next.</string>
<string name="host_hint">Proxy host</string>
<string name="port_hint">Proxy port</string>
<string name="dc_ip_hint">DC to IP mappings (one DC:IP per line)</string>
<string name="verbose_label">Verbose logging</string>
<string name="save_button">Save Settings</string>
<string name="start_button">Start Service</string>
<string name="stop_button">Stop Service</string>
<string name="settings_saved">Settings saved</string>
<string name="service_start_requested">Foreground service start requested</string>
<string name="notification_title">TG WS Proxy</string>
<string name="notification_channel_name">Proxy service</string>
<string name="notification_channel_description">Keeps the Telegram proxy service alive in the foreground.</string>
</resources>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="Theme.TgWsProxy" parent="Theme.Material3.Light.NoActionBar">
<item name="colorPrimary">@color/proxy_blue</item>
<item name="colorSecondary">@color/proxy_navy</item>
<item name="android:statusBarColor">@color/proxy_navy</item>
<item name="android:navigationBarColor">@color/proxy_white</item>
<item name="colorSurface">@color/proxy_surface</item>
<item name="android:windowLightStatusBar" tools:targetApi="m">false</item>
</style>
</resources>