add incognito/desktop toggle in cookies webview & add reverse option when selecting items after sharing playlist

This commit is contained in:
deniscerri 2025-07-12 23:36:39 +02:00
parent 5f43da1e4e
commit cfa700d6fc
No known key found for this signature in database
GPG key ID: 95C43D517D830350
10 changed files with 164 additions and 25 deletions

View file

@ -67,4 +67,6 @@ interface ResultDao {
@Query("SELECT * from results WHERE id > :item1 AND id < :item2 ORDER BY id")
fun getResultsBetweenTwoItems(item1: Long, item2: Long) : List<ResultItem>
@Query("UPDATE results SET id = :newID where id = :id")
fun updateID(id: Long, newID: Long)
}

View file

@ -370,6 +370,10 @@ class ResultRepository(private val resultDao: ResultDao, private val commandTemp
return resultDao.getAllByIDs(ids)
}
fun updateID(id: Long, newID: Long) {
resultDao.updateID(id, newID)
}
suspend fun getResultsFromSource(inputQuery: String, resetResults: Boolean, addToResults: Boolean = true, singleItem: Boolean = false) : List<ResultItem> {
return when(getQueryType(inputQuery)){
SourceType.YOUTUBE_VIDEO -> {

View file

@ -26,6 +26,7 @@ import com.deniscerri.ytdl.util.NotificationUtil
import com.yausername.youtubedl_android.YoutubeDLException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.joinAll
@ -383,4 +384,23 @@ class ResultViewModel(private val application: Application) : AndroidViewModel(a
fun getStreamingUrlAndChapters(url: String) : Pair<List<String>, List<ChapterItem>?> {
return repository.getStreamingUrlAndChapters(url)
}
fun reverseResults(resultItems: List<Long>): List<Long> {
val latestResult = resultItems.max()
val newIdsMap = mutableListOf<Pair<Long, Long>>()
var i = 0
resultItems.reversed().forEach {
newIdsMap.add(Pair(it, latestResult + (++i)))
}
viewModelScope.launch(Dispatchers.IO) {
delay(1000)
newIdsMap.forEach {
repository.updateID(it.first, it.second)
}
}
return newIdsMap.map { it.second }
}
}

View file

@ -232,6 +232,10 @@ class SelectPlaylistItemsDialog : BottomSheetDialogFragment(), PlaylistAdapter.O
count.text = "${listAdapter.getCheckedItems().size} ${resources.getString(R.string.selected)}"
}
}
R.id.reverse -> {
resultItemIDs = resultViewModel.reverseResults(resultItemIDs)
reset()
}
}
true
}
@ -251,7 +255,6 @@ class SelectPlaylistItemsDialog : BottomSheetDialogFragment(), PlaylistAdapter.O
toTextInput.isEnabled = !isLoading
items = it
resultItemIDs = items.map { itm -> itm.id }
}
}

View file

@ -6,7 +6,10 @@ import android.os.Build
import android.os.Bundle
import android.view.MenuItem
import android.webkit.CookieManager
import android.webkit.WebSettings
import android.webkit.WebStorage
import android.webkit.WebView
import android.webkit.WebViewDatabase
import android.widget.Toast
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
@ -15,6 +18,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import androidx.core.view.children
import androidx.core.view.forEach
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
@ -32,6 +36,7 @@ import com.google.accompanist.web.rememberWebViewState
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.appbar.MaterialToolbar
import com.google.android.material.button.MaterialButton
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@ -57,27 +62,52 @@ class WebViewActivity : BaseActivity() {
lifecycleScope.launch {
val appbar = findViewById<AppBarLayout>(R.id.webview_appbarlayout)
toolbar = appbar.findViewById(R.id.webviewToolbar)
if (!url.isYoutubeURL()) {
toolbar.menu.forEach { it.isVisible = false }
}else {
toolbar.setOnMenuItemClickListener { m : MenuItem ->
when(m.itemId) {
R.id.get_data_sync_id -> {
webView?.evaluateJavascript("ytcfg.get('DATASYNC_ID')") { id ->
UiUtil.copyToClipboard(id.replace("\"", ""), this@WebViewActivity)
}
}
else -> {}
}
true
}
}
generateBtn = toolbar.findViewById(R.id.generate)
webViewCompose = findViewById(R.id.webview_compose)
if (!url.isYoutubeURL()) {
toolbar.menu.children.firstOrNull { it.itemId == R.id.get_data_sync_id }?.isVisible = false
}
toolbar.setOnMenuItemClickListener { m : MenuItem ->
when(m.itemId) {
R.id.get_data_sync_id -> {
webView?.evaluateJavascript("ytcfg.get('DATASYNC_ID')") { id ->
UiUtil.copyToClipboard(id.replace("\"", ""), this@WebViewActivity)
}
}
R.id.incognito -> {
m.isChecked = !m.isChecked
webView.apply {
if (this == null) {
m.isChecked = false
return@apply
}
configureIncognito(this, m.isChecked)
this.reload()
}
}
R.id.desktop -> {
m.isChecked = !m.isChecked
webView.apply {
if (this == null) {
m.isChecked = false
return@apply
}
configureDesktopMode(this, m.isChecked)
this.reload()
}
}
else -> {}
}
true
}
cookieManager = CookieManager.getInstance()
cookieManager.removeAllCookies(null)
cookieManager.flush()
preferences = PreferenceManager.getDefaultSharedPreferences(this@WebViewActivity)
@ -134,6 +164,50 @@ class WebViewActivity : BaseActivity() {
}
private fun configureIncognito(webView: WebView, incognito: Boolean) {
if (!incognito) {
webView.settings.run {
cacheMode = WebSettings.LOAD_DEFAULT
domStorageEnabled = true
setGeolocationEnabled(true)
}
}else {
webView.settings.run {
cacheMode = WebSettings.LOAD_NO_CACHE
domStorageEnabled = false
setGeolocationEnabled(false)
}
}
if (incognito) {
WebStorage.getInstance().deleteAllData()
}
if (incognito) {
webView.apply {
clearHistory()
clearCache(true)
clearFormData()
}
}
}
private fun configureDesktopMode(webView: WebView, desktop: Boolean) {
webView.settings.apply {
if (desktop) {
userAgentString = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 " +
"(KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
useWideViewPort = true
loadWithOverviewMode = true
} else {
userAgentString = WebSettings.getDefaultUserAgent(webView.context)
useWideViewPort = false
loadWithOverviewMode = false
}
}
}
@SuppressLint("SetJavaScriptEnabled")
@Composable
fun WebViewView() {

View file

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:tint="#FF0000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M9.01,14H2v2h7.01v3L13,15l-3.99,-4V14zM14.99,13v-3H22V8h-7.01V5L11,9L14.99,13z"/>
</vector>

View file

@ -22,18 +22,23 @@
app:menu="@menu/select_playlist_menu"
android:layout_gravity="bottom">
<LinearLayout
android:layout_width="wrap_content"
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_marginStart="50dp"
android:layout_marginEnd="50dp"
android:layout_marginVertical="10dp"
android:layout_height="wrap_content">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/from_textinput"
style="@style/Widget.Material3.TextInputLayout.FilledBox.Dense"
android:layout_width="70dp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintEnd_toStartOf="@id/to_textinput"
app:layout_constraintStart_toStartOf="parent"
android:hint="@string/start">
<com.google.android.material.textfield.TextInputEditText
@ -47,11 +52,15 @@
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/to_textinput"
style="@style/Widget.Material3.TextInputLayout.FilledBox.Dense"
android:layout_width="70dp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="@string/end"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/colon">
app:layout_constraintStart_toEndOf="@id/from_textinput"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
>
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
@ -61,7 +70,7 @@
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.bottomappbar.BottomAppBar>

View file

@ -14,4 +14,11 @@
android:icon="@drawable/ic_terminal"
app:showAsAction="never"
android:id="@+id/invert_selected"/>
<item
android:id="@+id/reverse"
android:title="@string/reverse"
android:icon="@drawable/baseline_compare_arrows_24"
app:showAsAction="never" />
</menu>

View file

@ -1,10 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/get_data_sync_id"
android:title="Get Data Sync ID"
tools:ignore="HardcodedText" />
<item
android:id="@+id/incognito"
android:title="@string/incognito"
android:checkable="true"
app:showAsAction="never" />
<item
android:id="@+id/desktop"
android:title="Desktop"
android:checkable="true"
app:showAsAction="never" />
</menu>

View file

@ -480,4 +480,5 @@
<string name="select_between_desc">Specify the range of items to select</string>
<string name="potoken">PO Token</string>
<string name="web_client_po_token">Web Client PO Token</string>
<string name="reverse">Reverse</string>
</resources>