From f3d777c65cd72cb45e565eaad9e501a866667a94 Mon Sep 17 00:00:00 2001
From: John Zhen Mo <zhenmogukl@gmail.com>
Date: Sun, 8 Apr 2018 13:58:18 -0700
Subject: [PATCH] -Added accessibility caption style and text color resolver.
 -Added button to open captioning settings activity from appearance settings.
 -Modified player captions to use custom caption style when captioning manager
 is enabled. -Removed caption size settings from appearance settings.

---
 .../newpipe/player/MainVideoPlayer.java       | 16 ++++------
 .../newpipe/player/PopupVideoPlayer.java      | 15 ++++-----
 .../schabi/newpipe/player/VideoPlayer.java    | 13 ++++----
 .../newpipe/player/helper/PlayerHelper.java   | 32 +++++++++++++++++++
 .../settings/AppearanceSettingsFragment.java  | 26 ++++++++++++++-
 app/src/main/res/values/settings_keys.xml     | 18 +----------
 app/src/main/res/values/strings.xml           |  8 ++---
 app/src/main/res/xml/appearance_settings.xml  | 11 +++----
 8 files changed, 86 insertions(+), 53 deletions(-)

diff --git a/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java
index dbc34b11a..ebb39b381 100644
--- a/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java
+++ b/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java
@@ -50,6 +50,7 @@ import android.widget.TextView;
 import android.widget.Toast;
 
 import com.google.android.exoplayer2.Player;
+import com.google.android.exoplayer2.text.CaptionStyleCompat;
 import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
 import com.google.android.exoplayer2.ui.SubtitleView;
 
@@ -428,20 +429,15 @@ public final class MainVideoPlayer extends AppCompatActivity
 
         @Override
         protected void setupSubtitleView(@NonNull SubtitleView view,
-                                         @NonNull String captionSizeKey) {
-            final float captionRatioInverse;
-            if (captionSizeKey.equals(getString(R.string.smaller_caption_size_key))) {
-                captionRatioInverse = 22f;
-            } else if (captionSizeKey.equals(getString(R.string.larger_caption_size_key))) {
-                captionRatioInverse = 18f;
-            } else {
-                captionRatioInverse = 20f;
-            }
-
+                                         final float captionScale,
+                                         @NonNull final CaptionStyleCompat captionStyle) {
             final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
             final int minimumLength = Math.min(metrics.heightPixels, metrics.widthPixels);
+            final float captionRatioInverse = 20f + 4f * (1f - captionScale);
             view.setFixedTextSize(TypedValue.COMPLEX_UNIT_PX,
                     (float) minimumLength / captionRatioInverse);
+            view.setApplyEmbeddedStyles(captionStyle.equals(CaptionStyleCompat.DEFAULT));
+            view.setStyle(captionStyle);
         }
 
         @Override
diff --git a/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java
index 20860d9c5..9528bf2bc 100644
--- a/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java
+++ b/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java
@@ -52,6 +52,7 @@ import android.widget.TextView;
 import com.google.android.exoplayer2.C;
 import com.google.android.exoplayer2.PlaybackParameters;
 import com.google.android.exoplayer2.Player;
+import com.google.android.exoplayer2.text.CaptionStyleCompat;
 import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
 import com.google.android.exoplayer2.ui.SubtitleView;
 
@@ -397,14 +398,12 @@ public final class PopupVideoPlayer extends Service {
 
         @Override
         protected void setupSubtitleView(@NonNull SubtitleView view,
-                                         @NonNull String captionSizeKey) {
-            float captionRatio = SubtitleView.DEFAULT_TEXT_SIZE_FRACTION;
-            if (captionSizeKey.equals(getString(R.string.smaller_caption_size_key))) {
-                captionRatio *= 0.9;
-            } else if (captionSizeKey.equals(getString(R.string.larger_caption_size_key))) {
-                captionRatio *= 1.1;
-            }
-            view.setFractionalTextSize(captionRatio);
+                                         final float captionScale,
+                                         @NonNull final CaptionStyleCompat captionStyle) {
+            float captionRatio = (captionScale - 1f) / 5f + 1f;
+            view.setFractionalTextSize(SubtitleView.DEFAULT_TEXT_SIZE_FRACTION * captionRatio);
+            view.setApplyEmbeddedStyles(captionStyle.equals(CaptionStyleCompat.DEFAULT));
+            view.setStyle(captionStyle);
         }
 
         @Override
diff --git a/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java
index b019ea91e..0d427484e 100644
--- a/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java
+++ b/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java
@@ -32,7 +32,6 @@ import android.graphics.PorterDuff;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Handler;
-import android.preference.PreferenceManager;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.v4.content.ContextCompat;
@@ -55,6 +54,7 @@ import com.google.android.exoplayer2.source.MediaSource;
 import com.google.android.exoplayer2.source.MergingMediaSource;
 import com.google.android.exoplayer2.source.TrackGroup;
 import com.google.android.exoplayer2.source.TrackGroupArray;
+import com.google.android.exoplayer2.text.CaptionStyleCompat;
 import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
 import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
 import com.google.android.exoplayer2.ui.SubtitleView;
@@ -189,10 +189,10 @@ public abstract class VideoPlayer extends BasePlayer
         this.qualityTextView = rootView.findViewById(R.id.qualityTextView);
 
         this.subtitleView = rootView.findViewById(R.id.subtitleView);
-        final String captionSizeKey = PreferenceManager.getDefaultSharedPreferences(context)
-                .getString(context.getString(R.string.caption_size_key),
-                        context.getString(R.string.caption_size_default));
-        setupSubtitleView(subtitleView, captionSizeKey);
+
+        final float captionScale = PlayerHelper.getCaptionScale(context);
+        final CaptionStyleCompat captionStyle = PlayerHelper.getCaptionStyle(context);
+        setupSubtitleView(subtitleView, captionScale, captionStyle);
 
         this.resizeView =  rootView.findViewById(R.id.resizeTextView);
         resizeView.setText(PlayerHelper.resizeTypeOf(context, aspectRatioFrameLayout.getResizeMode()));
@@ -214,7 +214,8 @@ public abstract class VideoPlayer extends BasePlayer
     }
 
     protected abstract void setupSubtitleView(@NonNull SubtitleView view,
-                                              @NonNull String captionSizeKey);
+                                              final float captionScale,
+                                              @NonNull final CaptionStyleCompat captionStyle);
 
     @Override
     public void initListeners() {
diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java
index 63ac7e8a1..9d75f207e 100644
--- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java
+++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java
@@ -2,11 +2,14 @@ package org.schabi.newpipe.player.helper;
 
 import android.content.Context;
 import android.content.SharedPreferences;
+import android.os.Build;
 import android.preference.PreferenceManager;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import android.view.accessibility.CaptioningManager;
 
 import com.google.android.exoplayer2.SeekParameters;
+import com.google.android.exoplayer2.text.CaptionStyleCompat;
 import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
 import com.google.android.exoplayer2.util.MimeTypes;
 
@@ -215,6 +218,35 @@ public class PlayerHelper {
         return 2500;
     }
 
+    @NonNull
+    public static CaptionStyleCompat getCaptionStyle(@NonNull final Context context) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return CaptionStyleCompat.DEFAULT;
+
+        final CaptioningManager captioningManager = (CaptioningManager)
+                context.getSystemService(Context.CAPTIONING_SERVICE);
+        if (captioningManager == null || !captioningManager.isEnabled()) {
+            return CaptionStyleCompat.DEFAULT;
+        }
+
+        return CaptionStyleCompat.createFromCaptionStyle(captioningManager.getUserStyle());
+    }
+
+    /**
+     * System font scaling:
+     * Very small - 0.25f, Small - 0.5f, Normal - 1.0f, Large - 1.5f, Very Large - 2.0f
+     * */
+    @NonNull
+    public static float getCaptionScale(@NonNull final Context context) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return 1f;
+
+        final CaptioningManager captioningManager = (CaptioningManager)
+                context.getSystemService(Context.CAPTIONING_SERVICE);
+        if (captioningManager == null || !captioningManager.isEnabled()) {
+            return 1f;
+        }
+
+        return captioningManager.getFontScale();
+    }
     ////////////////////////////////////////////////////////////////////////////
     // Private helpers
     ////////////////////////////////////////////////////////////////////////////
diff --git a/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java
index 70b6e25ed..806b30a5b 100644
--- a/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java
@@ -1,17 +1,25 @@
 package org.schabi.newpipe.settings;
 
+import android.content.Intent;
+import android.os.Build;
 import android.os.Bundle;
+import android.provider.Settings;
 import android.support.annotation.Nullable;
 import android.support.v7.preference.Preference;
+import android.util.Log;
 
 import org.schabi.newpipe.R;
 import org.schabi.newpipe.util.Constants;
 
 public class AppearanceSettingsFragment extends BasePreferenceFragment {
+    private final static boolean CAPTIONING_SETTINGS_ACCESSIBLE =
+            Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
+
     /**
      * Theme that was applied when the settings was opened (or recreated after a theme change)
      */
     private String startThemeKey;
+    private String captionSettingsKey;
 
     @Override
     public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -19,6 +27,12 @@ public class AppearanceSettingsFragment extends BasePreferenceFragment {
         String themeKey = getString(R.string.theme_key);
         startThemeKey = defaultPreferences.getString(themeKey, getString(R.string.default_theme_value));
         findPreference(themeKey).setOnPreferenceChangeListener(themePreferenceChange);
+
+        captionSettingsKey = getString(R.string.caption_settings_key);
+        if (!CAPTIONING_SETTINGS_ACCESSIBLE)  {
+            final Preference captionSettings = findPreference(captionSettingsKey);
+            getPreferenceScreen().removePreference(captionSettings);
+        }
     }
 
     @Override
@@ -26,13 +40,23 @@ public class AppearanceSettingsFragment extends BasePreferenceFragment {
         addPreferencesFromResource(R.xml.appearance_settings);
     }
 
+    @Override
+    public boolean onPreferenceTreeClick(Preference preference) {
+        if (preference.getKey().equals(captionSettingsKey) && CAPTIONING_SETTINGS_ACCESSIBLE) {
+            startActivity(new Intent(Settings.ACTION_CAPTIONING_SETTINGS));
+        }
+
+        return super.onPreferenceTreeClick(preference);
+    }
+
     private Preference.OnPreferenceChangeListener themePreferenceChange = new Preference.OnPreferenceChangeListener() {
         @Override
         public boolean onPreferenceChange(Preference preference, Object newValue) {
             defaultPreferences.edit().putBoolean(Constants.KEY_THEME_CHANGE, true).apply();
             defaultPreferences.edit().putString(getString(R.string.theme_key), newValue.toString()).apply();
 
-            if (!newValue.equals(startThemeKey)) { // If it's not the current theme
+            if (!newValue.equals(startThemeKey) && getActivity() != null) {
+                // If it's not the current theme
                 getActivity().recreate();
             }
 
diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml
index 68d75737a..befe17958 100644
--- a/app/src/main/res/values/settings_keys.xml
+++ b/app/src/main/res/values/settings_keys.xml
@@ -109,23 +109,7 @@
     </string-array>
 
     <!-- Caption Size -->
-    <string name="caption_size_key" translatable="false">caption_size_key</string>
-    <string name="caption_size_default" translatable="false">@string/normal_caption_size_key</string>
-
-    <string name="smaller_caption_size_key" translatable="false">smaller_caption_size</string>
-    <string name="normal_caption_size_key" translatable="false">normal_caption_size</string>
-    <string name="larger_caption_size_key" translatable="false">larger_caption_size</string>
-
-    <string-array name="caption_size_descriptions_list" translatable="false">
-        <item>@string/smaller_caption_font_size</item>
-        <item>@string/normal_caption_font_size</item>
-        <item>@string/larger_caption_font_size</item>
-    </string-array>
-    <string-array name="caption_size_values_list" translatable="false">
-        <item>@string/smaller_caption_size_key</item>
-        <item>@string/normal_caption_size_key</item>
-        <item>@string/larger_caption_size_key</item>
-    </string-array>
+    <string name="caption_settings_key" translatable="false">caption_settings_key</string>
 
     <!-- Content & History -->
     <string name="show_search_suggestions_key" translatable="false">show_search_suggestions</string>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f22f42e95..16306ea6c 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -425,10 +425,10 @@
     <string name="resize_zoom">ZOOM</string>
 
     <string name="caption_auto_generated">Auto-generated</string>
-    <string name="caption_font_size_settings_title">Caption font size</string>
-    <string name="smaller_caption_font_size">Smaller font</string>
-    <string name="normal_caption_font_size">Normal font</string>
-    <string name="larger_caption_font_size">Larger font</string>
+
+    <!-- Caption Settings -->
+    <string name="caption_setting_title">Caption</string>
+    <string name="caption_setting_description">Modify player caption text scale and background styles. Require player restart to take effect.</string>
 
     <!-- Debug Settings -->
     <string name="enable_leak_canary_title">Enable LeakCanary</string>
diff --git a/app/src/main/res/xml/appearance_settings.xml b/app/src/main/res/xml/appearance_settings.xml
index 3ffbd9d81..239f5f3b3 100644
--- a/app/src/main/res/xml/appearance_settings.xml
+++ b/app/src/main/res/xml/appearance_settings.xml
@@ -22,11 +22,8 @@
         android:title="@string/show_hold_to_append_title"
         android:summary="@string/show_hold_to_append_summary"/>
 
-    <ListPreference
-        android:defaultValue="@string/caption_size_default"
-        android:entries="@array/caption_size_descriptions_list"
-        android:entryValues="@array/caption_size_values_list"
-        android:key="@string/caption_size_key"
-        android:summary="%s"
-        android:title="@string/caption_font_size_settings_title"/>
+    <Preference
+        android:key="@string/caption_settings_key"
+        android:title="@string/caption_setting_title"
+        android:summary="@string/caption_setting_description"/>
 </PreferenceScreen>