mirror of
https://github.com/KRTirtho/spotube.git
synced 2026-08-05 19:59:51 +00:00
Compare commits
2 Commits
4bc487782f
...
fe0ebb47fe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe0ebb47fe | ||
|
|
14ee4f6a4c |
16
.github/dependabot.yml
vendored
16
.github/dependabot.yml
vendored
@ -1,16 +0,0 @@
|
|||||||
version: 2
|
|
||||||
|
|
||||||
enable-beta-ecosystems: true
|
|
||||||
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: "pub"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
target-branch: "dev"
|
|
||||||
|
|
||||||
- package-ecosystem: "github-actions"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
target-branch: "dev"
|
|
||||||
@ -17,8 +17,20 @@
|
|||||||
|
|
||||||
package dev.krtirtho.spotube.core.webview
|
package dev.krtirtho.spotube.core.webview
|
||||||
|
|
||||||
|
import android.webkit.CookieManager
|
||||||
|
import android.webkit.WebStorage
|
||||||
|
import android.webkit.WebView
|
||||||
import io.github.kdroidfilter.webview.web.WebViewState
|
import io.github.kdroidfilter.webview.web.WebViewState
|
||||||
|
|
||||||
actual fun platformWebviewConfig(webView: WebViewState) {
|
actual fun platformWebviewConfig(webView: WebViewState, pluginId: String?) {
|
||||||
webView.webView?.nativeWebView?.settings?.domStorageEnabled = true
|
val nativeWebView = webView.webView?.nativeWebView as? WebView ?: return
|
||||||
|
nativeWebView.settings.domStorageEnabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
actual suspend fun platformClearWebviewData(pluginId: String?) {
|
||||||
|
if (pluginId == null) return
|
||||||
|
|
||||||
|
CookieManager.getInstance().removeAllCookies(null)
|
||||||
|
CookieManager.getInstance().flush()
|
||||||
|
WebStorage.getInstance().deleteAllData()
|
||||||
}
|
}
|
||||||
@ -38,6 +38,8 @@ class WebViewController(val navigationCommands: NavigationCommands): KoinCompone
|
|||||||
private var cookieManager: CookieManager? = null
|
private var cookieManager: CookieManager? = null
|
||||||
private val urlFlow = MutableStateFlow("")
|
private val urlFlow = MutableStateFlow("")
|
||||||
private val webViewCreated = MutableSharedFlow<Unit>(replay = 1)
|
private val webViewCreated = MutableSharedFlow<Unit>(replay = 1)
|
||||||
|
var currentPluginId: String? = null
|
||||||
|
private set
|
||||||
|
|
||||||
suspend fun getCookies(url: String): List<Cookie> {
|
suspend fun getCookies(url: String): List<Cookie> {
|
||||||
if (cookieManager == null) {
|
if (cookieManager == null) {
|
||||||
@ -104,19 +106,21 @@ class WebViewController(val navigationCommands: NavigationCommands): KoinCompone
|
|||||||
webViewNavigator = null
|
webViewNavigator = null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun navigateTo(url: String) {
|
fun navigateTo(url: String, pluginId: String) {
|
||||||
if (this.content != null) {
|
if (this.content != null) {
|
||||||
throw IllegalStateException("WebView is already open. Please close the current WebView before navigating to a new URL.")
|
throw IllegalStateException("WebView is already open. Please close the current WebView before navigating to a new URL.")
|
||||||
}
|
}
|
||||||
|
this.currentPluginId = pluginId
|
||||||
this.content = url
|
this.content = url
|
||||||
this.isHtmlContent = false
|
this.isHtmlContent = false
|
||||||
navigationCommands.navigateTo(Routes.WebView)
|
navigationCommands.navigateTo(Routes.WebView)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun navigateToHTML(html: String) {
|
fun navigateToHTML(html: String, pluginId: String) {
|
||||||
if (this.content != null) {
|
if (this.content != null) {
|
||||||
throw IllegalStateException("WebView is already open. Please close the current WebView before navigating to a new URL.")
|
throw IllegalStateException("WebView is already open. Please close the current WebView before navigating to a new URL.")
|
||||||
}
|
}
|
||||||
|
this.currentPluginId = pluginId
|
||||||
this.content = html
|
this.content = html
|
||||||
this.isHtmlContent = true
|
this.isHtmlContent = true
|
||||||
navigationCommands.navigateTo(Routes.WebView)
|
navigationCommands.navigateTo(Routes.WebView)
|
||||||
@ -138,12 +142,15 @@ class WebViewController(val navigationCommands: NavigationCommands): KoinCompone
|
|||||||
return completer.await()
|
return completer.await()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun clearData() {
|
suspend fun clearData(pluginId: String? = null) {
|
||||||
cookieManager?.removeAllCookies()
|
cookieManager?.removeAllCookies()
|
||||||
|
val targetPluginId = pluginId ?: currentPluginId
|
||||||
|
platformClearWebviewData(targetPluginId)
|
||||||
cookieManager = null
|
cookieManager = null
|
||||||
content = null
|
content = null
|
||||||
isHtmlContent = false
|
isHtmlContent = false
|
||||||
webViewNavigator = null
|
webViewNavigator = null
|
||||||
|
currentPluginId = null
|
||||||
}
|
}
|
||||||
|
|
||||||
val urlChangedFlow = urlFlow.asStateFlow()
|
val urlChangedFlow = urlFlow.asStateFlow()
|
||||||
|
|||||||
@ -19,4 +19,6 @@ package dev.krtirtho.spotube.core.webview
|
|||||||
|
|
||||||
import io.github.kdroidfilter.webview.web.WebViewState
|
import io.github.kdroidfilter.webview.web.WebViewState
|
||||||
|
|
||||||
expect fun platformWebviewConfig(webView: WebViewState)
|
expect fun platformWebviewConfig(webView: WebViewState, pluginId: String?)
|
||||||
|
|
||||||
|
expect suspend fun platformClearWebviewData(pluginId: String?)
|
||||||
|
|||||||
@ -19,7 +19,6 @@ 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
|
||||||
@ -40,30 +39,25 @@ import androidx.compose.material3.Text
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.runtime.snapshotFlow
|
import androidx.compose.runtime.snapshotFlow
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.github.kdroidfilter.webview.jsbridge.IJsMessageHandler
|
|
||||||
import io.github.kdroidfilter.webview.jsbridge.JsMessage
|
|
||||||
import io.github.kdroidfilter.webview.jsbridge.rememberWebViewJsBridge
|
|
||||||
import io.github.kdroidfilter.webview.web.WebView
|
|
||||||
import io.github.kdroidfilter.webview.web.rememberWebViewNavigator
|
|
||||||
import io.github.kdroidfilter.webview.web.WebViewState
|
|
||||||
import io.github.kdroidfilter.webview.web.WebViewNavigator
|
|
||||||
import compose.icons.FeatherIcons
|
import compose.icons.FeatherIcons
|
||||||
import compose.icons.feathericons.ChevronLeft
|
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 kotlinx.coroutines.launch
|
import io.github.kdroidfilter.webview.jsbridge.IJsMessageHandler
|
||||||
|
import io.github.kdroidfilter.webview.jsbridge.JsMessage
|
||||||
|
import io.github.kdroidfilter.webview.jsbridge.rememberWebViewJsBridge
|
||||||
|
import io.github.kdroidfilter.webview.web.WebView
|
||||||
|
import io.github.kdroidfilter.webview.web.WebViewNavigator
|
||||||
|
import io.github.kdroidfilter.webview.web.WebViewState
|
||||||
|
import io.github.kdroidfilter.webview.web.rememberWebViewNavigator
|
||||||
|
|
||||||
class PostMessageHandler(
|
class PostMessageHandler(
|
||||||
private val onMessageReceived: (String) -> Unit = {}
|
private val onMessageReceived: (String) -> Unit = {}
|
||||||
@ -98,7 +92,7 @@ fun PlatformWebViewScreen(webViewController: WebViewController) {
|
|||||||
)
|
)
|
||||||
}.apply {
|
}.apply {
|
||||||
this.content = webViewController.getWebContent()
|
this.content = webViewController.getWebContent()
|
||||||
platformWebviewConfig(this)
|
platformWebviewConfig(this, webViewController.currentPluginId)
|
||||||
}
|
}
|
||||||
|
|
||||||
val navigator = rememberWebViewNavigator()
|
val navigator = rememberWebViewNavigator()
|
||||||
|
|||||||
@ -141,7 +141,7 @@ open class ZiplinePluginService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val realHttpClientAPI = RealHttpClientAPI()
|
private val realHttpClientAPI = RealHttpClientAPI()
|
||||||
private val realWebViewAPI = RealWebViewAPI(scope, webViewController)
|
private val realWebViewAPI = RealWebViewAPI(scope, webViewController, pluginInfo.id)
|
||||||
|
|
||||||
private val persistedStorageAPI = RealPersistedStorageAPI(pluginInfo)
|
private val persistedStorageAPI = RealPersistedStorageAPI(pluginInfo)
|
||||||
private val cryptoAPI = RealCryptoAPI(scope.coroutineContext)
|
private val cryptoAPI = RealCryptoAPI(scope.coroutineContext)
|
||||||
|
|||||||
@ -22,26 +22,24 @@ import dev.krtirtho.plugin_interfaces.host_apis.WebViewAPI
|
|||||||
import dev.krtirtho.spotube.core.webview.WebViewController
|
import dev.krtirtho.spotube.core.webview.WebViewController
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.async
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.SharedFlow
|
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class RealWebViewAPI(
|
class RealWebViewAPI(
|
||||||
private val scope: CoroutineScope,
|
private val scope: CoroutineScope,
|
||||||
private val webViewController: WebViewController,
|
private val webViewController: WebViewController,
|
||||||
|
private val pluginId: String,
|
||||||
) : WebViewAPI {
|
) : WebViewAPI {
|
||||||
override fun navigateTo(url: String) {
|
override fun navigateTo(url: String) {
|
||||||
scope.launch(Dispatchers.Main) {
|
scope.launch(Dispatchers.Main) {
|
||||||
webViewController.navigateTo(url)
|
webViewController.navigateTo(url, pluginId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun navigateToHTML(html: String) {
|
override fun navigateToHTML(html: String) {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
webViewController.navigateToHTML(html)
|
webViewController.navigateToHTML(html, pluginId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -735,7 +735,7 @@ fun PluginScreen(
|
|||||||
selectedService.use { coreAPI.logout() }
|
selectedService.use { coreAPI.logout() }
|
||||||
}
|
}
|
||||||
// should clear webview data after logout
|
// should clear webview data after logout
|
||||||
scope.launch { webviewController.clearData() }
|
scope.launch { webviewController.clearData(plugin.id) }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
|
|||||||
@ -18,6 +18,24 @@
|
|||||||
package dev.krtirtho.spotube.core.webview
|
package dev.krtirtho.spotube.core.webview
|
||||||
|
|
||||||
import io.github.kdroidfilter.webview.web.WebViewState
|
import io.github.kdroidfilter.webview.web.WebViewState
|
||||||
|
import kotlinx.cinterop.ExperimentalForeignApi
|
||||||
|
import platform.Foundation.NSDate
|
||||||
|
import platform.Foundation.NSHTTPCookieStorage
|
||||||
|
import platform.Foundation.distantPast
|
||||||
|
import platform.WebKit.WKWebsiteDataStore
|
||||||
|
import platform.WebKit.WKWebsiteDataTypeCookies
|
||||||
|
import platform.WebKit.WKWebsiteDataTypeLocalStorage
|
||||||
|
|
||||||
actual fun platformWebviewConfig(webView: WebViewState) {
|
actual fun platformWebviewConfig(webView: WebViewState, pluginId: String?) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalForeignApi::class)
|
||||||
|
actual suspend fun platformClearWebviewData(pluginId: String?) {
|
||||||
|
if (pluginId == null) return
|
||||||
|
|
||||||
|
val dataStore = WKWebsiteDataStore.defaultDataStore()
|
||||||
|
val dataTypes = setOf(WKWebsiteDataTypeCookies, WKWebsiteDataTypeLocalStorage)
|
||||||
|
dataStore.removeDataOfTypes(dataTypes, NSDate.distantPast) {}
|
||||||
|
|
||||||
|
NSHTTPCookieStorage.sharedHTTPCookieStorage.removeCookiesSinceDate(NSDate.distantPast)
|
||||||
}
|
}
|
||||||
@ -19,13 +19,24 @@ package dev.krtirtho.spotube.core.webview
|
|||||||
|
|
||||||
import dev.krtirtho.spotube.core.paths.Paths
|
import dev.krtirtho.spotube.core.paths.Paths
|
||||||
import io.github.kdroidfilter.webview.web.WebViewState
|
import io.github.kdroidfilter.webview.web.WebViewState
|
||||||
import io.github.vinceglb.filekit.utils.div
|
import okio.FileSystem
|
||||||
import io.github.vinceglb.filekit.utils.toPath
|
import okio.Path.Companion.toPath
|
||||||
import org.koin.core.context.GlobalContext
|
import org.koin.core.context.GlobalContext
|
||||||
|
|
||||||
actual fun platformWebviewConfig(webView: WebViewState) {
|
actual fun platformWebviewConfig(webView: WebViewState, pluginId: String?) {
|
||||||
val paths = GlobalContext.get().get<Paths>()
|
val paths = GlobalContext.get().get<Paths>()
|
||||||
|
|
||||||
webView.webSettings.desktopWebSettings.dataDirectory =
|
val baseDir = "${paths.getApplicationCacheDirPath()}/webview_data".toPath()
|
||||||
(paths.getApplicationCacheDirPath().toPath() / "webview_data").toString()
|
val dataDir = if (pluginId != null) baseDir / pluginId else baseDir
|
||||||
|
webView.webSettings.desktopWebSettings.dataDirectory = dataDir.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
actual suspend fun platformClearWebviewData(pluginId: String?) {
|
||||||
|
if (pluginId == null) return
|
||||||
|
val paths = GlobalContext.get().get<Paths>()
|
||||||
|
val dataDirStr = "${paths.getApplicationCacheDirPath()}/webview_data/$pluginId"
|
||||||
|
val dataDir = dataDirStr.toPath()
|
||||||
|
if (FileSystem.SYSTEM.exists(dataDir)) {
|
||||||
|
FileSystem.SYSTEM.deleteRecursively(dataDir)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user