fix: separate update,delete buttons | TOS, privpol
This commit is contained in:
parent
43dee6ee49
commit
116de6324e
12 changed files with 197 additions and 117 deletions
|
@ -51,6 +51,7 @@ import ani.dantotsu.others.calc.CalcActivity
|
||||||
import ani.dantotsu.profile.ProfileActivity
|
import ani.dantotsu.profile.ProfileActivity
|
||||||
import ani.dantotsu.profile.activity.FeedActivity
|
import ani.dantotsu.profile.activity.FeedActivity
|
||||||
import ani.dantotsu.profile.notification.NotificationActivity
|
import ani.dantotsu.profile.notification.NotificationActivity
|
||||||
|
import ani.dantotsu.settings.AddRepositoryBottomSheet
|
||||||
import ani.dantotsu.settings.ExtensionsActivity
|
import ani.dantotsu.settings.ExtensionsActivity
|
||||||
import ani.dantotsu.settings.saving.PrefManager
|
import ani.dantotsu.settings.saving.PrefManager
|
||||||
import ani.dantotsu.settings.saving.PrefManager.asLiveBool
|
import ani.dantotsu.settings.saving.PrefManager.asLiveBool
|
||||||
|
@ -457,9 +458,11 @@ class MainActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
val savedRepos: Set<String> = PrefManager.getVal(prefName)
|
val savedRepos: Set<String> = PrefManager.getVal(prefName)
|
||||||
val newRepos = savedRepos.toMutableSet()
|
val newRepos = savedRepos.toMutableSet()
|
||||||
newRepos.add(url)
|
AddRepositoryBottomSheet.addRepoWarning(this) {
|
||||||
PrefManager.setVal(prefName, newRepos)
|
newRepos.add(url)
|
||||||
toast("${if (uri.scheme == "tachiyomi") "Manga" else "Anime"} Extension Repo added")
|
PrefManager.setVal(prefName, newRepos)
|
||||||
|
toast("${if (uri.scheme == "tachiyomi") "Manga" else "Anime"} Extension Repo added")
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (intent.type == null) return
|
if (intent.type == null) return
|
||||||
|
|
|
@ -22,7 +22,7 @@ import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
suspend fun getUserId(context: Context, block: () -> Unit) {
|
suspend fun getUserId(context: Context, block: () -> Unit) {
|
||||||
if (!Anilist.initialized) {
|
if (!Anilist.initialized && PrefManager.getVal<String>(PrefName.AnilistToken) != "") {
|
||||||
if (Anilist.query.getUserData()) {
|
if (Anilist.query.getUserData()) {
|
||||||
tryWithSuspend {
|
tryWithSuspend {
|
||||||
if (MAL.token != null && !MAL.query.getUserData())
|
if (MAL.token != null && !MAL.query.getUserData())
|
||||||
|
|
|
@ -159,7 +159,7 @@ class NovelExtensionManager(private val context: Context) {
|
||||||
*
|
*
|
||||||
* @param pkgName The package name of the application to uninstall.
|
* @param pkgName The package name of the application to uninstall.
|
||||||
*/
|
*/
|
||||||
fun uninstallExtension(pkgName: String, context: Context) {
|
fun uninstallExtension(pkgName: String) {
|
||||||
installer.uninstallApk(pkgName)
|
installer.uninstallApk(pkgName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package ani.dantotsu.settings
|
package ani.dantotsu.settings
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
@ -12,6 +13,7 @@ import ani.dantotsu.R
|
||||||
import ani.dantotsu.databinding.BottomSheetAddRepositoryBinding
|
import ani.dantotsu.databinding.BottomSheetAddRepositoryBinding
|
||||||
import ani.dantotsu.databinding.ItemRepoBinding
|
import ani.dantotsu.databinding.ItemRepoBinding
|
||||||
import ani.dantotsu.media.MediaType
|
import ani.dantotsu.media.MediaType
|
||||||
|
import ani.dantotsu.util.customAlertDialog
|
||||||
import com.xwray.groupie.GroupieAdapter
|
import com.xwray.groupie.GroupieAdapter
|
||||||
import com.xwray.groupie.viewbinding.BindableItem
|
import com.xwray.groupie.viewbinding.BindableItem
|
||||||
|
|
||||||
|
@ -72,8 +74,12 @@ class AddRepositoryBottomSheet : BottomSheetDialogFragment() {
|
||||||
val input = binding.repositoryInput.text.toString()
|
val input = binding.repositoryInput.text.toString()
|
||||||
val error = isValidUrl(input)
|
val error = isValidUrl(input)
|
||||||
if (error == null) {
|
if (error == null) {
|
||||||
onRepositoryAdded?.invoke(input, mediaType)
|
context?.let { context ->
|
||||||
dismiss()
|
addRepoWarning(context) {
|
||||||
|
onRepositoryAdded?.invoke(input, mediaType)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
binding.repositoryInput.error = error
|
binding.repositoryInput.error = error
|
||||||
}
|
}
|
||||||
|
@ -86,11 +92,16 @@ class AddRepositoryBottomSheet : BottomSheetDialogFragment() {
|
||||||
binding.repositoryInput.setOnEditorActionListener { textView, action, keyEvent ->
|
binding.repositoryInput.setOnEditorActionListener { textView, action, keyEvent ->
|
||||||
if (action == EditorInfo.IME_ACTION_DONE ||
|
if (action == EditorInfo.IME_ACTION_DONE ||
|
||||||
(keyEvent?.action == KeyEvent.ACTION_UP && keyEvent.keyCode == KeyEvent.KEYCODE_ENTER)) {
|
(keyEvent?.action == KeyEvent.ACTION_UP && keyEvent.keyCode == KeyEvent.KEYCODE_ENTER)) {
|
||||||
if (!textView.text.isNullOrBlank()) {
|
val url = textView.text.toString()
|
||||||
val error = isValidUrl(textView.text.toString())
|
if (url.isNotBlank()) {
|
||||||
|
val error = isValidUrl(url)
|
||||||
if (error == null) {
|
if (error == null) {
|
||||||
onRepositoryAdded?.invoke(textView.text.toString(), mediaType)
|
context?.let { context ->
|
||||||
dismiss()
|
addRepoWarning(context) {
|
||||||
|
onRepositoryAdded?.invoke(url, mediaType)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
return@setOnEditorActionListener true
|
return@setOnEditorActionListener true
|
||||||
} else {
|
} else {
|
||||||
binding.repositoryInput.error = error
|
binding.repositoryInput.error = error
|
||||||
|
@ -121,6 +132,16 @@ class AddRepositoryBottomSheet : BottomSheetDialogFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
fun addRepoWarning(context: Context, onRepositoryAdded: () -> Unit) {
|
||||||
|
context.customAlertDialog()
|
||||||
|
.setTitle(R.string.warning)
|
||||||
|
.setMessage(R.string.add_repository_warning)
|
||||||
|
.setPosButton(R.string.ok) {
|
||||||
|
onRepositoryAdded.invoke()
|
||||||
|
}
|
||||||
|
.setNegButton(R.string.cancel) { }
|
||||||
|
.show()
|
||||||
|
}
|
||||||
fun newInstance(
|
fun newInstance(
|
||||||
mediaType: MediaType,
|
mediaType: MediaType,
|
||||||
repositories: List<String>,
|
repositories: List<String>,
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package ani.dantotsu.settings
|
package ani.dantotsu.settings
|
||||||
|
|
||||||
import android.app.AlertDialog
|
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
@ -44,13 +43,10 @@ import kotlinx.coroutines.launch
|
||||||
import rx.android.schedulers.AndroidSchedulers
|
import rx.android.schedulers.AndroidSchedulers
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import java.util.Collections
|
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
|
|
||||||
class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
|
|
||||||
|
|
||||||
private var _binding: FragmentExtensionsBinding? = null
|
private var _binding: FragmentExtensionsBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
private lateinit var extensionsRecyclerView: RecyclerView
|
private lateinit var extensionsRecyclerView: RecyclerView
|
||||||
|
@ -122,15 +118,20 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ pkg, forceDelete ->
|
{ pkg ->
|
||||||
if (isAdded) { // Check if the fragment is currently added to its activity
|
if (isAdded) {
|
||||||
val context = requireContext() // Store context in a variable
|
animeExtensionManager.uninstallExtension(pkg.pkgName)
|
||||||
|
snackString("Extension uninstalled")
|
||||||
|
}
|
||||||
|
}, { pkg ->
|
||||||
|
if (isAdded) {
|
||||||
|
val context = requireContext()
|
||||||
val notificationManager =
|
val notificationManager =
|
||||||
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager // Initialize NotificationManager once
|
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
|
|
||||||
if (pkg.hasUpdate && !forceDelete) {
|
if (pkg.hasUpdate) {
|
||||||
animeExtensionManager.updateExtension(pkg)
|
animeExtensionManager.updateExtension(pkg)
|
||||||
.observeOn(AndroidSchedulers.mainThread()) // Observe on main thread
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(
|
.subscribe(
|
||||||
{ installStep ->
|
{ installStep ->
|
||||||
val builder = NotificationCompat.Builder(
|
val builder = NotificationCompat.Builder(
|
||||||
|
@ -145,7 +146,7 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
},
|
},
|
||||||
{ error ->
|
{ error ->
|
||||||
Injekt.get<CrashlyticsInterface>().logException(error)
|
Injekt.get<CrashlyticsInterface>().logException(error)
|
||||||
Logger.log(error) // Log the error
|
Logger.log(error)
|
||||||
val builder = NotificationCompat.Builder(
|
val builder = NotificationCompat.Builder(
|
||||||
context,
|
context,
|
||||||
Notifications.CHANNEL_DOWNLOADER_ERROR
|
Notifications.CHANNEL_DOWNLOADER_ERROR
|
||||||
|
@ -171,14 +172,13 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
animeExtensionManager.uninstallExtension(pkg.pkgName)
|
snackString("No update available")
|
||||||
snackString("Extension uninstalled")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}, skipIcons
|
}, skipIcons
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
|
@ -198,17 +198,10 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
viewHolder: RecyclerView.ViewHolder,
|
viewHolder: RecyclerView.ViewHolder,
|
||||||
target: RecyclerView.ViewHolder
|
target: RecyclerView.ViewHolder
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val newList = extensionsAdapter.currentList.toMutableList()
|
|
||||||
val fromPosition = viewHolder.absoluteAdapterPosition
|
val fromPosition = viewHolder.absoluteAdapterPosition
|
||||||
val toPosition = target.absoluteAdapterPosition
|
val toPosition = target.absoluteAdapterPosition
|
||||||
if (fromPosition < toPosition) { //probably need to switch to a recyclerview adapter
|
val newList = extensionsAdapter.currentList.toMutableList().apply {
|
||||||
for (i in fromPosition until toPosition) {
|
add(toPosition, removeAt(fromPosition))
|
||||||
Collections.swap(newList, i, i + 1)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (i in fromPosition downTo toPosition + 1) {
|
|
||||||
Collections.swap(newList, i, i - 1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
extensionsAdapter.submitList(newList)
|
extensionsAdapter.submitList(newList)
|
||||||
return true
|
return true
|
||||||
|
@ -270,7 +263,8 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
|
|
||||||
private class AnimeExtensionsAdapter(
|
private class AnimeExtensionsAdapter(
|
||||||
private val onSettingsClicked: (AnimeExtension.Installed) -> Unit,
|
private val onSettingsClicked: (AnimeExtension.Installed) -> Unit,
|
||||||
private val onUninstallClicked: (AnimeExtension.Installed, Boolean) -> Unit,
|
private val onUninstallClicked: (AnimeExtension.Installed) -> Unit,
|
||||||
|
private val onUpdateClicked: (AnimeExtension.Installed) -> Unit,
|
||||||
val skipIcons: Boolean
|
val skipIcons: Boolean
|
||||||
) : ListAdapter<AnimeExtension.Installed, AnimeExtensionsAdapter.ViewHolder>(
|
) : ListAdapter<AnimeExtension.Installed, AnimeExtensionsAdapter.ViewHolder>(
|
||||||
DIFF_CALLBACK_INSTALLED
|
DIFF_CALLBACK_INSTALLED
|
||||||
|
@ -304,20 +298,19 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
holder.extensionIconImageView.setImageDrawable(extension.icon)
|
holder.extensionIconImageView.setImageDrawable(extension.icon)
|
||||||
}
|
}
|
||||||
if (extension.hasUpdate) {
|
if (extension.hasUpdate) {
|
||||||
holder.closeTextView.setImageResource(R.drawable.ic_round_sync_24)
|
holder.updateView.isVisible = true
|
||||||
} else {
|
} else {
|
||||||
holder.closeTextView.setImageResource(R.drawable.ic_round_delete_24)
|
holder.updateView.isVisible = false
|
||||||
}
|
}
|
||||||
holder.closeTextView.setOnClickListener {
|
holder.deleteView.setOnClickListener {
|
||||||
onUninstallClicked(extension, false)
|
onUninstallClicked(extension)
|
||||||
|
}
|
||||||
|
holder.updateView.setOnClickListener {
|
||||||
|
onUpdateClicked(extension)
|
||||||
}
|
}
|
||||||
holder.settingsImageView.setOnClickListener {
|
holder.settingsImageView.setOnClickListener {
|
||||||
onSettingsClicked(extension)
|
onSettingsClicked(extension)
|
||||||
}
|
}
|
||||||
holder.closeTextView.setOnLongClickListener {
|
|
||||||
onUninstallClicked(extension, true)
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun filter(query: String, currentList: List<AnimeExtension.Installed>) {
|
fun filter(query: String, currentList: List<AnimeExtension.Installed>) {
|
||||||
|
@ -337,7 +330,8 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
view.findViewById(R.id.extensionVersionTextView)
|
view.findViewById(R.id.extensionVersionTextView)
|
||||||
val settingsImageView: ImageView = view.findViewById(R.id.settingsImageView)
|
val settingsImageView: ImageView = view.findViewById(R.id.settingsImageView)
|
||||||
val extensionIconImageView: ImageView = view.findViewById(R.id.extensionIconImageView)
|
val extensionIconImageView: ImageView = view.findViewById(R.id.extensionIconImageView)
|
||||||
val closeTextView: ImageView = view.findViewById(R.id.closeTextView)
|
val deleteView: ImageView = view.findViewById(R.id.deleteTextView)
|
||||||
|
val updateView: ImageView = view.findViewById(R.id.updateTextView)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package ani.dantotsu.settings
|
package ani.dantotsu.settings
|
||||||
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.app.AlertDialog
|
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
@ -28,6 +26,7 @@ import ani.dantotsu.R
|
||||||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
||||||
import ani.dantotsu.databinding.FragmentExtensionsBinding
|
import ani.dantotsu.databinding.FragmentExtensionsBinding
|
||||||
import ani.dantotsu.others.LanguageMapper
|
import ani.dantotsu.others.LanguageMapper
|
||||||
|
import ani.dantotsu.others.LanguageMapper.Companion.getLanguageName
|
||||||
import ani.dantotsu.parsers.MangaSources
|
import ani.dantotsu.parsers.MangaSources
|
||||||
import ani.dantotsu.settings.extensionprefs.MangaSourcePreferencesFragment
|
import ani.dantotsu.settings.extensionprefs.MangaSourcePreferencesFragment
|
||||||
import ani.dantotsu.settings.saving.PrefManager
|
import ani.dantotsu.settings.saving.PrefManager
|
||||||
|
@ -45,7 +44,6 @@ import kotlinx.coroutines.launch
|
||||||
import rx.android.schedulers.AndroidSchedulers
|
import rx.android.schedulers.AndroidSchedulers
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import java.util.Collections
|
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
|
@ -120,15 +118,20 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ pkg: MangaExtension.Installed, forceDelete: Boolean ->
|
{ pkg: MangaExtension.Installed ->
|
||||||
if (isAdded) { // Check if the fragment is currently added to its activity
|
if (isAdded) {
|
||||||
val context = requireContext() // Store context in a variable
|
mangaExtensionManager.uninstallExtension(pkg.pkgName)
|
||||||
|
snackString("Extension uninstalled")
|
||||||
|
}
|
||||||
|
}, { pkg ->
|
||||||
|
if (isAdded) {
|
||||||
|
val context = requireContext()
|
||||||
val notificationManager =
|
val notificationManager =
|
||||||
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager // Initialize NotificationManager once
|
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
|
|
||||||
if (pkg.hasUpdate && !forceDelete) {
|
if (pkg.hasUpdate) {
|
||||||
mangaExtensionManager.updateExtension(pkg)
|
mangaExtensionManager.updateExtension(pkg)
|
||||||
.observeOn(AndroidSchedulers.mainThread()) // Observe on main thread
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(
|
.subscribe(
|
||||||
{ installStep ->
|
{ installStep ->
|
||||||
val builder = NotificationCompat.Builder(
|
val builder = NotificationCompat.Builder(
|
||||||
|
@ -143,7 +146,7 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
},
|
},
|
||||||
{ error ->
|
{ error ->
|
||||||
Injekt.get<CrashlyticsInterface>().logException(error)
|
Injekt.get<CrashlyticsInterface>().logException(error)
|
||||||
Logger.log(error) // Log the error
|
Logger.log(error)
|
||||||
val builder = NotificationCompat.Builder(
|
val builder = NotificationCompat.Builder(
|
||||||
context,
|
context,
|
||||||
Notifications.CHANNEL_DOWNLOADER_ERROR
|
Notifications.CHANNEL_DOWNLOADER_ERROR
|
||||||
|
@ -160,7 +163,7 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
context,
|
context,
|
||||||
Notifications.CHANNEL_DOWNLOADER_PROGRESS
|
Notifications.CHANNEL_DOWNLOADER_PROGRESS
|
||||||
)
|
)
|
||||||
.setSmallIcon(R.drawable.ic_check)
|
.setSmallIcon(R.drawable.ic_circle_check)
|
||||||
.setContentTitle("Update complete")
|
.setContentTitle("Update complete")
|
||||||
.setContentText("The extension has been successfully updated.")
|
.setContentText("The extension has been successfully updated.")
|
||||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||||
|
@ -169,9 +172,9 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
mangaExtensionManager.uninstallExtension(pkg.pkgName)
|
snackString("No update available")
|
||||||
snackString("Extension uninstalled")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}, skipIcons
|
}, skipIcons
|
||||||
)
|
)
|
||||||
|
@ -195,17 +198,10 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
viewHolder: RecyclerView.ViewHolder,
|
viewHolder: RecyclerView.ViewHolder,
|
||||||
target: RecyclerView.ViewHolder
|
target: RecyclerView.ViewHolder
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val newList = extensionsAdapter.currentList.toMutableList()
|
|
||||||
val fromPosition = viewHolder.absoluteAdapterPosition
|
val fromPosition = viewHolder.absoluteAdapterPosition
|
||||||
val toPosition = target.absoluteAdapterPosition
|
val toPosition = target.absoluteAdapterPosition
|
||||||
if (fromPosition < toPosition) { //probably need to switch to a recyclerview adapter
|
val newList = extensionsAdapter.currentList.toMutableList().apply {
|
||||||
for (i in fromPosition until toPosition) {
|
add(toPosition, removeAt(fromPosition))
|
||||||
Collections.swap(newList, i, i + 1)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (i in fromPosition downTo toPosition + 1) {
|
|
||||||
Collections.swap(newList, i, i - 1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
extensionsAdapter.submitList(newList)
|
extensionsAdapter.submitList(newList)
|
||||||
return true
|
return true
|
||||||
|
@ -266,7 +262,8 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
|
|
||||||
private class MangaExtensionsAdapter(
|
private class MangaExtensionsAdapter(
|
||||||
private val onSettingsClicked: (MangaExtension.Installed) -> Unit,
|
private val onSettingsClicked: (MangaExtension.Installed) -> Unit,
|
||||||
private val onUninstallClicked: (MangaExtension.Installed, Boolean) -> Unit,
|
private val onUninstallClicked: (MangaExtension.Installed) -> Unit,
|
||||||
|
private val onUpdateClicked: (MangaExtension.Installed) -> Unit,
|
||||||
val skipIcons: Boolean
|
val skipIcons: Boolean
|
||||||
) : ListAdapter<MangaExtension.Installed, MangaExtensionsAdapter.ViewHolder>(
|
) : ListAdapter<MangaExtension.Installed, MangaExtensionsAdapter.ViewHolder>(
|
||||||
DIFF_CALLBACK_INSTALLED
|
DIFF_CALLBACK_INSTALLED
|
||||||
|
@ -276,24 +273,23 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
submitList(newExtensions)
|
submitList(newExtensions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updatePref() {
|
||||||
|
val map = currentList.map { it.name }
|
||||||
|
PrefManager.setVal(PrefName.MangaSourcesOrder, map)
|
||||||
|
MangaSources.pinnedMangaSources = map
|
||||||
|
MangaSources.performReorderMangaSources()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
val view = LayoutInflater.from(parent.context)
|
val view = LayoutInflater.from(parent.context)
|
||||||
.inflate(R.layout.item_extension, parent, false)
|
.inflate(R.layout.item_extension, parent, false)
|
||||||
return ViewHolder(view)
|
return ViewHolder(view)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updatePref() {
|
|
||||||
val map = currentList.map { it.name }.toList()
|
|
||||||
PrefManager.setVal(PrefName.MangaSourcesOrder, map)
|
|
||||||
MangaSources.pinnedMangaSources = map
|
|
||||||
MangaSources.performReorderMangaSources()
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
val extension = getItem(position) // Use getItem() from ListAdapter
|
val extension = getItem(position)
|
||||||
val nsfw = if (extension.isNsfw) "(18+)" else ""
|
val nsfw = if (extension.isNsfw) "(18+)" else ""
|
||||||
val lang = LanguageMapper.getLanguageName(extension.lang)
|
val lang = getLanguageName(extension.lang)
|
||||||
holder.extensionNameTextView.text = extension.name
|
holder.extensionNameTextView.text = extension.name
|
||||||
val versionText = "$lang ${extension.versionName} $nsfw"
|
val versionText = "$lang ${extension.versionName} $nsfw"
|
||||||
holder.extensionVersionTextView.text = versionText
|
holder.extensionVersionTextView.text = versionText
|
||||||
|
@ -301,12 +297,15 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
holder.extensionIconImageView.setImageDrawable(extension.icon)
|
holder.extensionIconImageView.setImageDrawable(extension.icon)
|
||||||
}
|
}
|
||||||
if (extension.hasUpdate) {
|
if (extension.hasUpdate) {
|
||||||
holder.closeTextView.setImageResource(R.drawable.ic_round_sync_24)
|
holder.updateView.isVisible = true
|
||||||
} else {
|
} else {
|
||||||
holder.closeTextView.setImageResource(R.drawable.ic_round_delete_24)
|
holder.updateView.isVisible = false
|
||||||
}
|
}
|
||||||
holder.closeTextView.setOnClickListener {
|
holder.deleteView.setOnClickListener {
|
||||||
onUninstallClicked(extension, false)
|
onUninstallClicked(extension)
|
||||||
|
}
|
||||||
|
holder.updateView.setOnClickListener {
|
||||||
|
onUpdateClicked(extension)
|
||||||
}
|
}
|
||||||
holder.settingsImageView.setOnClickListener {
|
holder.settingsImageView.setOnClickListener {
|
||||||
onSettingsClicked(extension)
|
onSettingsClicked(extension)
|
||||||
|
@ -330,7 +329,8 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
view.findViewById(R.id.extensionVersionTextView)
|
view.findViewById(R.id.extensionVersionTextView)
|
||||||
val settingsImageView: ImageView = view.findViewById(R.id.settingsImageView)
|
val settingsImageView: ImageView = view.findViewById(R.id.settingsImageView)
|
||||||
val extensionIconImageView: ImageView = view.findViewById(R.id.extensionIconImageView)
|
val extensionIconImageView: ImageView = view.findViewById(R.id.extensionIconImageView)
|
||||||
val closeTextView: ImageView = view.findViewById(R.id.closeTextView)
|
val deleteView: ImageView = view.findViewById(R.id.deleteTextView)
|
||||||
|
val updateView: ImageView = view.findViewById(R.id.updateTextView)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
@ -19,7 +20,6 @@ import androidx.recyclerview.widget.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
||||||
import ani.dantotsu.currContext
|
|
||||||
import ani.dantotsu.databinding.FragmentNovelExtensionsBinding
|
import ani.dantotsu.databinding.FragmentNovelExtensionsBinding
|
||||||
import ani.dantotsu.others.LanguageMapper
|
import ani.dantotsu.others.LanguageMapper
|
||||||
import ani.dantotsu.parsers.NovelSources
|
import ani.dantotsu.parsers.NovelSources
|
||||||
|
@ -34,7 +34,6 @@ import kotlinx.coroutines.launch
|
||||||
import rx.android.schedulers.AndroidSchedulers
|
import rx.android.schedulers.AndroidSchedulers
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import java.util.Collections
|
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
|
class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
|
@ -48,15 +47,21 @@ class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
Toast.makeText(requireContext(), "Source is not configurable", Toast.LENGTH_SHORT)
|
Toast.makeText(requireContext(), "Source is not configurable", Toast.LENGTH_SHORT)
|
||||||
.show()
|
.show()
|
||||||
},
|
},
|
||||||
{ pkg, forceDelete ->
|
{ pkg ->
|
||||||
if (isAdded) { // Check if the fragment is currently added to its activity
|
if (isAdded) {
|
||||||
val context = requireContext() // Store context in a variable
|
novelExtensionManager.uninstallExtension(pkg.pkgName)
|
||||||
val notificationManager =
|
snackString("Extension uninstalled")
|
||||||
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager // Initialize NotificationManager once
|
|
||||||
|
|
||||||
if (pkg.hasUpdate && !forceDelete) {
|
}
|
||||||
|
},
|
||||||
|
{ pkg ->
|
||||||
|
if (isAdded) {
|
||||||
|
val context = requireContext()
|
||||||
|
val notificationManager =
|
||||||
|
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
|
if (pkg.hasUpdate) {
|
||||||
novelExtensionManager.updateExtension(pkg)
|
novelExtensionManager.updateExtension(pkg)
|
||||||
.observeOn(AndroidSchedulers.mainThread()) // Observe on main thread
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(
|
.subscribe(
|
||||||
{ installStep ->
|
{ installStep ->
|
||||||
val builder = NotificationCompat.Builder(
|
val builder = NotificationCompat.Builder(
|
||||||
|
@ -71,7 +76,7 @@ class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
},
|
},
|
||||||
{ error ->
|
{ error ->
|
||||||
Injekt.get<CrashlyticsInterface>().logException(error)
|
Injekt.get<CrashlyticsInterface>().logException(error)
|
||||||
Logger.log(error) // Log the error
|
Logger.log(error)
|
||||||
val builder = NotificationCompat.Builder(
|
val builder = NotificationCompat.Builder(
|
||||||
context,
|
context,
|
||||||
Notifications.CHANNEL_DOWNLOADER_ERROR
|
Notifications.CHANNEL_DOWNLOADER_ERROR
|
||||||
|
@ -97,8 +102,7 @@ class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
novelExtensionManager.uninstallExtension(pkg.pkgName, currContext() ?: context)
|
snackString("No update available")
|
||||||
snackString("Extension uninstalled")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, skipIcons
|
}, skipIcons
|
||||||
|
@ -123,17 +127,10 @@ class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
viewHolder: RecyclerView.ViewHolder,
|
viewHolder: RecyclerView.ViewHolder,
|
||||||
target: RecyclerView.ViewHolder
|
target: RecyclerView.ViewHolder
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val newList = extensionsAdapter.currentList.toMutableList()
|
|
||||||
val fromPosition = viewHolder.absoluteAdapterPosition
|
val fromPosition = viewHolder.absoluteAdapterPosition
|
||||||
val toPosition = target.absoluteAdapterPosition
|
val toPosition = target.absoluteAdapterPosition
|
||||||
if (fromPosition < toPosition) { //probably need to switch to a recyclerview adapter
|
val newList = extensionsAdapter.currentList.toMutableList().apply {
|
||||||
for (i in fromPosition until toPosition) {
|
add(toPosition, removeAt(fromPosition))
|
||||||
Collections.swap(newList, i, i + 1)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (i in fromPosition downTo toPosition + 1) {
|
|
||||||
Collections.swap(newList, i, i - 1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
extensionsAdapter.submitList(newList)
|
extensionsAdapter.submitList(newList)
|
||||||
return true
|
return true
|
||||||
|
@ -195,7 +192,8 @@ class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
|
|
||||||
private class NovelExtensionsAdapter(
|
private class NovelExtensionsAdapter(
|
||||||
private val onSettingsClicked: (NovelExtension.Installed) -> Unit,
|
private val onSettingsClicked: (NovelExtension.Installed) -> Unit,
|
||||||
private val onUninstallClicked: (NovelExtension.Installed, Boolean) -> Unit,
|
private val onUninstallClicked: (NovelExtension.Installed) -> Unit,
|
||||||
|
private val onUpdateClicked: (NovelExtension.Installed) -> Unit,
|
||||||
val skipIcons: Boolean
|
val skipIcons: Boolean
|
||||||
) : ListAdapter<NovelExtension.Installed, NovelExtensionsAdapter.ViewHolder>(
|
) : ListAdapter<NovelExtension.Installed, NovelExtensionsAdapter.ViewHolder>(
|
||||||
DIFF_CALLBACK_INSTALLED
|
DIFF_CALLBACK_INSTALLED
|
||||||
|
@ -230,20 +228,19 @@ class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
holder.extensionIconImageView.setImageDrawable(extension.icon)
|
holder.extensionIconImageView.setImageDrawable(extension.icon)
|
||||||
}
|
}
|
||||||
if (extension.hasUpdate) {
|
if (extension.hasUpdate) {
|
||||||
holder.closeTextView.setImageResource(R.drawable.ic_round_sync_24)
|
holder.updateView.isVisible = true
|
||||||
} else {
|
} else {
|
||||||
holder.closeTextView.setImageResource(R.drawable.ic_round_delete_24)
|
holder.updateView.isVisible = false
|
||||||
}
|
}
|
||||||
holder.closeTextView.setOnClickListener {
|
holder.deleteView.setOnClickListener {
|
||||||
onUninstallClicked(extension, false)
|
onUninstallClicked(extension)
|
||||||
|
}
|
||||||
|
holder.updateView.setOnClickListener {
|
||||||
|
onUpdateClicked(extension)
|
||||||
}
|
}
|
||||||
holder.settingsImageView.setOnClickListener {
|
holder.settingsImageView.setOnClickListener {
|
||||||
onSettingsClicked(extension)
|
onSettingsClicked(extension)
|
||||||
}
|
}
|
||||||
holder.closeTextView.setOnLongClickListener {
|
|
||||||
onUninstallClicked(extension, true)
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun filter(query: String, currentList: List<NovelExtension.Installed>) {
|
fun filter(query: String, currentList: List<NovelExtension.Installed>) {
|
||||||
|
@ -263,7 +260,8 @@ class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
view.findViewById(R.id.extensionVersionTextView)
|
view.findViewById(R.id.extensionVersionTextView)
|
||||||
val settingsImageView: ImageView = view.findViewById(R.id.settingsImageView)
|
val settingsImageView: ImageView = view.findViewById(R.id.settingsImageView)
|
||||||
val extensionIconImageView: ImageView = view.findViewById(R.id.extensionIconImageView)
|
val extensionIconImageView: ImageView = view.findViewById(R.id.extensionIconImageView)
|
||||||
val closeTextView: ImageView = view.findViewById(R.id.closeTextView)
|
val deleteView: ImageView = view.findViewById(R.id.deleteTextView)
|
||||||
|
val updateView: ImageView = view.findViewById(R.id.updateTextView)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -10,6 +10,8 @@ import androidx.core.view.updateLayoutParams
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import ani.dantotsu.BuildConfig
|
import ani.dantotsu.BuildConfig
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
|
import ani.dantotsu.buildMarkwon
|
||||||
|
import ani.dantotsu.client
|
||||||
import ani.dantotsu.databinding.ActivitySettingsAboutBinding
|
import ani.dantotsu.databinding.ActivitySettingsAboutBinding
|
||||||
import ani.dantotsu.initActivity
|
import ani.dantotsu.initActivity
|
||||||
import ani.dantotsu.navBarHeight
|
import ani.dantotsu.navBarHeight
|
||||||
|
@ -20,6 +22,9 @@ import ani.dantotsu.settings.saving.PrefName
|
||||||
import ani.dantotsu.statusBarHeight
|
import ani.dantotsu.statusBarHeight
|
||||||
import ani.dantotsu.themes.ThemeManager
|
import ani.dantotsu.themes.ThemeManager
|
||||||
import ani.dantotsu.util.Logger
|
import ani.dantotsu.util.Logger
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class SettingsAboutActivity : AppCompatActivity() {
|
class SettingsAboutActivity : AppCompatActivity() {
|
||||||
private lateinit var binding: ActivitySettingsAboutBinding
|
private lateinit var binding: ActivitySettingsAboutBinding
|
||||||
|
@ -130,6 +135,48 @@ class SettingsAboutActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
Settings(
|
||||||
|
type = 1,
|
||||||
|
name = getString(R.string.privacy_policy),
|
||||||
|
desc = getString(R.string.privacy_policy_desc),
|
||||||
|
icon = R.drawable.ic_incognito_24,
|
||||||
|
onClick = {
|
||||||
|
val text = TextView(context)
|
||||||
|
val pPLink = "https://raw.githubusercontent.com/rebelonion/Dantotsu/main/privacy_policy.md"
|
||||||
|
val backup = "https://gcore.jsdelivr.net/gh/rebelonion/dantotsu/privacy_policy.md"
|
||||||
|
text.text = getString(R.string.loading)
|
||||||
|
val markWon = try {
|
||||||
|
buildMarkwon(this@SettingsAboutActivity, false)
|
||||||
|
} catch (e: IllegalArgumentException) {
|
||||||
|
return@Settings
|
||||||
|
}
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
val res = try {
|
||||||
|
val out = client.get(pPLink)
|
||||||
|
if (out.code != 200) {
|
||||||
|
client.get(backup)
|
||||||
|
} else {
|
||||||
|
out
|
||||||
|
}.text
|
||||||
|
} catch (e: Exception) {
|
||||||
|
getString(R.string.failed_to_load)
|
||||||
|
}
|
||||||
|
runOnUiThread {
|
||||||
|
markWon.setMarkdown(text, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomBottomDialog.newInstance().apply {
|
||||||
|
setTitleText(context.getString(R.string.privacy_policy))
|
||||||
|
addView(text)
|
||||||
|
setNegativeButton(context.getString(R.string.close)) {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
show(supportFragmentManager, "dialog")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
binding.settingsRecyclerView.layoutManager =
|
binding.settingsRecyclerView.layoutManager =
|
||||||
|
|
|
@ -48,7 +48,8 @@ class SubscriptionSource(
|
||||||
|
|
||||||
binding.extensionPinImageView.visibility = View.GONE
|
binding.extensionPinImageView.visibility = View.GONE
|
||||||
binding.extensionVersionTextView.visibility = View.GONE
|
binding.extensionVersionTextView.visibility = View.GONE
|
||||||
binding.closeTextView.visibility = View.GONE
|
binding.deleteTextView.visibility = View.GONE
|
||||||
|
binding.updateTextView.visibility = View.GONE
|
||||||
binding.settingsImageView.visibility = View.GONE
|
binding.settingsImageView.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ internal class ExtensionGithubApi {
|
||||||
sources = it.sources?.toAnimeExtensionSources().orEmpty(),
|
sources = it.sources?.toAnimeExtensionSources().orEmpty(),
|
||||||
apkName = it.apk,
|
apkName = it.apk,
|
||||||
repository = repository,
|
repository = repository,
|
||||||
iconUrl = "${repository}/icon/${it.pkg}.png",
|
iconUrl = "${repository.removeSuffix("/index.min.json")}/icon/${it.pkg}.png",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ internal class ExtensionGithubApi {
|
||||||
sources = it.sources?.toMangaExtensionSources().orEmpty(),
|
sources = it.sources?.toMangaExtensionSources().orEmpty(),
|
||||||
apkName = it.apk,
|
apkName = it.apk,
|
||||||
repository = repository,
|
repository = repository,
|
||||||
iconUrl = "${repository}/icon/${it.pkg}.png",
|
iconUrl = "${repository.removeSuffix("/index.min.json")}/icon/${it.pkg}.png",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,11 +73,23 @@
|
||||||
tools:ignore="ContentDescription"/>
|
tools:ignore="ContentDescription"/>
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/closeTextView"
|
android:id="@+id/updateTextView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_weight="0"
|
android:layout_weight="0"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
android:src="@drawable/ic_round_sync_24"
|
||||||
|
app:tint="?attr/colorOnBackground"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/deleteTextView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_weight="0"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
android:src="@drawable/ic_round_delete_24"
|
android:src="@drawable/ic_round_delete_24"
|
||||||
app:tint="?attr/colorOnBackground"
|
app:tint="?attr/colorOnBackground"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
|
@ -1091,5 +1091,9 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc
|
||||||
<string name="add_repository">Add Repository</string>
|
<string name="add_repository">Add Repository</string>
|
||||||
<string name="add_repository_desc">A repository link should look like this: https://raw.githubusercontent.com/username/repo/branch/index.min.json</string>
|
<string name="add_repository_desc">A repository link should look like this: https://raw.githubusercontent.com/username/repo/branch/index.min.json</string>
|
||||||
<string name="current_repositories">Current Repositories</string>
|
<string name="current_repositories">Current Repositories</string>
|
||||||
|
<string name="add_repository_warning">Warning: Extensions from the repository can run arbitrary code on your device. Only use repositories you trust. \n\nBy adding a repository, you agree to: \n\n1. Not use the app for viewing or distributing copyrighted content. \n2. Not use the app for any illegal activities. \n3. Not use the app for any activities that violate the terms of service of the content providers. \n\nThe app or it\'s maintainer are not affiliated in any way with extension providers. The developers are not responsible for any damages caused by the app. \n\nBy adding a repository, you agree to these terms.</string>
|
||||||
|
<string name="privacy_policy">Privacy Policy</string>
|
||||||
|
<string name="privacy_policy_desc">Read our privacy policy</string>
|
||||||
|
<string name="failed_to_load">Failed to load</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue