add preferred content language selection to AccountFragment
this contains only gui work
This commit is contained in:
		| @ -456,8 +456,8 @@ object Crunchyroll { | ||||
|         val watchlistEndpoint = "/content/v1/$accountID/watchlist" | ||||
|         val parameters = listOf("locale" to locale, "n" to n) | ||||
|  | ||||
|         val watchlistResult = request(watchlistEndpoint, parameters) | ||||
|         val list: ContinueWatchingList = watchlistResult.component1()?.obj()?.let { | ||||
|         val result = request(watchlistEndpoint, parameters) | ||||
|         val list: ContinueWatchingList = result.component1()?.obj()?.let { | ||||
|             json.decodeFromString(it.toString()) | ||||
|         } ?: NoneContinueWatchingList | ||||
|  | ||||
| @ -475,10 +475,23 @@ object Crunchyroll { | ||||
|         val watchlistEndpoint = "/content/v1/$accountID/up_next_account" | ||||
|         val parameters = listOf("locale" to locale, "n" to n) | ||||
|  | ||||
|         val resultUpNextAccount = request(watchlistEndpoint, parameters) | ||||
|         return resultUpNextAccount.component1()?.obj()?.let { | ||||
|         val result = request(watchlistEndpoint, parameters) | ||||
|         return result.component1()?.obj()?.let { | ||||
|             json.decodeFromString(it.toString()) | ||||
|         } ?: NoneContinueWatchingList | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Account/Profile functions | ||||
|      */ | ||||
|  | ||||
|     suspend fun profile(): Profile { | ||||
|         val profileEndpoint = "/accounts/v1/me/profile" | ||||
|  | ||||
|         val result = request(profileEndpoint) | ||||
|         return result.component1()?.obj()?.let { | ||||
|             json.decodeFromString(it.toString()) | ||||
|         } ?: NoneProfile | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| @ -4,6 +4,20 @@ import kotlinx.serialization.SerialName | ||||
| import kotlinx.serialization.Serializable | ||||
| import java.util.* | ||||
|  | ||||
| val supportedLocals = listOf( | ||||
|     Locale.forLanguageTag("ar-SA"), | ||||
|     Locale.forLanguageTag("de-DE"), | ||||
|     Locale.forLanguageTag("en-US"), | ||||
|     Locale.forLanguageTag("es-419"), | ||||
|     Locale.forLanguageTag("es-ES"), | ||||
|     Locale.forLanguageTag("fr-FR"), | ||||
|     Locale.forLanguageTag("it-IT"), | ||||
|     Locale.forLanguageTag("pt-BR"), | ||||
|     Locale.forLanguageTag("pt-PT"), | ||||
|     Locale.forLanguageTag("ru-RU"), | ||||
|     Locale.ROOT | ||||
| ) | ||||
|  | ||||
| /** | ||||
|  * data classes for browse | ||||
|  * TODO make class names more clear/possibly overlapping for now | ||||
| @ -295,3 +309,19 @@ val NonePlayback = Playback( | ||||
|         mapOf(), mapOf(), mapOf(), mapOf(), mapOf(), mapOf(), | ||||
|     ) | ||||
| ) | ||||
|  | ||||
| @Serializable | ||||
| data class Profile( | ||||
|     @SerialName("avatar") val avatar: String, | ||||
|     @SerialName("email") val email: String, | ||||
|     @SerialName("maturity_rating") val maturityRating: String, | ||||
|     @SerialName("preferred_content_subtitle_language") val preferredContentSubtitleLanguage: String, | ||||
|     @SerialName("username") val username: String, | ||||
| ) | ||||
| val NoneProfile = Profile( | ||||
|     avatar = "", | ||||
|     email = "", | ||||
|     maturityRating = "", | ||||
|     preferredContentSubtitleLanguage = "", | ||||
|     username = "" | ||||
| ) | ||||
|  | ||||
| @ -6,27 +6,34 @@ import android.os.Bundle | ||||
| import android.view.LayoutInflater | ||||
| import android.view.View | ||||
| import android.view.ViewGroup | ||||
| import android.widget.Toast | ||||
| import androidx.activity.result.contract.ActivityResultContracts | ||||
| import androidx.core.view.isVisible | ||||
| import androidx.fragment.app.Fragment | ||||
| import androidx.lifecycle.lifecycleScope | ||||
| import com.afollestad.materialdialogs.MaterialDialog | ||||
| import com.afollestad.materialdialogs.list.listItemsSingleChoice | ||||
| import com.google.android.material.dialog.MaterialAlertDialogBuilder | ||||
| import kotlinx.coroutines.Deferred | ||||
| import kotlinx.coroutines.async | ||||
| import kotlinx.coroutines.launch | ||||
| import org.mosad.teapod.BuildConfig | ||||
| import org.mosad.teapod.R | ||||
| import org.mosad.teapod.databinding.FragmentAccountBinding | ||||
| import org.mosad.teapod.parser.crunchyroll.Crunchyroll | ||||
| import org.mosad.teapod.parser.crunchyroll.Profile | ||||
| import org.mosad.teapod.parser.crunchyroll.supportedLocals | ||||
| import org.mosad.teapod.preferences.EncryptedPreferences | ||||
| import org.mosad.teapod.preferences.Preferences | ||||
| import org.mosad.teapod.ui.activity.main.MainActivity | ||||
| import org.mosad.teapod.ui.components.LoginDialog | ||||
| import org.mosad.teapod.util.DataTypes.Theme | ||||
| import org.mosad.teapod.util.showFragment | ||||
| import java.util.* | ||||
|  | ||||
| class AccountFragment : Fragment() { | ||||
|  | ||||
|     private lateinit var binding: FragmentAccountBinding | ||||
|     private val profile: Deferred<Profile> = lifecycleScope.async { | ||||
|         Crunchyroll.profile() | ||||
|     } | ||||
|  | ||||
|     private val getUriExport = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> | ||||
|         if (result.resultCode == Activity.RESULT_OK) { | ||||
| @ -58,7 +65,9 @@ class AccountFragment : Fragment() { | ||||
|     override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||||
|         super.onViewCreated(view, savedInstanceState) | ||||
|  | ||||
|         // TODO reimplement for ct, if possible (maybe account status would be better? (premium)) | ||||
|         binding.textAccountLogin.text = EncryptedPreferences.login | ||||
|  | ||||
|         // TODO reimplement for cr, if possible (maybe account status would be better? (premium)) | ||||
|         // load subscription (async) info before anything else | ||||
|         binding.textAccountSubscription.text = getString(R.string.account_subscription, getString(R.string.loading)) | ||||
|         lifecycleScope.launch { | ||||
| @ -68,18 +77,23 @@ class AccountFragment : Fragment() { | ||||
|             ) | ||||
|         } | ||||
|  | ||||
|         binding.textAccountLogin.text = EncryptedPreferences.login | ||||
|         binding.textInfoAboutDesc.text = getString(R.string.info_about_desc, BuildConfig.VERSION_NAME, getString(R.string.build_time)) | ||||
|         // add preferred subtitles | ||||
|         lifecycleScope.launch { | ||||
|             binding.textSettingsContentLanguageDesc.text = Locale.forLanguageTag( | ||||
|                 profile.await().preferredContentSubtitleLanguage | ||||
|             ).displayLanguage | ||||
|         } | ||||
|         binding.switchSecondary.isChecked = Preferences.preferSecondary | ||||
|         binding.switchAutoplay.isChecked = Preferences.autoplay | ||||
|         binding.textThemeSelected.text = when (Preferences.theme) { | ||||
|             Theme.DARK -> getString(R.string.theme_dark) | ||||
|             else -> getString(R.string.theme_light) | ||||
|         } | ||||
|  | ||||
|         binding.switchSecondary.isChecked = Preferences.preferSecondary | ||||
|         binding.switchAutoplay.isChecked = Preferences.autoplay | ||||
|  | ||||
|         binding.linearDevSettings.isVisible = Preferences.devSettings | ||||
|  | ||||
|         binding.textInfoAboutDesc.text = getString(R.string.info_about_desc, BuildConfig.VERSION_NAME, getString(R.string.build_time)) | ||||
|  | ||||
|         initActions() | ||||
|     } | ||||
|  | ||||
| @ -93,12 +107,8 @@ class AccountFragment : Fragment() { | ||||
|             //startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(AoDParser.getSubscriptionUrl()))) | ||||
|         } | ||||
|  | ||||
|         binding.linearTheme.setOnClickListener { | ||||
|             showThemeDialog() | ||||
|         } | ||||
|  | ||||
|         binding.linearInfo.setOnClickListener { | ||||
|             activity?.showFragment(AboutFragment()) | ||||
|         binding.linearSettingsContentLanguage.setOnClickListener { | ||||
|             showContentLanguageSelection() | ||||
|         } | ||||
|  | ||||
|         binding.switchSecondary.setOnClickListener { | ||||
| @ -109,6 +119,14 @@ class AccountFragment : Fragment() { | ||||
|             Preferences.saveAutoplay(requireContext(), binding.switchAutoplay.isChecked) | ||||
|         } | ||||
|  | ||||
|         binding.linearTheme.setOnClickListener { | ||||
|             showThemeDialog() | ||||
|         } | ||||
|  | ||||
|         binding.linearInfo.setOnClickListener { | ||||
|             activity?.showFragment(AboutFragment()) | ||||
|         } | ||||
|  | ||||
|         binding.linearExportData.setOnClickListener { | ||||
|             val i = Intent(Intent.ACTION_CREATE_DOCUMENT).apply { | ||||
|                 addCategory(Intent.CATEGORY_OPENABLE) | ||||
| @ -142,24 +160,43 @@ class AccountFragment : Fragment() { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun showContentLanguageSelection() { | ||||
|         val items = supportedLocals.map { | ||||
|             if (it.displayLanguage.isNotEmpty() && it.displayCountry.isNotEmpty()) { | ||||
|                 "${it.displayLanguage} (${it.displayCountry})" | ||||
|             } else if (it.displayCountry.isNotEmpty()) { | ||||
|                 it.displayLanguage | ||||
|             } else { | ||||
|                 getString(R.string.settings_content_language_none) | ||||
|             } | ||||
|         }.toTypedArray() | ||||
|  | ||||
|         MaterialAlertDialogBuilder(requireContext()) | ||||
|             .setTitle(R.string.settings_content_language) | ||||
|             .setSingleChoiceItems(items, 0){ _, which -> | ||||
|                 // TODO | ||||
|             } | ||||
|             .show() | ||||
|     } | ||||
|  | ||||
|     private fun showThemeDialog() { | ||||
|         val themes = listOf( | ||||
|         val items = arrayOf( | ||||
|             resources.getString(R.string.theme_light), | ||||
|             resources.getString(R.string.theme_dark) | ||||
|         ) | ||||
|  | ||||
|         MaterialDialog(requireContext()).show { | ||||
|             title(R.string.theme) | ||||
|             listItemsSingleChoice(items = themes, initialSelection = Preferences.theme.ordinal) { _, index, _ -> | ||||
|                 when(index) { | ||||
|                     0 -> Preferences.saveTheme(context, Theme.LIGHT) | ||||
|                     1 -> Preferences.saveTheme(context, Theme.DARK) | ||||
|                     else -> Preferences.saveTheme(context, Theme.DARK) | ||||
|         MaterialAlertDialogBuilder(requireContext()) | ||||
|             .setTitle(R.string.settings_content_language) | ||||
|             .setSingleChoiceItems(items, Preferences.theme.ordinal){ _, which -> | ||||
|                 when(which) { | ||||
|                     0 -> Preferences.saveTheme(requireContext(), Theme.LIGHT) | ||||
|                     1 -> Preferences.saveTheme(requireContext(), Theme.DARK) | ||||
|                     else -> Preferences.saveTheme(requireContext(), Theme.DARK) | ||||
|                 } | ||||
|  | ||||
|                 (activity as MainActivity).restart() | ||||
|             } | ||||
|         } | ||||
|             .show() | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										5
									
								
								app/src/main/res/drawable/ic_baseline_language_24.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								app/src/main/res/drawable/ic_baseline_language_24.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| <vector android:height="24dp" android:tint="#FFFFFF" | ||||
|     android:viewportHeight="24" android:viewportWidth="24" | ||||
|     android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <path android:fillColor="@android:color/white" android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM18.92,8h-2.95c-0.32,-1.25 -0.78,-2.45 -1.38,-3.56 1.84,0.63 3.37,1.91 4.33,3.56zM12,4.04c0.83,1.2 1.48,2.53 1.91,3.96h-3.82c0.43,-1.43 1.08,-2.76 1.91,-3.96zM4.26,14C4.1,13.36 4,12.69 4,12s0.1,-1.36 0.26,-2h3.38c-0.08,0.66 -0.14,1.32 -0.14,2 0,0.68 0.06,1.34 0.14,2L4.26,14zM5.08,16h2.95c0.32,1.25 0.78,2.45 1.38,3.56 -1.84,-0.63 -3.37,-1.9 -4.33,-3.56zM8.03,8L5.08,8c0.96,-1.66 2.49,-2.93 4.33,-3.56C8.81,5.55 8.35,6.75 8.03,8zM12,19.96c-0.83,-1.2 -1.48,-2.53 -1.91,-3.96h3.82c-0.43,1.43 -1.08,2.76 -1.91,3.96zM14.34,14L9.66,14c-0.09,-0.66 -0.16,-1.32 -0.16,-2 0,-0.68 0.07,-1.35 0.16,-2h4.68c0.09,0.65 0.16,1.32 0.16,2 0,0.68 -0.07,1.34 -0.16,2zM14.59,19.56c0.6,-1.11 1.06,-2.31 1.38,-3.56h2.95c-0.96,1.65 -2.49,2.93 -4.33,3.56zM16.36,14c0.08,-0.66 0.14,-1.32 0.14,-2 0,-0.68 -0.06,-1.34 -0.14,-2h3.38c0.16,0.64 0.26,1.31 0.26,2s-0.1,1.36 -0.26,2h-3.38z"/> | ||||
| </vector> | ||||
| @ -146,6 +146,46 @@ | ||||
|                     android:textSize="16sp" | ||||
|                     android:textStyle="bold" /> | ||||
|  | ||||
|                 <LinearLayout | ||||
|                     android:id="@+id/linear_settings_content_language" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="match_parent" | ||||
|                     android:orientation="horizontal" | ||||
|                     android:padding="7dp"> | ||||
|  | ||||
|                     <ImageView | ||||
|                         android:id="@+id/imageView4" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         android:contentDescription="@string/settings_content_language" | ||||
|                         android:minWidth="48dp" | ||||
|                         android:minHeight="48dp" | ||||
|                         android:padding="9dp" | ||||
|                         android:scaleType="fitXY" | ||||
|                         android:src="@drawable/ic_baseline_language_24" | ||||
|                         app:tint="?iconColor" /> | ||||
|  | ||||
|                     <LinearLayout | ||||
|                         android:layout_width="match_parent" | ||||
|                         android:layout_height="match_parent" | ||||
|                         android:orientation="vertical"> | ||||
|  | ||||
|                         <TextView | ||||
|                             android:id="@+id/text_settings_content_language" | ||||
|                             android:layout_width="match_parent" | ||||
|                             android:layout_height="wrap_content" | ||||
|                             android:text="@string/settings_content_language" | ||||
|                             android:textSize="16sp" /> | ||||
|  | ||||
|                         <TextView | ||||
|                             android:id="@+id/text_settings_content_language_desc" | ||||
|                             android:layout_width="match_parent" | ||||
|                             android:layout_height="wrap_content" | ||||
|                             android:text="@string/settings_content_language_desc" | ||||
|                             android:textColor="?textSecondary" /> | ||||
|                     </LinearLayout> | ||||
|                 </LinearLayout> | ||||
|  | ||||
|                 <LinearLayout | ||||
|                     android:id="@+id/linear_settings_secondary" | ||||
|                     android:layout_width="match_parent" | ||||
|  | ||||
| @ -39,6 +39,9 @@ | ||||
|     <string name="info">Info</string> | ||||
|     <string name="info_about_desc">Version %1$s (%2$s)</string> | ||||
|     <string name="settings">Einstellungen</string> | ||||
|     <string name="settings_content_language">Bevorzuge Inhaltssprache</string> | ||||
|     <string name="settings_content_language_desc">Englisch</string> | ||||
|     <string name="settings_content_language_none">Keine</string> | ||||
|     <string name="settings_secondary">Bevorzuge Japanisch (OmU)</string> | ||||
|     <string name="settings_secondary_desc">Japanisch verwenden, sofern vorhanden</string> | ||||
|     <string name="settings_autoplay">Autoplay</string> | ||||
|  | ||||
| @ -46,12 +46,12 @@ | ||||
|     <string name="account_login_desc">Tap to edit</string> | ||||
|     <string name="account_subscription">Subscription %1$s</string> | ||||
|     <string name="account_subscription_desc">Tap to extend</string> | ||||
|     <string name="info">Info</string> | ||||
|     <string name="info_about" translatable="false">Teapod by @Seil0</string> | ||||
|     <string name="info_about_desc">Version %1$s (%2$s)</string> | ||||
|     <string name="settings">Settings</string> | ||||
|     <string name="settings_content_language">Preferred content language</string> | ||||
|     <string name="settings_content_language_desc">English</string> | ||||
|     <string name="settings_content_language_none">None</string> | ||||
|     <string name="settings_secondary">Prefer japanese (sub)</string> | ||||
|     <string name="settings_secondary_desc">Use the japanese, if present</string> | ||||
|     <string name="settings_secondary_desc">Use japanese, if present</string> | ||||
|     <string name="settings_autoplay">Autoplay</string> | ||||
|     <string name="settings_autoplay_desc">Play next episode automatically</string> | ||||
|     <string name="theme">Theme</string> | ||||
| @ -63,6 +63,9 @@ | ||||
|     <string name="import_data">import data</string> | ||||
|     <string name="import_data_desc">import "My list" from a file</string> | ||||
|     <string name="import_data_success">imported "My list" successfully</string> | ||||
|     <string name="info">Info</string> | ||||
|     <string name="info_about" translatable="false">Teapod by @Seil0</string> | ||||
|     <string name="info_about_desc">Version %1$s (%2$s)</string> | ||||
|  | ||||
|  | ||||
|     <!-- about fragment --> | ||||
|  | ||||
| @ -36,15 +36,30 @@ | ||||
|         <item name="shapeTextBackground">@color/textBackgroundDark</item> | ||||
|         <item name="iconColor">@color/iconColorDark</item> | ||||
|         <item name="buttonBackground">@color/buttonBackgroundDark</item> | ||||
|  | ||||
|         <item name="md_background_color">@color/themeSecondaryDark</item> | ||||
|         <item name="md_color_content">@color/textSecondaryDark</item> | ||||
|  | ||||
|         <!-- without this, the unchecked single choice buttons while be black --> | ||||
|         <item name="md_color_widget_unchecked">@color/textSecondaryDark</item> | ||||
|  | ||||
|         <item name="materialAlertDialogTheme">@style/ThemeOverlay.App.MaterialAlertDialog.Dark</item> | ||||
|         <!-- change on click indicator color for manually set components --> | ||||
|         <item name="colorControlHighlight">@color/controlHighlightDark</item> | ||||
|     </style> | ||||
|  | ||||
|     <!-- dialog themes --> | ||||
|     <style name="ThemeOverlay.App.MaterialAlertDialog.Dark" parent="ThemeOverlay.MaterialComponents.MaterialAlertDialog"> | ||||
|         <item name="colorPrimary">@color/colorPrimary</item> | ||||
|         <item name="colorSurface">@color/themeSecondaryDark</item> | ||||
|         <item name="colorOnSurface">@color/textPrimaryDark</item> | ||||
|         <item name="android:colorControlNormal">@color/textSecondaryDark</item> <!-- Radio button unchecked--> | ||||
|         <item name="materialAlertDialogTitleTextStyle">@style/MaterialAlertDialog.App.Title.Text</item> | ||||
|     </style> | ||||
|  | ||||
|     <style name="MaterialAlertDialog.App.Title.Text" parent="MaterialAlertDialog.MaterialComponents.Title.Text"> | ||||
|         <item name="android:textColor">?textPrimary</item> | ||||
|     </style> | ||||
|  | ||||
|     <!-- player theme --> | ||||
|     <style name="PlayerTheme" parent="Theme.MaterialComponents.Light.NoActionBar"> | ||||
|         <item name="android:windowNoTitle">true</item> | ||||
|  | ||||
		Reference in New Issue
	
	Block a user