mirror of
https://github.com/KRTirtho/spotube.git
synced 2026-09-20 22:54:00 +00:00
Compare commits
2 Commits
e0b9ab530d
...
95e9d563ec
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
95e9d563ec | ||
|
|
e826052691 |
@ -19,6 +19,7 @@ package dev.krtirtho.spotube
|
|||||||
|
|
||||||
import androidx.compose.animation.ExperimentalSharedTransitionApi
|
import androidx.compose.animation.ExperimentalSharedTransitionApi
|
||||||
import androidx.compose.animation.SharedTransitionLayout
|
import androidx.compose.animation.SharedTransitionLayout
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@ -41,6 +42,7 @@ import dev.krtirtho.spotube.core.ui.theming.SpotubeTheme
|
|||||||
import dev.krtirtho.spotube.modules.settings.SettingsRepository
|
import dev.krtirtho.spotube.modules.settings.SettingsRepository
|
||||||
import dev.krtirtho.spotube.modules.settings.UserSettings
|
import dev.krtirtho.spotube.modules.settings.UserSettings
|
||||||
import dev.krtirtho.spotube.modules.shell.AppShell
|
import dev.krtirtho.spotube.modules.shell.AppShell
|
||||||
|
import dev.krtirtho.spotube.modules.webview.WebViewScreen
|
||||||
import dev.krtirtho.spotube.resources.iconsax.Iconsax
|
import dev.krtirtho.spotube.resources.iconsax.Iconsax
|
||||||
import dev.krtirtho.spotube.resources.iconsax.IconsaxHome
|
import dev.krtirtho.spotube.resources.iconsax.IconsaxHome
|
||||||
import dev.krtirtho.spotube.resources.iconsax.IconsaxHomeBroken
|
import dev.krtirtho.spotube.resources.iconsax.IconsaxHomeBroken
|
||||||
@ -89,7 +91,11 @@ val tabs = listOf(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@OptIn(KoinExperimentalAPI::class, ExperimentalCoroutinesApi::class, ExperimentalSharedTransitionApi::class)
|
@OptIn(
|
||||||
|
KoinExperimentalAPI::class,
|
||||||
|
ExperimentalCoroutinesApi::class,
|
||||||
|
ExperimentalSharedTransitionApi::class
|
||||||
|
)
|
||||||
@Composable
|
@Composable
|
||||||
fun App(
|
fun App(
|
||||||
content: @Composable () -> Unit = {}
|
content: @Composable () -> Unit = {}
|
||||||
@ -108,6 +114,10 @@ fun App(
|
|||||||
SpotubeTheme(settings = userSettings) {
|
SpotubeTheme(settings = userSettings) {
|
||||||
val baseUITheme = rememberBaseUITheme()
|
val baseUITheme = rememberBaseUITheme()
|
||||||
CompositionLocalProvider(LocalBaseUITheme provides baseUITheme) {
|
CompositionLocalProvider(LocalBaseUITheme provides baseUITheme) {
|
||||||
|
Box(modifier = Modifier.fillMaxSize()) {
|
||||||
|
val currentRoute = navigationState.backStacks[navigationState.topLevelRoute]?.last()
|
||||||
|
|
||||||
|
Box(Modifier.fillMaxSize()) {
|
||||||
AppShell(navigator, navigationState) {
|
AppShell(navigator, navigationState) {
|
||||||
SharedTransitionLayout {
|
SharedTransitionLayout {
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
@ -123,6 +133,12 @@ fun App(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
when (currentRoute) {
|
||||||
|
Routes.WebView -> WebViewScreen(koinInject())
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
content()
|
content()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,9 +18,8 @@
|
|||||||
package dev.krtirtho.spotube.core.navigation
|
package dev.krtirtho.spotube.core.navigation
|
||||||
|
|
||||||
import androidx.navigation3.runtime.NavKey
|
import androidx.navigation3.runtime.NavKey
|
||||||
import dev.krtirtho.spotube.modules.artist.ArtistScreen
|
|
||||||
import dev.krtirtho.spotube.modules.album.AlbumScreen
|
import dev.krtirtho.spotube.modules.album.AlbumScreen
|
||||||
import dev.krtirtho.spotube.modules.artist.ArtistViewModel
|
import dev.krtirtho.spotube.modules.artist.ArtistScreen
|
||||||
import dev.krtirtho.spotube.modules.blacklist.BlacklistScreen
|
import dev.krtirtho.spotube.modules.blacklist.BlacklistScreen
|
||||||
import dev.krtirtho.spotube.modules.home.HomeScreen
|
import dev.krtirtho.spotube.modules.home.HomeScreen
|
||||||
import dev.krtirtho.spotube.modules.library.LibraryScreen
|
import dev.krtirtho.spotube.modules.library.LibraryScreen
|
||||||
@ -31,7 +30,6 @@ import dev.krtirtho.spotube.modules.saved_tracks.SAVED_TRACKS_COLLECTION_ID
|
|||||||
import dev.krtirtho.spotube.modules.saved_tracks.SavedTracksScreen
|
import dev.krtirtho.spotube.modules.saved_tracks.SavedTracksScreen
|
||||||
import dev.krtirtho.spotube.modules.search.SearchScreen
|
import dev.krtirtho.spotube.modules.search.SearchScreen
|
||||||
import dev.krtirtho.spotube.modules.settings.SettingsScreen
|
import dev.krtirtho.spotube.modules.settings.SettingsScreen
|
||||||
import dev.krtirtho.spotube.modules.webview.WebViewScreen
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import org.koin.compose.viewmodel.koinViewModel
|
import org.koin.compose.viewmodel.koinViewModel
|
||||||
import org.koin.core.annotation.KoinExperimentalAPI
|
import org.koin.core.annotation.KoinExperimentalAPI
|
||||||
@ -97,9 +95,7 @@ val navigationModule = module {
|
|||||||
navigation<Routes.Plugins> {
|
navigation<Routes.Plugins> {
|
||||||
PluginScreen(pluginManager = get())
|
PluginScreen(pluginManager = get())
|
||||||
}
|
}
|
||||||
navigation<Routes.WebView> {
|
navigation<Routes.WebView> {}
|
||||||
WebViewScreen(get())
|
|
||||||
}
|
|
||||||
navigation<Routes.Playlist> {
|
navigation<Routes.Playlist> {
|
||||||
PlaylistScreen(
|
PlaylistScreen(
|
||||||
playlistId = it.playlistId,
|
playlistId = it.playlistId,
|
||||||
|
|||||||
@ -19,6 +19,7 @@ package dev.krtirtho.spotube.core.webview
|
|||||||
|
|
||||||
import androidx.compose.foundation.BorderStroke
|
import androidx.compose.foundation.BorderStroke
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
@ -51,6 +52,7 @@ import compose.icons.feathericons.ChevronLeft
|
|||||||
import compose.icons.feathericons.ChevronRight
|
import compose.icons.feathericons.ChevronRight
|
||||||
import compose.icons.feathericons.X
|
import compose.icons.feathericons.X
|
||||||
import dev.krtirtho.spotube.core.tools.user_agents.UserAgents
|
import dev.krtirtho.spotube.core.tools.user_agents.UserAgents
|
||||||
|
import dev.krtirtho.spotube.core.ui.component.ApplicationMainBar
|
||||||
import dev.nucleusframework.webview.jsbridge.IJsMessageHandler
|
import dev.nucleusframework.webview.jsbridge.IJsMessageHandler
|
||||||
import dev.nucleusframework.webview.jsbridge.JsMessage
|
import dev.nucleusframework.webview.jsbridge.JsMessage
|
||||||
import dev.nucleusframework.webview.jsbridge.rememberWebViewJsBridge
|
import dev.nucleusframework.webview.jsbridge.rememberWebViewJsBridge
|
||||||
@ -149,6 +151,8 @@ fun PlatformWebViewScreen(webViewController: WebViewController) {
|
|||||||
Scaffold(
|
Scaffold(
|
||||||
contentWindowInsets = WindowInsets.statusBars,
|
contentWindowInsets = WindowInsets.statusBars,
|
||||||
topBar = {
|
topBar = {
|
||||||
|
ApplicationMainBar(
|
||||||
|
title = {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth().statusBarsPadding().height(56.dp),
|
modifier = Modifier.fillMaxWidth().statusBarsPadding().height(56.dp),
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
@ -199,14 +203,11 @@ fun PlatformWebViewScreen(webViewController: WebViewController) {
|
|||||||
.wrapContentHeight(Alignment.CenterVertically)
|
.wrapContentHeight(Alignment.CenterVertically)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
IconButton(
|
|
||||||
onClick = {
|
|
||||||
webViewController.closeWebview()
|
|
||||||
}) {
|
|
||||||
Icon(FeatherIcons.X, contentDescription = "Close WebView")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}) { innerPadding ->
|
)
|
||||||
|
})
|
||||||
|
{ innerPadding ->
|
||||||
WebView(
|
WebView(
|
||||||
state = state,
|
state = state,
|
||||||
modifier = Modifier.padding(innerPadding).fillMaxSize(),
|
modifier = Modifier.padding(innerPadding).fillMaxSize(),
|
||||||
|
|||||||
@ -26,6 +26,8 @@ import androidx.compose.runtime.setValue
|
|||||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.rememberWindowState
|
import androidx.compose.ui.window.rememberWindowState
|
||||||
|
import com.sun.jna.Library
|
||||||
|
import com.sun.jna.Native
|
||||||
import dev.krtirtho.spotube.core.di.initKoin
|
import dev.krtirtho.spotube.core.di.initKoin
|
||||||
import dev.krtirtho.spotube.core.newpipe.NewPipeDownloader
|
import dev.krtirtho.spotube.core.newpipe.NewPipeDownloader
|
||||||
import dev.krtirtho.spotube.core.paths.Paths
|
import dev.krtirtho.spotube.core.paths.Paths
|
||||||
@ -55,8 +57,33 @@ private object KoinServicesProvider : KoinComponent {
|
|||||||
val settingsProvider: SettingsProvider get() = get()
|
val settingsProvider: SettingsProvider get() = get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private interface LibC : Library {
|
||||||
|
fun setenv(name: String, value: String, overwrite: Int): Int
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val INSTANCE: LibC = Native.load("c", LibC::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WebKitGTK is only used on Linux (Windows = WebView2, macOS = WKWebView).
|
||||||
|
* The webview is created *after* the window is already mapped and the Tao
|
||||||
|
* render/swap loop is running. WebKitGTK's accelerated-compositing path then
|
||||||
|
* initialises its own GL context in-process, racing Tao's swap thread on the
|
||||||
|
* same Mesa display, which deterministically segfaults `libgallium` on the
|
||||||
|
* next Compose flush. Disabling WebKit's hardware-accelerated compositing
|
||||||
|
* (and its DMABUF renderer) removes that GL context entirely — login pages
|
||||||
|
* render fine in software. Must run before libwebkit2gtk is loaded.
|
||||||
|
*/
|
||||||
|
private fun disableWebKitGpuCompositing() {
|
||||||
|
if (!System.getProperty("os.name").lowercase().contains("linux")) return
|
||||||
|
LibC.INSTANCE.setenv("WEBKIT_DISABLE_COMPOSITING_MODE", "1", 1)
|
||||||
|
LibC.INSTANCE.setenv("WEBKIT_DISABLE_DMABUF_RENDERER", "1", 1)
|
||||||
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalComposeUiApi::class)
|
@OptIn(ExperimentalComposeUiApi::class)
|
||||||
fun main() {
|
fun main() {
|
||||||
|
disableWebKitGpuCompositing()
|
||||||
FileKit.init(appId = "dev.krtirtho.spotube")
|
FileKit.init(appId = "dev.krtirtho.spotube")
|
||||||
initKoin()
|
initKoin()
|
||||||
NewPipeDownloader.init(KoinPathsProvider.paths)
|
NewPipeDownloader.init(KoinPathsProvider.paths)
|
||||||
|
|||||||
@ -20,6 +20,7 @@ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
|
|||||||
|
|
||||||
pluginManagement {
|
pluginManagement {
|
||||||
repositories {
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
google {
|
google {
|
||||||
mavenContent {
|
mavenContent {
|
||||||
includeGroupAndSubgroups("androidx")
|
includeGroupAndSubgroups("androidx")
|
||||||
@ -29,13 +30,13 @@ pluginManagement {
|
|||||||
}
|
}
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
mavenLocal()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencyResolutionManagement {
|
dependencyResolutionManagement {
|
||||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||||
repositories {
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
google {
|
google {
|
||||||
mavenContent {
|
mavenContent {
|
||||||
includeGroupAndSubgroups("androidx")
|
includeGroupAndSubgroups("androidx")
|
||||||
@ -45,7 +46,6 @@ dependencyResolutionManagement {
|
|||||||
}
|
}
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven("https://jitpack.io")
|
maven("https://jitpack.io")
|
||||||
mavenLocal()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user