subtitles done

This commit is contained in:
LagradOst 2021-08-07 03:53:45 +02:00
parent 362b9f5a0a
commit 6c93e48447
24 changed files with 276 additions and 58 deletions

View file

@ -13,8 +13,8 @@ android {
applicationId "com.lagradost.cloudstream3"
minSdkVersion 21
targetSdkVersion 30
versionCode 10
versionName "1.1.8"
versionCode 11
versionName "1.2.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@ -52,7 +52,7 @@ dependencies {
implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'

View file

@ -797,9 +797,11 @@ class PlayerFragment : Fragment() {
//endregion
private fun onSubStyleChanged(style : SaveCaptionStyle) {
subStyle = style
subView?.setStyle(fromSaveToStyle(style))
subView?.translationY = -style.elevation.toPx.toFloat()
context?.let { ctx ->
subStyle = style
subView?.setStyle(ctx.fromSaveToStyle(style))
subView?.translationY = -style.elevation.toPx.toFloat()
}
}
@SuppressLint("SetTextI18n")
@ -1129,14 +1131,14 @@ class PlayerFragment : Fragment() {
val speedsNumbers = listOf(0.5f, 0.75f, 1f, 1.25f, 1.5f, 1.75f, 2f)
val speedIndex = speedsNumbers.indexOf(playbackSpeed)
context?.showDialog(speedsText,speedIndex,"Player Speed", false) { index ->
context?.showDialog(speedsText,speedIndex,"Player Speed", false, {
activity?.hideSystemUI()
}) { index ->
playbackSpeed = speedsNumbers[index]
requireContext().setKey(PLAYBACK_SPEED_KEY, playbackSpeed)
val param = PlaybackParameters(playbackSpeed)
exoPlayer.playbackParameters = param
player_speed_text.text = "Speed (${playbackSpeed}x)".replace(".0x", "x")
activity?.hideSystemUI()
}
}
@ -1158,7 +1160,7 @@ class PlayerFragment : Fragment() {
val subtitleList = sourceDialog.findViewById<ListView>(R.id.sort_subtitles)!!
val applyButton = sourceDialog.findViewById<MaterialButton>(R.id.apply_btt)!!
val cancelButton = sourceDialog.findViewById<MaterialButton>(R.id.cancel_btt)!!
val subsSettings = sourceDialog.findViewById<ImageView>(R.id.subs_settings)!!
val subsSettings = sourceDialog.findViewById<View>(R.id.subs_settings)!!
subsSettings.setOnClickListener {
SubtitlesFragment.push(activity)

View file

@ -1,8 +1,10 @@
package com.lagradost.cloudstream3.ui.settings
import android.os.Bundle
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.ui.subtitles.SubtitlesFragment
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
class SettingsFragment : PreferenceFragmentCompat() {
@ -10,4 +12,13 @@ class SettingsFragment : PreferenceFragmentCompat() {
hideKeyboard()
setPreferencesFromResource(R.xml.settings, rootKey)
}
override fun onPreferenceTreeClick(preference: Preference?): Boolean {
if (preference != null) {
if (preference.key == "subtitle_settings_key") {
SubtitlesFragment.push(activity, false)
}
}
return super.onPreferenceTreeClick(preference)
}
}

View file

@ -13,6 +13,8 @@ import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import androidx.annotation.FontRes
import androidx.core.content.res.ResourcesCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import com.google.android.exoplayer2.text.Cue
@ -38,7 +40,8 @@ data class SaveCaptionStyle(
@CaptionStyleCompat.EdgeType
var edgeType: Int,
var edgeColor: Int,
var typeface: String?,
@FontRes
var typeface: Int?,
/**in dp**/
var elevation: Int,
)
@ -47,14 +50,15 @@ class SubtitlesFragment : Fragment() {
companion object {
val applyStyleEvent = Event<SaveCaptionStyle>()
fun fromSaveToStyle(data: SaveCaptionStyle): CaptionStyleCompat {
fun Context.fromSaveToStyle(data: SaveCaptionStyle): CaptionStyleCompat {
val typeface = data.typeface
return CaptionStyleCompat(
data.foregroundColor, data.backgroundColor, data.windowColor, data.edgeType, data.edgeColor,
Typeface.SANS_SERIF
if (typeface == null) Typeface.SANS_SERIF else ResourcesCompat.getFont(this, typeface)
)
}
fun push(activity: Activity?) {
fun push(activity: Activity?, hide: Boolean = true) {
(activity as FragmentActivity?)?.supportFragmentManager?.beginTransaction()
?.setCustomAnimations(
R.anim.enter_anim,
@ -64,7 +68,11 @@ class SubtitlesFragment : Fragment() {
)
?.add(
R.id.homeRoot,
SubtitlesFragment()
SubtitlesFragment().apply {
arguments = Bundle().apply {
putBoolean("hide", hide)
}
}
)
?.commit()
}
@ -106,15 +114,17 @@ class SubtitlesFragment : Fragment() {
}
private fun onColorSelected(stuff: Pair<Int, Int>) {
setColor(stuff.first, stuff.second)
activity?.hideSystemUI()
context?.setColor(stuff.first, stuff.second)
if (hide)
activity?.hideSystemUI()
}
private fun onDialogDismissed(id: Int) {
activity?.hideSystemUI()
if (hide)
activity?.hideSystemUI()
}
private fun setColor(id: Int, color: Int?) {
private fun Context.setColor(id: Int, color: Int?) {
val realColor = color ?: getDefColor(id)
when (id) {
0 -> state.foregroundColor = realColor
@ -128,7 +138,7 @@ class SubtitlesFragment : Fragment() {
updateState()
}
private fun updateState() {
private fun Context.updateState() {
subtitle_text?.setStyle(fromSaveToStyle(state))
}
@ -153,7 +163,8 @@ class SubtitlesFragment : Fragment() {
return inflater.inflate(R.layout.subtitle_settings, container, false)
}
lateinit var state: SaveCaptionStyle
private lateinit var state: SaveCaptionStyle
private var hide: Boolean = true
override fun onDestroy() {
super.onDestroy()
@ -162,13 +173,14 @@ class SubtitlesFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
hide = arguments?.getBoolean("hide") ?: true
MainActivity.onColorSelectedEvent += ::onColorSelected
MainActivity.onDialogDismissedEvent += ::onDialogDismissed
context?.fixPaddingStatusbar(subs_root)
state = requireContext().getCurrentSavedStyle()
updateState()
context?.updateState()
fun View.setup(id: Int) {
this.setOnClickListener {
@ -181,7 +193,7 @@ class SubtitlesFragment : Fragment() {
}
this.setOnLongClickListener {
setColor(id, null)
it.context.setColor(id, null)
Toast.makeText(it.context, R.string.subs_default_reset_toast, Toast.LENGTH_SHORT).show()
return@setOnLongClickListener true
}
@ -192,6 +204,11 @@ class SubtitlesFragment : Fragment() {
subs_background_color.setup(2)
subs_window_color.setup(3)
val dismissCallback = {
if (hide)
activity?.hideSystemUI()
}
subs_subtitle_elevation.setOnClickListener { textView ->
val elevationTypes = listOf(
Pair(0, "None"),
@ -205,17 +222,19 @@ class SubtitlesFragment : Fragment() {
elevationTypes.map { it.second },
elevationTypes.map { it.first }.indexOf(state.elevation),
(textView as TextView).text.toString(),
false
false,
dismissCallback
) { index ->
state.elevation = elevationTypes.map { it.first }[index]
updateState()
activity?.hideSystemUI()
textView.context.updateState()
if (hide)
activity?.hideSystemUI()
}
}
subs_subtitle_elevation.setOnLongClickListener {
state.elevation = 0
updateState()
it.context.updateState()
Toast.makeText(it.context, R.string.subs_default_reset_toast, Toast.LENGTH_SHORT).show()
return@setOnLongClickListener true
}
@ -233,17 +252,53 @@ class SubtitlesFragment : Fragment() {
edgeTypes.map { it.second },
edgeTypes.map { it.first }.indexOf(state.edgeType),
(textView as TextView).text.toString(),
false
false,
dismissCallback
) { index ->
state.edgeType = edgeTypes.map { it.first }[index]
updateState()
activity?.hideSystemUI()
textView.context.updateState()
}
}
subs_edge_type.setOnLongClickListener {
state.edgeType = CaptionStyleCompat.EDGE_TYPE_OUTLINE
updateState()
it.context.updateState()
Toast.makeText(it.context, R.string.subs_default_reset_toast, Toast.LENGTH_SHORT).show()
return@setOnLongClickListener true
}
subs_font.setOnClickListener { textView ->
val fontTypes = listOf(
Pair(null, "Normal"),
Pair(R.font.trebuchet_ms, "Trebuchet MS"),
Pair(R.font.google_sans, "Google Sans"),
Pair(R.font.open_sans, "Open Sans"),
Pair(R.font.futura, "Futura"),
Pair(R.font.consola, "Consola"),
Pair(R.font.gotham, "Gotham"),
Pair(R.font.lucida_grande, "Lucida Grande"),
Pair(R.font.stix_general, "STIX General"),
Pair(R.font.times_new_roman, "Times New Roman"),
Pair(R.font.verdana, "Verdana"),
Pair(R.font.ubuntu_regular, "Ubuntu"),
Pair(R.font.poppins_regular, "Poppins"),
)
textView.context.showBottomDialog(
fontTypes.map { it.second },
fontTypes.map { it.first }.indexOf(state.typeface),
(textView as TextView).text.toString(),
false,
dismissCallback
) { index ->
state.typeface = fontTypes.map { it.first }[index]
textView.context.updateState()
}
}
subs_font.setOnLongClickListener {
state.typeface = null
it.context.updateState()
Toast.makeText(it.context, R.string.subs_default_reset_toast, Toast.LENGTH_SHORT).show()
return@setOnLongClickListener true
}
@ -255,7 +310,7 @@ class SubtitlesFragment : Fragment() {
apply_btt.setOnClickListener {
it.context.saveStyle(state)
applyStyleEvent.invoke(state)
fromSaveToStyle(state)
it.context.fromSaveToStyle(state)
activity?.popCurrentPage()
}

View file

@ -18,7 +18,8 @@ object SingleSelectionHelper {
selectedIndex: Int,
name: String,
showApply: Boolean,
callback: (Int) -> Unit
callback: (Int) -> Unit,
dismissCallback: () -> Unit
) {
val listView = dialog.findViewById<ListView>(R.id.listview1)!!
val textView = dialog.findViewById<TextView>(R.id.text1)!!
@ -46,6 +47,10 @@ object SingleSelectionHelper {
var currentIndex = selectedIndex
dialog.setOnDismissListener {
dismissCallback.invoke()
}
listView.setOnItemClickListener { _, _, which, _ ->
if (showApply) {
currentIndex = which
@ -71,14 +76,15 @@ object SingleSelectionHelper {
selectedIndex: Int,
name: String,
showApply: Boolean,
callback: (Int) -> Unit
dismissCallback: () -> Unit,
callback: (Int) -> Unit,
) {
val builder =
AlertDialog.Builder(this, R.style.AlertDialogCustom).setView(R.layout.bottom_selection_dialog)
val dialog = builder.create()
dialog.show()
showDialog(dialog, items, selectedIndex, name, showApply, callback)
showDialog(dialog, items, selectedIndex, name, showApply, callback, dismissCallback)
}
fun Context.showBottomDialog(
@ -86,13 +92,14 @@ object SingleSelectionHelper {
selectedIndex: Int,
name: String,
showApply: Boolean,
callback: (Int) -> Unit
dismissCallback: () -> Unit,
callback: (Int) -> Unit,
) {
val builder =
BottomSheetDialog(this)
builder.setContentView(R.layout.bottom_selection_dialog)
builder.show()
showDialog(builder, items, selectedIndex, name, showApply, callback)
showDialog(builder, items, selectedIndex, name, showApply, callback, dismissCallback)
}
}

View 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="M20,4L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2zM20,18L4,18L4,6h16v12zM6,10h2v2L6,12zM6,14h8v2L6,16zM16,14h2v2h-2zM10,10h8v2h-8z"/>
</vector>

View file

@ -0,0 +1,31 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="108"
android:viewportHeight="108"
android:name="vector"
android:tint="?attr/white"
>
<!-- ScaleX = 108/24 -->
<group
android:scaleX="0.22"
android:scaleY="0.22"
>
<path android:name="path"
android:pathData="M 475.35 304.28 C 432.112 306.219 389.584 315.994 349.84 333.13 C 311.168 349.86 275.547 372.909 244.44 401.33 L 244.44 97.04 C 275.547 68.619 311.168 45.57 349.84 28.84 C 389.589 11.727 432.116 1.968 475.35 0.04 L 475.35 304.28"
android:fillColor="@color/white"
android:strokeWidth="1"/>
<path android:name="path_1"
android:pathData="M 348.22 364.24 C 310.074 381.02 275.008 404.073 244.48 432.44 L 244.48 411.44 C 275.006 383.062 310.072 359.999 348.22 343.21 M 348.22 364.24 C 387.267 347.125 429.132 337.342 471.72 335.38 L 471.72 314.38 C 429.134 316.333 387.269 326.106 348.22 343.21"
android:fillColor="@color/white"
android:strokeWidth="1"/>
<path android:name="path_2"
android:pathData="M 127.44 364.24 C 165.5 381.028 200.476 404.082 230.91 432.44 L 230.91 411.44 C 200.476 383.082 165.5 360.028 127.44 343.24 M 127.44 364.24 C 88.492 347.123 46.718 337.339 4.22 335.38 L 4.22 314.38 C 46.718 316.339 88.492 326.123 127.44 343.24"
android:fillColor="@color/white"
android:strokeWidth="1"/>
<path android:name="path_3"
android:pathData="M 0 304.28 C 43.238 306.218 85.766 315.994 125.51 333.13 C 164.182 349.86 199.803 372.909 230.91 401.33 L 230.91 97.04 C 199.803 68.619 164.182 45.57 125.51 28.84 C 85.761 11.725 43.234 1.967 0 0.04 L 0 304.28"
android:fillColor="@color/white"
android:strokeWidth="1"/>
</group>
</vector>

View file

@ -0,0 +1,61 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="27dp"
android:height="27dp"
android:tint="?attr/white"
android:viewportWidth="864"
android:viewportHeight="864">
<!--
<path
android:pathData="M551,735S386,423 383,423s-208,74 -208,74L37.33,607.9C104.69,758.82 256.06,864 432,864a431.62,431.62 0,0 0,132.15 -20.59Z"
android:fillColor="#fef1f0"
android:fillType="evenOdd"/>-->
<path
android:pathData="M373,362c-126.94,5.21 -204.5,34.5 -253,106 -27,39.74 -64,97 -86,129 -0.28,0.41 -0.57,0.81 -0.86,1.21q4.63,11.12 9.86,21.9L89,601a595,595 0,0 0,-23.2 60.27,432.49 432.49,0 0,0 37.37,50.9c4.84,-40.86 19,-70.62 36.83,-99.17 27.5,-44.14 95,-119 95,-119s-29,83.5 -8,172c11.4,48 60,117 60,117s-17,-52.5 -17,-120c0,-44 14,-139 14,-139s12.5,84.5 40,173c27.83,89.56 109.61,135.78 187.89,159.62a430.5,430.5 0,0 0,206.24 -101c3.39,-32.9 21.64,-114 -44.13,-238.66C631,435.5 531.5,355.5 373,362Z"
android:fillColor="#FFF"
android:fillType="evenOdd"/>
<path
android:pathData="M779.2,689.09C775.15,595.1 730,464.38 667,396c-50.3,-54.61 -156,-146 -202,-147 -31,-0.67 -55,27 -96,62a565.63,565.63 0,0 0,-70 72s98,-23 224,20S690,596 700,645c4.74,23.24 -1.31,79.76 -9,132.77A434.47,434.47 0,0 0,779.2 689.09Z"
android:fillColor="#FFF"
android:fillType="evenOdd"/>
<path
android:pathData="M363,765s-54,-54 -84,-193 -14,-70 -14,-70l63,-2Z"
android:fillColor="#FFF"
android:fillType="evenOdd"/>
<path
android:pathData="M40.8,615.49a431.76,431.76 0,0 0,52.3 84.42,372.64 372.64,0 0,1 19.57,-71.68L74.67,578Z"
android:fillColor="#FFF"
android:fillType="evenOdd"/>
<path
android:pathData="M428.76,364.58c4.55,-17.61 44.76,-44 78.24,-56.58 30.58,-11.47 72.09,-13.93 124,-10 25.13,1.9 64.54,12 93,15 30.53,3.18 60,-11 60,-11s-21.33,58.67 -27,72 -40.87,86.34 -52,101c-11.48,15.11 -26.12,28.21 -36,35 0,0 -12.67,-21 -25,-37s-79.17,-64.91 -104,-77C517.1,384.84 450,361.07 428.76,364.58Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:startY="510"
android:startX="606.38"
android:endY="296.26"
android:endX="606.38"
android:type="linear">
<item android:offset="0" android:color="#FFF"/><!--FFC72622-->
<item android:offset="1" android:color="#FFF"/><!--FFEB5A53-->
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M134,267s-30.6,41.14 -30,96c0.51,46.49 8.23,76.35 23,95 0,0 51,-59.67 109,-74s97,-20 97,-20 -0.67,-12.67 -18,-22 -64.15,-17.21 -89,-23c-24.33,-5.67 -52.33,-14.67 -67,-27A211,211 0,0 1,134 267Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:startY="458"
android:startX="218.5"
android:endY="267"
android:endX="218.5"
android:type="linear">
<item android:offset="0.05" android:color="#FFF"/> <!--FFC72622-->
<item android:offset="0.99" android:color="#FFF"/><!--FFEB5A53-->
</gradient>
</aapt:attr>
</path>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -19,10 +19,11 @@
android:orientation="vertical"
android:layout_weight="50">
<TextView
android:layout_marginTop="10dp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:layout_marginTop="20dp"
android:layout_marginBottom="10dp"
android:textStyle="bold"
android:text="@string/pick_source"
android:textSize="20sp"
@ -32,8 +33,6 @@
android:layout_height="wrap_content">
</TextView>
<ListView
android:layout_marginTop="-10dp"
android:paddingTop="10dp"
android:id="@+id/sort_providers"
android:background="?attr/bitDarkerGrayBackground"
tools:listitem="@layout/sort_bottom_single_choice"
@ -49,14 +48,18 @@
android:orientation="vertical"
android:layout_weight="50">
<FrameLayout
android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:id="@+id/subs_settings"
android:orientation="horizontal"
android:layout_marginTop="10dp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<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/pick_subtitle"
android:textSize="20sp"
@ -67,22 +70,19 @@
</TextView>
<ImageView
android:id="@+id/subs_settings"
android:layout_marginTop="20dp"
android:visibility="gone"
android:layout_marginTop="0dp"
android:layout_marginEnd="10dp"
android:layout_gravity="end"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:layout_gravity="end|center_vertical"
android:src="@drawable/ic_outline_settings_24"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_height="wrap_content"
android:contentDescription="@string/home_change_provider">
</ImageView>
</FrameLayout>
<ListView
android:layout_marginTop="-10dp"
android:paddingTop="10dp"
android:id="@+id/sort_subtitles"
android:background="?attr/bitDarkerGrayBackground"
tools:listitem="@layout/sort_bottom_single_choice"

View file

@ -25,15 +25,29 @@
android:layout_height="wrap_content">
</TextView>
<com.google.android.exoplayer2.ui.SubtitleView
android:id="@+id/subtitle_text"
android:background="@drawable/subtitles_background_gradient"
android:layout_width="match_parent"
android:layout_gravity="center"
android:foregroundGravity="center"
android:layout_height="75sp">
</com.google.android.exoplayer2.ui.SubtitleView>
<FrameLayout android:layout_width="match_parent" android:layout_height="75sp">
<ImageView
android:scaleType="centerCrop"
android:src="@drawable/subtitles_preview_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/preview_background">
</ImageView>
<com.google.android.exoplayer2.ui.SubtitleView
android:id="@+id/subtitle_text"
android:layout_width="match_parent"
android:layout_gravity="center"
android:foregroundGravity="center"
android:layout_height="match_parent">
</com.google.android.exoplayer2.ui.SubtitleView>
</FrameLayout>
<TextView
android:id="@+id/subs_font"
android:text="@string/subs_font"
style="@style/SettingsItem"
/>
<TextView
android:id="@+id/subs_text_color"
android:text="@string/subs_text_color"

View file

@ -78,4 +78,6 @@
<string name="subs_edge_type">Edge Type</string>
<string name="subs_subtitle_elevation">Subtitle Elevation</string>
<string name="subs_default_reset_toast">Reset to default value</string>
<string name="preview_background">Preview Background</string>
<string name="subs_font">Font</string>
</resources>

View file

@ -7,6 +7,13 @@
android:title="Player"
app:isPreferenceVisible="true"
>
<Preference
android:key="subtitle_settings_key"
android:title="Subtitles"
android:icon="@drawable/ic_outline_subtitles_24"
app:summary="Player subtitles settings">
</Preference>
<SwitchPreference
android:icon="@drawable/ic_baseline_picture_in_picture_alt_24"
app:key="pip_enabled"
@ -49,6 +56,14 @@
android:summary="Tap twice on the right or left side to seek forwards or backwards"
app:defaultValue="false"
/>
</PreferenceCategory>
<PreferenceCategory
android:key="info"
android:title="Info"
app:isPreferenceVisible="true"
>
<SwitchPreference
android:key="acra.disable"
android:icon="@drawable/ic_baseline_bug_report_24"
@ -63,6 +78,21 @@
<intent android:action="android.intent.action.VIEW"
android:data="https://github.com/LagradOst/CloudStream-3"/>
</Preference>
<Preference
android:title="Light novel app by the same devs"
android:icon="@drawable/quick_novel_icon"
app:summary="https://github.com/LagradOst/QuickNovel">
<intent android:action="android.intent.action.VIEW"
android:data="https://github.com/LagradOst/QuickNovel"/>
</Preference>
<Preference
android:title="Anime app by the same devs"
android:icon="@drawable/shiro_icon"
app:summary="https://github.com/Blatzar/shiro-app">
<intent android:action="android.intent.action.VIEW"
android:data="https://github.com/Blatzar/shiro-app"/>
</Preference>
<Preference
android:title="Join Discord"
android:icon="@drawable/ic_baseline_discord_24"