This commit is contained in:
jahruz67
2026-05-21 16:51:20 -07:00
parent c78c430c43
commit b4d312da41
4 changed files with 106 additions and 69 deletions
@@ -73,6 +73,7 @@ public class MainActivity extends Activity {
private Calendar visibleMonthCalendar;
private int loadGeneration;
private float readingFontSp;
private boolean isEnglish;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -85,6 +86,7 @@ public class MainActivity extends Activity {
preferences = getSharedPreferences("preferencias_lectura", MODE_PRIVATE);
readingFontSp = preferences.getFloat("tamano_letra", 20f);
isEnglish = preferences.getBoolean("is_english", false);
selectedDateCalendar = startOfDay(Calendar.getInstance());
visibleMonthCalendar = startOfMonth(selectedDateCalendar);
executor = Executors.newSingleThreadExecutor();
@@ -102,6 +104,16 @@ public class MainActivity extends Activity {
}
}
@Override
protected void onResume() {
super.onResume();
boolean currentLanguage = UpdateManager.isEnglish(this);
if (currentLanguage != isEnglish) {
isEnglish = currentLanguage;
recreate();
}
}
private View createScreen() {
FrameLayout root = new FrameLayout(this);
root.setBackgroundColor(COLOR_BACKGROUND);
@@ -201,7 +213,7 @@ public class MainActivity extends Activity {
topRow.addView(createDateChip());
header.addView(topRow);
TextView title = textView("Palabra del día", 34, COLOR_INK, Typeface.BOLD);
TextView title = textView(isEnglish ? "Word of the day" : "Palabra del día", 34, COLOR_INK, Typeface.BOLD);
title.setIncludeFontPadding(false);
LinearLayout.LayoutParams titleParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
@@ -245,7 +257,7 @@ public class MainActivity extends Activity {
button.setGravity(Gravity.CENTER);
button.setPadding(dp(16), 0, dp(16), 0);
button.setBackground(roundedRect(COLOR_ACCENT, dp(8), Color.TRANSPARENT, 0));
button.setContentDescription("Abrir extras");
button.setContentDescription(isEnglish ? "Open extras" : "Abrir extras");
button.setOnClickListener(view -> {
calendarPanel.setVisibility(View.GONE);
if (fontPanel != null) {
@@ -262,7 +274,7 @@ public class MainActivity extends Activity {
chip.setGravity(Gravity.CENTER_VERTICAL);
chip.setPadding(dp(12), dp(8), dp(10), dp(8));
chip.setBackground(roundedRect(Color.WHITE, dp(8), Color.rgb(219, 226, 222), dp(1)));
chip.setContentDescription("Elegir fecha");
chip.setContentDescription(isEnglish ? "Choose date" : "Elegir fecha");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
chip.setElevation(dp(1));
}
@@ -602,20 +614,8 @@ public class MainActivity extends Activity {
}
private void checkForUpdateOnStartup() {
if (!UpdateManager.isAutoUpdatesEnabled(this) || executor == null || executor.isShutdown()) {
return;
}
executor.submit(() -> {
try {
UpdateManager.UpdateInfo info = UpdateManager.fetchLatestUpdate(this);
if (info.updateAvailable) {
runOnUiThread(() -> UpdateManager.showUpdateDialog(this, info));
}
} catch (Exception ignored) {
// Startup update checks stay quiet so daily readings remain the main experience.
}
});
// Auto updates are disabled as per user request.
// We only keep the manual check in SettingsActivity.
}
private void loadSelectedDate() {
@@ -652,34 +652,40 @@ public class MainActivity extends Activity {
sectionsLayout.removeAllViews();
statusBlock.setVisibility(View.VISIBLE);
dateText.setText(formatDisplayDate(date));
liturgyText.setText("Lecturas según la fecha del dispositivo.");
statusText.setText("Cargando la Palabra de hoy...");
liturgyText.setText(isEnglish ? "Readings according to device date." : "Lecturas según la fecha del dispositivo.");
statusText.setText(isEnglish ? "Loading today's Word..." : "Cargando la Palabra de hoy...");
progressBar.setVisibility(View.VISIBLE);
retryButton.setVisibility(View.GONE);
sourceText.setText("Fuente: Vatican News\n" + url);
sourceText.setText((isEnglish ? "Source: " : "Fuente: ") + "Vatican News\n" + url);
}
private void renderReading(DailyReading reading) {
statusBlock.setVisibility(View.GONE);
progressBar.setVisibility(View.GONE);
retryButton.setVisibility(View.GONE);
statusText.setText("Actualizado desde Vatican News.");
statusText.setText(isEnglish ? "Updated from Vatican News." : "Actualizado desde Vatican News.");
resizableTextViews.clear();
sectionsLayout.removeAllViews();
dateText.setText(reading.displayDate);
if (reading.liturgicalTitle.isEmpty()) {
liturgyText.setText("Palabra del día");
liturgyText.setText(isEnglish ? "Word of the day" : "Palabra del día");
} else {
liturgyText.setText(reading.liturgicalTitle);
}
if (isEnglish) {
addScriptureCard("Word of God", "Gospel of the Day", reading.gospel, true);
addScriptureCard("Reading of the Day", null, reading.firstReading, false);
addReflectionCard(reading.papalWords);
sourceText.setText("Source: Vatican News\n" + reading.sourceUrl);
} else {
addScriptureCard("Palabra de Dios", "Evangelio del Día", reading.gospel, true);
addScriptureCard("Lectura del Día", null, reading.firstReading, false);
addReflectionCard(reading.papalWords);
sourceText.setText("Fuente: Vatican News\n" + reading.sourceUrl);
}
applyReadingFontSize();
}
@@ -687,10 +693,11 @@ public class MainActivity extends Activity {
statusBlock.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
retryButton.setVisibility(View.VISIBLE);
retryButton.setText(isEnglish ? "Retry" : "Reintentar");
sectionsLayout.removeAllViews();
statusText.setText("No se pudo cargar la lectura de hoy. Revisa la conexión e intenta de nuevo.\n\n"
statusText.setText(isEnglish ? "Could not load today's reading. Check your connection and try again.\n\n" : "No se pudo cargar la lectura de hoy. Revisa la conexión e intenta de nuevo.\n\n"
+ cleanErrorMessage(error));
sourceText.setText("Fuente prevista: Vatican News\n" + url);
sourceText.setText((isEnglish ? "Intended source: " : "Fuente prevista: ") + "Vatican News\n" + url);
}
private void addScriptureCard(String title, String overline, DailySection section, boolean featured) {
@@ -701,7 +708,7 @@ public class MainActivity extends Activity {
LinearLayout card = createCard(featured ? dp(22) : dp(18));
if (overline != null && !overline.isEmpty()) {
TextView overlineText = textView(overline.toUpperCase(spanishLocale), 12, COLOR_WARM, Typeface.BOLD);
TextView overlineText = textView(overline.toUpperCase(isEnglish ? Locale.US : spanishLocale), 12, COLOR_WARM, Typeface.BOLD);
card.addView(overlineText);
}
@@ -749,7 +756,7 @@ public class MainActivity extends Activity {
LinearLayout card = createCard(dp(18));
TextView title = textView("Las palabras de los Papas", 22, COLOR_INK, Typeface.BOLD);
TextView title = textView(isEnglish ? "The Pope's words" : "Las palabras de los Papas", 22, COLOR_INK, Typeface.BOLD);
title.setIncludeFontPadding(false);
card.addView(title);
@@ -797,11 +804,11 @@ public class MainActivity extends Activity {
connection.setConnectTimeout(12000);
connection.setReadTimeout(12000);
connection.setRequestProperty("User-Agent", "BibliaDiaria/1.0 Android");
connection.setRequestProperty("Accept-Language", "es-ES,es;q=0.9");
connection.setRequestProperty("Accept-Language", isEnglish ? "en-US,en;q=0.9" : "es-ES,es;q=0.9");
int responseCode = connection.getResponseCode();
if (responseCode < 200 || responseCode >= 300) {
throw new IOException("Vatican News respondió con código " + responseCode + ".");
throw new IOException(isEnglish ? "Vatican News responded with code " + responseCode + "." : "Vatican News respondió con código " + responseCode + ".");
}
try (InputStream stream = connection.getInputStream()) {
@@ -824,27 +831,42 @@ public class MainActivity extends Activity {
}
private DailyReading parseDailyReading(String html, Date date, String url) throws IOException {
String firstReadingText = extractHtmlContentByHeading(html, "Lectura del Día");
String gospelText = extractHtmlContentByHeading(html, "Evangelio del Día");
String papalText = extractHtmlContentByHeading(html, "Las palabras de los Papas");
String firstReadingHeading = isEnglish ? "Reading of the Day" : "Lectura del Día";
String gospelHeading = isEnglish ? "Gospel of the Day" : "Evangelio del Día";
String papalHeading = isEnglish ? "The Pope's words" : "Las palabras de los Papas";
String firstReadingText = extractHtmlContentByHeading(html, firstReadingHeading);
String gospelText = extractHtmlContentByHeading(html, gospelHeading);
String papalText = extractHtmlContentByHeading(html, papalHeading);
String plainText = htmlToPlainText(html);
if (firstReadingText.isEmpty()) {
firstReadingText = extractSection(plainText, "Lectura del Día", "Evangelio del Día");
firstReadingText = extractSection(plainText, firstReadingHeading, gospelHeading);
}
if (gospelText.isEmpty()) {
gospelText = extractSection(plainText, "Evangelio del Día", "Las palabras de los Papas");
gospelText = extractSection(plainText, gospelHeading, papalHeading);
}
if (papalText.isEmpty()) {
if (isEnglish) {
papalText = extractSection(
plainText,
"Las palabras de los Papas",
papalHeading,
"His contribution",
"The texts of the Holy Scripture",
"Send",
"Other scheduled events"
);
} else {
papalText = extractSection(
plainText,
papalHeading,
"Su contribución",
"Los textos de la Sagrada Escritura",
"Enviar",
"Otros eventos programados"
);
}
}
DailySection firstReading = DailySection.fromScripture(firstReadingText);
DailySection gospel = DailySection.fromScripture(gospelText);
@@ -1030,21 +1052,22 @@ public class MainActivity extends Activity {
return htmlTitle;
}
String dateToken = new SimpleDateFormat("dd/MM/yyyy", spanishLocale).format(date);
int start = text.indexOf("Fecha" + dateToken);
String dateToken = new SimpleDateFormat("dd/MM/yyyy", isEnglish ? Locale.US : spanishLocale).format(date);
String dateLabel = isEnglish ? "Date" : "Fecha";
int start = text.indexOf(dateLabel + dateToken);
if (start >= 0) {
start += ("Fecha" + dateToken).length();
start += (dateLabel + dateToken).length();
} else {
start = text.indexOf("Fecha");
start = text.indexOf(dateLabel);
if (start < 0) {
return "";
}
start += "Fecha".length();
start += dateLabel.length();
}
int end = text.indexOf("La Palabra del día es", start);
int end = text.indexOf(isEnglish ? "Today's Word is" : "La Palabra del día es", start);
if (end < 0) {
end = text.indexOf("Lectura del Día", start);
end = text.indexOf(isEnglish ? "Reading of the Day" : "Lectura del Día", start);
}
if (end < 0 || end <= start) {
return "";
@@ -1111,15 +1134,20 @@ public class MainActivity extends Activity {
private String buildVaticanUrl(Date date) {
String pathDate = new SimpleDateFormat("yyyy/MM/dd", Locale.US).format(date);
return "https://www.vaticannews.va/es/evangelio-de-hoy/" + pathDate + ".html";
String langPath = isEnglish ? "en" : "es";
String pageName = isEnglish ? "word-of-the-day" : "evangelio-de-hoy";
return "https://www.vaticannews.va/" + langPath + "/" + pageName + "/" + pathDate + ".html";
}
private String formatDisplayDate(Date date) {
if (isEnglish) {
return new SimpleDateFormat("EEEE, MMMM d, yyyy", Locale.US).format(date);
}
return new SimpleDateFormat("EEEE, d 'de' MMMM 'de' yyyy", spanishLocale).format(date);
}
private String formatMonthTitle(Date date) {
return new SimpleDateFormat("MMMM yyyy", spanishLocale).format(date);
return new SimpleDateFormat("MMMM yyyy", isEnglish ? Locale.US : spanishLocale).format(date);
}
private void updateDateChip() {
@@ -1128,8 +1156,9 @@ public class MainActivity extends Activity {
}
Date selectedDate = selectedDateCalendar.getTime();
dateChipPrimary.setText(new SimpleDateFormat("EEE d", spanishLocale).format(selectedDate));
dateChipSecondary.setText(new SimpleDateFormat("MMM yyyy", spanishLocale).format(selectedDate));
Locale locale = isEnglish ? Locale.US : spanishLocale;
dateChipPrimary.setText(new SimpleDateFormat("EEE d", locale).format(selectedDate));
dateChipSecondary.setText(new SimpleDateFormat("MMM yyyy", locale).format(selectedDate));
}
private Calendar startOfDay(Calendar calendar) {
@@ -82,7 +82,7 @@ public class SettingsActivity extends Activity {
titleParams.setMargins(0, dp(18), 0, dp(18));
content.addView(title, titleParams);
content.addView(createAutoUpdatesCard());
content.addView(createLanguageCard());
content.addView(createVersionCard());
checkButton = actionButton("Check now", COLOR_ACCENT, Color.WHITE);
@@ -151,7 +151,7 @@ public class SettingsActivity extends Activity {
return topBar;
}
private View createAutoUpdatesCard() {
private View createLanguageCard() {
LinearLayout card = createCard();
card.setOrientation(LinearLayout.HORIZONTAL);
card.setGravity(Gravity.CENTER_VERTICAL);
@@ -159,11 +159,11 @@ public class SettingsActivity extends Activity {
LinearLayout copy = new LinearLayout(this);
copy.setOrientation(LinearLayout.VERTICAL);
TextView title = textView("Auto updates", 20, COLOR_INK, Typeface.BOLD);
TextView title = textView("Language", 20, COLOR_INK, Typeface.BOLD);
title.setIncludeFontPadding(false);
copy.addView(title);
TextView subtitle = textView("Check for new builds on startup", 14, COLOR_MUTED, Typeface.NORMAL);
TextView subtitle = textView("Select the language for daily readings", 14, COLOR_MUTED, Typeface.NORMAL);
LinearLayout.LayoutParams subtitleParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
@@ -177,14 +177,13 @@ public class SettingsActivity extends Activity {
1f
));
Switch autoSwitch = new Switch(this);
autoSwitch.setChecked(UpdateManager.isAutoUpdatesEnabled(this));
autoSwitch.setContentDescription("Auto updates");
autoSwitch.setOnCheckedChangeListener((button, checked) -> {
UpdateManager.setAutoUpdatesEnabled(this, checked);
statusText.setText(checked ? "Startup checks are on." : "Startup checks are off.");
TextView langToggle = actionButton(UpdateManager.isEnglish(this) ? "English" : "Spanish", COLOR_ACCENT, Color.WHITE);
langToggle.setOnClickListener(view -> {
boolean current = UpdateManager.isEnglish(this);
UpdateManager.setEnglish(this, !current);
langToggle.setText(!current ? "English" : "Spanish");
});
card.addView(autoSwitch);
card.addView(langToggle, new LinearLayout.LayoutParams(dp(100), dp(40)));
return card;
}
@@ -23,6 +23,7 @@ import java.nio.charset.StandardCharsets;
final class UpdateManager {
static final String PREFS_NAME = "preferencias_lectura";
static final String KEY_AUTO_UPDATES = "auto_updates_enabled";
static final String KEY_IS_ENGLISH = "is_english";
static final String LATEST_JSON_URL =
"https://github.com/jahruz67/Bible-Daily/releases/download/latest/latest.json";
static final String APK_URL =
@@ -39,6 +40,14 @@ final class UpdateManager {
preferences(context).edit().putBoolean(KEY_AUTO_UPDATES, enabled).apply();
}
static boolean isEnglish(Context context) {
return preferences(context).getBoolean(KEY_IS_ENGLISH, false);
}
static void setEnglish(Context context, boolean enabled) {
preferences(context).edit().putBoolean(KEY_IS_ENGLISH, enabled).apply();
}
static UpdateInfo fetchLatestUpdate(Context context) throws Exception {
String jsonText = download(LATEST_JSON_URL, "application/json");
JSONObject json = new JSONObject(jsonText);
File diff suppressed because one or more lines are too long