implemented cookies
This commit is contained in:
parent
f5ad2aee1d
commit
6fc87df98d
23 changed files with 1241 additions and 5 deletions
421
app/schemas/com.deniscerri.ytdlnis.database.DBManager/3.json
Normal file
421
app/schemas/com.deniscerri.ytdlnis.database.DBManager/3.json
Normal file
|
|
@ -0,0 +1,421 @@
|
||||||
|
{
|
||||||
|
"formatVersion": 1,
|
||||||
|
"database": {
|
||||||
|
"version": 3,
|
||||||
|
"identityHash": "f911bed4915605d5b09bfd82892e2d7a",
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"tableName": "results",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `duration` TEXT NOT NULL, `thumb` TEXT NOT NULL, `website` TEXT NOT NULL, `playlistTitle` TEXT NOT NULL, `formats` TEXT NOT NULL, `creationTime` INTEGER NOT NULL)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "url",
|
||||||
|
"columnName": "url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "title",
|
||||||
|
"columnName": "title",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "author",
|
||||||
|
"columnName": "author",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "duration",
|
||||||
|
"columnName": "duration",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "thumb",
|
||||||
|
"columnName": "thumb",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "website",
|
||||||
|
"columnName": "website",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "playlistTitle",
|
||||||
|
"columnName": "playlistTitle",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "formats",
|
||||||
|
"columnName": "formats",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "creationTime",
|
||||||
|
"columnName": "creationTime",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "history",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `duration` TEXT NOT NULL, `thumb` TEXT NOT NULL, `type` TEXT NOT NULL, `time` INTEGER NOT NULL, `downloadPath` TEXT NOT NULL, `website` TEXT NOT NULL, `format` TEXT NOT NULL)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "url",
|
||||||
|
"columnName": "url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "title",
|
||||||
|
"columnName": "title",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "author",
|
||||||
|
"columnName": "author",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "duration",
|
||||||
|
"columnName": "duration",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "thumb",
|
||||||
|
"columnName": "thumb",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "type",
|
||||||
|
"columnName": "type",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "time",
|
||||||
|
"columnName": "time",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "downloadPath",
|
||||||
|
"columnName": "downloadPath",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "website",
|
||||||
|
"columnName": "website",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "format",
|
||||||
|
"columnName": "format",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "downloads",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `thumb` TEXT NOT NULL, `duration` TEXT NOT NULL, `type` TEXT NOT NULL, `format` TEXT NOT NULL, `downloadSections` TEXT NOT NULL DEFAULT '', `allFormats` TEXT NOT NULL, `downloadPath` TEXT NOT NULL, `website` TEXT NOT NULL, `downloadSize` TEXT NOT NULL, `playlistTitle` TEXT NOT NULL, `audioPreferences` TEXT NOT NULL, `videoPreferences` TEXT NOT NULL, `customFileNameTemplate` TEXT NOT NULL, `SaveThumb` INTEGER NOT NULL, `status` TEXT NOT NULL DEFAULT 'Queued', `downloadStartTime` INTEGER NOT NULL DEFAULT 0)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "url",
|
||||||
|
"columnName": "url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "title",
|
||||||
|
"columnName": "title",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "author",
|
||||||
|
"columnName": "author",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "thumb",
|
||||||
|
"columnName": "thumb",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "duration",
|
||||||
|
"columnName": "duration",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "type",
|
||||||
|
"columnName": "type",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "format",
|
||||||
|
"columnName": "format",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "downloadSections",
|
||||||
|
"columnName": "downloadSections",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "''"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "allFormats",
|
||||||
|
"columnName": "allFormats",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "downloadPath",
|
||||||
|
"columnName": "downloadPath",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "website",
|
||||||
|
"columnName": "website",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "downloadSize",
|
||||||
|
"columnName": "downloadSize",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "playlistTitle",
|
||||||
|
"columnName": "playlistTitle",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "audioPreferences",
|
||||||
|
"columnName": "audioPreferences",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "videoPreferences",
|
||||||
|
"columnName": "videoPreferences",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "customFileNameTemplate",
|
||||||
|
"columnName": "customFileNameTemplate",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "SaveThumb",
|
||||||
|
"columnName": "SaveThumb",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "status",
|
||||||
|
"columnName": "status",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "'Queued'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "downloadStartTime",
|
||||||
|
"columnName": "downloadStartTime",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "commandTemplates",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "title",
|
||||||
|
"columnName": "title",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "content",
|
||||||
|
"columnName": "content",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "searchHistory",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `query` TEXT NOT NULL)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "query",
|
||||||
|
"columnName": "query",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "templateShortcuts",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `content` TEXT NOT NULL)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "content",
|
||||||
|
"columnName": "content",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "cookies",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `content` TEXT NOT NULL)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "url",
|
||||||
|
"columnName": "url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "content",
|
||||||
|
"columnName": "content",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"views": [],
|
||||||
|
"setupQueries": [
|
||||||
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'f911bed4915605d5b09bfd82892e2d7a')"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -144,6 +144,32 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".ui.more.CookiesActivity"
|
||||||
|
android:configChanges="layoutDirection|locale"
|
||||||
|
android:exported="true"
|
||||||
|
android:parentActivityName=".MainActivity"
|
||||||
|
android:windowSoftInputMode="adjustResize">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="ytdlnis.CookiesActivity" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".ui.more.WebViewActivity"
|
||||||
|
android:configChanges="layoutDirection|locale"
|
||||||
|
android:exported="true"
|
||||||
|
android:parentActivityName=".MainActivity"
|
||||||
|
android:windowSoftInputMode="adjustResize">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="ytdlnis.WebViewActivity" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
<receiver android:name=".receiver.CancelDownloadNotificationReceiver" />
|
<receiver android:name=".receiver.CancelDownloadNotificationReceiver" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.navigation.fragment.NavHostFragment
|
import androidx.navigation.fragment.NavHostFragment
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.navigation.ui.setupWithNavController
|
import androidx.navigation.ui.setupWithNavController
|
||||||
|
import com.deniscerri.ytdlnis.database.viewmodel.CookieViewModel
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
||||||
import com.deniscerri.ytdlnis.ui.HomeFragment
|
import com.deniscerri.ytdlnis.ui.HomeFragment
|
||||||
import com.deniscerri.ytdlnis.ui.downloads.DownloadQueueActivity
|
import com.deniscerri.ytdlnis.ui.downloads.DownloadQueueActivity
|
||||||
|
|
@ -48,6 +49,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
lateinit var context: Context
|
lateinit var context: Context
|
||||||
private lateinit var preferences: SharedPreferences
|
private lateinit var preferences: SharedPreferences
|
||||||
private lateinit var resultViewModel: ResultViewModel
|
private lateinit var resultViewModel: ResultViewModel
|
||||||
|
private lateinit var cookieViewModel: CookieViewModel
|
||||||
private lateinit var bottomNav: BottomNavigationView
|
private lateinit var bottomNav: BottomNavigationView
|
||||||
private lateinit var navHostFragment : NavHostFragment
|
private lateinit var navHostFragment : NavHostFragment
|
||||||
|
|
||||||
|
|
@ -58,6 +60,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
context = baseContext
|
context = baseContext
|
||||||
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
||||||
|
cookieViewModel = ViewModelProvider(this)[CookieViewModel::class.java]
|
||||||
preferences = context.getSharedPreferences("root_preferences", MODE_PRIVATE)
|
preferences = context.getSharedPreferences("root_preferences", MODE_PRIVATE)
|
||||||
|
|
||||||
if (preferences.getBoolean("incognito", false)){
|
if (preferences.getBoolean("incognito", false)){
|
||||||
|
|
@ -99,6 +102,10 @@ class MainActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cookieViewModel.getCookiesFromDB().getOrNull()?.let{
|
||||||
|
File(cacheDir, "cookies.txt").apply { writeText(it) }
|
||||||
|
}
|
||||||
|
|
||||||
val intent = intent
|
val intent = intent
|
||||||
handleIntents(intent)
|
handleIntents(intent)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
package com.deniscerri.ytdlnis.adapter
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
import androidx.recyclerview.widget.AsyncDifferConfig
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.deniscerri.ytdlnis.R
|
||||||
|
import com.deniscerri.ytdlnis.database.models.CookieItem
|
||||||
|
|
||||||
|
class CookieAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<CookieItem?, CookieAdapter.ViewHolder>(AsyncDifferConfig.Builder(DIFF_CALLBACK).build()) {
|
||||||
|
private val onItemClickListener: OnItemClickListener
|
||||||
|
private val activity: Activity
|
||||||
|
|
||||||
|
init {
|
||||||
|
this.onItemClickListener = onItemClickListener
|
||||||
|
this.activity = activity
|
||||||
|
}
|
||||||
|
|
||||||
|
class ViewHolder(itemView: View, onItemClickListener: OnItemClickListener?) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
val item: ConstraintLayout
|
||||||
|
|
||||||
|
init {
|
||||||
|
item = itemView.findViewById(R.id.command_template_item_constraint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
val cardView = LayoutInflater.from(parent.context)
|
||||||
|
.inflate(R.layout.command_template_item, parent, false)
|
||||||
|
return ViewHolder(cardView, onItemClickListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
|
val item = getItem(position)
|
||||||
|
val card = holder.item
|
||||||
|
|
||||||
|
val title = card.findViewById<TextView>(R.id.title)
|
||||||
|
title.text = item?.url
|
||||||
|
|
||||||
|
val content = card.findViewById<TextView>(R.id.content)
|
||||||
|
content.visibility = View.GONE
|
||||||
|
|
||||||
|
card.setOnClickListener {
|
||||||
|
onItemClickListener.onItemClick(item!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
card.setOnLongClickListener {
|
||||||
|
onItemClickListener.onDelete(item!!); true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OnItemClickListener {
|
||||||
|
fun onItemClick(commandTemplate: CookieItem)
|
||||||
|
fun onSelected(commandTemplate: CookieItem)
|
||||||
|
fun onDelete(commandTemplate: CookieItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val DIFF_CALLBACK: DiffUtil.ItemCallback<CookieItem> = object : DiffUtil.ItemCallback<CookieItem>() {
|
||||||
|
override fun areItemsTheSame(oldItem: CookieItem, newItem: CookieItem): Boolean {
|
||||||
|
return oldItem.id == newItem.id
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItem: CookieItem, newItem: CookieItem): Boolean {
|
||||||
|
return oldItem.id == newItem.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,16 +2,16 @@ package com.deniscerri.ytdlnis.database
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.room.*
|
import androidx.room.*
|
||||||
import androidx.room.migration.AutoMigrationSpec
|
|
||||||
import com.deniscerri.ytdlnis.database.dao.*
|
import com.deniscerri.ytdlnis.database.dao.*
|
||||||
import com.deniscerri.ytdlnis.database.models.*
|
import com.deniscerri.ytdlnis.database.models.*
|
||||||
|
|
||||||
@TypeConverters(Converters::class)
|
@TypeConverters(Converters::class)
|
||||||
@Database(
|
@Database(
|
||||||
entities = [ResultItem::class, HistoryItem::class, DownloadItem::class, CommandTemplate::class, SearchHistoryItem::class, TemplateShortcut::class],
|
entities = [ResultItem::class, HistoryItem::class, DownloadItem::class, CommandTemplate::class, SearchHistoryItem::class, TemplateShortcut::class, CookieItem::class],
|
||||||
version = 2,
|
version = 3,
|
||||||
autoMigrations = [
|
autoMigrations = [
|
||||||
AutoMigration (from = 1, to = 2)
|
AutoMigration (from = 1, to = 2),
|
||||||
|
AutoMigration (from = 2, to = 3)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
abstract class DBManager : RoomDatabase(){
|
abstract class DBManager : RoomDatabase(){
|
||||||
|
|
@ -20,6 +20,7 @@ abstract class DBManager : RoomDatabase(){
|
||||||
abstract val downloadDao : DownloadDao
|
abstract val downloadDao : DownloadDao
|
||||||
abstract val commandTemplateDao : CommandTemplateDao
|
abstract val commandTemplateDao : CommandTemplateDao
|
||||||
abstract val searchHistoryDao: SearchHistoryDao
|
abstract val searchHistoryDao: SearchHistoryDao
|
||||||
|
abstract val cookieDao: CookieDao
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
//prevents multiple instances of db getting created at the same time
|
//prevents multiple instances of db getting created at the same time
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.deniscerri.ytdlnis.database.dao
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.room.*
|
||||||
|
import com.deniscerri.ytdlnis.database.models.CookieItem
|
||||||
|
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface CookieDao {
|
||||||
|
@Query("SELECT * FROM cookies ORDER BY id DESC")
|
||||||
|
fun getAllCookies() : List<CookieItem>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM cookies ORDER BY id DESC")
|
||||||
|
fun getAllCookiesLiveData() : LiveData<List<CookieItem>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM cookies WHERE url=:url")
|
||||||
|
fun checkIfExistsWithSameURL(url: String) : CookieItem
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||||
|
suspend fun insert(item: CookieItem)
|
||||||
|
|
||||||
|
@Query("DELETE FROM cookies")
|
||||||
|
suspend fun deleteAll()
|
||||||
|
|
||||||
|
@Query("DELETE FROM cookies WHERE id=:itemId")
|
||||||
|
suspend fun delete(itemId: Long)
|
||||||
|
|
||||||
|
@Update(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
suspend fun update(item: CookieItem)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.deniscerri.ytdlnis.database.models
|
||||||
|
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
|
@Entity(tableName = "cookies")
|
||||||
|
data class CookieItem(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
var id: Long,
|
||||||
|
var url: String,
|
||||||
|
var content: String
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.deniscerri.ytdlnis.database.repository
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import com.deniscerri.ytdlnis.database.dao.CookieDao
|
||||||
|
import com.deniscerri.ytdlnis.database.models.CookieItem
|
||||||
|
|
||||||
|
class CookieRepository(private val cookieDao: CookieDao) {
|
||||||
|
val items : LiveData<List<CookieItem>> = cookieDao.getAllCookiesLiveData()
|
||||||
|
|
||||||
|
fun getAll() : List<CookieItem> {
|
||||||
|
return cookieDao.getAllCookies()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
suspend fun insert(item: CookieItem){
|
||||||
|
try{
|
||||||
|
cookieDao.checkIfExistsWithSameURL(item.url)
|
||||||
|
}catch(e: Exception){
|
||||||
|
cookieDao.insert(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun delete(item: CookieItem){
|
||||||
|
cookieDao.delete(item.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
suspend fun deleteAll(){
|
||||||
|
cookieDao.deleteAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun update(item: CookieItem){
|
||||||
|
cookieDao.update(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,130 @@
|
||||||
|
package com.deniscerri.ytdlnis.database.viewmodel
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Application
|
||||||
|
import android.content.ClipboardManager
|
||||||
|
import android.content.Context
|
||||||
|
import android.database.sqlite.SQLiteDatabase
|
||||||
|
import android.database.sqlite.SQLiteDatabase.OPEN_READONLY
|
||||||
|
import android.webkit.CookieManager
|
||||||
|
import androidx.lifecycle.AndroidViewModel
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.deniscerri.ytdlnis.database.DBManager
|
||||||
|
import com.deniscerri.ytdlnis.database.models.CommandTemplateExport
|
||||||
|
import com.deniscerri.ytdlnis.database.models.CookieItem
|
||||||
|
import com.deniscerri.ytdlnis.database.repository.CookieRepository
|
||||||
|
import com.deniscerri.ytdlnis.ui.more.WebViewActivity
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import kotlinx.serialization.encodeToString
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
|
class CookieViewModel(private val application: Application) : AndroidViewModel(application) {
|
||||||
|
private val repository: CookieRepository
|
||||||
|
val items: LiveData<List<CookieItem>>
|
||||||
|
private val jsonFormat = Json { prettyPrint = true }
|
||||||
|
|
||||||
|
|
||||||
|
init {
|
||||||
|
val dao = DBManager.getInstance(application).cookieDao
|
||||||
|
repository = CookieRepository(dao)
|
||||||
|
items = repository.items
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAll(): List<CookieItem> {
|
||||||
|
return repository.getAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun insert(item: CookieItem) = viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
repository.insert(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun delete(item: CookieItem) = viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
repository.delete(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteAll() = viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
repository.deleteAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(item: CookieItem) = viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
repository.update(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
object CookieObject {
|
||||||
|
const val NAME = "name"
|
||||||
|
const val VALUE = "value"
|
||||||
|
const val SECURE = "is_secure"
|
||||||
|
const val EXPIRY = "expires_utc"
|
||||||
|
const val HOST = "host_key"
|
||||||
|
const val PATH = "path"
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SdCardPath")
|
||||||
|
fun getCookiesFromDB() : Result<String> = kotlin.runCatching {
|
||||||
|
CookieManager.getInstance().run {
|
||||||
|
if (!hasCookies()) throw Exception("There is no cookies in the database!")
|
||||||
|
flush()
|
||||||
|
}
|
||||||
|
SQLiteDatabase.openDatabase(
|
||||||
|
"/data/data/com.deniscerri.ytdl/app_webview/Default/Cookies", null, OPEN_READONLY
|
||||||
|
).run {
|
||||||
|
val projection = arrayOf(
|
||||||
|
CookieObject.HOST,
|
||||||
|
CookieObject.EXPIRY,
|
||||||
|
CookieObject.PATH,
|
||||||
|
CookieObject.NAME,
|
||||||
|
CookieObject.VALUE,
|
||||||
|
CookieObject.SECURE
|
||||||
|
)
|
||||||
|
val cookieList = mutableListOf<WebViewActivity.CookieItem>()
|
||||||
|
query(
|
||||||
|
"cookies", projection, null, null, null, null, null
|
||||||
|
).run {
|
||||||
|
while (moveToNext()) {
|
||||||
|
val expiry = getLong(getColumnIndexOrThrow(CookieObject.EXPIRY))
|
||||||
|
val name = getString(getColumnIndexOrThrow(CookieObject.NAME))
|
||||||
|
val value = getString(getColumnIndexOrThrow(CookieObject.VALUE))
|
||||||
|
val path = getString(getColumnIndexOrThrow(CookieObject.PATH))
|
||||||
|
val secure = getLong(getColumnIndexOrThrow(CookieObject.SECURE)) == 1L
|
||||||
|
val hostKey = getString(getColumnIndexOrThrow(CookieObject.HOST))
|
||||||
|
|
||||||
|
val host = if (hostKey[0] != '.') ".$hostKey" else hostKey
|
||||||
|
cookieList.add(
|
||||||
|
WebViewActivity.CookieItem(
|
||||||
|
domain = host,
|
||||||
|
name = name,
|
||||||
|
value = value,
|
||||||
|
path = path,
|
||||||
|
secure = secure,
|
||||||
|
expiry = expiry
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
close()
|
||||||
|
val header = "# Netscape HTTP Cookie File\n" +
|
||||||
|
"# WebView Generated by the YTDLnis app\n"
|
||||||
|
cookieList.fold(StringBuilder(header)) { acc, cookie ->
|
||||||
|
acc.append(cookie.toNetscapeFormat()).append("\n")
|
||||||
|
}.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exportToClipboard() = viewModelScope.launch {
|
||||||
|
try{
|
||||||
|
val clipboard: ClipboardManager =
|
||||||
|
application.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
|
|
||||||
|
getCookiesFromDB().getOrNull()?.let {
|
||||||
|
clipboard.setText(it)
|
||||||
|
}
|
||||||
|
}catch (e: Exception){
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -28,6 +28,7 @@ import com.deniscerri.ytdlnis.MainActivity
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||||
|
import com.deniscerri.ytdlnis.database.viewmodel.CookieViewModel
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
||||||
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadBottomSheetDialog
|
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadBottomSheetDialog
|
||||||
|
|
@ -45,6 +46,7 @@ class ShareActivity : AppCompatActivity() {
|
||||||
lateinit var context: Context
|
lateinit var context: Context
|
||||||
private lateinit var resultViewModel: ResultViewModel
|
private lateinit var resultViewModel: ResultViewModel
|
||||||
private lateinit var downloadViewModel: DownloadViewModel
|
private lateinit var downloadViewModel: DownloadViewModel
|
||||||
|
private lateinit var cookieViewModel: CookieViewModel
|
||||||
private lateinit var sharedPreferences: SharedPreferences
|
private lateinit var sharedPreferences: SharedPreferences
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -73,8 +75,13 @@ class ShareActivity : AppCompatActivity() {
|
||||||
context = baseContext
|
context = baseContext
|
||||||
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
||||||
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||||
|
cookieViewModel = ViewModelProvider(this)[CookieViewModel::class.java]
|
||||||
sharedPreferences = getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
sharedPreferences = getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
||||||
|
|
||||||
|
cookieViewModel.getCookiesFromDB().getOrNull()?.let{
|
||||||
|
File(cacheDir, "cookies.txt").apply { writeText(it) }
|
||||||
|
}
|
||||||
|
|
||||||
val intent = intent
|
val intent = intent
|
||||||
handleIntents(intent)
|
handleIntents(intent)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,149 @@
|
||||||
|
package com.deniscerri.ytdlnis.ui.more
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.DialogInterface
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.inputmethod.InputMethodManager
|
||||||
|
import android.widget.EditText
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.deniscerri.ytdlnis.R
|
||||||
|
import com.deniscerri.ytdlnis.adapter.CookieAdapter
|
||||||
|
import com.deniscerri.ytdlnis.database.models.CookieItem
|
||||||
|
import com.deniscerri.ytdlnis.database.viewmodel.CookieViewModel
|
||||||
|
import com.deniscerri.ytdlnis.util.FileUtil
|
||||||
|
import com.deniscerri.ytdlnis.util.UiUtil
|
||||||
|
import com.google.android.material.appbar.MaterialToolbar
|
||||||
|
import com.google.android.material.chip.Chip
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import java.io.File
|
||||||
|
import java.net.CookieManager
|
||||||
|
|
||||||
|
|
||||||
|
class CookiesActivity : AppCompatActivity(), CookieAdapter.OnItemClickListener {
|
||||||
|
private lateinit var recyclerView: RecyclerView
|
||||||
|
private lateinit var listAdapter: CookieAdapter
|
||||||
|
private lateinit var topAppBar: MaterialToolbar
|
||||||
|
private lateinit var cookiesViewModel: CookieViewModel
|
||||||
|
private lateinit var uiUtil: UiUtil
|
||||||
|
var context: Context? = null
|
||||||
|
|
||||||
|
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_cookies)
|
||||||
|
context = baseContext
|
||||||
|
|
||||||
|
topAppBar = findViewById(R.id.logs_toolbar)
|
||||||
|
topAppBar.setNavigationOnClickListener { onBackPressedDispatcher.onBackPressed() }
|
||||||
|
|
||||||
|
listAdapter =
|
||||||
|
CookieAdapter(
|
||||||
|
this,
|
||||||
|
this@CookiesActivity
|
||||||
|
)
|
||||||
|
recyclerView = findViewById(R.id.template_recyclerview)
|
||||||
|
recyclerView.layoutManager = LinearLayoutManager(context)
|
||||||
|
recyclerView.adapter = listAdapter
|
||||||
|
|
||||||
|
uiUtil = UiUtil(FileUtil())
|
||||||
|
|
||||||
|
cookiesViewModel = ViewModelProvider(this)[CookieViewModel::class.java]
|
||||||
|
cookiesViewModel.items.observe(this) {
|
||||||
|
listAdapter.submitList(it)
|
||||||
|
}
|
||||||
|
initMenu()
|
||||||
|
initChips()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initMenu() {
|
||||||
|
topAppBar.setOnMenuItemClickListener { m: MenuItem ->
|
||||||
|
when (m.itemId) {
|
||||||
|
R.id.delete_cookies -> {
|
||||||
|
val deleteDialog = MaterialAlertDialogBuilder(this)
|
||||||
|
deleteDialog.setTitle(getString(R.string.confirm_delete_history))
|
||||||
|
deleteDialog.setMessage(getString(R.string.confirm_delete_cookies_desc))
|
||||||
|
deleteDialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, _: Int -> dialogInterface.cancel() }
|
||||||
|
deleteDialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int ->
|
||||||
|
android.webkit.CookieManager.getInstance().removeAllCookies(null)
|
||||||
|
kotlin.runCatching {
|
||||||
|
File(cacheDir, "cookies.txt").apply { writeText("") }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
deleteDialog.show()
|
||||||
|
}
|
||||||
|
R.id.export_clipboard -> {
|
||||||
|
cookiesViewModel.exportToClipboard()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initChips() {
|
||||||
|
val new = findViewById<Chip>(R.id.newCookie)
|
||||||
|
new.setOnClickListener {
|
||||||
|
showDialog("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showDialog(url: String){
|
||||||
|
val builder = MaterialAlertDialogBuilder(this)
|
||||||
|
builder.setTitle(getString(R.string.cookies))
|
||||||
|
val inputLayout = layoutInflater.inflate(R.layout.textinput, null)
|
||||||
|
val editText = inputLayout.findViewById<EditText>(R.id.url_edittext)
|
||||||
|
editText.setText(url)
|
||||||
|
builder.setView(inputLayout)
|
||||||
|
builder.setPositiveButton(
|
||||||
|
getString(R.string.get_cookies)
|
||||||
|
) { dialog: DialogInterface?, which: Int ->
|
||||||
|
val myIntent = Intent(this, WebViewActivity::class.java)
|
||||||
|
myIntent.putExtra("url", editText.text.toString())
|
||||||
|
startActivity(myIntent)
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle the negative button of the alert dialog
|
||||||
|
builder.setNegativeButton(
|
||||||
|
getString(R.string.cancel)
|
||||||
|
) { dialog: DialogInterface?, which: Int -> }
|
||||||
|
val dialog = builder.create()
|
||||||
|
editText.setOnKeyListener { view, i, keyEvent ->
|
||||||
|
dialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = editText.text.isNotEmpty()
|
||||||
|
false
|
||||||
|
}
|
||||||
|
dialog.show()
|
||||||
|
val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
|
editText!!.postDelayed({
|
||||||
|
editText.requestFocus()
|
||||||
|
imm.showSoftInput(editText, 0)
|
||||||
|
}, 300)
|
||||||
|
dialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = editText.text.isNotEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "CookiesActivity"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemClick(cookie: CookieItem) {
|
||||||
|
showDialog(cookie.url)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSelected(cookie: CookieItem) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDelete(cookie: CookieItem) {
|
||||||
|
val deleteDialog = MaterialAlertDialogBuilder(this)
|
||||||
|
deleteDialog.setTitle(getString(R.string.you_are_going_to_delete) + " \"" + cookie.url + "\"!")
|
||||||
|
deleteDialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, _: Int -> dialogInterface.cancel() }
|
||||||
|
deleteDialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int ->
|
||||||
|
cookiesViewModel.delete(cookie)
|
||||||
|
}
|
||||||
|
deleteDialog.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -31,6 +31,7 @@ class MoreFragment : Fragment() {
|
||||||
private lateinit var logs: TextView
|
private lateinit var logs: TextView
|
||||||
private lateinit var commandTemplates: TextView
|
private lateinit var commandTemplates: TextView
|
||||||
private lateinit var downloadQueue: TextView
|
private lateinit var downloadQueue: TextView
|
||||||
|
private lateinit var cookies: TextView
|
||||||
private lateinit var terminateApp: TextView
|
private lateinit var terminateApp: TextView
|
||||||
private lateinit var settings: TextView
|
private lateinit var settings: TextView
|
||||||
private lateinit var mainActivity: MainActivity
|
private lateinit var mainActivity: MainActivity
|
||||||
|
|
@ -52,6 +53,7 @@ class MoreFragment : Fragment() {
|
||||||
logs = view.findViewById(R.id.logs)
|
logs = view.findViewById(R.id.logs)
|
||||||
commandTemplates = view.findViewById(R.id.command_templates)
|
commandTemplates = view.findViewById(R.id.command_templates)
|
||||||
downloadQueue = view.findViewById(R.id.download_queue)
|
downloadQueue = view.findViewById(R.id.download_queue)
|
||||||
|
cookies = view.findViewById(R.id.cookies)
|
||||||
terminateApp = view.findViewById(R.id.terminate)
|
terminateApp = view.findViewById(R.id.terminate)
|
||||||
settings = view.findViewById(R.id.settings)
|
settings = view.findViewById(R.id.settings)
|
||||||
|
|
||||||
|
|
@ -84,6 +86,11 @@ class MoreFragment : Fragment() {
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cookies.setOnClickListener {
|
||||||
|
val intent = Intent(context, CookiesActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
|
||||||
terminateApp.setOnClickListener {
|
terminateApp.setOnClickListener {
|
||||||
if (mainSharedPreferences.getBoolean("ask_terminate_app", true)){
|
if (mainSharedPreferences.getBoolean("ask_terminate_app", true)){
|
||||||
var doNotShowAgain = false
|
var doNotShowAgain = false
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,127 @@
|
||||||
|
package com.deniscerri.ytdlnis.ui.more
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.webkit.CookieManager
|
||||||
|
import android.webkit.WebView
|
||||||
|
import android.webkit.WebViewClient
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import com.deniscerri.ytdlnis.R
|
||||||
|
import com.deniscerri.ytdlnis.database.models.CookieItem
|
||||||
|
import com.deniscerri.ytdlnis.database.viewmodel.CookieViewModel
|
||||||
|
import com.google.android.material.appbar.AppBarLayout
|
||||||
|
import com.google.android.material.appbar.MaterialToolbar
|
||||||
|
import com.google.android.material.button.MaterialButton
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
|
class WebViewActivity : AppCompatActivity() {
|
||||||
|
private lateinit var cookiesViewModel: CookieViewModel
|
||||||
|
private lateinit var webView: WebView
|
||||||
|
private lateinit var toolbar: MaterialToolbar
|
||||||
|
private lateinit var generateBtn: MaterialButton
|
||||||
|
private lateinit var cookieManager: CookieManager
|
||||||
|
private lateinit var url: String
|
||||||
|
private lateinit var cookies: String
|
||||||
|
|
||||||
|
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.webview_activity)
|
||||||
|
url = intent.extras!!.getString("url")!!
|
||||||
|
cookies = ""
|
||||||
|
cookiesViewModel = ViewModelProvider(this)[CookieViewModel::class.java]
|
||||||
|
val appbar = findViewById<AppBarLayout>(R.id.webview_appbarlayout)
|
||||||
|
toolbar = appbar.findViewById(R.id.webviewToolbar)
|
||||||
|
generateBtn = toolbar.findViewById(R.id.generate)
|
||||||
|
cookieManager = CookieManager.getInstance()
|
||||||
|
|
||||||
|
webView = findViewById(R.id.webview)
|
||||||
|
webView.settings.javaScriptEnabled = true
|
||||||
|
webView.settings.domStorageEnabled = true
|
||||||
|
webView.settings.javaScriptCanOpenWindowsAutomatically = true
|
||||||
|
|
||||||
|
cookieManager = CookieManager.getInstance()
|
||||||
|
|
||||||
|
toolbar.setNavigationOnClickListener {
|
||||||
|
cookieManager.flush()
|
||||||
|
onBackPressedDispatcher.onBackPressed()
|
||||||
|
}
|
||||||
|
|
||||||
|
val webViewClient: WebViewClient = object : WebViewClient() {
|
||||||
|
|
||||||
|
override fun onPageFinished(view: WebView, url: String) {
|
||||||
|
super.onPageFinished(view, url)
|
||||||
|
kotlin.runCatching {
|
||||||
|
toolbar.title = view.title
|
||||||
|
cookies = CookieManager.getInstance().getCookie(view.url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
webView.webViewClient = webViewClient
|
||||||
|
|
||||||
|
generateBtn.setOnClickListener {
|
||||||
|
cookiesViewModel.getCookiesFromDB().getOrNull()?.let {
|
||||||
|
File(cacheDir , "/cookies.txt").apply { writeText(it) }
|
||||||
|
}
|
||||||
|
kotlin.runCatching {
|
||||||
|
cookiesViewModel.insert(
|
||||||
|
CookieItem(
|
||||||
|
0,
|
||||||
|
url,
|
||||||
|
""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}.onFailure {
|
||||||
|
Toast.makeText(this, "Something went wrong", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
cookieManager.flush()
|
||||||
|
onBackPressedDispatcher.onBackPressed()
|
||||||
|
}
|
||||||
|
|
||||||
|
webView.loadUrl(url)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val TAG = "WebViewActivity"
|
||||||
|
}
|
||||||
|
|
||||||
|
data class CookieItem(
|
||||||
|
val domain: String = "",
|
||||||
|
val name: String = "",
|
||||||
|
val value: String = "",
|
||||||
|
val includeSubdomains: Boolean = true,
|
||||||
|
val path: String = "/",
|
||||||
|
val secure: Boolean = true,
|
||||||
|
val expiry: Long = 0L,
|
||||||
|
) {
|
||||||
|
constructor(
|
||||||
|
url: String,
|
||||||
|
name: String,
|
||||||
|
value: String
|
||||||
|
) : this(domain = url.replace(Regex("""http(s)?://(\w*(www|m|account|sso))?|/.*"""), ""), name = name, value = value)
|
||||||
|
|
||||||
|
fun toNetscapeFormat(): String {
|
||||||
|
val stringList = listOf(domain,
|
||||||
|
includeSubdomains.toString().uppercase(),
|
||||||
|
path,
|
||||||
|
secure.toString().uppercase(),
|
||||||
|
expiry.toString(),
|
||||||
|
name,
|
||||||
|
value)
|
||||||
|
|
||||||
|
val builder = StringBuilder(stringList.first())
|
||||||
|
|
||||||
|
for (s in stringList.subList(1, stringList.size)) {
|
||||||
|
if (s.isNotEmpty()) {
|
||||||
|
if (builder.isNotEmpty())
|
||||||
|
builder.append("\u0009")
|
||||||
|
builder.append(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@ package com.deniscerri.ytdlnis.util
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.os.Environment
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.database.models.Format
|
import com.deniscerri.ytdlnis.database.models.Format
|
||||||
|
|
@ -13,13 +14,14 @@ import org.json.JSONArray
|
||||||
import org.json.JSONException
|
import org.json.JSONException
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import java.io.BufferedReader
|
import java.io.BufferedReader
|
||||||
|
import java.io.File
|
||||||
import java.io.InputStreamReader
|
import java.io.InputStreamReader
|
||||||
import java.net.HttpURLConnection
|
import java.net.HttpURLConnection
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
class InfoUtil(context: Context) {
|
class InfoUtil(private val context: Context) {
|
||||||
private var items: ArrayList<ResultItem?>
|
private var items: ArrayList<ResultItem?>
|
||||||
private var key: String? = null
|
private var key: String? = null
|
||||||
private var useInvidous = false
|
private var useInvidous = false
|
||||||
|
|
@ -494,6 +496,12 @@ class InfoUtil(context: Context) {
|
||||||
request.addOption("-R", "1")
|
request.addOption("-R", "1")
|
||||||
request.addOption("--socket-timeout", "5")
|
request.addOption("--socket-timeout", "5")
|
||||||
if (!query.contains("http")) request.addOption("--default-search", "ytsearch25")
|
if (!query.contains("http")) request.addOption("--default-search", "ytsearch25")
|
||||||
|
|
||||||
|
val cookiesFile = File(context.cacheDir, "cookies.txt")
|
||||||
|
if (cookiesFile.exists()){
|
||||||
|
request.addOption("--cookies", cookiesFile.absolutePath)
|
||||||
|
}
|
||||||
|
|
||||||
val youtubeDLResponse = YoutubeDL.getInstance().execute(request)
|
val youtubeDLResponse = YoutubeDL.getInstance().execute(request)
|
||||||
val results: Array<String?> = try {
|
val results: Array<String?> = try {
|
||||||
val lineSeparator = System.getProperty("line.separator")
|
val lineSeparator = System.getProperty("line.separator")
|
||||||
|
|
@ -637,6 +645,12 @@ class InfoUtil(context: Context) {
|
||||||
request.addOption("--skip-download")
|
request.addOption("--skip-download")
|
||||||
request.addOption("-R", "1")
|
request.addOption("-R", "1")
|
||||||
request.addOption("--socket-timeout", "5")
|
request.addOption("--socket-timeout", "5")
|
||||||
|
|
||||||
|
val cookiesFile = File(context.cacheDir, "cookies.txt")
|
||||||
|
if (cookiesFile.exists()){
|
||||||
|
request.addOption("--cookies", cookiesFile.absolutePath)
|
||||||
|
}
|
||||||
|
|
||||||
val youtubeDLResponse = YoutubeDL.getInstance().execute(request)
|
val youtubeDLResponse = YoutubeDL.getInstance().execute(request)
|
||||||
val results: Array<String?> = try {
|
val results: Array<String?> = try {
|
||||||
val lineSeparator = System.getProperty("line.separator")
|
val lineSeparator = System.getProperty("line.separator")
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,11 @@ class DownloadWorker(
|
||||||
request.addOption("--restrict-filenames")
|
request.addOption("--restrict-filenames")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val cookiesFile = File(context.cacheDir, "cookies.txt")
|
||||||
|
if (cookiesFile.exists()){
|
||||||
|
request.addOption("--cookies", cookiesFile.absolutePath)
|
||||||
|
}
|
||||||
|
|
||||||
when(type){
|
when(type){
|
||||||
DownloadViewModel.Type.audio -> {
|
DownloadViewModel.Type.audio -> {
|
||||||
var audioQualityId : String = downloadItem.format.format_id
|
var audioQualityId : String = downloadItem.format.format_id
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,11 @@ class TerminalDownloadWorker(
|
||||||
}.absolutePath
|
}.absolutePath
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val cookiesFile = File(context.cacheDir, "cookies.txt")
|
||||||
|
if (cookiesFile.exists()){
|
||||||
|
request.addOption("--cookies", cookiesFile.absolutePath)
|
||||||
|
}
|
||||||
|
|
||||||
request.addOption("-P", tempFileDir.absolutePath)
|
request.addOption("-P", tempFileDir.absolutePath)
|
||||||
|
|
||||||
val logDownloads = sharedPreferences.getBoolean("log_downloads", false) && !sharedPreferences.getBoolean("incognito", false)
|
val logDownloads = sharedPreferences.getBoolean("log_downloads", false) && !sharedPreferences.getBoolean("incognito", false)
|
||||||
|
|
|
||||||
5
app/src/main/res/drawable/baseline_cookie_24.xml
Normal file
5
app/src/main/res/drawable/baseline_cookie_24.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector android:height="24dp"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="?android:colorAccent" android:pathData="M21.95,10.99c-1.79,-0.03 -3.7,-1.95 -2.68,-4.22c-2.98,1 -5.77,-1.59 -5.19,-4.56C6.95,0.71 2,6.58 2,12c0,5.52 4.48,10 10,10C17.89,22 22.54,16.92 21.95,10.99zM8.5,15C7.67,15 7,14.33 7,13.5S7.67,12 8.5,12s1.5,0.67 1.5,1.5S9.33,15 8.5,15zM10.5,10C9.67,10 9,9.33 9,8.5S9.67,7 10.5,7S12,7.67 12,8.5S11.33,10 10.5,10zM15,16c-0.55,0 -1,-0.45 -1,-1c0,-0.55 0.45,-1 1,-1s1,0.45 1,1C16,15.55 15.55,16 15,16z"/>
|
||||||
|
</vector>
|
||||||
61
app/src/main/res/layout/activity_cookies.xml
Normal file
61
app/src/main/res/layout/activity_cookies.xml
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context="com.deniscerri.ytdlnis.ui.more.TerminalActivity">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:liftOnScroll="true"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:fitsSystemWindows="true">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
|
android:id="@+id/logs_toolbar"
|
||||||
|
android:elevation="0dp"
|
||||||
|
app:title="@string/cookies"
|
||||||
|
app:menu="@menu/cookies_menu"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
app:navigationIcon="@drawable/ic_back"
|
||||||
|
android:layout_height="match_parent"/>
|
||||||
|
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
|
||||||
|
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/newCookie"
|
||||||
|
style="@style/Widget.Material3.Chip.Assist"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/new_cookie"
|
||||||
|
app:chipIcon="@drawable/ic_plus" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:layout_below="@+id/newCookie"
|
||||||
|
android:id="@+id/template_recyclerview"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
>
|
||||||
|
|
||||||
|
</androidx.recyclerview.widget.RecyclerView>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<include layout="@layout/history_no_results"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
@ -81,6 +81,21 @@
|
||||||
android:paddingHorizontal="15dp"
|
android:paddingHorizontal="15dp"
|
||||||
app:drawableStartCompat="@drawable/ic_concurrent_downloads" />
|
app:drawableStartCompat="@drawable/ic_concurrent_downloads" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/cookies"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawablePadding="35dp"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:paddingVertical="15dp"
|
||||||
|
android:text="@string/cookies"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:paddingHorizontal="15dp"
|
||||||
|
app:drawableStartCompat="@drawable/baseline_cookie_24" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/terminate"
|
android:id="@+id/terminate"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
||||||
26
app/src/main/res/layout/textinput.xml
Normal file
26
app/src/main/res/layout/textinput.xml
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:id="@+id/url_textinput"
|
||||||
|
style="@style/Widget.Material3.TextInputLayout.FilledBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="URL"
|
||||||
|
android:padding="10dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/url_edittext"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="text" />
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
57
app/src/main/res/layout/webview_activity.xml
Normal file
57
app/src/main/res/layout/webview_activity.xml
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:id="@+id/webview_appbarlayout"
|
||||||
|
app:liftOnScroll="true"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:elevation="0dp"
|
||||||
|
app:elevation="0dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
|
android:id="@+id/webviewToolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
app:layout_scrollFlags="scroll"
|
||||||
|
app:navigationIcon="?attr/homeAsUpIndicator"
|
||||||
|
android:theme="@style/Toolbar"
|
||||||
|
>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/generate"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_marginHorizontal="10dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:autoLink="all"
|
||||||
|
android:text="@string/ok"
|
||||||
|
app:icon="@drawable/ic_check"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:ignore="PrivateResource" />
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.MaterialToolbar>
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<WebView
|
||||||
|
android:id="@+id/webview"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
13
app/src/main/res/menu/cookies_menu.xml
Normal file
13
app/src/main/res/menu/cookies_menu.xml
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
<item
|
||||||
|
android:id="@+id/delete_cookies"
|
||||||
|
android:title="@string/delete_all_cookies"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/export_clipboard"
|
||||||
|
android:title="@string/export_from_clipboard"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
</menu>
|
||||||
|
|
@ -197,4 +197,11 @@
|
||||||
<string name="suggested">Suggested</string>
|
<string name="suggested">Suggested</string>
|
||||||
<string name="select_all">Select All</string>
|
<string name="select_all">Select All</string>
|
||||||
<string name="share">Share</string>
|
<string name="share">Share</string>
|
||||||
|
<string name="cookies">Cookies</string>
|
||||||
|
<string name="new_cookie">New Cookie</string>
|
||||||
|
<string name="cookie">Cookie</string>
|
||||||
|
<string name="create_cookie">Create Cookie</string>
|
||||||
|
<string name="get_cookies">Get Cookies</string>
|
||||||
|
<string name="delete_all_cookies">Delete All Cookies</string>
|
||||||
|
<string name="confirm_delete_cookies_desc">Delete all the cookies, permanently</string>
|
||||||
</resources>
|
</resources>
|
||||||
Loading…
Reference in a new issue