/* * mygram-droid: Android TV client for Foldergram. * Copyright (C) 2026 Danilo M. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ package mygram.droid; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.text.InputType; import android.view.ViewGroup; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.ScrollView; import android.widget.Toast; /** Viewer password, durations, app PIN, change instance. */ public final class SettingsActivity extends Activity { private static final int PIN_INPUT = InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD; @Override protected void onCreate(Bundle state) { super.onCreate(state); LinearLayout box = Ui.column(this); box.addView(Ui.text(this, Prefs.server(), 18)); box.addView(Ui.text(this, "Viewer password", 14)); EditText pw = Ui.field(this, "Password", Ui.password()); pw.setText(Prefs.password()); box.addView(pw); box.addView(Ui.text(this, "Photo duration, seconds", 14)); EditText photo = Ui.field(this, "8", InputType.TYPE_CLASS_NUMBER); photo.setText(String.valueOf(Prefs.photoSeconds())); box.addView(photo); box.addView(Ui.text(this, "Background change, seconds", 14)); EditText bg = Ui.field(this, "15", InputType.TYPE_CLASS_NUMBER); bg.setText(String.valueOf(Prefs.backgroundSeconds())); box.addView(bg); box.addView(Ui.text(this, Prefs.hasPin() ? "New app PIN, 4 to 8 digits (empty keeps it)" : "App PIN, 4 to 8 digits (empty for none)", 14)); EditText pin = Ui.field(this, "PIN", PIN_INPUT); box.addView(pin); EditText again = Ui.field(this, "Repeat PIN", PIN_INPUT); box.addView(again); LinearLayout row = Ui.row(this); row.addView(Ui.iconButton(this, R.drawable.ic_check, "Save", v -> save(pw.getText().toString(), photo.getText().toString(), bg.getText().toString(), pin.getText().toString(), again.getText().toString()))); if (Prefs.hasPin()) row.addView(Ui.iconButton(this, R.drawable.ic_lock_open, "Remove PIN", v -> { Prefs.setPin(null); Toast.makeText(this, "PIN removed", Toast.LENGTH_SHORT).show(); finish(); })); row.addView(Ui.iconButton(this, R.drawable.ic_swap, "Change instance", v -> startActivity(new Intent(this, SetupActivity.class)))); box.addView(row); // Taller than the screen with the PIN fields; the scroll view follows focus. ScrollView scroll = new ScrollView(this); scroll.addView(box); LinearLayout column = new LinearLayout(this); column.setOrientation(LinearLayout.VERTICAL); column.addView(Ui.header(this, "Settings")); column.addView(scroll, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, 1)); setContentView(column); row.getChildAt(0).requestFocus(); } private void save(String password, String photo, String background, String pin, String again) { int p = seconds(photo), b = seconds(background); if (p < 1 || b < 1) { toast("Durations must be 1 to 600 seconds"); return; } if (!pin.isEmpty() || !again.isEmpty()) { if (!Prefs.validPin(pin)) { toast("The PIN must be 4 to 8 digits"); return; } if (!pin.equals(again)) { toast("The two PINs differ"); return; } } Prefs.setTimes(p, b); if (!pin.isEmpty()) { Prefs.setPin(pin); App.locked = false; // just typed it; ask from the next time the app leaves the screen } if (password.equals(Prefs.password())) { finish(); return; } Api.async(() -> { Api.login(Prefs.server(), password); return true; }, ok -> { Prefs.setPassword(password); finish(); }, e -> toast("Login failed: " + e.getMessage())); } private void toast(String s) { Toast.makeText(this, s, Toast.LENGTH_LONG).show(); } private static int seconds(String s) { try { int v = Integer.parseInt(s.trim()); return v <= 600 ? v : -1; } catch (NumberFormatException e) { return -1; } } }