mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
init
This commit is contained in:
parent
65f848987d
commit
1549f67cd7
40 changed files with 589 additions and 143 deletions
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
|
|
|
@ -40,19 +40,23 @@ dependencies {
|
|||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation 'androidx.core:core-ktx:1.3.2'
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
implementation 'com.google.android.material:material:1.1.0'
|
||||
implementation 'com.google.android.material:material:1.3.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||
implementation 'androidx.navigation:navigation-fragment:2.3.5'
|
||||
implementation 'androidx.navigation:navigation-ui:2.3.5'
|
||||
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
|
||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
|
||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
|
||||
implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
|
||||
testImplementation 'junit:junit:4.+'
|
||||
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
|
||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
|
||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
|
||||
implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||
|
||||
implementation "io.karn:khttp-android:0.1.2"
|
||||
implementation 'org.jsoup:jsoup:1.13.1'
|
||||
implementation "com.fasterxml.jackson.module:jackson-module-kotlin:2.11.3"
|
||||
|
||||
implementation("com.google.android.material:material:1.3.0")
|
||||
|
||||
implementation "androidx.preference:preference-ktx:1.1.1"
|
||||
}
|
|
@ -3,6 +3,7 @@ package com.lagradost.cloudstream3
|
|||
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper
|
||||
import com.fasterxml.jackson.module.kotlin.KotlinModule
|
||||
import com.lagradost.cloudstream3.animeproviders.ShiroProvider
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
|
@ -11,7 +12,14 @@ val baseHeader = mapOf("User-Agent" to USER_AGENT)
|
|||
val mapper = JsonMapper.builder().addModule(KotlinModule())
|
||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).build()!!
|
||||
|
||||
open class MainAPI {
|
||||
object APIHolder {
|
||||
val apis = arrayListOf<MainAPI>(
|
||||
ShiroProvider()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
abstract class MainAPI {
|
||||
open val name = "NONE"
|
||||
open val mainUrl = "NONE"
|
||||
open fun search(query: String): ArrayList<Any>? { // SearchResponse
|
||||
|
@ -29,14 +37,14 @@ open class MainAPI {
|
|||
|
||||
data class Link(
|
||||
val name: String,
|
||||
val url : String,
|
||||
val url: String,
|
||||
val quality: Int?,
|
||||
val referer : String?,
|
||||
val referer: String?,
|
||||
)
|
||||
|
||||
interface LinkExtractor {
|
||||
val linkStart : String // THIS IS USED TO AUTO-EXTRACT LINKS FROM URL
|
||||
fun extract(link : String, referer : String) : ArrayList<Link>
|
||||
val linkStart: String // THIS IS USED TO AUTO-EXTRACT LINKS FROM URL
|
||||
fun extract(link: String, referer: String): ArrayList<Link>
|
||||
}
|
||||
|
||||
enum class ShowStatus {
|
||||
|
|
|
@ -5,7 +5,6 @@ import com.google.android.material.bottomnavigation.BottomNavigationView
|
|||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.navigation.ui.AppBarConfiguration
|
||||
import androidx.navigation.ui.setupActionBarWithNavController
|
||||
import androidx.navigation.ui.setupWithNavController
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
@ -19,7 +18,7 @@ class MainActivity : AppCompatActivity() {
|
|||
// Passing each menu ID as a set of Ids because each
|
||||
// menu should be considered as top level destinations.
|
||||
val appBarConfiguration = AppBarConfiguration(setOf(
|
||||
R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications))
|
||||
R.id.navigation_home, R.id.navigation_search, R.id.navigation_notifications))
|
||||
//setupActionBarWithNavController(navController, appBarConfiguration)
|
||||
navView.setupWithNavController(navController)
|
||||
}
|
||||
|
|
20
app/src/main/java/com/lagradost/cloudstream3/UIHelper.kt
Normal file
20
app/src/main/java/com/lagradost/cloudstream3/UIHelper.kt
Normal file
|
@ -0,0 +1,20 @@
|
|||
package com.lagradost.cloudstream3
|
||||
|
||||
import android.app.Activity
|
||||
import android.view.View
|
||||
|
||||
object UIHelper {
|
||||
fun Activity.getStatusBarHeight(): Int {
|
||||
var result = 0
|
||||
val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
|
||||
if (resourceId > 0) {
|
||||
result = resources.getDimensionPixelSize(resourceId)
|
||||
}
|
||||
return result
|
||||
|
||||
}
|
||||
|
||||
fun Activity.fixPaddingStatusbar(v: View) {
|
||||
v.setPadding(v.paddingLeft, v.paddingTop + getStatusBarHeight(), v.paddingRight, v.paddingBottom)
|
||||
}
|
||||
}
|
|
@ -43,44 +43,40 @@ class ShiroProvider : MainAPI() {
|
|||
@JsonProperty("slug") val slug: String,
|
||||
@JsonProperty("name") val name: String,
|
||||
)
|
||||
|
||||
data class ShiroSearchResponse(
|
||||
@JsonProperty("data") val data: List<ShiroSearchResponseShow>,
|
||||
@JsonProperty("status") val status: String
|
||||
@JsonProperty("status") val status: String,
|
||||
)
|
||||
|
||||
data class ShiroFullSearchResponseCurrentPage(
|
||||
@JsonProperty("items") val items: List<ShiroSearchResponseShow>
|
||||
@JsonProperty("items") val items: List<ShiroSearchResponseShow>,
|
||||
)
|
||||
|
||||
data class ShiroFullSearchResponseNavItems(
|
||||
@JsonProperty("currentPage") val currentPage: ShiroFullSearchResponseCurrentPage
|
||||
@JsonProperty("currentPage") val currentPage: ShiroFullSearchResponseCurrentPage,
|
||||
)
|
||||
|
||||
data class ShiroFullSearchResponseNav(
|
||||
@JsonProperty("nav") val nav: ShiroFullSearchResponseNavItems
|
||||
@JsonProperty("nav") val nav: ShiroFullSearchResponseNavItems,
|
||||
)
|
||||
|
||||
data class ShiroFullSearchResponse(
|
||||
@JsonProperty("data") val data: ShiroFullSearchResponseNav,
|
||||
@JsonProperty("status") val status: String
|
||||
@JsonProperty("status") val status: String,
|
||||
)
|
||||
|
||||
override fun search(query: String): ArrayList<Any>? {
|
||||
if(!autoLoadToken()) return null
|
||||
try {
|
||||
val returnValue: ArrayList<Any> = ArrayList()
|
||||
val response = khttp.get("https://tapi.shiro.is/advanced?search=${
|
||||
URLEncoder.encode(
|
||||
query,
|
||||
"UTF-8"
|
||||
)
|
||||
}&token=$token")
|
||||
val mapped = response.let { mapper.readValue<ShiroSearchResponse>(it.text) }
|
||||
if (!autoLoadToken()) return null
|
||||
val returnValue: ArrayList<Any> = ArrayList()
|
||||
val response = khttp.get("https://tapi.shiro.is/advanced?search=${
|
||||
URLEncoder.encode(
|
||||
query,
|
||||
"UTF-8"
|
||||
)
|
||||
}&token=$token")
|
||||
val mapped = response.let { mapper.readValue<ShiroSearchResponse>(it.text) }
|
||||
|
||||
|
||||
|
||||
return returnValue
|
||||
}
|
||||
catch (e : Exception) {
|
||||
return null
|
||||
}
|
||||
return returnValue
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package com.lagradost.cloudstream3.mvvm
|
||||
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
fun <T> LifecycleOwner.observe(liveData: LiveData<T>, action: (t: T) -> Unit) {
|
||||
liveData.observe(this, Observer { it?.let { t -> action(t) } })
|
||||
}
|
||||
|
||||
sealed class Resource<out T> {
|
||||
data class Success<out T>(val value: T) : Resource<T>()
|
||||
data class Failure(
|
||||
val isNetworkError: Boolean,
|
||||
val errorCode: Int?,
|
||||
val errorResponse: Any?, //ResponseBody
|
||||
val errorString: String,
|
||||
) : Resource<Nothing>()
|
||||
}
|
||||
|
||||
suspend fun <T> safeApiCall(
|
||||
apiCall: suspend () -> T,
|
||||
): Resource<T> {
|
||||
return withContext(Dispatchers.IO) {
|
||||
try {
|
||||
Resource.Success(apiCall.invoke())
|
||||
} catch (throwable: Throwable) {
|
||||
Log.d("ApiError", "-------------------------------------------------------------------")
|
||||
Log.d("ApiError", "safeApiCall: " + throwable.localizedMessage)
|
||||
Log.d("ApiError", "safeApiCall: " + throwable.message)
|
||||
Log.d("ApiError", "-------------------------------------------------------------------")
|
||||
when (throwable) {
|
||||
/*is HttpException -> {
|
||||
Resource.Failure(false, throwable.code(), throwable.response()?.errorBody(), throwable.localizedMessage)
|
||||
}
|
||||
is SocketTimeoutException -> {
|
||||
Resource.Failure(true,null,null,"Please try again later.")
|
||||
}
|
||||
is UnknownHostException ->{
|
||||
Resource.Failure(true,null,null,"Cannot connect to server, try again later.")
|
||||
}*/
|
||||
else -> {
|
||||
Resource.Failure(true, null, null, throwable.localizedMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
package com.lagradost.cloudstream3.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import kotlin.math.abs
|
||||
|
||||
class GrdLayoutManager(val context: Context, val spanCoun: Int) : GridLayoutManager(context, spanCoun) {
|
||||
override fun onFocusSearchFailed(
|
||||
focused: View,
|
||||
focusDirection: Int,
|
||||
recycler: RecyclerView.Recycler,
|
||||
state: RecyclerView.State
|
||||
): View? {
|
||||
return try {
|
||||
val fromPos = getPosition(focused)
|
||||
println("Search failed $fromPos")
|
||||
val nextPos = getNextViewPos(fromPos, focusDirection)
|
||||
findViewByPosition(nextPos)
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRequestChildFocus(
|
||||
parent: RecyclerView,
|
||||
state: RecyclerView.State,
|
||||
child: View,
|
||||
focused: View?
|
||||
): Boolean {
|
||||
// android.widget.FrameLayout$LayoutParams cannot be cast to androidx.recyclerview.widget.RecyclerView$LayoutParams
|
||||
return try {
|
||||
val pos = maxOf(0, getPosition(focused!!) - 2)
|
||||
parent.scrollToPosition(pos)
|
||||
super.onRequestChildFocus(parent, state, child, focused)
|
||||
} catch (e: Exception){
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
// Allows moving right and left with focus https://gist.github.com/vganin/8930b41f55820ec49e4d
|
||||
override fun onInterceptFocusSearch(focused: View, direction: Int): View? {
|
||||
return try {
|
||||
val fromPos = getPosition(focused)
|
||||
val nextPos = getNextViewPos(fromPos, direction)
|
||||
findViewByPosition(nextPos)
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private fun getNextViewPos(fromPos: Int, direction: Int): Int {
|
||||
val offset = calcOffsetToNextView(direction)
|
||||
|
||||
if (hitBorder(fromPos, offset)) {
|
||||
return fromPos
|
||||
}
|
||||
|
||||
return fromPos + offset
|
||||
}
|
||||
|
||||
private fun calcOffsetToNextView(direction: Int): Int {
|
||||
println("calc")
|
||||
|
||||
val spanCount = this.spanCoun
|
||||
val orientation = this.orientation
|
||||
|
||||
if (orientation == VERTICAL) {
|
||||
when (direction) {
|
||||
View.FOCUS_DOWN -> {
|
||||
return spanCount
|
||||
}
|
||||
View.FOCUS_UP -> {
|
||||
return -spanCount
|
||||
}
|
||||
View.FOCUS_RIGHT -> {
|
||||
return 1
|
||||
}
|
||||
View.FOCUS_LEFT -> {
|
||||
return -1
|
||||
}
|
||||
|
||||
}
|
||||
} else if (orientation == HORIZONTAL) {
|
||||
when (direction) {
|
||||
View.FOCUS_DOWN -> {
|
||||
return 1
|
||||
}
|
||||
View.FOCUS_UP -> {
|
||||
return -1
|
||||
}
|
||||
View.FOCUS_RIGHT -> {
|
||||
return spanCount
|
||||
}
|
||||
View.FOCUS_LEFT -> {
|
||||
return -spanCount
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
private fun hitBorder(from: Int, offset: Int): Boolean {
|
||||
val spanCount = spanCount
|
||||
|
||||
return if (abs(offset) == 1) {
|
||||
val spanIndex = from % spanCount
|
||||
val newSpanIndex = spanIndex + offset
|
||||
newSpanIndex < 0 || newSpanIndex >= spanCount
|
||||
} else {
|
||||
val newPos = from + offset
|
||||
newPos in spanCount..-1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AutofitRecyclerView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||
RecyclerView(context, attrs) {
|
||||
|
||||
private val manager = GrdLayoutManager(context, 2) // THIS CONTROLS SPANS
|
||||
|
||||
private var columnWidth = -1
|
||||
|
||||
var spanCount = 0
|
||||
set(value) {
|
||||
field = value
|
||||
if (value > 0) {
|
||||
manager.spanCount = value
|
||||
}
|
||||
}
|
||||
|
||||
val itemWidth: Int
|
||||
get() = measuredWidth / manager.spanCount
|
||||
|
||||
init {
|
||||
if (attrs != null) {
|
||||
val attrsArray = intArrayOf(android.R.attr.columnWidth)
|
||||
val array = context.obtainStyledAttributes(attrs, attrsArray)
|
||||
columnWidth = array.getDimensionPixelSize(0, -1)
|
||||
array.recycle()
|
||||
}
|
||||
|
||||
layoutManager = manager
|
||||
}
|
||||
|
||||
|
||||
/*override fun onMeasure(widthSpec: Int, heightSpec: Int) {
|
||||
super.onMeasure(widthSpec, heightSpec)
|
||||
if (spanCount == 0 && columnWidth > 0) {
|
||||
val count = max(1, measuredWidth / columnWidth)
|
||||
spanCount = count
|
||||
}
|
||||
}*/
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package com.lagradost.cloudstream3.ui.dashboard
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.lagradost.cloudstream3.R
|
||||
|
||||
class DashboardFragment : Fragment() {
|
||||
|
||||
private lateinit var dashboardViewModel: DashboardViewModel
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
dashboardViewModel =
|
||||
ViewModelProvider(this).get(DashboardViewModel::class.java)
|
||||
val root = inflater.inflate(R.layout.fragment_dashboard, container, false)
|
||||
val textView: TextView = root.findViewById(R.id.text_dashboard)
|
||||
dashboardViewModel.text.observe(viewLifecycleOwner, Observer {
|
||||
textView.text = it
|
||||
})
|
||||
return root
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
package com.lagradost.cloudstream3.ui.dashboard
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
|
||||
class DashboardViewModel : ViewModel() {
|
||||
|
||||
private val _text = MutableLiveData<String>().apply {
|
||||
value = "This is dashboard Fragment"
|
||||
}
|
||||
val text: LiveData<String> = _text
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.lagradost.cloudstream3.ui.search
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
|
||||
|
||||
class SearchFragment : Fragment() {
|
||||
|
||||
private lateinit var searchViewModel: SearchViewModel
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
searchViewModel =
|
||||
ViewModelProvider(this).get(SearchViewModel::class.java)
|
||||
|
||||
return inflater.inflate(R.layout.fragment_search, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
// activity?.fixPaddingStatusbar(searchRoot)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package com.lagradost.cloudstream3.ui.search
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.lagradost.cloudstream3.APIHolder.apis
|
||||
import com.lagradost.cloudstream3.MainAPI
|
||||
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
||||
|
||||
class SearchViewModel : ViewModel() {
|
||||
|
||||
private val _text = MutableLiveData<String>().apply {
|
||||
value = "This is dashboard Fragment"
|
||||
}
|
||||
val text: LiveData<String> = _text
|
||||
|
||||
val api : MainAPI = apis[0]
|
||||
|
||||
suspend fun search(query: String) = safeApiCall {
|
||||
api.search(query)
|
||||
}
|
||||
}
|
7
app/src/main/res/drawable/dialog__window_background.xml
Normal file
7
app/src/main/res/drawable/dialog__window_background.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<inset xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<shape android:shape="rectangle">
|
||||
<corners android:radius="10dp" />
|
||||
<solid android:color="@color/darkBackground" />
|
||||
</shape>
|
||||
</inset>
|
5
app/src/main/res/drawable/ic_baseline_tune_24.xml
Normal file
5
app/src/main/res/drawable/ic_baseline_tune_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="M3,17v2h6v-2L3,17zM3,5v2h10L13,5L3,5zM13,21v-2h8v-2h-8v-2h-2v6h2zM7,9v2L3,11v2h4v2h2L9,9L7,9zM21,13v-2L11,11v2h10zM15,9h2L17,7h4L21,5h-4L17,3h-2v6z"/>
|
||||
</vector>
|
14
app/src/main/res/drawable/netflix_download.xml
Normal file
14
app/src/main/res/drawable/netflix_download.xml
Normal file
|
@ -0,0 +1,14 @@
|
|||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:name="vector"
|
||||
android:width="850dp"
|
||||
android:height="850dp"
|
||||
android:viewportWidth="850"
|
||||
android:viewportHeight="850">
|
||||
<path
|
||||
android:name="path_2"
|
||||
android:pathData="M 233.86 666.14 L 616.54 666.14 M 425.2 539.08 L 425.2 159.6 M 410.14 554.17 L 581.98 454.96 M 268.41 454.96 L 440.25 554.17"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeWidth="60"
|
||||
android:strokeMiterLimit="10"/>
|
||||
</vector>
|
8
app/src/main/res/drawable/rounded_dialog.xml
Normal file
8
app/src/main/res/drawable/rounded_dialog.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/grayBackground"/>
|
||||
<corners android:topLeftRadius="16dp"
|
||||
android:topRightRadius="16dp"/>
|
||||
|
||||
</shape>
|
5
app/src/main/res/drawable/search_background.xml
Normal file
5
app/src/main/res/drawable/search_background.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||
<corners android:radius="5dp" />
|
||||
<solid android:color="@color/colorSearch"/>
|
||||
<!--<stroke android:width="0.5dp" android:color="@color/searchColorTransparent" />-->
|
||||
</shape>
|
20
app/src/main/res/drawable/search_icon.xml
Normal file
20
app/src/main/res/drawable/search_icon.xml
Normal file
|
@ -0,0 +1,20 @@
|
|||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:name="vector"
|
||||
android:width="850dp"
|
||||
android:height="850dp"
|
||||
android:viewportWidth="850"
|
||||
android:viewportHeight="850">
|
||||
<path
|
||||
android:name="path"
|
||||
android:pathData="M 425.2 172.91 C 363.2 172.91 303.676 197.566 259.836 241.406 C 215.996 285.246 191.34 344.77 191.34 406.77 C 191.34 468.77 215.996 528.294 259.836 572.134 C 303.676 615.974 363.2 640.63 425.2 640.63 C 487.2 640.63 546.724 615.974 590.564 572.134 C 634.404 528.294 659.06 468.77 659.06 406.77 C 659.06 344.77 634.404 285.246 590.564 241.406 C 546.724 197.566 487.2 172.91 425.2 172.91 Z"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeWidth="60"
|
||||
android:strokeMiterLimit="10"/>
|
||||
<path
|
||||
android:name="path_1"
|
||||
android:pathData="M 599.86 562.28 L 719.87 682.29"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeWidth="60"
|
||||
android:strokeMiterLimit="10"/>
|
||||
</vector>
|
5
app/src/main/res/drawable/tab_selector.xml
Normal file
5
app/src/main/res/drawable/tab_selector.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/colorPrimary"/>
|
||||
<corners android:topLeftRadius="5dp" android:topRightRadius="5dp"/>
|
||||
</shape>
|
59
app/src/main/res/font/google_sans.xml
Normal file
59
app/src/main/res/font/google_sans.xml
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<font-family xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<font
|
||||
app:fontStyle="normal"
|
||||
app:fontWeight="100"
|
||||
app:font="@font/productsans_thin" />
|
||||
<font
|
||||
app:fontStyle="italic"
|
||||
app:fontWeight="100"
|
||||
app:font="@font/productsans_thinitalic" />
|
||||
|
||||
<font
|
||||
app:fontStyle="normal"
|
||||
app:fontWeight="300"
|
||||
app:font="@font/productsans_light" />
|
||||
|
||||
<font
|
||||
app:fontStyle="italic"
|
||||
app:fontWeight="300"
|
||||
app:font="@font/productsans_lightitalic" />
|
||||
|
||||
<font
|
||||
app:fontStyle="normal"
|
||||
app:fontWeight="400"
|
||||
app:font="@font/productsans_regular" />
|
||||
|
||||
<font
|
||||
app:fontStyle="italic"
|
||||
app:fontWeight="400"
|
||||
app:font="@font/productsans_italic" />
|
||||
|
||||
<font
|
||||
app:fontStyle="normal"
|
||||
app:fontWeight="500"
|
||||
app:font="@font/productsans_medium" />
|
||||
<font
|
||||
app:fontStyle="italic"
|
||||
app:fontWeight="500"
|
||||
app:font="@font/productsans_mediumitalic" />
|
||||
|
||||
<font
|
||||
app:fontStyle="normal"
|
||||
app:fontWeight="700"
|
||||
app:font="@font/productsans_bold" />
|
||||
<font
|
||||
app:fontStyle="italic"
|
||||
app:fontWeight="700"
|
||||
app:font="@font/productsans_bolditalic" />
|
||||
|
||||
<font
|
||||
app:fontStyle="normal"
|
||||
app:fontWeight="900"
|
||||
app:font="@font/productsans_black" />
|
||||
<font
|
||||
app:fontStyle="italic"
|
||||
app:fontWeight="900"
|
||||
app:font="@font/productsans_blackitalic" />
|
||||
</font-family>
|
BIN
app/src/main/res/font/productsans_black.ttf
Normal file
BIN
app/src/main/res/font/productsans_black.ttf
Normal file
Binary file not shown.
BIN
app/src/main/res/font/productsans_blackitalic.ttf
Normal file
BIN
app/src/main/res/font/productsans_blackitalic.ttf
Normal file
Binary file not shown.
BIN
app/src/main/res/font/productsans_bold.ttf
Normal file
BIN
app/src/main/res/font/productsans_bold.ttf
Normal file
Binary file not shown.
BIN
app/src/main/res/font/productsans_bolditalic.ttf
Normal file
BIN
app/src/main/res/font/productsans_bolditalic.ttf
Normal file
Binary file not shown.
BIN
app/src/main/res/font/productsans_italic.ttf
Normal file
BIN
app/src/main/res/font/productsans_italic.ttf
Normal file
Binary file not shown.
BIN
app/src/main/res/font/productsans_light.ttf
Normal file
BIN
app/src/main/res/font/productsans_light.ttf
Normal file
Binary file not shown.
BIN
app/src/main/res/font/productsans_lightitalic.ttf
Normal file
BIN
app/src/main/res/font/productsans_lightitalic.ttf
Normal file
Binary file not shown.
BIN
app/src/main/res/font/productsans_medium.ttf
Normal file
BIN
app/src/main/res/font/productsans_medium.ttf
Normal file
Binary file not shown.
BIN
app/src/main/res/font/productsans_mediumitalic.ttf
Normal file
BIN
app/src/main/res/font/productsans_mediumitalic.ttf
Normal file
Binary file not shown.
BIN
app/src/main/res/font/productsans_regular.ttf
Normal file
BIN
app/src/main/res/font/productsans_regular.ttf
Normal file
Binary file not shown.
BIN
app/src/main/res/font/productsans_thin.ttf
Normal file
BIN
app/src/main/res/font/productsans_thin.ttf
Normal file
Binary file not shown.
BIN
app/src/main/res/font/productsans_thinitalic.ttf
Normal file
BIN
app/src/main/res/font/productsans_thinitalic.ttf
Normal file
Binary file not shown.
|
@ -1,23 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
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"
|
||||
tools:context=".ui.dashboard.DashboardFragment">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_dashboard"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:textAlignment="center"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
74
app/src/main/res/layout/fragment_search.xml
Normal file
74
app/src/main/res/layout/fragment_search.xml
Normal file
|
@ -0,0 +1,74 @@
|
|||
<?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:id="@+id/searchRoot"
|
||||
tools:context=".ui.search.SearchFragment"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginTop="@dimen/navbarHeight"
|
||||
|
||||
android:background="@color/grayBackground">
|
||||
|
||||
<FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content"
|
||||
android:layout_margin="10dp" android:background="@drawable/search_background"
|
||||
>
|
||||
<FrameLayout android:layout_width="match_parent" android:layout_marginEnd="30dp"
|
||||
android:layout_height="wrap_content">
|
||||
<androidx.appcompat.widget.SearchView
|
||||
|
||||
android:animateLayoutChanges="true"
|
||||
android:id="@+id/main_search"
|
||||
app:queryBackground="@color/transparent"
|
||||
app:searchIcon="@drawable/search_icon"
|
||||
android:paddingStart="-10dp"
|
||||
android:iconifiedByDefault="false"
|
||||
app:queryHint="@string/search_hint"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_margin="10dp"
|
||||
app:iconifiedByDefault="false"
|
||||
tools:ignore="RtlSymmetry">
|
||||
<androidx.core.widget.ContentLoadingProgressBar
|
||||
android:id="@+id/search_loading_bar"
|
||||
android:layout_width="20dp" android:layout_height="20dp"
|
||||
android:layout_marginStart="-35dp"
|
||||
style="@style/Widget.AppCompat.ProgressBar"
|
||||
android:foregroundTint="@color/white"
|
||||
android:progressTint="@color/white"
|
||||
android:layout_gravity="center">
|
||||
|
||||
</androidx.core.widget.ContentLoadingProgressBar>
|
||||
<!--app:queryHint="@string/search_hint"
|
||||
android:background="@color/grayBackground" @color/itemBackground
|
||||
app:searchHintIcon="@drawable/search_white"
|
||||
-->
|
||||
</androidx.appcompat.widget.SearchView>
|
||||
</FrameLayout>
|
||||
<ImageView
|
||||
android:id="@+id/search_filter"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_baseline_tune_24"
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:layout_margin="10dp"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
app:tint="@color/textColor"
|
||||
android:contentDescription="@string/change_providers_descript">
|
||||
</ImageView>
|
||||
</FrameLayout>
|
||||
<com.lagradost.cloudstream3.ui.AutofitRecyclerView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="5dp"
|
||||
app:spanCount="3"
|
||||
android:paddingEnd="8dp"
|
||||
android:id="@+id/cardSpace"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
</com.lagradost.cloudstream3.ui.AutofitRecyclerView>
|
||||
</LinearLayout>
|
|
@ -7,13 +7,13 @@
|
|||
android:title="@string/title_home"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/navigation_dashboard"
|
||||
android:icon="@drawable/ic_dashboard_black_24dp"
|
||||
android:title="@string/title_dashboard"/>
|
||||
android:id="@+id/navigation_search"
|
||||
android:icon="@drawable/search_icon"
|
||||
android:title="@string/title_search"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/navigation_notifications"
|
||||
android:icon="@drawable/ic_notifications_black_24dp"
|
||||
android:title="@string/title_notifications"/>
|
||||
android:icon="@drawable/netflix_download"
|
||||
android:title="@string/title_downloads"/>
|
||||
|
||||
</menu>
|
|
@ -3,23 +3,23 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/mobile_navigation"
|
||||
app:startDestination="@+id/navigation_home">
|
||||
app:startDestination="@+id/navigation_search">
|
||||
|
||||
<fragment
|
||||
<!-- <fragment
|
||||
android:id="@+id/navigation_home"
|
||||
android:name="com.lagradost.cloudstream3.ui.home.HomeFragment"
|
||||
android:label="@string/title_home"
|
||||
tools:layout="@layout/fragment_home"/>
|
||||
|
||||
-->
|
||||
<fragment
|
||||
android:id="@+id/navigation_dashboard"
|
||||
android:name="com.lagradost.cloudstream3.ui.dashboard.DashboardFragment"
|
||||
android:label="@string/title_dashboard"
|
||||
tools:layout="@layout/fragment_dashboard"/>
|
||||
android:id="@+id/navigation_search"
|
||||
android:name="com.lagradost.cloudstream3.ui.search.SearchFragment"
|
||||
android:label="@string/title_search"
|
||||
tools:layout="@layout/fragment_search"/>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/navigation_notifications"
|
||||
android:name="com.lagradost.cloudstream3.ui.notifications.NotificationsFragment"
|
||||
android:label="@string/title_notifications"
|
||||
android:label="@string/title_downloads"
|
||||
tools:layout="@layout/fragment_notifications"/>
|
||||
</navigation>
|
|
@ -1,7 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#3d50fa</color>
|
||||
<color name="colorSearch">#3444D1</color> <!--#3444D1-->
|
||||
<color name="colorRipple">#1A3D50FA</color>
|
||||
<color name="colorSearch">@color/itemBackground</color> <!--#3444D1-->
|
||||
<color name="colorItemSeen">#1E1E32</color>
|
||||
<color name="colorOngoing">#F53B66</color> <!--FF8181-->
|
||||
<color name="colorPrimaryDark">#3700B3</color>
|
||||
|
@ -20,9 +21,4 @@
|
|||
<color name="transparent">#00000000</color>
|
||||
|
||||
<color name="white">#FFF</color>
|
||||
<color name="readerBackground">#292832</color> <!--3c3c3c-->
|
||||
<color name="readerTextColor">#cccccc</color>
|
||||
<color name="readerHightlightedTextColor">#206f96</color>
|
||||
<color name="readerHightlightedMetaInfo">#0D000000</color>
|
||||
<color name="roundedTextBorder">#DD0277BD</color>
|
||||
</resources>
|
|
@ -2,4 +2,6 @@
|
|||
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
<dimen name="roundedImageRadius">4dp</dimen>
|
||||
<dimen name="navbarHeight">0dp</dimen>
|
||||
</resources>
|
|
@ -1,6 +1,8 @@
|
|||
<resources>
|
||||
<string name="app_name">CloudStream</string>
|
||||
<string name="title_home">Home</string>
|
||||
<string name="title_dashboard">Dashboard</string>
|
||||
<string name="title_notifications">Notifications</string>
|
||||
<string name="title_search">Search</string>
|
||||
<string name="title_downloads">Downloads</string>
|
||||
<string name="search_hint">Search...</string>
|
||||
<string name="change_providers_descript">Change Providers</string>
|
||||
</resources>
|
|
@ -16,21 +16,41 @@
|
|||
<item name="android:scrollbarThumbVertical">@null</item>
|
||||
<item name="android:scrollbarThumbHorizontal">@null</item>
|
||||
|
||||
<item name="android:windowTranslucentStatus">true</item>
|
||||
<item name="android:windowTranslucentStatus">true</item> <!--true-->
|
||||
<item name="android:windowTranslucentNavigation">false</item>
|
||||
<!--
|
||||
<item name="alertDialogTheme">@style/Theme.AlertDialog</item>
|
||||
|
||||
<item name="android:textViewStyle">@style/RobotoTextViewStyle</item>
|
||||
<item name="android:buttonStyle">@style/RobotoButtonStyle</item>
|
||||
<item name="materialButtonStyle">@style/RobotoMaterialButtonStyle</item>
|
||||
<item name="preferenceFragmentCompatStyle">@style/PreferenceTheme</item>-->
|
||||
<item name="android:textViewStyle">@style/AppTextViewStyle</item>
|
||||
<item name="android:buttonStyle">@style/AppButtonStyle</item>
|
||||
<item name="materialButtonStyle">@style/AppMaterialButtonStyle</item>
|
||||
<item name="preferenceFragmentCompatStyle">@style/PreferenceTheme</item>
|
||||
<item name="bottomSheetDialogTheme">@style/AppBottomSheetDialogTheme</item>
|
||||
<item name="searchViewStyle">@style/AppSearchViewStyle</item>
|
||||
<item name="tabStyle">@style/Theme.Widget.Tabs</item>
|
||||
</style>
|
||||
|
||||
<style name="AppSearchViewStyle"
|
||||
parent="Theme.MaterialComponents.NoActionBar">
|
||||
<item name="android:searchIcon">@drawable/search_icon</item>
|
||||
<item name="android:queryHint">@string/search_hint</item>
|
||||
<item name="android:background">@color/transparent</item>
|
||||
<item name="android:fontFamily">@font/google_sans</item>
|
||||
</style>
|
||||
<style name="AppBottomSheetDialogTheme"
|
||||
parent="Theme.Design.Light.BottomSheetDialog">
|
||||
<item name="bottomSheetStyle">@style/AppModalStyle</item>
|
||||
</style>
|
||||
|
||||
<style name="AppModalStyle"
|
||||
parent="Widget.Design.BottomSheet.Modal">
|
||||
<item name="android:background">@drawable/rounded_dialog</item>
|
||||
</style>
|
||||
|
||||
|
||||
<style name="PreferenceTheme" parent="@style/AppTheme">
|
||||
</style>
|
||||
|
||||
<!--
|
||||
|
||||
<style name="Theme.AlertDialog" parent="ThemeOverlay.MaterialComponents.Dialog.Alert">
|
||||
<item name="android:windowMinWidthMajor">@android:dimen/dialog_min_width_major</item>
|
||||
<item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_minor</item>
|
||||
|
@ -38,24 +58,28 @@
|
|||
<item name="textAllCaps">false</item>
|
||||
</style>
|
||||
|
||||
<style name="RoundedBgTextView" parent="@android:style/Widget.TextView">
|
||||
<item name="roundedTextHorizontalPadding">2dp</item>
|
||||
<item name="roundedTextVerticalPadding">2dp</item>
|
||||
<item name="roundedTextDrawable">@drawable/rounded_text_bg</item>
|
||||
<item name="roundedTextDrawableLeft">@drawable/rounded_text_bg_left</item>
|
||||
<item name="roundedTextDrawableMid">@drawable/rounded_text_bg_mid</item>
|
||||
<item name="roundedTextDrawableRight">@drawable/rounded_text_bg_right</item>
|
||||
</style>
|
||||
|
||||
<style name="RobotoTextViewStyle" parent="android:Widget.TextView">
|
||||
<style name="AppTextViewStyle" parent="android:Widget.TextView">
|
||||
<item name="android:fontFamily">@font/google_sans</item>
|
||||
</style>
|
||||
|
||||
<style name="RobotoButtonStyle" parent="android:Widget.Holo.Button">
|
||||
<style name="AppButtonStyle" parent="android:Widget.Holo.Button">
|
||||
<item name="android:fontFamily">@font/google_sans</item>
|
||||
</style>
|
||||
|
||||
<style name="RobotoMaterialButtonStyle" parent="Widget.MaterialComponents.Button">
|
||||
<style name="AppMaterialButtonStyle" parent="Widget.MaterialComponents.Button">
|
||||
<item name="android:fontFamily">@font/google_sans</item>
|
||||
</style>-->
|
||||
</style>
|
||||
|
||||
<style name="Theme.Widget.Tabs" parent="Widget.MaterialComponents.TabLayout.Colored">
|
||||
<item name="tabGravity">center</item>
|
||||
<item name="backgroundTint">@color/transparent</item>
|
||||
<item name="tabIndicator">@drawable/tab_selector</item>
|
||||
<item name="tabIndicatorColor">@color/colorPrimary</item>
|
||||
<item name="tabTextColor">@color/colorPrimary</item>
|
||||
<item name="tabIndicatorFullWidth">false</item>
|
||||
<item name="tabIndicatorHeight">3dp</item>
|
||||
<item name="tabInlineLabel">true</item>
|
||||
<item name="tabMinWidth">75dp</item>
|
||||
<item name="tabMode">scrollable</item>
|
||||
</style>
|
||||
</resources>
|
Loading…
Reference in a new issue