1
0
mirror of https://github.com/TeamNewPipe/NewPipe synced 2026-06-08 21:52:10 +00:00

Hook up URL handling for about page

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
Aayush Gupta
2026-05-09 18:03:39 +08:00
parent 8523aa48ba
commit 2b5a2e8bf3
9 changed files with 153 additions and 7 deletions
+3
View File
@@ -95,6 +95,8 @@ kotlin {
implementation(libs.russhwolf.settings)
implementation(libs.about.libraries.compose.m3)
implementation(libs.touchlab.kermit)
}
commonTest.dependencies {
implementation(libs.kotlin.test.core)
@@ -104,6 +106,7 @@ kotlin {
implementation(libs.jetbrains.compose.preview)
implementation(libs.androidx.activity)
implementation(libs.androidx.preference)
implementation(libs.androidx.browser)
}
val androidDeviceTest by getting {
dependencies {
@@ -0,0 +1,36 @@
/*
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package net.newpipe.app.platform
import android.content.Context
import android.content.Intent
import androidx.browser.customtabs.CustomTabsIntent
import androidx.core.net.toUri
import co.touchlab.kermit.Logger
import org.koin.core.annotation.Singleton
/**
* Handles sharing of data and information on Android
* @property context Context on Android, injected automatically by Koin
*/
@Singleton(binds = [ShareHandler::class])
class AndroidShareHandler(private val context: Context) : ShareHandler {
override fun openUrlInBrowser(url: String) {
try {
CustomTabsIntent.Builder()
.build()
.also { customIntent ->
customIntent.intent.addFlags(
Intent.FLAG_ACTIVITY_NEW_TASK
)
}
.launchUrl(context, url.toUri())
} catch (exception: Exception) {
Logger.e(messageString = "Failed to share URL", throwable = exception)
}
}
}
@@ -0,0 +1,20 @@
/*
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package net.newpipe.app.platform
import org.koin.core.annotation.ComponentScan
import org.koin.core.annotation.Configuration
import org.koin.core.annotation.Module
/**
* Module to access various common implementations that are dependent upon platform.
* See individual interfaces in this package and their implementations on platform packages
* for the declarations included in this module.
*/
@Module
@ComponentScan
@Configuration
object PlatformModule
@@ -0,0 +1,14 @@
/*
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package net.newpipe.app.platform
/**
* Helper methods related to sharing of data and information
* See individual platform classes for real implementation.
*/
interface ShareHandler {
fun openUrlInBrowser(url: String)
}
@@ -93,7 +93,10 @@ private val DEFAULT_LINKS = listOf(
)
@Composable
fun AboutPage(links: List<Link> = DEFAULT_LINKS) {
fun AboutPage(
links: List<Link> = DEFAULT_LINKS,
onOpenUrl: (url: String) -> Unit = {}
) {
LazyColumn(
modifier = Modifier.fillMaxWidth(),
contentPadding = PaddingValues(spaceNormal),
@@ -137,7 +140,8 @@ fun AboutPage(links: List<Link> = DEFAULT_LINKS) {
// Links about NewPipe
items(items = links, key = { link -> link.url }) { link ->
LinkListItem(
link = link
link = link,
onAction = { onOpenUrl(link.url) }
)
}
}
@@ -24,23 +24,30 @@ import androidx.compose.ui.tooling.preview.PreviewWrapper
import androidx.compose.ui.util.fastForEachIndexed
import kotlinx.coroutines.launch
import net.newpipe.app.composable.TopAppBar
import net.newpipe.app.platform.ShareHandler
import net.newpipe.app.preview.ThemePreviewProvider
import org.jetbrains.compose.resources.stringResource
import net.newpipe.app.screen.about.navigation.Page
import newpipe.composeapp.generated.resources.Res
import newpipe.composeapp.generated.resources.title_activity_about
import org.koin.compose.koinInject
@Composable
fun AboutScreen(onNavigateUp: () -> Unit) {
fun AboutScreen(
onNavigateUp: () -> Unit,
shareHandler: ShareHandler = koinInject()
) {
ScreenContent(
onNavigateUp = onNavigateUp
onNavigateUp = onNavigateUp,
onOpenUrl = { url -> shareHandler.openUrlInBrowser(url) }
)
}
@Composable
private fun ScreenContent(
pages: List<Page> = listOf(Page.ABOUT, Page.LICENSE),
onNavigateUp: () -> Unit = {}
onNavigateUp: () -> Unit = {},
onOpenUrl: (url: String) -> Unit = {}
) {
Scaffold(
topBar = {
@@ -78,7 +85,7 @@ private fun ScreenContent(
HorizontalPager(state = pagerState, modifier = Modifier.fillMaxSize()) { page ->
when (pages[page]) {
Page.ABOUT -> AboutPage()
Page.ABOUT -> AboutPage(onOpenUrl = onOpenUrl)
Page.LICENSE -> LicensePage()
}
}
@@ -0,0 +1,30 @@
/*
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package net.newpipe.app.platform
import co.touchlab.kermit.Logger
import org.koin.core.annotation.Singleton
import platform.Foundation.NSURL
import platform.SafariServices.SFSafariViewController
import platform.UIKit.UIApplication
/**
* Handles sharing of data and information on iOS
*/
@Singleton(binds = [ShareHandler::class])
class IosShareHandler : ShareHandler {
override fun openUrlInBrowser(url: String) {
val nsUrl = NSURL.URLWithString(url)
if (nsUrl == null) {
Logger.e(messageString = "Unable to open malformatted URL, bailing out!")
} else {
val safariVC = SFSafariViewController(uRL = nsUrl)
val rootVC = UIApplication.sharedApplication.keyWindow?.rootViewController
rootVC?.presentViewController(safariVC, animated = true, completion = null)
}
}
}
@@ -0,0 +1,28 @@
/*
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package net.newpipe.app.platform
import co.touchlab.kermit.Logger
import org.koin.core.annotation.ComponentScan
import org.koin.core.annotation.Configuration
import org.koin.core.annotation.Module
import org.koin.core.annotation.Singleton
import java.awt.Desktop
import java.net.URI
/**
* Handles sharing of data and information on JVM
*/
@Singleton(binds = [ShareHandler::class])
class JvmShareHandler : ShareHandler {
override fun openUrlInBrowser(url: String) {
when {
Desktop.isDesktopSupported() -> Desktop.getDesktop().browse(URI(url))
else -> Logger.e(messageString = "Unsupported platform! Cannot open URL in browser")
}
}
}
+5 -1
View File
@@ -13,6 +13,7 @@ assertj = "3.27.7"
autoservice-google = "1.1.1"
autoservice-zacsweers = "1.2.0"
bridge = "v2.0.2"
browser = "1.10.0"
cardview = "1.0.0"
checkstyle = "13.4.0"
coil = "3.4.0"
@@ -29,6 +30,7 @@ groupie = "2.10.1"
jsoup = "1.22.2"
junit = "4.13.2"
junit-ext = "1.3.0"
kermit = "2.1.0"
koin = "4.2.1"
koin-plugin = "1.0.0-RC2"
kotlin = "2.3.21"
@@ -81,6 +83,7 @@ acra-core = { module = "ch.acra:acra-core", version.ref = "acra" }
android-desugar = { module = "com.android.tools:desugar_jdk_libs_nio", version.ref = "desugar" }
androidx-activity = { module = "androidx.activity:activity-compose", version.ref = "activity" }
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
androidx-browser = { module = "androidx.browser:browser", version.ref = "browser" }
androidx-cardview = { module = "androidx.cardview:cardview", version.ref = "cardview" }
androidx-compose-test-ui-junit = { module = "androidx.compose.ui:ui-test-junit4-android", version.ref = "compose" }
androidx-compose-test-ui-manifest = { module = "androidx.compose.ui:ui-test-manifest", version.ref = "compose" }
@@ -129,9 +132,9 @@ jetbrains-compose-material3 = { module = "org.jetbrains.compose.material3:materi
jetbrains-compose-preview = { module = "org.jetbrains.compose.ui:ui-tooling-preview", version.ref = "multiplatform" }
jetbrains-compose-resources = { module = "org.jetbrains.compose.components:components-resources", version.ref = "multiplatform" }
jetbrains-compose-runtime = { module = "org.jetbrains.compose.runtime:runtime", version.ref = "multiplatform" }
jetbrains-compose-test-ui = { module = "org.jetbrains.compose.ui:ui-test", version.ref = "multiplatform" }
jetbrains-compose-tooling = { module = "org.jetbrains.compose.ui:ui-tooling", version.ref = "multiplatform" }
jetbrains-compose-ui = { module = "org.jetbrains.compose.ui:ui", version.ref = "multiplatform" }
jetbrains-compose-test-ui = { module = "org.jetbrains.compose.ui:ui-test", version.ref = "multiplatform" }
jetbrains-coroutines-swing = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-swing", version.ref = "coroutines" }
jetbrains-lifecycle-navigation3 = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-navigation3", version.ref = "lifecycle" }
jetbrains-lifecycle-viewmodel = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycle" }
@@ -162,6 +165,7 @@ squareup-leakcanary-core = { module = "com.squareup.leakcanary:leakcanary-androi
squareup-leakcanary-plumber = { module = "com.squareup.leakcanary:plumber-android", version.ref = "leakcanary" }
squareup-leakcanary-watcher = { module = "com.squareup.leakcanary:leakcanary-object-watcher-android", version.ref = "leakcanary" }
squareup-okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
touchlab-kermit = { module = "co.touchlab:kermit", version.ref = "kermit" }
zacsweers-autoservice-compiler = { module = "dev.zacsweers.autoservice:auto-service-ksp", version.ref = "autoservice-zacsweers" }
[plugins]