Skip to content

Commit

Permalink
enhancement: allow to skip internal resolution for external URLs (#737)
Browse files Browse the repository at this point in the history
* add allowOpenInternal option to CustomUriHandler

* simplify deep link management with extension

* update UI components

* update AnnouncementsScreen

* update CalendarScreen

* update CircleTimelineScreen

* update EntryDetailScreen

* update ExploreScreen

* update FavoritesScreen

* update ForumListScreen

* update HashtagScreen

* update InboxScreen

* update LoginIntroScreen

* update LicencesScreen

* update MyAccountScreen

* update SearchScreen

* update ThreadScreen

* update TimelineScreen

* update UserDetailScreen
  • Loading branch information
AkesiSeli authored Jan 14, 2025
1 parent 9e2dbf5 commit 6c57ae6
Show file tree
Hide file tree
Showing 45 changed files with 237 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import com.livefast.eattrash.raccoonforfriendica.domain.identity.usecase.di.getA
import com.livefast.eattrash.raccoonforfriendica.domain.identity.usecase.di.getSetupAccountUseCase
import com.livefast.eattrash.raccoonforfriendica.domain.urlhandler.ProvideCustomUriHandler
import com.livefast.eattrash.raccoonforfriendica.domain.urlhandler.di.getCustomUriHandler
import com.livefast.eattrash.raccoonforfriendica.domain.urlhandler.openInternally
import com.livefast.eattrash.raccoonforfriendica.feature.drawer.DrawerContent
import com.livefast.eattrash.raccoonforfriendica.main.MainScreen
import kotlinx.coroutines.FlowPreview
Expand Down Expand Up @@ -130,10 +131,7 @@ fun App(onLoadingFinished: (() -> Unit)? = null) {
navigationCoordinator.deepLinkUrl
.debounce(750)
.onEach { url ->
customUriHandler.openUri(
uri = url,
allowOpenExternal = false,
)
customUriHandler.openInternally(url)
}.launchIn(this)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ internal fun CardTimelineItem(
onFavorite: ((TimelineEntryModel) -> Unit)? = null,
onDislike: ((TimelineEntryModel) -> Unit)? = null,
onOpenImage: ((List<String>, Int, List<Int>) -> Unit)? = null,
onOpenUrl: ((String) -> Unit)? = null,
onOpenUrl: ((String, Boolean) -> Unit)? = null,
onOpenUser: ((UserModel) -> Unit)? = null,
onOpenUsersFavorite: ((TimelineEntryModel) -> Unit)? = null,
onOpenUsersReblog: ((TimelineEntryModel) -> Unit)? = null,
Expand Down Expand Up @@ -218,7 +218,7 @@ internal fun CardTimelineItem(
autoloadImages = autoloadImages,
emojis = entryToDisplay.emojis,
onClick = { onClick?.invoke(entryToDisplay) },
onOpenUrl = onOpenUrl,
onOpenUrl = onOpenUrl?.let { block -> { url -> block(url, true) } },
)
}

Expand All @@ -239,7 +239,7 @@ internal fun CardTimelineItem(
maxLines = maxBodyLines,
emojis = entryToDisplay.emojis,
onClick = { onClick?.invoke(entryToDisplay) },
onOpenUrl = onOpenUrl,
onOpenUrl = onOpenUrl?.let { block -> { url -> block(url, true) } },
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ internal fun CompactTimelineItem(
onFavorite: ((TimelineEntryModel) -> Unit)? = null,
onDislike: ((TimelineEntryModel) -> Unit)? = null,
onOpenImage: ((List<String>, Int, List<Int>) -> Unit)? = null,
onOpenUrl: ((String) -> Unit)? = null,
onOpenUrl: ((String, Boolean) -> Unit)? = null,
onOpenUser: ((UserModel) -> Unit)? = null,
onOpenUsersFavorite: ((TimelineEntryModel) -> Unit)? = null,
onOpenUsersReblog: ((TimelineEntryModel) -> Unit)? = null,
Expand Down Expand Up @@ -212,7 +212,7 @@ internal fun CompactTimelineItem(
autoloadImages = autoloadImages,
emojis = entryToDisplay.emojis,
onClick = { onClick?.invoke(entryToDisplay) },
onOpenUrl = onOpenUrl,
onOpenUrl = onOpenUrl?.let { block -> { url -> block(url, true) } },
)
}

Expand All @@ -233,7 +233,7 @@ internal fun CompactTimelineItem(
maxLines = maxBodyLines,
emojis = entryToDisplay.emojis,
onClick = { onClick?.invoke(entryToDisplay) },
onOpenUrl = onOpenUrl,
onOpenUrl = onOpenUrl?.let { block -> { url -> block(url, true) } },
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ internal fun DistractionFreeTimelineItem(
onClick: ((TimelineEntryModel) -> Unit)? = null,
onFavorite: ((TimelineEntryModel) -> Unit)? = null,
onDislike: ((TimelineEntryModel) -> Unit)? = null,
onOpenUrl: ((String) -> Unit)? = null,
onOpenUrl: ((String, Boolean) -> Unit)? = null,
onOpenUser: ((UserModel) -> Unit)? = null,
onOptionSelected: ((OptionId) -> Unit)? = null,
onOptionsMenuToggled: ((Boolean) -> Unit)? = null,
Expand Down Expand Up @@ -191,7 +191,7 @@ internal fun DistractionFreeTimelineItem(
autoloadImages = autoloadImages,
emojis = entryToDisplay.emojis,
onClick = { onClick?.invoke(entryToDisplay) },
onOpenUrl = onOpenUrl,
onOpenUrl = onOpenUrl?.let { block -> { url -> block(url, true) } },
)
}

Expand All @@ -212,7 +212,7 @@ internal fun DistractionFreeTimelineItem(
maxLines = maxBodyLines,
emojis = entryToDisplay.emojis,
onClick = { onClick?.invoke(entryToDisplay) },
onOpenUrl = onOpenUrl,
onOpenUrl = onOpenUrl?.let { block -> { url -> block(url, true) } },
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ internal fun FullTimelineItem(
onFavorite: ((TimelineEntryModel) -> Unit)? = null,
onDislike: ((TimelineEntryModel) -> Unit)? = null,
onOpenImage: ((List<String>, Int, List<Int>) -> Unit)? = null,
onOpenUrl: ((String) -> Unit)? = null,
onOpenUrl: ((String, Boolean) -> Unit)? = null,
onOpenUser: ((UserModel) -> Unit)? = null,
onOpenUsersFavorite: ((TimelineEntryModel) -> Unit)? = null,
onOpenUsersReblog: ((TimelineEntryModel) -> Unit)? = null,
Expand Down Expand Up @@ -200,7 +200,7 @@ internal fun FullTimelineItem(
autoloadImages = autoloadImages,
emojis = entryToDisplay.emojis,
onClick = { onClick?.invoke(entryToDisplay) },
onOpenUrl = onOpenUrl,
onOpenUrl = onOpenUrl?.let { block -> { url -> block(url, true) } },
)
}

Expand All @@ -221,7 +221,7 @@ internal fun FullTimelineItem(
maxLines = maxBodyLines,
emojis = entryToDisplay.emojis,
onClick = { onClick?.invoke(entryToDisplay) },
onOpenUrl = onOpenUrl,
onOpenUrl = onOpenUrl?.let { block -> { url -> block(url, true) } },
)
}

Expand Down Expand Up @@ -285,7 +285,7 @@ internal fun FullTimelineItem(
image = preview.image.takeIf { attachments.isEmpty() },
),
autoloadImages = autoloadImages,
onOpen = onOpenUrl,
onOpen = onOpenUrl?.let { block -> { url -> block(url, false) } },
onOpenImage = { url ->
onOpenImage?.invoke(listOf(url), 0, emptyList())
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ fun TimelineItem(
maxBodyLines: Int = Int.MAX_VALUE,
layout: TimelineLayout = TimelineLayout.Full,
options: List<Option> = emptyList(),
onOpenUrl: ((String) -> Unit)? = null,
onOpenUrl: ((String, Boolean) -> Unit)? = null,
onClick: ((TimelineEntryModel) -> Unit)? = null,
onOpenUser: ((UserModel) -> Unit)? = null,
onReply: ((TimelineEntryModel) -> Unit)? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ fun TimelineReplyItem(
autoloadImages: Boolean = true,
layout: TimelineLayout = TimelineLayout.Full,
options: List<Option> = emptyList(),
onOpenUrl: ((String) -> Unit)? = null,
onOpenUrl: ((String, Boolean) -> Unit)? = null,
onClick: ((TimelineEntryModel) -> Unit)? = null,
onOpenUser: ((UserModel) -> Unit)? = null,
onReply: ((TimelineEntryModel) -> Unit)? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fun UserFields(
fields: List<FieldModel> = emptyList(),
autoloadImages: Boolean = true,
modifier: Modifier = Modifier,
onOpenUrl: ((String) -> Unit)? = null,
onOpenUrl: ((String, Boolean) -> Unit)? = null,
) {
val ancillaryColor = MaterialTheme.colorScheme.onBackground.copy(ancillaryTextAlpha)

Expand Down Expand Up @@ -76,7 +76,7 @@ fun UserFields(
.firstOrNull()
?.item
if (!url.isNullOrBlank()) {
onOpenUrl?.invoke(url)
onOpenUrl?.invoke(url, true)
}
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ fun UserHeader(
onOpenImage: ((String) -> Unit)? = null,
onOpenFollowers: (() -> Unit)? = null,
onOpenFollowing: (() -> Unit)? = null,
onOpenUrl: ((String) -> Unit)? = null,
onOpenUrl: ((String, Boolean) -> Unit)? = null,
onRelationshipClicked: ((RelationshipStatusNextAction) -> Unit)? = null,
onNotificationsClicked: ((NotificationStatusNextAction) -> Unit)? = null,
onEditClicked: (() -> Unit)? = null,
Expand Down Expand Up @@ -209,7 +209,7 @@ fun UserHeader(
ContentBody(
content = bio,
emojis = user.emojis,
onOpenUrl = onOpenUrl,
onOpenUrl = onOpenUrl?.let { block -> { url -> block(url, true) } },
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,23 @@ import androidx.compose.ui.platform.UriHandler
interface CustomUriHandler : UriHandler {
fun openUri(
uri: String,
allowOpenExternal: Boolean,
allowOpenExternal: Boolean = true,
allowOpenInternal: Boolean = true,
)
}

fun UriHandler.openExternally(uri: String) {
if (this is CustomUriHandler) {
openUri(uri = uri, allowOpenInternal = false)
} else {
openUri(uri)
}
}

fun UriHandler.openInternally(uri: String) {
if (this is CustomUriHandler) {
openUri(uri = uri, allowOpenExternal = false)
} else {
openUri(uri)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,28 @@ internal class DefaultCustomUriHandler(
override fun openUri(uri: String) {
openUri(
uri = uri,
allowOpenInternal = true,
allowOpenExternal = true,
)
}

override fun openUri(
uri: String,
allowOpenExternal: Boolean,
allowOpenInternal: Boolean,
) {
val urlOpeningMode =
settingsRepository.current.value?.urlOpeningMode ?: UrlOpeningMode.External

val processors =
// careful: topmost items have higher priority
listOf(
hashtagProcessor,
userProcessor,
entryProcessor,
)
buildList {
// careful: topmost items have higher priority
if (allowOpenInternal) {
this += hashtagProcessor
this += userProcessor
this += entryProcessor
}
}
scope.launch {
if (processors.none { it.process(uri) }) {
if (allowOpenExternal) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,6 @@ class DefaultCustomUriHandlerTest {

@Test
fun `given hashtag URL when openUri then interactions are as expected`() {
every {
settingsRepository.current
} returns MutableStateFlow(SettingsModel())
everySuspend { hashtagProcessor.process(any()) } returns true
val tag = "fake-hashtag"
val url = "https://$CURRENT_INSTANCE/search?tag=$tag"
Expand All @@ -135,9 +132,6 @@ class DefaultCustomUriHandlerTest {

@Test
fun `given user profile URL when openUri then interactions are as expected`() {
every {
settingsRepository.current
} returns MutableStateFlow(SettingsModel())
everySuspend { userProcessor.process(any()) } returns true
val url = "https://$CURRENT_INSTANCE/profile/username"

Expand All @@ -153,9 +147,6 @@ class DefaultCustomUriHandlerTest {

@Test
fun `given post display URL when openUri then interactions are as expected`() {
every {
settingsRepository.current
} returns MutableStateFlow(SettingsModel())
everySuspend { entryProcessor.process(any()) } returns true
val url = "https://$CURRENT_INSTANCE/display/objectId"

Expand All @@ -169,8 +160,39 @@ class DefaultCustomUriHandlerTest {
}
}

@Test
fun `given URL when openUri with allowOpenInternal false then interactions are as expected`() {
val url = "https://$CURRENT_INSTANCE/display/objectId"

sut.openUri(uri = url, allowOpenInternal = false)

verifySuspend(mode = VerifyMode.not) {
hashtagProcessor.process(any())
userProcessor.process(any())
entryProcessor.process(any())
}
verify {
defaultHandler.openUri(url)
}
}

@Test
fun `given URL when openUri with allowOpenExternal false then interactions are as expected`() {
val url = "https://$CURRENT_INSTANCE/display/objectId"

sut.openUri(uri = url, allowOpenExternal = false)

verifySuspend {
hashtagProcessor.process(any())
userProcessor.process(any())
entryProcessor.process(any())
}
verify(mode = VerifyMode.not) {
defaultHandler.openUri(url)
}
}

companion object {
private const val CURRENT_INSTANCE = "fake-instance.com"
private const val OTHER_INSTANCE = "other-instance.com"
}
}
1 change: 1 addition & 0 deletions feature/announcements/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ kotlin {
implementation(projects.domain.content.repository)
implementation(projects.domain.identity.data)
implementation(projects.domain.identity.repository)
implementation(projects.domain.urlhandler)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import com.livefast.eattrash.raccoonforfriendica.core.commonui.content.InsertEmo
import com.livefast.eattrash.raccoonforfriendica.core.commonui.content.TimelineDivider
import com.livefast.eattrash.raccoonforfriendica.core.l10n.LocalStrings
import com.livefast.eattrash.raccoonforfriendica.core.navigation.di.getNavigationCoordinator
import com.livefast.eattrash.raccoonforfriendica.domain.urlhandler.openExternally
import com.livefast.eattrash.raccoonforfriendica.feature.announcements.components.AnnouncementCard
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
Expand Down Expand Up @@ -182,8 +183,12 @@ class AnnouncementsScreen : Screen {
AnnouncementCard(
announcement = announcement,
autoloadImages = uiState.autoloadImages,
onOpenUrl = { url ->
uriHandler.openUri(url)
onOpenUrl = { url, allowOpenInternal ->
if (allowOpenInternal) {
uriHandler.openUri(url)
} else {
uriHandler.openExternally(url)
}
},
onAddNewReaction = {
chooseReactionAnnouncementIdBottomSheetOpened = announcement.id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ internal fun AnnouncementCard(
announcement: AnnouncementModel,
modifier: Modifier = Modifier,
autoloadImages: Boolean = true,
onOpenUrl: ((String) -> Unit)? = null,
onOpenUrl: ((String, Boolean) -> Unit)? = null,
onAddNewReaction: (() -> Unit)? = null,
onAddReaction: ((String) -> Unit)? = null,
onRemoveReaction: ((String) -> Unit)? = null,
Expand Down Expand Up @@ -67,7 +67,7 @@ internal fun AnnouncementCard(
content = body,
autoloadImages = autoloadImages,
emojis = announcement.emojis,
onOpenUrl = onOpenUrl,
onOpenUrl = onOpenUrl?.let { block -> { url -> block(url, true) } },
)
}

Expand Down
1 change: 1 addition & 0 deletions feature/calendar/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ kotlin {
implementation(projects.domain.content.repository)
implementation(projects.domain.identity.data)
implementation(projects.domain.identity.repository)
implementation(projects.domain.urlhandler)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ fun CalendarRow(
event: EventModel,
modifier: Modifier = Modifier,
options: List<Option> = emptyList(),
onOpenUrl: ((String) -> Unit)? = null,
onOpenUrl: ((String, Boolean) -> Unit)? = null,
onClick: (() -> Unit)? = null,
onOptionSelected: ((OptionId) -> Unit)? = null,
) {
Expand All @@ -67,7 +67,7 @@ fun CalendarRow(
ContentTitle(
modifier = Modifier.weight(1f).padding(horizontal = Spacing.s),
content = event.title,
onOpenUrl = onOpenUrl,
onOpenUrl = onOpenUrl?.let { block -> { url -> block(url, true) } },
maxLines = 5,
onClick = {
onClick?.invoke()
Expand Down
Loading

0 comments on commit 6c57ae6

Please sign in to comment.