add incognito/desktop toggle in cookies webview & add reverse option when selecting items after sharing playlist
This commit is contained in:
parent
5f43da1e4e
commit
cfa700d6fc
10 changed files with 164 additions and 25 deletions
|
|
@ -67,4 +67,6 @@ interface ResultDao {
|
||||||
@Query("SELECT * from results WHERE id > :item1 AND id < :item2 ORDER BY id")
|
@Query("SELECT * from results WHERE id > :item1 AND id < :item2 ORDER BY id")
|
||||||
fun getResultsBetweenTwoItems(item1: Long, item2: Long) : List<ResultItem>
|
fun getResultsBetweenTwoItems(item1: Long, item2: Long) : List<ResultItem>
|
||||||
|
|
||||||
|
@Query("UPDATE results SET id = :newID where id = :id")
|
||||||
|
fun updateID(id: Long, newID: Long)
|
||||||
}
|
}
|
||||||
|
|
@ -370,6 +370,10 @@ class ResultRepository(private val resultDao: ResultDao, private val commandTemp
|
||||||
return resultDao.getAllByIDs(ids)
|
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> {
|
suspend fun getResultsFromSource(inputQuery: String, resetResults: Boolean, addToResults: Boolean = true, singleItem: Boolean = false) : List<ResultItem> {
|
||||||
return when(getQueryType(inputQuery)){
|
return when(getQueryType(inputQuery)){
|
||||||
SourceType.YOUTUBE_VIDEO -> {
|
SourceType.YOUTUBE_VIDEO -> {
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import com.deniscerri.ytdl.util.NotificationUtil
|
||||||
import com.yausername.youtubedl_android.YoutubeDLException
|
import com.yausername.youtubedl_android.YoutubeDLException
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.joinAll
|
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>?> {
|
fun getStreamingUrlAndChapters(url: String) : Pair<List<String>, List<ChapterItem>?> {
|
||||||
return repository.getStreamingUrlAndChapters(url)
|
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 }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -232,6 +232,10 @@ class SelectPlaylistItemsDialog : BottomSheetDialogFragment(), PlaylistAdapter.O
|
||||||
count.text = "${listAdapter.getCheckedItems().size} ${resources.getString(R.string.selected)}"
|
count.text = "${listAdapter.getCheckedItems().size} ${resources.getString(R.string.selected)}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
R.id.reverse -> {
|
||||||
|
resultItemIDs = resultViewModel.reverseResults(resultItemIDs)
|
||||||
|
reset()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
@ -251,7 +255,6 @@ class SelectPlaylistItemsDialog : BottomSheetDialogFragment(), PlaylistAdapter.O
|
||||||
toTextInput.isEnabled = !isLoading
|
toTextInput.isEnabled = !isLoading
|
||||||
|
|
||||||
items = it
|
items = it
|
||||||
resultItemIDs = items.map { itm -> itm.id }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,10 @@ import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.webkit.CookieManager
|
import android.webkit.CookieManager
|
||||||
|
import android.webkit.WebSettings
|
||||||
|
import android.webkit.WebStorage
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
|
import android.webkit.WebViewDatabase
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
|
@ -15,6 +18,7 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.ComposeView
|
import androidx.compose.ui.platform.ComposeView
|
||||||
|
import androidx.core.view.children
|
||||||
import androidx.core.view.forEach
|
import androidx.core.view.forEach
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
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.AppBarLayout
|
||||||
import com.google.android.material.appbar.MaterialToolbar
|
import com.google.android.material.appbar.MaterialToolbar
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
@ -57,27 +62,52 @@ class WebViewActivity : BaseActivity() {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
val appbar = findViewById<AppBarLayout>(R.id.webview_appbarlayout)
|
val appbar = findViewById<AppBarLayout>(R.id.webview_appbarlayout)
|
||||||
toolbar = appbar.findViewById(R.id.webviewToolbar)
|
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)
|
generateBtn = toolbar.findViewById(R.id.generate)
|
||||||
webViewCompose = findViewById(R.id.webview_compose)
|
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 = CookieManager.getInstance()
|
||||||
cookieManager.removeAllCookies(null)
|
cookieManager.removeAllCookies(null)
|
||||||
|
cookieManager.flush()
|
||||||
|
|
||||||
preferences = PreferenceManager.getDefaultSharedPreferences(this@WebViewActivity)
|
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")
|
@SuppressLint("SetJavaScriptEnabled")
|
||||||
@Composable
|
@Composable
|
||||||
fun WebViewView() {
|
fun WebViewView() {
|
||||||
|
|
|
||||||
5
app/src/main/res/drawable/baseline_compare_arrows_24.xml
Normal file
5
app/src/main/res/drawable/baseline_compare_arrows_24.xml
Normal 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>
|
||||||
|
|
@ -22,18 +22,23 @@
|
||||||
app:menu="@menu/select_playlist_menu"
|
app:menu="@menu/select_playlist_menu"
|
||||||
android:layout_gravity="bottom">
|
android:layout_gravity="bottom">
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_marginStart="50dp"
|
android:layout_marginStart="50dp"
|
||||||
|
android:layout_marginEnd="50dp"
|
||||||
android:layout_marginVertical="10dp"
|
android:layout_marginVertical="10dp"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/from_textinput"
|
android:id="@+id/from_textinput"
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox.Dense"
|
style="@style/Widget.Material3.TextInputLayout.FilledBox.Dense"
|
||||||
android:layout_width="70dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="10dp"
|
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">
|
android:hint="@string/start">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
|
@ -47,11 +52,15 @@
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/to_textinput"
|
android:id="@+id/to_textinput"
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox.Dense"
|
style="@style/Widget.Material3.TextInputLayout.FilledBox.Dense"
|
||||||
android:layout_width="70dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="@string/end"
|
android:hint="@string/end"
|
||||||
|
app:layout_constraintHorizontal_weight="1"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
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
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
@ -61,7 +70,7 @@
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
</com.google.android.material.bottomappbar.BottomAppBar>
|
</com.google.android.material.bottomappbar.BottomAppBar>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,4 +14,11 @@
|
||||||
android:icon="@drawable/ic_terminal"
|
android:icon="@drawable/ic_terminal"
|
||||||
app:showAsAction="never"
|
app:showAsAction="never"
|
||||||
android:id="@+id/invert_selected"/>
|
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>
|
</menu>
|
||||||
|
|
@ -1,10 +1,24 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<menu xmlns:tools="http://schemas.android.com/tools"
|
<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
|
<item
|
||||||
android:id="@+id/get_data_sync_id"
|
android:id="@+id/get_data_sync_id"
|
||||||
android:title="Get Data Sync ID"
|
android:title="Get Data Sync ID"
|
||||||
tools:ignore="HardcodedText" />
|
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>
|
</menu>
|
||||||
|
|
@ -480,4 +480,5 @@
|
||||||
<string name="select_between_desc">Specify the range of items to select</string>
|
<string name="select_between_desc">Specify the range of items to select</string>
|
||||||
<string name="potoken">PO Token</string>
|
<string name="potoken">PO Token</string>
|
||||||
<string name="web_client_po_token">Web Client PO Token</string>
|
<string name="web_client_po_token">Web Client PO Token</string>
|
||||||
|
<string name="reverse">Reverse</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue