sms-translate/app/src/main/res/layout/activity_settings.xml
Jeena 99649c54d7 feat: on-the-fly SMS translation via offline-translator AIDL
Adds a small `:translate` Gradle module that translates received SMS /
MMS bubbles and conversation-list snippets on the fly by binding to the
offline-translator app on F-Droid (`dev.davidv.translator`). The actual
translation runs there — Mozilla Bergamot/Marian on-device — so this
patch ships no model, no inference, and no permissions beyond an
Android 11+ <queries> block for package visibility.

Behavior:
- User-defined source-language allowlist + target language in
  Settings → Translation (right after Language). Off by default.
- Auto-translate fires on RecyclerView bind for received bubbles and
  conversation snippets. Detection uses ML Kit Language Identification
  (CLD3, on-device). Once dev.davidv.translator exposes a
  detectLanguage() AIDL method we'll route through that and drop ML Kit.
- AIDL latency is sub-second, so the bubble just quietly swaps from
  the original to the translation — no loading spinner.
- Tap the translate icon next to a bubble to flip it back to the
  original; tap again to flip to the translation. Cached in process
  memory.
- Long-press → ⋮ → Translate forces a one-off translation regardless
  of the allowlist (useful for messages in non-allowlisted languages),
  with a toast surfacing AIDL errors like 'language pack not installed'.
- Copy / Share / Select on a translated bubble captures what the user
  sees, not the underlying source body.
- Silently no-ops when offline-translator isn't installed; settings
  screen shows an F-Droid install banner.
- Translation Settings is a regular Fossify sub-screen with
  MyAppBarLayout + MaterialToolbar + NestedScrollView, matching
  Manage Blocked Numbers / Keywords / SettingsActivity.

No new database, no service, no boot receiver, no foreground service.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 04:44:51 +00:00

515 lines
22 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/settings_coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.fossify.commons.views.MyAppBarLayout
android:id="@+id/settings_appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/settings_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/color_primary"
app:title="@string/settings"
app:titleTextAppearance="@style/AppTheme.ActionBar.TitleTextStyle" />
</org.fossify.commons.views.MyAppBarLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/settings_nested_scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:scrollbars="none"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:id="@+id/settings_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/settings_color_customization_section_label"
style="@style/SettingsSectionLabelStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/color_customization" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/settings_color_customization_holder"
style="@style/SettingsHolderTextViewOneLinerStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyTextView
android:id="@+id/settings_color_customization_label"
style="@style/SettingsTextLabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/customize_colors"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<include
android:id="@+id/settings_color_customization_divider"
layout="@layout/divider" />
<TextView
android:id="@+id/settings_general_settings_label"
style="@style/SettingsSectionLabelStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/general_settings" />
<org.fossify.commons.views.PurchaseThankYouItem
android:id="@+id/settings_purchase_thank_you_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<RelativeLayout
android:id="@+id/settings_use_english_holder"
style="@style/SettingsHolderSwitchStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyMaterialSwitch
android:id="@+id/settings_use_english"
style="@style/SettingsSwitchStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/use_english_language" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_language_holder"
style="@style/SettingsHolderTextViewStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyTextView
android:id="@+id/settings_language_label"
style="@style/SettingsTextLabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/language" />
<org.fossify.commons.views.MyTextView
android:id="@+id/settings_language"
style="@style/SettingsTextValueStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/settings_language_label"
tools:text="English" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_translation_holder"
style="@style/SettingsHolderTextViewOneLinerStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyTextView
android:id="@+id/settings_translation"
style="@style/SettingsTextLabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/translation_settings" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_change_date_time_format_holder"
style="@style/SettingsHolderTextViewOneLinerStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyTextView
android:id="@+id/settings_change_date_time_format"
style="@style/SettingsTextLabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/change_date_and_time_format" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_manage_blocked_numbers_holder"
style="@style/SettingsHolderTextViewOneLinerStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyTextView
android:id="@+id/settings_manage_blocked_numbers"
style="@style/SettingsTextLabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/manage_blocked_numbers" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_manage_blocked_keywords_holder"
style="@style/SettingsHolderTextViewOneLinerStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyTextView
android:id="@+id/settings_manage_blocked_keywords"
style="@style/SettingsTextLabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/manage_blocked_keywords" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_font_size_holder"
style="@style/SettingsHolderTextViewStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyTextView
android:id="@+id/settings_font_size_label"
style="@style/SettingsTextLabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/font_size" />
<org.fossify.commons.views.MyTextView
android:id="@+id/settings_font_size"
style="@style/SettingsTextValueStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/settings_font_size_label"
tools:text="@string/medium" />
</RelativeLayout>
<include
android:id="@+id/settings_general_settings_divider"
layout="@layout/divider" />
<TextView
android:id="@+id/settings_notifications_label"
style="@style/SettingsSectionLabelStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/notifications" />
<RelativeLayout
android:id="@+id/settings_customize_notifications_holder"
style="@style/SettingsHolderTextViewOneLinerStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyTextView
android:id="@+id/settings_customize_notifications_label"
style="@style/SettingsTextLabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/customize_notifications" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_lock_screen_visibility_holder"
style="@style/SettingsHolderTextViewStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyTextView
android:id="@+id/settings_lock_screen_visibility_label"
style="@style/SettingsTextLabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/lock_screen_visibility" />
<org.fossify.commons.views.MyTextView
android:id="@+id/settings_lock_screen_visibility"
style="@style/SettingsTextValueStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/settings_lock_screen_visibility_label"
tools:text="@string/sender_and_message" />
</RelativeLayout>
<include
android:id="@+id/settings_notifications_divider"
layout="@layout/divider" />
<TextView
android:id="@+id/settings_outgoing_messages_label"
style="@style/SettingsSectionLabelStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/outgoing_messages" />
<RelativeLayout
android:id="@+id/settings_show_character_counter_holder"
style="@style/SettingsHolderSwitchStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyMaterialSwitch
android:id="@+id/settings_show_character_counter"
style="@style/SettingsSwitchStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/show_character_counter" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_use_simple_characters_holder"
style="@style/SettingsHolderSwitchStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyMaterialSwitch
android:id="@+id/settings_use_simple_characters"
style="@style/SettingsSwitchStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/use_simple_characters" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_send_on_enter_holder"
style="@style/SettingsHolderSwitchStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyMaterialSwitch
android:id="@+id/settings_send_on_enter"
style="@style/SettingsSwitchStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/send_on_enter" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_enable_delivery_reports_holder"
style="@style/SettingsHolderSwitchStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyMaterialSwitch
android:id="@+id/settings_enable_delivery_reports"
style="@style/SettingsSwitchStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/enable_delivery_reports" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_send_long_message_mms_holder"
style="@style/SettingsHolderSwitchStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyMaterialSwitch
android:id="@+id/settings_send_long_message_mms"
style="@style/SettingsSwitchStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/send_long_message_mms" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_send_group_message_mms_holder"
style="@style/SettingsHolderSwitchStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyMaterialSwitch
android:id="@+id/settings_send_group_message_mms"
style="@style/SettingsSwitchStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/group_message_mms" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_mms_file_size_limit_holder"
style="@style/SettingsHolderTextViewStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyTextView
android:id="@+id/settings_mms_file_size_limit_label"
style="@style/SettingsTextLabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/mms_file_size_limit" />
<org.fossify.commons.views.MyTextView
android:id="@+id/settings_mms_file_size_limit"
style="@style/SettingsTextValueStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/settings_mms_file_size_limit_label"
tools:text="@string/mms_file_size_limit_none" />
</RelativeLayout>
<include
android:id="@+id/settings_outgoing_messages_divider"
layout="@layout/divider" />
<TextView
android:id="@+id/settings_archived_messages_label"
style="@style/SettingsSectionLabelStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/archived_conversations" />
<RelativeLayout
android:id="@+id/settings_keep_conversations_archived_holder"
style="@style/SettingsHolderSwitchStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyMaterialSwitch
android:id="@+id/settings_keep_conversations_archived"
style="@style/SettingsSwitchStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/keep_conversations_archived" />
</RelativeLayout>
<include
android:id="@+id/settings_archive_divider"
layout="@layout/divider" />
<TextView
android:id="@+id/settings_recycle_bin_label"
style="@style/SettingsSectionLabelStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/recycle_bin" />
<RelativeLayout
android:id="@+id/settings_use_recycle_bin_holder"
style="@style/SettingsHolderSwitchStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyMaterialSwitch
android:id="@+id/settings_use_recycle_bin"
style="@style/SettingsSwitchStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/move_items_into_recycle_bin" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_empty_recycle_bin_holder"
style="@style/SettingsHolderTextViewStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyTextView
android:id="@+id/settings_empty_recycle_bin_label"
style="@style/SettingsTextLabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/empty_recycle_bin" />
<org.fossify.commons.views.MyTextView
android:id="@+id/settings_empty_recycle_bin_size"
style="@style/SettingsTextValueStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/settings_empty_recycle_bin_label"
tools:text="0 B" />
</RelativeLayout>
<include
android:id="@+id/settings_recycle_bin_divider"
layout="@layout/divider" />
<TextView
android:id="@+id/settings_security_label"
style="@style/SettingsSectionLabelStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/security" />
<RelativeLayout
android:id="@+id/settings_app_password_protection_holder"
style="@style/SettingsHolderSwitchStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyMaterialSwitch
android:id="@+id/settings_app_password_protection"
style="@style/SettingsSwitchStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/password_protect_whole_app" />
</RelativeLayout>
<include
android:id="@+id/settings_migrating_divider"
layout="@layout/divider" />
<TextView
android:id="@+id/settings_migrating_label"
style="@style/SettingsSectionLabelStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/migrating" />
<RelativeLayout
android:id="@+id/settings_export_messages_holder"
style="@style/SettingsHolderTextViewOneLinerStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyTextView
android:id="@+id/settings_export_messages"
style="@style/SettingsTextLabelStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/export_messages" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_import_messages_holder"
style="@style/SettingsHolderTextViewOneLinerStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyTextView
android:id="@+id/settings_import_messages"
style="@style/SettingsTextLabelStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/import_messages" />
</RelativeLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>