Skip to content

Commit

Permalink
feat: Allow skipping thumbnail fetching
Browse files Browse the repository at this point in the history
  • Loading branch information
1fexd committed May 17, 2024
1 parent a97c768 commit 493e367
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import fe.linksheet.extension.android.newIntent
import fe.linksheet.extension.android.queryResolveInfosByIntent
import fe.linksheet.extension.android.toDisplayActivityInfos
import fe.linksheet.extension.koin.injectLogger
import fe.linksheet.extension.kotlinx.awaitOrNull
import fe.linksheet.module.database.entity.LibRedirectDefault
import fe.linksheet.module.database.entity.PreferredApp
import fe.linksheet.module.downloader.DownloadCheckResult
Expand All @@ -34,11 +35,9 @@ import fe.linksheet.module.resolver.urlresolver.amp2html.Amp2HtmlUrlResolver
import fe.linksheet.module.resolver.urlresolver.base.ResolvePredicate
import fe.linksheet.module.resolver.urlresolver.redirect.RedirectUrlResolver
import fe.linksheet.util.IntentParser
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.withContext
import me.saket.unfurl.UnfurlResult
import me.saket.unfurl.Unfurler
import mozilla.components.support.utils.SafeIntent
Expand Down Expand Up @@ -112,25 +111,40 @@ class ImprovedIntentResolver(
private val _events = MutableStateFlow<ResolveEvent>(value = ResolveEvent.Initialized)
val events = _events.asStateFlow()

private val _interactions = MutableStateFlow<ResolverInteraction>(value = ResolverInteraction.None)
val interactions = _interactions.asStateFlow()

private fun emitEvent(message: String) {
_events.tryEmit(ResolveEvent.Message(message))
logger.info(message)
}

private fun emitInteraction(interaction: ResolverInteraction) {
_interactions.tryEmit(interaction)
logger.info("Emitted interaction $interaction")
}

private fun fail(error: String, result: IntentResolveResult): IntentResolveResult {
logger.error(error)
return result
}

suspend fun resolve(intent: SafeIntent, referrer: Uri?): IntentResolveResult {
private suspend fun initState(event: ResolveEvent.Message, interaction: ResolverInteraction) {
_events.emit(event)
_interactions.emit(interaction)
}

suspend fun resolve(intent: SafeIntent, referrer: Uri?): IntentResolveResult = coroutineScope {
initState(ResolveEvent.Initialized, ResolverInteraction.None)

val searchIntentResult = tryHandleSearchIntent(intent)
if (searchIntentResult != null) return searchIntentResult
if (searchIntentResult != null) return@coroutineScope searchIntentResult

var uri = getUriFromIntent(intent)

if (uri == null) {
Log.d("ImprovedIntentResolver", "Failed to parse intent ${intent.action}")
return IntentResolveResult.IntentParseFailed
return@coroutineScope IntentResolveResult.IntentParseFailed
}

emitEvent("Querying browser list")
Expand All @@ -144,7 +158,7 @@ class ImprovedIntentResolver(
)

if (uri == null) {
return fail("Failed to run uri modifiers", IntentResolveResult.UrlModificationFailed)
return@coroutineScope fail("Failed to run uri modifiers", IntentResolveResult.UrlModificationFailed)
}

val (resolveStatus, resolvedUri) = runResolvers(
Expand All @@ -166,7 +180,7 @@ class ImprovedIntentResolver(
)

if (resolvedUri == null) {
return fail("Failed to run resolvers", IntentResolveResult.ResolveUrlFailed)
return@coroutineScope fail("Failed to run resolvers", IntentResolveResult.ResolveUrlFailed)
}

uri = runUriModifiers(
Expand All @@ -177,7 +191,7 @@ class ImprovedIntentResolver(
)

if (uri == null) {
return fail("Failed to run uri modifiers", IntentResolveResult.UrlModificationFailed)
return@coroutineScope fail("Failed to run uri modifiers", IntentResolveResult.UrlModificationFailed)
}

val libRedirectResult = tryRunLibRedirect(
Expand Down Expand Up @@ -221,9 +235,20 @@ class ImprovedIntentResolver(
returnLastChosen = !dontShowFilteredItem()
)

val unfurl = tryUnfurl(enabled = previewUrl(), uri = uri)
val unfurlDeferred = async { tryUnfurl(enabled = previewUrl(), uri = uri) }
val unfurlCancel = ResolverInteraction.Cancelable(1) {
Log.d("Cancel", "Cancelling $unfurlDeferred")
unfurlDeferred.cancel()
}

emitInteraction(unfurlCancel)

Log.d("ImprovedIntentResolver", "Awaiting..")
val unfurl = unfurlDeferred.awaitOrNull()

emitInteraction(ResolverInteraction.None)

return IntentResolveResult.Default(
return@coroutineScope IntentResolveResult.Default(
newIntent,
uri,
unfurl,
Expand Down Expand Up @@ -317,6 +342,7 @@ class ImprovedIntentResolver(
if (!enabled) return@withContext null

emitEvent("Generating preview")
// delay(10_000)
// TODO: Move everything to okhttp
unfurler.unfurl(uri.toString())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ sealed interface ResolveEvent {
@Stable
value class Message(val message: String) : ResolveEvent

companion object{
companion object {
val Initialized = Message("Initialized")
}
}

sealed interface ResolverInteraction {
data object None : ResolverInteraction
data class Cancelable(val id: Int, val cancel: () -> Unit) : ResolverInteraction
}
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,9 @@ class ImprovedBottomSheet(
hide = hide,
sheetContent = {
if (status is IntentResolveResult.Pending) {
LoadingIndicator(events = resolver.events)
LoadingIndicator(events = resolver.events, interactions = resolver.interactions, requestExpand = {
coroutineScope.launch { drawerState.expand() }
})
} else if (status is IntentResolveResult.Default) {
AppWrapper_Temp(
status as IntentResolveResult.Default,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,42 @@ package fe.linksheet.experiment.improved.resolver.activity.bottomsheet

import android.util.Log
import androidx.compose.foundation.layout.*
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import fe.linksheet.R
import fe.linksheet.experiment.improved.resolver.ImprovedIntentResolver
import fe.linksheet.experiment.improved.resolver.ResolveEvent
import fe.linksheet.experiment.improved.resolver.ResolverInteraction
import fe.linksheet.extension.kotlin.collectOnIO
import fe.linksheet.ui.HkGroteskFontFamily
import fe.linksheet.ui.PreviewTheme
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow

@Composable
fun LoadingIndicator(events: StateFlow<ResolveEvent>) {
fun LoadingIndicator(
events: StateFlow<ResolveEvent>,
interactions: StateFlow<ResolverInteraction>,
requestExpand: () -> Unit
) {
val event by events.collectOnIO(initialState = ResolveEvent.Initialized)
val interaction by interactions.collectOnIO(initialState = ResolverInteraction.None)

LaunchedEffect(key1 = interaction) {
requestExpand()
}

Column(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 20.dp),
.padding(horizontal = 20.dp, vertical = 20.dp),
horizontalAlignment = Alignment.CenterHorizontally,
// verticalArrangement = Arrangement.spacedBy(15.dp),
) {
Expand All @@ -45,6 +51,18 @@ fun LoadingIndicator(events: StateFlow<ResolveEvent>) {
)

Text(text = "${(event as? ResolveEvent.Message)?.message}", style = MaterialTheme.typography.bodyMedium)

if (interaction is ResolverInteraction.Cancelable) {
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.End) {

Button(onClick = {
Log.d("Interact", "Cancel")
(interaction as ResolverInteraction.Cancelable).cancel()
}) {
Text(text = stringResource(id = R.string.bottom_sheet_loading_indicator__button_skip_job))
}
}
}
// LinearProgressIndicator(modifier = Modifier.fillMaxWidth().padding(horizontal = 4.dp))
}
}
Expand All @@ -53,17 +71,26 @@ fun LoadingIndicator(events: StateFlow<ResolveEvent>) {
@Composable
private fun LoadingIndicatorPreview() {
val events = MutableStateFlow<ResolveEvent>(ResolveEvent.Initialized)
val interactions = MutableStateFlow<ResolverInteraction>(ResolverInteraction.None)

LaunchedEffect(key1 = Unit) {
var i = 0
while (true) {
events.emit(ResolveEvent.Message("Message $i"))
if (i % 5 == 0) {
interactions.emit(ResolverInteraction.Cancelable(1) { Log.d("Preview", "Cancel clicked") })
}

delay(2000)


i++
}
}

PreviewTheme {
LoadingIndicator(events = events)
LoadingIndicator(events = events, interactions = interactions, requestExpand = {

})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package fe.linksheet.extension.kotlinx

import kotlinx.coroutines.Deferred
import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.ensureActive

suspend fun <T> Deferred<T>.awaitOrNull(): T? {
return runCatching { await() }.onFailure { currentCoroutineContext().ensureActive() }.getOrNull()
}
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -741,4 +741,5 @@
<string name="settings_credits__app_credit_reason_seal">Design inspiration</string>
<string name="settings_credits__app_name_gmsflags">GMS-Flags</string>
<string name="settings_credits__app_credit_reason_gmsflags">Design inspiration</string>
<string name="bottom_sheet_loading_indicator__button_skip_job">Skip</string>
</resources>

0 comments on commit 493e367

Please sign in to comment.