Skip to content

Commit

Permalink
add extensions add button clear data recommended
Browse files Browse the repository at this point in the history
  • Loading branch information
brahmkshatriya committed Oct 21, 2024
1 parent 0ba5ad5 commit 04a3287
Show file tree
Hide file tree
Showing 22 changed files with 584 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ import dev.brahmkshatriya.echo.ui.extension.ExtensionInstallerBottomSheet
import dev.brahmkshatriya.echo.viewmodels.ExtensionViewModel
import kotlinx.coroutines.launch
import java.io.File
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine

class ExtensionOpenerActivity : Activity() {
override fun onStart() {
super.onStart()
val uri = intent.data

println("uri : $uri")
println("mime : ${contentResolver.getType(uri!!)}")
val file = when (uri.scheme) {
val file = when (uri?.scheme) {
"content" -> getTempFile(uri)
"file" -> getTempFile(uri.toFile())
else -> null
Expand All @@ -42,7 +42,7 @@ class ExtensionOpenerActivity : Activity() {
startActivity(startIntent)
}

private fun getTempFile(bytes:ByteArray) : File {
private fun getTempFile(bytes: ByteArray): File {
val tempFile = File.createTempFile("temp", ".apk", getTempApkDir())
tempFile.writeBytes(bytes)
return tempFile
Expand All @@ -54,7 +54,7 @@ class ExtensionOpenerActivity : Activity() {
return getTempFile(bytes)
}

private fun getTempFile(file:File) : File {
private fun getTempFile(file: File): File {
val bytes = file.readBytes()
return getTempFile(bytes)
}
Expand All @@ -69,8 +69,13 @@ class ExtensionOpenerActivity : Activity() {
}

fun FragmentActivity.openExtensionInstaller(uri: Uri) {
lifecycleScope.launch {
installExtension(uri.toString())
}
}

ExtensionInstallerBottomSheet.newInstance(uri.toString())
suspend fun FragmentActivity.installExtension(fileString: String) = suspendCoroutine {
ExtensionInstallerBottomSheet.newInstance(fileString)
.show(supportFragmentManager, null)

supportFragmentManager.setFragmentResultListener(EXTENSION_INSTALLER, this) { _, b ->
Expand All @@ -86,27 +91,34 @@ class ExtensionOpenerActivity : Activity() {
if (result && installAsApk) {
context.createLinksDialog(file, links)
}
it.resume(result)
}
}
}

}

private fun Context.createLinksDialog(
private suspend fun Context.createLinksDialog(
file: File, links: List<String>
) = MaterialAlertDialogBuilder(this)
.setTitle(getString(R.string.allow_opening_links))
.setMessage(
links.joinToString("\n") + "\n" +
getString(R.string.open_links_instruction)
)
.setPositiveButton(getString(R.string.ok)) { dialog, _ ->
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
val packageName = getPackageName(file.path)
intent.setData(Uri.parse("package:$packageName"))
startActivity(intent)
dialog.dismiss()
}
.setNegativeButton(getString(R.string.cancel)) { dialog, _ -> dialog.dismiss() }
.show()
) = suspendCoroutine { cont ->
MaterialAlertDialogBuilder(this)
.setTitle(getString(R.string.allow_opening_links))
.setMessage(
links.joinToString("\n") + "\n" +
getString(R.string.open_links_instruction)
)
.setPositiveButton(getString(R.string.ok)) { dialog, _ ->
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
val packageName = getPackageName(file.path)
intent.setData(Uri.parse("package:$packageName"))
startActivity(intent)
dialog.dismiss()
}
.setNegativeButton(getString(R.string.cancel)) { dialog, _ -> dialog.dismiss() }
.setOnDismissListener {
cont.resume(Unit)
}
.show()
}
}
}
1 change: 0 additions & 1 deletion app/src/main/java/dev/brahmkshatriya/echo/PlayerService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ class PlayerService : MediaLibraryService() {
}
}

//TODO: extension updater
//TODO: Spotify
//TODO: EQ, Pitch, Tempo, Reverb & Sleep Timer(5m, 10m, 15m, 30m, 45m, 1hr, End of track)
// val equalizer = Equalizer(1, exoPlayer.audioSessionId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ sealed class ExtensionRepo<T : ExtensionClient>(
ApkManifestParser(ImportType.App),
loader
)
LazyRepoComposer(appPluginRepo, apkFilePluginRepo, *repo)
LazyRepoComposer(*repo, appPluginRepo, apkFilePluginRepo)
}

private fun injected() = composed.getAllPlugins().mapState { list ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ fun Context.getPackageName(path: String) = packageManager.getPackageArchiveInfo(
path, ApkPluginSource.PACKAGE_FLAGS
)!!.packageName

private suspend fun FragmentActivity.waitForResult(intent: Intent) = suspendCoroutine { cont ->
suspend fun FragmentActivity.waitForResult(intent: Intent) = suspendCoroutine { cont ->
val contract = ActivityResultContracts.StartActivityForResult()
val activityResultLauncher = registerActivityResultLauncher(contract) {
cont.resume(it)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package dev.brahmkshatriya.echo.extensions

class InvalidExtensionListException(override val cause: Throwable) : Exception(cause)
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,25 @@ data class Asset(
val name: String,
@SerialName("browser_download_url")
val browserDownloadUrl: String
)

suspend fun getExtensionList(
link: String,
client: OkHttpClient
) = runIOCatching {
val request = Request.Builder()
.addHeader("Cookie", "preview=1")
.url(link).build()
client.newCall(request).await().body.string().toData<List<ExtensionAssetResponse>>()
}.getOrElse {
throw InvalidExtensionListException(it)
}

@Serializable
data class ExtensionAssetResponse(
val id: String,
val name: String,
val subtitle: String? = null,
val iconUrl: String? = null,
val updateUrl: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class ApkManifestParser(
path = data.path,
className = get("class"),
importType = importType,
id = get("id") + importType.name,
id = get("id"),
name = get("name"),
version = get("version"),
description = get("description"),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
package dev.brahmkshatriya.echo.extensions.plugger

import dev.brahmkshatriya.echo.common.models.Metadata
import tel.jeelpa.plugger.PluginRepo
import tel.jeelpa.plugger.utils.combineStates
import tel.jeelpa.plugger.utils.mapState

interface LazyPluginRepo<T, R> : PluginRepo<T, Lazy<Result<R>>>

class LazyRepoComposer<TMetadata, TPlugin>(
private vararg val repos: LazyPluginRepo<TMetadata, TPlugin>
) : LazyPluginRepo<TMetadata, TPlugin> {
class LazyRepoComposer<TPlugin>(
private vararg val repos: LazyPluginRepo<Metadata, TPlugin>
) : LazyPluginRepo<Metadata, TPlugin> {
override fun getAllPlugins() = repos.map { it.getAllPlugins() }
.reduce { a, b -> combineStates(a, b) { x, y -> x + y } }
.mapState { list ->
list.groupBy { it.getOrNull()?.first?.id }.map { entry ->
entry.value.minBy {
it.getOrNull()?.first?.importType?.ordinal ?: Int.MAX_VALUE
}
}
}
}

fun <T> catchLazy(function: () -> T) = lazy { runCatching { function() } }
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import dev.brahmkshatriya.echo.EchoApplication.Companion.appVersion
import dev.brahmkshatriya.echo.R
import dev.brahmkshatriya.echo.databinding.FragmentExceptionBinding
import dev.brahmkshatriya.echo.extensions.ExtensionLoadingException
import dev.brahmkshatriya.echo.extensions.InvalidExtensionListException
import dev.brahmkshatriya.echo.extensions.RequiredExtensionsException
import dev.brahmkshatriya.echo.playback.MediaItemUtils.audioIndex
import dev.brahmkshatriya.echo.playback.MediaItemUtils.clientId
Expand Down Expand Up @@ -98,6 +99,7 @@ class ExceptionFragment : Fragment() {
throwable.name,
throwable.requiredExtensions.joinToString(", ")
)
is InvalidExtensionListException -> getString(R.string.invalid_extension_list)
is AppException -> throwable.run {
when (this) {
is AppException.Unauthorized ->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package dev.brahmkshatriya.echo.ui.extension

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import dev.brahmkshatriya.echo.R
import dev.brahmkshatriya.echo.common.models.ImageHolder.Companion.toImageHolder
import dev.brahmkshatriya.echo.databinding.ItemExtensionAddBinding
import dev.brahmkshatriya.echo.databinding.ItemExtensionAddFooterBinding
import dev.brahmkshatriya.echo.databinding.ItemExtensionAddHeaderBinding
import dev.brahmkshatriya.echo.extensions.ExtensionAssetResponse
import dev.brahmkshatriya.echo.utils.loadAsCircle

class ExtensionsAddListAdapter(
val map: List<Item>,
val listener: Listener
) : RecyclerView.Adapter<ExtensionsAddListAdapter.ViewHolder>() {

data class Item(
val item: ExtensionAssetResponse,
val isChecked: Boolean,
val isInstalled: Boolean
)

fun interface Listener {
fun onChecked(item: ExtensionAssetResponse, isChecked: Boolean)
}

inner class ViewHolder(val binding: ItemExtensionAddBinding) :
RecyclerView.ViewHolder(binding.root)

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val binding = ItemExtensionAddBinding.inflate(inflater, parent, false)
return ViewHolder(binding)
}

override fun getItemCount() = map.size

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val (item, isChecked, isInstalled) = map[position]
val binding = holder.binding
binding.extensionName.text = if (!isInstalled) item.name
else binding.root.context.getString(R.string.extension_installed, item.name)
binding.extensionSubtitle.text = item.subtitle ?: item.id
binding.itemExtension.apply {
item.iconUrl?.toImageHolder().loadAsCircle(this, R.drawable.ic_extension) {
setImageDrawable(it)
}
}
binding.extensionSwitch.isChecked = isChecked
binding.extensionSwitch.setOnCheckedChangeListener { _, checked ->
listener.onChecked(item, checked)
}
binding.root.setOnClickListener {
binding.extensionSwitch.isChecked = !binding.extensionSwitch.isChecked
}
binding.extensionSwitch.isClickable = false
}

class Header(
val listener: Listener
) : RecyclerView.Adapter<Header.ViewHolder>() {

fun interface Listener {
fun onClose()
}

class ViewHolder(val binding: ItemExtensionAddHeaderBinding) :
RecyclerView.ViewHolder(binding.root)

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val binding = ItemExtensionAddHeaderBinding.inflate(inflater, parent, false)
return ViewHolder(binding)
}

override fun getItemCount() = 1

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.binding.root.setOnClickListener { listener.onClose() }
}

}

class Footer(
val listener: Listener
) : RecyclerView.Adapter<Footer.ViewHolder>() {

fun interface Listener {
fun onAdd()
}

class ViewHolder(val binding: ItemExtensionAddFooterBinding) :
RecyclerView.ViewHolder(binding.root)

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val binding = ItemExtensionAddFooterBinding.inflate(inflater, parent, false)
return ViewHolder(binding)
}

override fun getItemCount() = 1

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.binding.root.setOnClickListener { listener.onAdd() }
}

}
}
Loading

0 comments on commit 04a3287

Please sign in to comment.