Skip to content
This repository has been archived by the owner on Sep 12, 2023. It is now read-only.

Commit

Permalink
Development (#41)
Browse files Browse the repository at this point in the history
* Develop/country support (#40)

* Added country code picker on login

* Added settings menu in video player, added support for multiple subtitles and definitions

* Removed bedtime mode button, added idle dialog

* Close dialog after timer end

* Updated release.md

* Added Off description to settings caption item
  • Loading branch information
janjanmedinaaa authored Feb 23, 2023
1 parent e1aa252 commit 2c3b0bd
Show file tree
Hide file tree
Showing 73 changed files with 1,353 additions and 242 deletions.
4 changes: 2 additions & 2 deletions .idea/deploymentTargetDropDown.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 6 additions & 4 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Watcher v2.9
# Watcher v2.10

## What's New
- Added More Error Toasts
- Removed annoying update notification on start
- Added double click on item to Remove video from Watch History
- Added other Countries for OTP Login
- Added support for other languages for subtitles
- Removed other button controls Video Player
- Added new Settings menu for Video Player to change subtitles, definition, and playback speed
- Removed bedtime mode and added new Idle Dialog
9 changes: 7 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ android {
applicationId "com.medina.juanantonio.watcher"
minSdk 21
targetSdk 33
versionCode 26
versionName "2.9"
versionCode 27
versionName "2.10"

javaCompileOptions {
annotationProcessorOptions {
Expand Down Expand Up @@ -83,6 +83,7 @@ dependencies {

def leanback_version = "1.2.0-alpha02"
implementation "androidx.leanback:leanback:$leanback_version"
implementation "androidx.leanback:leanback-preference:$leanback_version"

implementation "androidx.constraintlayout:constraintlayout:2.1.4"

Expand Down Expand Up @@ -164,4 +165,8 @@ dependencies {

// Used for version checking
implementation 'org.apache.maven:maven-artifact:3.0.3'

// Country Code Picker
implementation 'io.michaelrocks:libphonenumber-android:8.13.5'
implementation 'com.github.joielechong:countrycodepicker:2.4.2'
}
6 changes: 3 additions & 3 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,11 @@

<!-- Content provider used to expose our metadata database to other apps like Assistant -->
<provider
tools:ignore="ExportedContentProvider"
android:name=".data.providers.SearchResultsProvider"
android:permission="${applicationId}.MEDIA"
android:authorities="@string/authority"
android:exported="true">
android:exported="true"
android:permission="${applicationId}.MEDIA"
tools:ignore="ExportedContentProvider">
<path-permission
android:pathPrefix="/search"
android:readPermission="android.permission.GLOBAL_SEARCH" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package com.medina.juanantonio.watcher.data.adapters

import android.annotation.SuppressLint
import android.graphics.Color
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import com.medina.juanantonio.watcher.R
import com.medina.juanantonio.watcher.data.models.settings.SettingsItem
import com.medina.juanantonio.watcher.data.models.settings.SettingsScreen
import com.medina.juanantonio.watcher.data.models.settings.SettingsSelectionItem
import com.medina.juanantonio.watcher.databinding.ItemSettingsScreenBinding
import com.medina.juanantonio.watcher.databinding.ItemSettingsSelectionBinding

class SettingsAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private val _settingsItemList = arrayListOf<SettingsItem>()
private var _onClickListener: (SettingsItem) -> Unit = {}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
R.layout.item_settings_screen -> SettingsScreenViewHolder(
ItemSettingsScreenBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
else -> SettingsSelectionItemViewHolder(
ItemSettingsSelectionBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
}

override fun getItemCount() = _settingsItemList.size

override fun getItemViewType(position: Int): Int {
return _settingsItemList[position].viewType
}

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (val item = _settingsItemList[position]) {
is SettingsScreen -> (holder as? SettingsScreenViewHolder)?.bind(item)
is SettingsSelectionItem -> (holder as? SettingsSelectionItemViewHolder)?.bind(item)
}
}

@SuppressLint("NotifyDataSetChanged")
fun setSettingsItems(
settingsItemList: List<SettingsItem>,
onClickListener: (SettingsItem) -> Unit = {}
) {
_settingsItemList.clear()
_settingsItemList.addAll(settingsItemList)
_onClickListener = onClickListener
notifyDataSetChanged()
}

inner class SettingsScreenViewHolder(
private val binding: ItemSettingsScreenBinding
) : RecyclerView.ViewHolder(binding.root) {

fun bind(item: SettingsScreen) {
binding.root.setOnFocusChangeListener { _, onFocus ->
binding.textViewTitle.setTextColor(if (onFocus) Color.BLACK else Color.WHITE)
binding.imageViewIcon.setColorFilter(if (onFocus) Color.BLACK else Color.WHITE)
binding.imageViewArrow.setColorFilter(if (onFocus) Color.BLACK else Color.WHITE)
}

binding.root.setOnClickListener {
_onClickListener(item)
}

binding.imageViewIcon.setImageResource(item.icon)
binding.textViewTitle.text = item.title
binding.textViewDescription.apply {
isVisible = !item.description.isNullOrBlank()
text = item.description
}
}
}

inner class SettingsSelectionItemViewHolder(
private val binding: ItemSettingsSelectionBinding
) : RecyclerView.ViewHolder(binding.root) {

fun bind(item: SettingsSelectionItem) {
binding.root.setOnFocusChangeListener { _, onFocus ->
binding.textViewTitle.setTextColor(if (onFocus) Color.BLACK else Color.WHITE)
binding.imageViewIcon.setColorFilter(if (onFocus) Color.BLACK else Color.WHITE)
binding.imageViewSelected.setColorFilter(if (onFocus) Color.BLACK else Color.WHITE)
}

binding.root.setOnClickListener {
_onClickListener(item)
}

binding.textViewTitle.text = item.title
binding.textViewDescription.apply {
isVisible = !item.description.isNullOrBlank()
text = item.description
}
binding.imageViewSelected.isVisible = item.isSelected
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.medina.juanantonio.watcher.data.models.settings

interface SettingsItem {
val viewType: Int
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.medina.juanantonio.watcher.data.models.settings

import androidx.annotation.DrawableRes
import com.medina.juanantonio.watcher.R

data class SettingsScreen(
val key: String,
val title: String,
val description: String?,
@DrawableRes val icon: Int
): SettingsItem {

override val viewType: Int
get() = R.layout.item_settings_screen
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.medina.juanantonio.watcher.data.models.settings

data class SettingsSelectionItem(
val title: String,
val description: String?,
val isSelected: Boolean,
val key: String,
val type: Type
): SettingsItem {

override val viewType: Int
get() = 1

enum class Type {
QUALITY,
CAPTIONS,
PLAYBACK_SPEED
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
package com.medina.juanantonio.watcher.data.models.video

import android.os.Parcelable
import com.medina.juanantonio.watcher.network.models.player.*
import kotlinx.android.parcel.Parcelize

@Parcelize
data class VideoMedia(
val id: Int, // The id of the specific video media
val contentId: Int, // The id of the show or movie
val categoryId: Int, // The id indicator if the show is a movie or series
val title: String,
val introduction: String,
val mediaUrl: String,
val definitions: List<Definition>,
val subtitles: List<Subtitle>?,
val connectedVideos: List<VideoSuggestion>?,
val videoSuggestions: List<VideoSuggestion>?,
Expand All @@ -21,12 +19,14 @@ data class VideoMedia(
val coverVerticalUrl: String,
val coverHorizontalUrl: String,
val isComingSoon: Boolean
) : Parcelable {
) {

// Storing the score in the videoMedia so that
// the video can use it when saving to local storage
var score: Double = 0.0

var currentDefinition = Definition.DefinitionCode.UNKNOWN

constructor(
contentId: Int,
categoryId: Int,
Expand All @@ -46,6 +46,7 @@ data class VideoMedia(
},
introduction = detailsResponse.introduction,
mediaUrl = mediaResponse.mediaUrl,
definitions = episodeBean.definitionList,
subtitles = detailsResponse.episodeVo.firstOrNull {
it.id == episodeBean.id
}?.subtitlingList,
Expand All @@ -61,9 +62,12 @@ data class VideoMedia(
isComingSoon = isComingSoon
) {
this.score = score
this.currentDefinition = mediaResponse.currentDefinition
}

fun getPreferredSubtitle(): Subtitle? {
return subtitles?.firstOrNull { it.languageAbbr == "en" } ?: subtitles?.firstOrNull()
fun getPreferredSubtitle(languageAbbr: String = "en"): Subtitle? {
return subtitles?.firstOrNull {
it.languageAbbr == languageAbbr
} ?: subtitles?.firstOrNull()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.medina.juanantonio.watcher.features.dialog

import android.content.DialogInterface
import android.graphics.Color
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.medina.juanantonio.watcher.R
import com.medina.juanantonio.watcher.databinding.FragmentIdleDialogBinding
import com.medina.juanantonio.watcher.shared.utils.autoCleared

class IdleDialogFragment : androidx.fragment.app.DialogFragment() {

companion object {
private const val TITLE_KEY = "TITLE_KEY"
private var onClickListener: (IdleDialogButton) -> Unit = {}

fun getInstance(
title: String,
onClickListener: (IdleDialogButton) -> Unit = {}
): IdleDialogFragment {
this.onClickListener = onClickListener

return IdleDialogFragment().apply {
arguments = Bundle().apply {
putString(TITLE_KEY, title)
}
}
}
}

private var binding: FragmentIdleDialogBinding by autoCleared()

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentIdleDialogBinding.inflate(inflater, container, false)
dialog?.window?.decorView?.setBackgroundColor(Color.TRANSPARENT)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

val title = arguments?.getString(TITLE_KEY)
binding.textViewPromptTitle.text = getString(R.string.are_you_still_watching_title, title)
binding.buttonAskAgainLater.setOnClickListener {
onClickListener(IdleDialogButton.ASK_AGAIN)
dismiss()
}
binding.buttonPlayWithoutAskingAgain.setOnClickListener {
onClickListener(IdleDialogButton.PLAY_WITHOUT_ASKING)
dismiss()
}
binding.buttonImDone.setOnClickListener {
onClickListener(IdleDialogButton.DONE)
dismiss()
}
}

override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
onClickListener(IdleDialogButton.ASK_AGAIN)
onClickListener = {}
}
}

enum class IdleDialogButton {
ASK_AGAIN,
PLAY_WITHOUT_ASKING,
DONE
}
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ class HomeFragment : RowsSupportFragment() {
viewModel.videoMedia.observeEvent(viewLifecycleOwner) {
activityViewModel.setMovieBackground()
findNavController().safeNavigate(
HomeFragmentDirections.actionHomeFragmentToPlayerFragment(it)
HomeFragmentDirections.actionHomeFragmentToPlayerFragment()
)
}

Expand Down
Loading

0 comments on commit 2c3b0bd

Please sign in to comment.