summaryrefslogtreecommitdiff
path: root/ui/common/src/main/java
diff options
context:
space:
mode:
authorByteHamster <ByteHamster@users.noreply.github.com>2024-03-17 18:43:55 +0100
committerGitHub <noreply@github.com>2024-03-17 18:43:55 +0100
commit0cbd97b5cbffa5ba1b2458a2b33248e98a376d7e (patch)
treeb1967d54efbcc71bc07bd8ef40f0d371c8b0f292 /ui/common/src/main/java
parent17f5a5d1b85f07bada36abe6541ed0fc1e1d83a2 (diff)
downloadAntennaPod-0cbd97b5cbffa5ba1b2458a2b33248e98a376d7e.zip
Move theme to :ui:common module (#6997)
This enables creating Activities outside the app and core modules
Diffstat (limited to 'ui/common/src/main/java')
-rw-r--r--ui/common/src/main/java/de/danoeh/antennapod/ui/common/Converter.java123
-rw-r--r--ui/common/src/main/java/de/danoeh/antennapod/ui/common/DateFormatter.java39
-rw-r--r--ui/common/src/main/java/de/danoeh/antennapod/ui/common/ThemeSwitcher.java72
3 files changed, 234 insertions, 0 deletions
diff --git a/ui/common/src/main/java/de/danoeh/antennapod/ui/common/Converter.java b/ui/common/src/main/java/de/danoeh/antennapod/ui/common/Converter.java
new file mode 100644
index 000000000..05fb2dcbc
--- /dev/null
+++ b/ui/common/src/main/java/de/danoeh/antennapod/ui/common/Converter.java
@@ -0,0 +1,123 @@
+package de.danoeh.antennapod.ui.common;
+
+import android.content.Context;
+
+import android.content.res.Resources;
+import java.util.Locale;
+
+/** Provides methods for converting various units. */
+public final class Converter {
+ /** Class shall not be instantiated. */
+ private Converter() {
+ }
+
+ private static final int HOURS_MIL = 3600000;
+ private static final int MINUTES_MIL = 60000;
+ private static final int SECONDS_MIL = 1000;
+
+ /**
+ * Converts milliseconds to a string containing hours, minutes and seconds.
+ */
+ public static String getDurationStringLong(int duration) {
+ if (duration <= 0) {
+ return "00:00:00";
+ } else {
+ int[] hms = millisecondsToHms(duration);
+ return String.format(Locale.getDefault(), "%02d:%02d:%02d", hms[0], hms[1], hms[2]);
+ }
+ }
+
+ private static int[] millisecondsToHms(long duration) {
+ int h = (int) (duration / HOURS_MIL);
+ long rest = duration - h * HOURS_MIL;
+ int m = (int) (rest / MINUTES_MIL);
+ rest -= m * MINUTES_MIL;
+ int s = (int) (rest / SECONDS_MIL);
+ return new int[] {h, m, s};
+ }
+
+ /**
+ * Converts milliseconds to a string containing hours and minutes or minutes and seconds.
+ */
+ public static String getDurationStringShort(int duration, boolean durationIsInHours) {
+ int firstPartBase = durationIsInHours ? HOURS_MIL : MINUTES_MIL;
+ int firstPart = duration / firstPartBase;
+ int leftoverFromFirstPart = duration - firstPart * firstPartBase;
+ int secondPart = leftoverFromFirstPart / (durationIsInHours ? MINUTES_MIL : SECONDS_MIL);
+
+ return String.format(Locale.getDefault(), "%02d:%02d", firstPart, secondPart);
+ }
+
+ /**
+ * Converts long duration string (HH:MM:SS) to milliseconds.
+ */
+ public static int durationStringLongToMs(String input) {
+ String[] parts = input.split(":");
+ if (parts.length != 3) {
+ return 0;
+ }
+ return Integer.parseInt(parts[0]) * 3600 * 1000
+ + Integer.parseInt(parts[1]) * 60 * 1000
+ + Integer.parseInt(parts[2]) * 1000;
+ }
+
+ /**
+ * Converts short duration string (XX:YY) to milliseconds. If durationIsInHours is true then the
+ * format is HH:MM, otherwise it's MM:SS.
+ */
+ public static int durationStringShortToMs(String input, boolean durationIsInHours) {
+ String[] parts = input.split(":");
+ if (parts.length != 2) {
+ return 0;
+ }
+
+ int modifier = durationIsInHours ? 60 : 1;
+
+ return Integer.parseInt(parts[0]) * 60 * 1000 * modifier
+ + Integer.parseInt(parts[1]) * 1000 * modifier;
+ }
+
+ /**
+ * Converts milliseconds to a localized string containing hours and minutes.
+ */
+ public static String getDurationStringLocalized(Context context, long duration) {
+ return getDurationStringLocalized(context.getResources(), duration, false);
+ }
+
+ public static String getDurationStringLocalized(Resources resources, long duration, boolean includeDays) {
+ String result = "";
+ int h = (int) (duration / HOURS_MIL);
+ int d = h / 24;
+ if (!includeDays) {
+ d = 0;
+ } else if (d > 0) {
+ String days = resources.getQuantityString(R.plurals.time_days_quantified, d, d);
+ result += days.replace(" ", "\u00A0") + " ";
+ h -= d * 24;
+ }
+ int rest = (int) (duration - (d * 24 + h) * HOURS_MIL);
+ int m = rest / MINUTES_MIL;
+ if (h > 0) {
+ String hours = resources.getQuantityString(R.plurals.time_hours_quantified, h, h);
+ result += hours.replace(" ", "\u00A0");
+ if (d == 0) {
+ result += " ";
+ }
+ }
+ if (d == 0) {
+ String minutes = resources.getQuantityString(R.plurals.time_minutes_quantified, m, m);
+ result += minutes.replace(" ", "\u00A0");
+ }
+ return result;
+ }
+
+ /**
+ * Converts seconds to a localized representation.
+ * @param time The time in seconds
+ * @return "HH:MM hours"
+ */
+ public static String shortLocalizedDuration(Context context, long time) {
+ float hours = (float) time / 3600f;
+ return String.format(Locale.getDefault(), "%.1f ", hours) + context.getString(R.string.time_hours);
+ }
+}
diff --git a/ui/common/src/main/java/de/danoeh/antennapod/ui/common/DateFormatter.java b/ui/common/src/main/java/de/danoeh/antennapod/ui/common/DateFormatter.java
new file mode 100644
index 000000000..1bf4fad23
--- /dev/null
+++ b/ui/common/src/main/java/de/danoeh/antennapod/ui/common/DateFormatter.java
@@ -0,0 +1,39 @@
+package de.danoeh.antennapod.ui.common;
+
+import android.content.Context;
+
+import java.text.DateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+/**
+ * Formats dates.
+ */
+public class DateFormatter {
+ private DateFormatter() {
+
+ }
+
+ public static String formatAbbrev(final Context context, final Date date) {
+ if (date == null) {
+ return "";
+ }
+ GregorianCalendar now = new GregorianCalendar();
+ GregorianCalendar cal = new GregorianCalendar();
+ cal.setTime(date);
+ boolean withinLastYear = now.get(Calendar.YEAR) == cal.get(Calendar.YEAR);
+ int format = android.text.format.DateUtils.FORMAT_ABBREV_ALL;
+ if (withinLastYear) {
+ format |= android.text.format.DateUtils.FORMAT_NO_YEAR;
+ }
+ return android.text.format.DateUtils.formatDateTime(context, date.getTime(), format);
+ }
+
+ public static String formatForAccessibility(final Date date) {
+ if (date == null) {
+ return "";
+ }
+ return DateFormat.getDateInstance(DateFormat.LONG).format(date);
+ }
+}
diff --git a/ui/common/src/main/java/de/danoeh/antennapod/ui/common/ThemeSwitcher.java b/ui/common/src/main/java/de/danoeh/antennapod/ui/common/ThemeSwitcher.java
new file mode 100644
index 000000000..9efb4e0f7
--- /dev/null
+++ b/ui/common/src/main/java/de/danoeh/antennapod/ui/common/ThemeSwitcher.java
@@ -0,0 +1,72 @@
+package de.danoeh.antennapod.ui.common;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import androidx.annotation.StyleRes;
+import de.danoeh.antennapod.storage.preferences.UserPreferences;
+
+public abstract class ThemeSwitcher {
+ @StyleRes
+ public static int getTheme(Context context) {
+ boolean dynamic = UserPreferences.getIsThemeColorTinted();
+ switch (readThemeValue(context)) {
+ case DARK:
+ return dynamic ? R.style.Theme_AntennaPod_Dynamic_Dark : R.style.Theme_AntennaPod_Dark;
+ case BLACK:
+ return dynamic ? R.style.Theme_AntennaPod_Dynamic_TrueBlack : R.style.Theme_AntennaPod_TrueBlack;
+ case LIGHT: // fall-through
+ default:
+ return dynamic ? R.style.Theme_AntennaPod_Dynamic_Light : R.style.Theme_AntennaPod_Light;
+ }
+ }
+
+ @StyleRes
+ public static int getNoTitleTheme(Context context) {
+ boolean dynamic = UserPreferences.getIsThemeColorTinted();
+ switch (readThemeValue(context)) {
+ case DARK:
+ return dynamic ? R.style.Theme_AntennaPod_Dynamic_Dark_NoTitle : R.style.Theme_AntennaPod_Dark_NoTitle;
+ case BLACK:
+ return dynamic ? R.style.Theme_AntennaPod_Dynamic_TrueBlack_NoTitle
+ : R.style.Theme_AntennaPod_TrueBlack_NoTitle;
+ case LIGHT: // fall-through
+ default:
+ return dynamic ? R.style.Theme_AntennaPod_Dynamic_Light_NoTitle
+ : R.style.Theme_AntennaPod_Light_NoTitle;
+ }
+ }
+
+ @StyleRes
+ public static int getTranslucentTheme(Context context) {
+ boolean dynamic = UserPreferences.getIsThemeColorTinted();
+ switch (readThemeValue(context)) {
+ case DARK:
+ return dynamic ? R.style.Theme_AntennaPod_Dynamic_Dark_Translucent
+ : R.style.Theme_AntennaPod_Dark_Translucent;
+ case BLACK:
+ return dynamic ? R.style.Theme_AntennaPod_Dynamic_TrueBlack_Translucent
+ : R.style.Theme_AntennaPod_TrueBlack_Translucent;
+ case LIGHT: // fall-through
+ default:
+ return dynamic ? R.style.Theme_AntennaPod_Dynamic_Light_Translucent
+ : R.style.Theme_AntennaPod_Light_Translucent;
+ }
+ }
+
+ private static UserPreferences.ThemePreference readThemeValue(Context context) {
+ UserPreferences.ThemePreference theme = UserPreferences.getTheme();
+ if (theme == UserPreferences.ThemePreference.SYSTEM) {
+ int nightMode = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
+ if (nightMode == Configuration.UI_MODE_NIGHT_YES) {
+ theme = UserPreferences.ThemePreference.DARK;
+ } else {
+ theme = UserPreferences.ThemePreference.LIGHT;
+
+ }
+ }
+ if (theme == UserPreferences.ThemePreference.DARK && UserPreferences.getIsBlackTheme()) {
+ theme = UserPreferences.ThemePreference.BLACK;
+ }
+ return theme;
+ }
+}