mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
added local accounts
This commit is contained in:
parent
b06f098447
commit
180987e2d0
17 changed files with 693 additions and 29 deletions
|
@ -148,6 +148,14 @@ class AcraApplication : Application() {
|
|||
_context = WeakReference(value)
|
||||
}
|
||||
|
||||
fun <T : Any> getKeyClass(path: String, valueType: Class<T>): T? {
|
||||
return context?.getKey(path, valueType)
|
||||
}
|
||||
|
||||
fun <T : Any> setKeyClass(path: String, value: T) {
|
||||
context?.setKey(path, value)
|
||||
}
|
||||
|
||||
fun removeKeys(folder: String): Int? {
|
||||
return context?.removeKeys(folder)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
package com.lagradost.cloudstream3.ui
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.lagradost.cloudstream3.databinding.WhoIsWatchingAccountAddBinding
|
||||
import com.lagradost.cloudstream3.databinding.WhoIsWatchingAccountBinding
|
||||
import com.lagradost.cloudstream3.ui.result.setImage
|
||||
import com.lagradost.cloudstream3.utils.DataStoreHelper
|
||||
|
||||
class WhoIsWatchingAdapter(
|
||||
private val selectCallBack: (DataStoreHelper.Account) -> Unit = { },
|
||||
private val editCallBack: (DataStoreHelper.Account) -> Unit = { },
|
||||
private val addAccountCallback: () -> Unit = {}
|
||||
) :
|
||||
ListAdapter<DataStoreHelper.Account, WhoIsWatchingAdapter.WhoIsWatchingHolder>(DiffCallback()) {
|
||||
|
||||
companion object {
|
||||
const val FOOTER = 1
|
||||
const val NORMAL = 0
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return currentList.size + 1
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int = when (position) {
|
||||
currentList.size -> FOOTER
|
||||
else -> NORMAL
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WhoIsWatchingHolder =
|
||||
WhoIsWatchingHolder(
|
||||
binding = when (viewType) {
|
||||
NORMAL -> WhoIsWatchingAccountBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
|
||||
FOOTER -> WhoIsWatchingAccountAddBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
|
||||
else -> throw NotImplementedError()
|
||||
},
|
||||
selectCallBack = selectCallBack,
|
||||
addAccountCallback = addAccountCallback,
|
||||
editCallBack = editCallBack,
|
||||
)
|
||||
|
||||
|
||||
override fun onBindViewHolder(holder: WhoIsWatchingHolder, position: Int) =
|
||||
holder.bind(currentList.getOrNull(position))
|
||||
|
||||
class WhoIsWatchingHolder(
|
||||
val binding: ViewBinding,
|
||||
val selectCallBack: (DataStoreHelper.Account) -> Unit,
|
||||
val addAccountCallback: () -> Unit,
|
||||
val editCallBack: (DataStoreHelper.Account) -> Unit
|
||||
) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(card: DataStoreHelper.Account?) {
|
||||
when (binding) {
|
||||
is WhoIsWatchingAccountBinding -> binding.apply {
|
||||
if(card == null) return@apply
|
||||
outline.isVisible = card.keyIndex == DataStoreHelper.selectedKeyIndex
|
||||
profileText.text = card.name
|
||||
profileImageBackground.setImage(card.image)
|
||||
root.setOnClickListener {
|
||||
selectCallBack(card)
|
||||
}
|
||||
root.setOnLongClickListener {
|
||||
editCallBack(card)
|
||||
return@setOnLongClickListener true
|
||||
}
|
||||
}
|
||||
|
||||
is WhoIsWatchingAccountAddBinding -> binding.apply {
|
||||
root.setOnClickListener {
|
||||
addAccountCallback()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DiffCallback : DiffUtil.ItemCallback<DataStoreHelper.Account>() {
|
||||
override fun areItemsTheSame(
|
||||
oldItem: DataStoreHelper.Account,
|
||||
newItem: DataStoreHelper.Account
|
||||
): Boolean = oldItem.keyIndex == newItem.keyIndex
|
||||
|
||||
override fun areContentsTheSame(
|
||||
oldItem: DataStoreHelper.Account,
|
||||
newItem: DataStoreHelper.Account
|
||||
): Boolean = oldItem == newItem
|
||||
}
|
||||
}
|
|
@ -40,6 +40,7 @@ import com.lagradost.cloudstream3.utils.DataStoreHelper
|
|||
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog
|
||||
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showOptionSelectStringRes
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbarMargin
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbarView
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
||||
|
||||
|
@ -250,6 +251,11 @@ class HomeParentItemAdapterPreview(
|
|||
private var bookmarkRecyclerView: RecyclerView =
|
||||
itemView.findViewById(R.id.home_bookmarked_child_recyclerview)
|
||||
|
||||
private var homeAccount: View? =
|
||||
itemView.findViewById(R.id.home_switch_account)
|
||||
|
||||
private var topPadding : View? = itemView.findViewById(R.id.home_padding)
|
||||
|
||||
private val homeNonePadding: View = itemView.findViewById(R.id.home_none_padding)
|
||||
|
||||
private val previewCallback: ViewPager2.OnPageChangeCallback =
|
||||
|
@ -432,6 +438,8 @@ class HomeParentItemAdapterPreview(
|
|||
resumeRecyclerView.setLinearListLayout()
|
||||
bookmarkRecyclerView.setLinearListLayout()
|
||||
|
||||
fixPaddingStatusbarMargin(topPadding)
|
||||
|
||||
for ((chip, watch) in toggleList) {
|
||||
chip.isChecked = false
|
||||
chip.setOnCheckedChangeListener { _, isChecked ->
|
||||
|
@ -445,6 +453,10 @@ class HomeParentItemAdapterPreview(
|
|||
}
|
||||
}
|
||||
|
||||
homeAccount?.setOnClickListener { v ->
|
||||
DataStoreHelper.showWhoIsWatching(v?.context ?: return@setOnClickListener)
|
||||
}
|
||||
|
||||
(binding as? FragmentHomeHeadTvBinding)?.apply {
|
||||
homePreviewChangeApi.setOnClickListener { view ->
|
||||
view.context.selectHomepage(viewModel.repo?.name) { api ->
|
||||
|
@ -485,8 +497,6 @@ class HomeParentItemAdapterPreview(
|
|||
}
|
||||
|
||||
(binding as? FragmentHomeHeadBinding)?.apply {
|
||||
fixPaddingStatusbar(binding.homeSearch)
|
||||
|
||||
homeSearch.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||
override fun onQueryTextSubmit(query: String): Boolean {
|
||||
viewModel.queryTextSubmit(query)
|
||||
|
|
|
@ -96,8 +96,8 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
|
|||
// protected var currentPrefQuality =
|
||||
// Qualities.P2160.value // preferred maximum quality, used for ppl w bad internet or on cell
|
||||
protected var fastForwardTime = 10000L
|
||||
protected var androidTVInterfaceOffSeekTime = 10000L;
|
||||
protected var androidTVInterfaceOnSeekTime = 30000L;
|
||||
protected var androidTVInterfaceOffSeekTime = 10000L
|
||||
protected var androidTVInterfaceOnSeekTime = 30000L
|
||||
protected var swipeHorizontalEnabled = false
|
||||
protected var swipeVerticalEnabled = false
|
||||
protected var playBackSpeedEnabled = false
|
||||
|
|
|
@ -1252,7 +1252,6 @@ class GeneratorPlayer : FullScreenPlayer() {
|
|||
private fun displayTimeStamp(show: Boolean) {
|
||||
if (timestampShowState == show) return
|
||||
skipIndex++
|
||||
println("displayTimeStamp = $show")
|
||||
timestampShowState = show
|
||||
playerBinding?.skipChapterButton?.apply {
|
||||
val showWidth = 170.toPx
|
||||
|
@ -1294,7 +1293,6 @@ class GeneratorPlayer : FullScreenPlayer() {
|
|||
|
||||
override fun onTimestamp(timestamp: EpisodeSkip.SkipStamp?) {
|
||||
if (timestamp != null) {
|
||||
println("timestamp: $timestamp")
|
||||
playerBinding?.skipChapterButton?.setText(timestamp.uiText)
|
||||
displayTimeStamp(true)
|
||||
val currentIndex = skipIndex
|
||||
|
|
|
@ -6,7 +6,12 @@ import androidx.preference.PreferenceManager
|
|||
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper
|
||||
import com.fasterxml.jackson.module.kotlin.KotlinModule
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.getKeyClass
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.setKeyClass
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
const val DOWNLOAD_HEADER_CACHE = "download_header_cache"
|
||||
|
||||
|
@ -20,6 +25,31 @@ const val PREFERENCES_NAME = "rebuild_preference"
|
|||
|
||||
// TODO degelgate by value for get & set
|
||||
|
||||
class PreferenceDelegate<T : Any>(
|
||||
val key: String, val default: T //, private val klass: KClass<T>
|
||||
) {
|
||||
private val klass: KClass<out T> = default::class
|
||||
// simple cache to make it not get the key every time it is accessed, however this requires
|
||||
// that ONLY this changes the key
|
||||
private var cache: T? = null
|
||||
|
||||
operator fun getValue(self: Any?, property: KProperty<*>) =
|
||||
cache ?: getKeyClass(key, klass.java).also { newCache -> cache = newCache } ?: default
|
||||
|
||||
operator fun setValue(
|
||||
self: Any?,
|
||||
property: KProperty<*>,
|
||||
t: T?
|
||||
) {
|
||||
cache = t
|
||||
if (t == null) {
|
||||
removeKey(key)
|
||||
} else {
|
||||
setKeyClass(key, t)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object DataStore {
|
||||
val mapper: JsonMapper = JsonMapper.builder().addModule(KotlinModule())
|
||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).build()
|
||||
|
@ -89,7 +119,7 @@ object DataStore {
|
|||
}
|
||||
|
||||
fun Context.removeKeys(folder: String): Int {
|
||||
val keys = getKeys(folder)
|
||||
val keys = getKeys("$folder/")
|
||||
keys.forEach { value ->
|
||||
removeKey(value)
|
||||
}
|
||||
|
@ -106,6 +136,15 @@ object DataStore {
|
|||
}
|
||||
}
|
||||
|
||||
fun <T> Context.getKey(path: String, valueType: Class<T>): T? {
|
||||
try {
|
||||
val json: String = getSharedPrefs().getString(path, null) ?: return null
|
||||
return json.toKotlinObject(valueType)
|
||||
} catch (e: Exception) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> Context.setKey(folder: String, path: String, value: T) {
|
||||
setKey(getFolderName(folder, path), value)
|
||||
}
|
||||
|
@ -114,6 +153,10 @@ object DataStore {
|
|||
return mapper.readValue(this, T::class.java)
|
||||
}
|
||||
|
||||
fun <T> String.toKotlinObject(valueType: Class<T>): T {
|
||||
return mapper.readValue(this, valueType)
|
||||
}
|
||||
|
||||
// GET KEY GIVEN PATH AND DEFAULT VALUE, NULL IF ERROR
|
||||
inline fun <reified T : Any> Context.getKey(path: String, defVal: T?): T? {
|
||||
try {
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
package com.lagradost.cloudstream3.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
import android.text.Editable
|
||||
import android.view.LayoutInflater
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.view.isGone
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.APIHolder.unixTimeMS
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
||||
|
@ -8,10 +16,20 @@ import com.lagradost.cloudstream3.AcraApplication.Companion.getKeys
|
|||
import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.removeKeys
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
|
||||
import com.lagradost.cloudstream3.CommonActivity.showToast
|
||||
import com.lagradost.cloudstream3.databinding.WhoIsWatchingAccountEditBinding
|
||||
import com.lagradost.cloudstream3.databinding.WhoIsWatchingBinding
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import com.lagradost.cloudstream3.syncproviders.AccountManager
|
||||
import com.lagradost.cloudstream3.syncproviders.SyncAPI
|
||||
import com.lagradost.cloudstream3.ui.WatchType
|
||||
import com.lagradost.cloudstream3.ui.WhoIsWatchingAdapter
|
||||
import com.lagradost.cloudstream3.ui.result.UiImage
|
||||
import com.lagradost.cloudstream3.ui.result.VideoWatchState
|
||||
import com.lagradost.cloudstream3.ui.result.setImage
|
||||
import com.lagradost.cloudstream3.ui.result.setLinearListLayout
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.setDefaultFocus
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
|
||||
|
||||
const val VIDEO_POS_DUR = "video_pos_dur"
|
||||
const val VIDEO_WATCH_STATE = "video_watch_state"
|
||||
|
@ -26,6 +44,197 @@ const val RESULT_SEASON = "result_season"
|
|||
const val RESULT_DUB = "result_dub"
|
||||
|
||||
object DataStoreHelper {
|
||||
// be aware, don't change the index of these as Account uses the index for the art
|
||||
private val profileImages = arrayOf(
|
||||
R.drawable.profile_bg_dark_blue,
|
||||
R.drawable.profile_bg_blue,
|
||||
R.drawable.profile_bg_orange,
|
||||
R.drawable.profile_bg_pink,
|
||||
R.drawable.profile_bg_purple,
|
||||
R.drawable.profile_bg_red,
|
||||
R.drawable.profile_bg_teal
|
||||
)
|
||||
|
||||
data class Account(
|
||||
@JsonProperty("keyIndex")
|
||||
val keyIndex: Int,
|
||||
@JsonProperty("name")
|
||||
val name: String,
|
||||
@JsonProperty("customImage")
|
||||
val customImage: String? = null,
|
||||
@JsonProperty("defaultImageIndex")
|
||||
val defaultImageIndex: Int,
|
||||
) {
|
||||
val image: UiImage
|
||||
get() = customImage?.let { UiImage.Image(it) } ?: UiImage.Drawable(
|
||||
profileImages.getOrNull(defaultImageIndex) ?: profileImages.first()
|
||||
)
|
||||
}
|
||||
|
||||
const val TAG = "data_store_helper"
|
||||
private var accounts by PreferenceDelegate("$TAG/account", arrayOf<Account>())
|
||||
var selectedKeyIndex by PreferenceDelegate("$TAG/account_key_index", 0)
|
||||
val currentAccount: String get() = selectedKeyIndex.toString()
|
||||
|
||||
private fun setAccount(account: Account) {
|
||||
selectedKeyIndex = account.keyIndex
|
||||
showToast(account.name)
|
||||
MainActivity.bookmarksUpdatedEvent(true)
|
||||
}
|
||||
|
||||
private fun editAccount(context: Context, account: Account, isNewAccount: Boolean) {
|
||||
val binding =
|
||||
WhoIsWatchingAccountEditBinding.inflate(LayoutInflater.from(context), null, false)
|
||||
val builder =
|
||||
AlertDialog.Builder(context, R.style.AlertDialogCustom)
|
||||
.setView(binding.root)
|
||||
|
||||
var currentEditAccount = account
|
||||
val dialog = builder.show()
|
||||
binding.accountName.text = Editable.Factory.getInstance()?.newEditable(account.name)
|
||||
binding.accountName.doOnTextChanged { text, _, _, _ ->
|
||||
currentEditAccount = currentEditAccount.copy(name = text?.toString() ?: "")
|
||||
}
|
||||
|
||||
binding.deleteBtt.isGone = isNewAccount
|
||||
binding.deleteBtt.setOnClickListener {
|
||||
val dialogClickListener =
|
||||
DialogInterface.OnClickListener { _, which ->
|
||||
when (which) {
|
||||
DialogInterface.BUTTON_POSITIVE -> {
|
||||
// remove all keys as well as the account, note that default wont get
|
||||
// deleted from currentAccounts, as it is not part of "accounts",
|
||||
// but the watch keys will
|
||||
removeKeys(account.keyIndex.toString())
|
||||
val currentAccounts = accounts.toMutableList()
|
||||
currentAccounts.removeIf { it.keyIndex == account.keyIndex }
|
||||
accounts = currentAccounts.toTypedArray()
|
||||
|
||||
// update UI
|
||||
setAccount(getDefaultAccount(context))
|
||||
MainActivity.bookmarksUpdatedEvent(true)
|
||||
dialog?.dismissSafe()
|
||||
}
|
||||
|
||||
DialogInterface.BUTTON_NEGATIVE -> {}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
AlertDialog.Builder(context).setTitle(R.string.delete).setMessage(
|
||||
context.getString(R.string.delete_message).format(
|
||||
currentEditAccount.name
|
||||
)
|
||||
)
|
||||
.setPositiveButton(R.string.delete, dialogClickListener)
|
||||
.setNegativeButton(R.string.cancel, dialogClickListener)
|
||||
.show().setDefaultFocus()
|
||||
} catch (t: Throwable) {
|
||||
logError(t)
|
||||
// ye you somehow fucked up formatting did you?
|
||||
}
|
||||
}
|
||||
|
||||
binding.cancelBtt.setOnClickListener {
|
||||
dialog?.dismissSafe()
|
||||
}
|
||||
|
||||
binding.profilePic.setImage(account.image)
|
||||
binding.profilePic.setOnClickListener {
|
||||
// rolls the image forwards once
|
||||
currentEditAccount =
|
||||
currentEditAccount.copy(defaultImageIndex = (currentEditAccount.defaultImageIndex + 1) % profileImages.size)
|
||||
binding.profilePic.setImage(currentEditAccount.image)
|
||||
}
|
||||
|
||||
binding.applyBtt.setOnClickListener {
|
||||
val currentAccounts = accounts.toMutableList()
|
||||
|
||||
val overrideIndex =
|
||||
currentAccounts.indexOfFirst { it.keyIndex == currentEditAccount.keyIndex }
|
||||
|
||||
// if an account is found that has the same keyIndex then override that one, if not then append it
|
||||
if (overrideIndex != -1) {
|
||||
currentAccounts[overrideIndex] = currentEditAccount
|
||||
} else {
|
||||
currentAccounts.add(currentEditAccount)
|
||||
}
|
||||
|
||||
// set the new default account as well as add the key for the new account
|
||||
setAccount(currentEditAccount)
|
||||
accounts = currentAccounts.toTypedArray()
|
||||
|
||||
dialog.dismissSafe()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDefaultAccount(context: Context): Account {
|
||||
return accounts.let { currentAccounts ->
|
||||
currentAccounts.getOrNull(currentAccounts.indexOfFirst { it.keyIndex == 0 }) ?: Account(
|
||||
keyIndex = 0,
|
||||
name = context.getString(R.string.default_account),
|
||||
defaultImageIndex = 0
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun showWhoIsWatching(context: Context) {
|
||||
val binding: WhoIsWatchingBinding = WhoIsWatchingBinding.inflate(
|
||||
LayoutInflater.from(context)
|
||||
)
|
||||
|
||||
val showAccount = accounts.toMutableList().apply {
|
||||
val item = getDefaultAccount(context)
|
||||
remove(item)
|
||||
add(0, item)
|
||||
}
|
||||
|
||||
val builder =
|
||||
BottomSheetDialog(context)
|
||||
builder.setContentView(binding.root)
|
||||
val accountName = context.getString(R.string.account)
|
||||
|
||||
binding.profilesRecyclerview.setLinearListLayout(isHorizontal = true)
|
||||
binding.profilesRecyclerview.adapter = WhoIsWatchingAdapter(
|
||||
selectCallBack = { account ->
|
||||
setAccount(account)
|
||||
builder.dismissSafe()
|
||||
},
|
||||
addAccountCallback = {
|
||||
val currentAccounts = accounts
|
||||
val remainingImages =
|
||||
profileImages.toSet() - currentAccounts.filter { it.customImage == null }
|
||||
.mapNotNull { profileImages.getOrNull(it.defaultImageIndex) }.toSet()
|
||||
val image =
|
||||
profileImages.indexOf(remainingImages.randomOrNull() ?: profileImages.random())
|
||||
val keyIndex = (currentAccounts.maxOfOrNull { it.keyIndex } ?: 0) + 1
|
||||
|
||||
// create a new dummy account
|
||||
editAccount(
|
||||
context,
|
||||
Account(
|
||||
keyIndex = keyIndex,
|
||||
name = "$accountName $keyIndex",
|
||||
customImage = null,
|
||||
defaultImageIndex = image
|
||||
), isNewAccount = true
|
||||
)
|
||||
builder.dismissSafe()
|
||||
},
|
||||
editCallBack = { account ->
|
||||
editAccount(
|
||||
context, account, isNewAccount = false
|
||||
)
|
||||
builder.dismissSafe()
|
||||
}
|
||||
).apply {
|
||||
submitList(showAccount)
|
||||
}
|
||||
|
||||
builder.show()
|
||||
}
|
||||
|
||||
|
||||
data class PosDur(
|
||||
@JsonProperty("position") val position: Long,
|
||||
@JsonProperty("duration") val duration: Long
|
||||
|
@ -117,7 +326,6 @@ object DataStoreHelper {
|
|||
/**
|
||||
* A datastore wide account for future implementations of a multiple account system
|
||||
**/
|
||||
var currentAccount: String = "0" //TODO ACCOUNT IMPLEMENTATION
|
||||
|
||||
fun getAllWatchStateIds(): List<Int>? {
|
||||
val folder = "$currentAccount/$RESULT_WATCH_STATE"
|
||||
|
|
|
@ -15,6 +15,7 @@ import android.graphics.drawable.Drawable
|
|||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.*
|
||||
import android.view.ViewGroup.MarginLayoutParams
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.ImageView
|
||||
import android.widget.ListAdapter
|
||||
|
@ -33,6 +34,10 @@ import androidx.core.graphics.blue
|
|||
import androidx.core.graphics.drawable.toBitmapOrNull
|
||||
import androidx.core.graphics.green
|
||||
import androidx.core.graphics.red
|
||||
import androidx.core.view.marginBottom
|
||||
import androidx.core.view.marginLeft
|
||||
import androidx.core.view.marginRight
|
||||
import androidx.core.view.marginTop
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
|
@ -55,7 +60,6 @@ import com.lagradost.cloudstream3.mvvm.logError
|
|||
import com.lagradost.cloudstream3.ui.result.UiImage
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isEmulatorSettings
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute
|
||||
import jp.wasabeef.glide.transformations.BlurTransformation
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
|
@ -77,8 +81,8 @@ object UIHelper {
|
|||
|| Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
|
||||
}
|
||||
|
||||
fun populateChips(view: ChipGroup?, tags : List<String>) {
|
||||
if(view == null) return
|
||||
fun populateChips(view: ChipGroup?, tags: List<String>) {
|
||||
if (view == null) return
|
||||
view.removeAllViews()
|
||||
val context = view.context ?: return
|
||||
|
||||
|
@ -304,7 +308,7 @@ object UIHelper {
|
|||
else req
|
||||
}
|
||||
|
||||
if(radius > 0) {
|
||||
if (radius > 0) {
|
||||
builder = builder.apply(bitmapTransform(BlurTransformation(radius, sample)))
|
||||
}
|
||||
|
||||
|
@ -496,6 +500,22 @@ object UIHelper {
|
|||
)
|
||||
}
|
||||
|
||||
fun fixPaddingStatusbarMargin(v: View?) {
|
||||
if (v == null) return
|
||||
val ctx = v.context ?: return
|
||||
|
||||
v.layoutParams = v.layoutParams.apply {
|
||||
if (this is MarginLayoutParams) {
|
||||
setMargins(
|
||||
v.marginLeft,
|
||||
v.marginTop + ctx.getStatusBarHeight(),
|
||||
v.marginRight,
|
||||
v.marginBottom
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun fixPaddingStatusbarView(v: View?) {
|
||||
if (v == null) return
|
||||
val ctx = v.context ?: return
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
<vector android:height="24dp" android:tint="#000000"
|
||||
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="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10s10,-4.48 10,-10S17.52,2 12,2zM7.35,18.5C8.66,17.56 10.26,17 12,17s3.34,0.56 4.65,1.5C15.34,19.44 13.74,20 12,20S8.66,19.44 7.35,18.5zM18.14,17.12L18.14,17.12C16.45,15.8 14.32,15 12,15s-4.45,0.8 -6.14,2.12l0,0C4.7,15.73 4,13.95 4,12c0,-4.42 3.58,-8 8,-8s8,3.58 8,8C20,13.95 19.3,15.73 18.14,17.12z"/>
|
||||
<path android:fillColor="@android:color/white" android:pathData="M12,6c-1.93,0 -3.5,1.57 -3.5,3.5S10.07,13 12,13s3.5,-1.57 3.5,-3.5S13.93,6 12,6zM12,11c-0.83,0 -1.5,-0.67 -1.5,-1.5S11.17,8 12,8s1.5,0.67 1.5,1.5S12.83,11 12,11z"/>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="?attr/white"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10s10,-4.48 10,-10S17.52,2 12,2zM7.35,18.5C8.66,17.56 10.26,17 12,17s3.34,0.56 4.65,1.5C15.34,19.44 13.74,20 12,20S8.66,19.44 7.35,18.5zM18.14,17.12L18.14,17.12C16.45,15.8 14.32,15 12,15s-4.45,0.8 -6.14,2.12l0,0C4.7,15.73 4,13.95 4,12c0,-4.42 3.58,-8 8,-8s8,3.58 8,8C20,13.95 19.3,15.73 18.14,17.12z" />
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,6c-1.93,0 -3.5,1.57 -3.5,3.5S10.07,13 12,13s3.5,-1.57 3.5,-3.5S13.93,6 12,6zM12,11c-0.83,0 -1.5,-0.67 -1.5,-1.5S11.17,8 12,8s1.5,0.67 1.5,1.5S12.83,11 12,11z" />
|
||||
</vector>
|
||||
|
|
|
@ -1,21 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="@android:color/white">
|
||||
android:color="@android:color/white">
|
||||
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<stroke
|
||||
android:width="2dp"
|
||||
android:color="@android:color/white" />
|
||||
<corners android:radius="2dp" />
|
||||
android:width="2dp"
|
||||
android:color="@android:color/white" />
|
||||
<corners android:radius="@dimen/rounded_image_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:id="@android:id/mask">
|
||||
<shape android:shape="rectangle">
|
||||
<corners android:radius="2dp" />
|
||||
<corners android:radius="@dimen/rounded_image_radius" />
|
||||
<solid android:color="?attr/iconGrayBackground" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</ripple>
|
|
@ -38,16 +38,21 @@
|
|||
<LinearLayout
|
||||
android:id="@+id/home_padding"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
android:layout_height="50dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<androidx.appcompat.widget.SearchView
|
||||
android:id="@+id/home_search"
|
||||
android:nextFocusRight="@id/home_switch_account"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:layout_gravity="start"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:padding="0dp"
|
||||
android:layout_marginEnd="50dp"
|
||||
android:editTextColor="@color/white"
|
||||
android:gravity="start"
|
||||
android:gravity="center_vertical"
|
||||
|
||||
android:iconifiedByDefault="true"
|
||||
android:textColor="@color/white"
|
||||
android:textColorHint="@color/white"
|
||||
|
@ -57,6 +62,19 @@
|
|||
app:queryHint="@string/search_hint"
|
||||
app:searchIcon="@drawable/search_icon"
|
||||
tools:ignore="RtlSymmetry" />
|
||||
|
||||
<ImageView
|
||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||
|
||||
android:nextFocusLeft="@id/home_search"
|
||||
android:id="@+id/home_switch_account"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="-50dp"
|
||||
android:contentDescription="@string/account"
|
||||
android:padding="10dp"
|
||||
android:src="@drawable/ic_outline_account_circle_24" />
|
||||
</LinearLayout>
|
||||
|
||||
<!--
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
android:id="@+id/outline"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/outline"
|
||||
android:background="@drawable/outline_card"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
|
|
35
app/src/main/res/layout/who_is_watching.xml
Normal file
35
app/src/main/res/layout/who_is_watching.xml
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<TextView
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:textStyle="bold"
|
||||
android:text="@string/switch_account"
|
||||
android:textSize="20sp"
|
||||
android:textColor="?attr/textColor"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_rowWeight="1"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:descendantFocusability="afterDescendants"
|
||||
android:id="@+id/profiles_recyclerview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
android:orientation="horizontal"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:itemCount="4"
|
||||
tools:listitem="@layout/who_is_watching_account">
|
||||
|
||||
<requestFocus />
|
||||
</androidx.recyclerview.widget.RecyclerView>
|
||||
</LinearLayout>
|
47
app/src/main/res/layout/who_is_watching_account.xml
Normal file
47
app/src/main/res/layout/who_is_watching_account.xml
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/card_view"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:animateLayoutChanges="true"
|
||||
android:backgroundTint="?attr/primaryGrayBackground"
|
||||
android:foreground="?attr/selectableItemBackgroundBorderless"
|
||||
app:cardCornerRadius="@dimen/rounded_image_radius"
|
||||
android:layout_margin="5dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintDimensionRatio="1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHeight_percent="0.4"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/profile_image_background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:alpha="0.4"
|
||||
android:contentDescription="@string/profile_background_des"
|
||||
android:scaleType="centerCrop" />
|
||||
|
||||
<View
|
||||
android:id="@+id/outline"
|
||||
tools:visibility="visible"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/outline_card"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/profile_text"
|
||||
tools:text="@string/mobile_data"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:padding="10dp"
|
||||
android:textSize="16sp" />
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
29
app/src/main/res/layout/who_is_watching_account_add.xml
Normal file
29
app/src/main/res/layout/who_is_watching_account_add.xml
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/card_view"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:animateLayoutChanges="true"
|
||||
android:backgroundTint="?attr/primaryGrayBackground"
|
||||
android:foreground="?attr/selectableItemBackgroundBorderless"
|
||||
app:cardCornerRadius="@dimen/rounded_image_radius"
|
||||
android:layout_margin="5dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintDimensionRatio="1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHeight_percent="0.4"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/ic_baseline_add_24"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:contentDescription="@string/add_account" />
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
135
app/src/main/res/layout/who_is_watching_account_edit.xml
Normal file
135
app/src/main/res/layout/who_is_watching_account_edit.xml
Normal file
|
@ -0,0 +1,135 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_rowWeight="1"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||
android:text="@string/create_account"
|
||||
android:textColor="?attr/textColor"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<!-- <com.google.android.material.button.MaterialButton-->
|
||||
<!-- android:nextFocusDown="@id/repo_name_input"-->
|
||||
<!-- android:id="@+id/list_repositories"-->
|
||||
<!-- android:nextFocusLeft="@id/apply_btt"-->
|
||||
<!-- android:nextFocusRight="@id/cancel_btt"-->
|
||||
<!-- style="@style/WhiteButton"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_gravity="center_vertical"-->
|
||||
<!-- android:text="@string/view_public_repositories_button_short" />-->
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text2"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_rowWeight="1"
|
||||
android:layout_gravity="center_vertical"
|
||||
|
||||
android:layout_marginBottom="10dp"
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||
android:textColor="?attr/grayTextColor"
|
||||
android:textSize="15sp"
|
||||
android:visibility="gone"
|
||||
tools:text="Gogoanime" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="10dp"
|
||||
android:layout_marginBottom="60dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/account_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:autofillHints="username"
|
||||
android:hint="@string/default_account"
|
||||
android:inputType="text"
|
||||
android:nextFocusLeft="@id/apply_btt"
|
||||
android:nextFocusRight="@id/cancel_btt"
|
||||
android:nextFocusDown="@id/site_url_input"
|
||||
android:requiresFadingEdge="vertical"
|
||||
android:textColorHint="?attr/grayTextColor"
|
||||
tools:ignore="LabelFor" />
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:cardCornerRadius="@dimen/rounded_image_radius">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/profile_pic"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:layout_gravity="center"
|
||||
android:contentDescription="@string/preview_background_img_des"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/profile_bg_blue" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/apply_btt_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_marginTop="-60dp"
|
||||
android:orientation="horizontal"
|
||||
android:padding="10dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/delete_btt"
|
||||
style="@style/BlackButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:nextFocusRight="@id/apply_btt"
|
||||
android:text="@string/delete" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/apply_btt"
|
||||
style="@style/WhiteButton"
|
||||
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:layout_toStartOf="@+id/cancel_btt"
|
||||
android:nextFocusLeft="@id/delete_btt"
|
||||
android:nextFocusRight="@id/cancel_btt"
|
||||
android:text="@string/sort_apply" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/cancel_btt"
|
||||
style="@style/BlackButton"
|
||||
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:nextFocusLeft="@id/apply_btt"
|
||||
android:text="@string/sort_cancel" />
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
|
@ -307,6 +307,7 @@
|
|||
<string name="queued">queued</string>
|
||||
<string name="no_subtitles">No Subtitles</string>
|
||||
<string name="default_subtitles">Default</string>
|
||||
<string name="default_account">@string/default_subtitles</string>
|
||||
<string name="free_storage">Free</string>
|
||||
<string name="used_storage">Used</string>
|
||||
<string name="app_storage">App</string>
|
||||
|
|
Loading…
Reference in a new issue