added custom command and shortcuts buttons to terminal screen

This commit is contained in:
deniscerri 2023-03-25 21:58:48 +01:00
parent 506929b453
commit 467c0bd16e
No known key found for this signature in database
GPG key ID: 95C43D517D830350
12 changed files with 452 additions and 131 deletions

View file

@ -41,6 +41,10 @@ class CommandTemplateViewModel(private val application: Application) : AndroidVi
return repository.getAll() return repository.getAll()
} }
fun getAllShortcuts() : List<TemplateShortcut> {
return repository.getAllShortCuts()
}
fun getTotalNumber(): Int { fun getTotalNumber(): Int {
return repository.getTotalNumber() return repository.getTotalNumber()
} }

View file

@ -15,7 +15,7 @@ class HistoryViewModel(application: Application) : AndroidViewModel(application)
private val repository : HistoryRepository private val repository : HistoryRepository
val sortOrder = MutableLiveData(HistorySort.DESC) val sortOrder = MutableLiveData(HistorySort.DESC)
val sortType = MutableLiveData(HistorySortType.DATE) val sortType = MutableLiveData(HistorySortType.DATE)
private val websiteFilter = MutableLiveData("") val websiteFilter = MutableLiveData("")
private val queryFilter = MutableLiveData("") private val queryFilter = MutableLiveData("")
private val formatFilter = MutableLiveData("") private val formatFilter = MutableLiveData("")
val allItems : LiveData<List<HistoryItem>> val allItems : LiveData<List<HistoryItem>>
@ -48,6 +48,7 @@ class HistoryViewModel(application: Application) : AndroidViewModel(application)
return _items return _items
} }
fun setSorting(sort: HistorySortType){ fun setSorting(sort: HistorySortType){
if (sortType.value != sort){ if (sortType.value != sort){
sortOrder.value = HistorySort.DESC sortOrder.value = HistorySort.DESC

View file

@ -333,6 +333,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
private fun updateWebsiteChips(list : List<HistoryItem>) { private fun updateWebsiteChips(list : List<HistoryItem>) {
val websites = mutableListOf<String>() val websites = mutableListOf<String>()
val websiteFilter = historyViewModel.websiteFilter.value
for (item in list){ for (item in list){
if (!websites.contains(item.website)) websites.add(item.website) if (!websites.contains(item.website)) websites.add(item.website)
} }
@ -353,6 +354,9 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
tmp.isChecked = false tmp.isChecked = false
} }
} }
if (w == websiteFilter){
tmp.isChecked = true
}
websiteGroup!!.addView(tmp) websiteGroup!!.addView(tmp)
} }
} }

View file

@ -1,12 +1,14 @@
package com.deniscerri.ytdlnis.ui.more package com.deniscerri.ytdlnis.ui.more
import android.app.Activity import android.app.Activity
import android.content.DialogInterface
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.CheckBox
import android.widget.TextView import android.widget.TextView
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.Navigation import androidx.navigation.Navigation
@ -18,10 +20,13 @@ import com.deniscerri.ytdlnis.databinding.FragmentHomeBinding
import com.deniscerri.ytdlnis.ui.downloads.DownloadQueueActivity import com.deniscerri.ytdlnis.ui.downloads.DownloadQueueActivity
import com.deniscerri.ytdlnis.ui.more.downloadLogs.DownloadLogListActivity import com.deniscerri.ytdlnis.ui.more.downloadLogs.DownloadLogListActivity
import com.deniscerri.ytdlnis.ui.more.settings.SettingsActivity import com.deniscerri.ytdlnis.ui.more.settings.SettingsActivity
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import java.util.ArrayList
import kotlin.system.exitProcess import kotlin.system.exitProcess
class MoreFragment : Fragment() { class MoreFragment : Fragment() {
private lateinit var mainSharedPreferences: SharedPreferences private lateinit var mainSharedPreferences: SharedPreferences
private lateinit var mainSharedPreferencesEditor: SharedPreferences.Editor
private lateinit var terminal: TextView private lateinit var terminal: TextView
private lateinit var logs: TextView private lateinit var logs: TextView
private lateinit var commandTemplates: TextView private lateinit var commandTemplates: TextView
@ -42,6 +47,7 @@ class MoreFragment : Fragment() {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
mainSharedPreferences = requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE) mainSharedPreferences = requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
mainSharedPreferencesEditor = mainSharedPreferences.edit()
terminal = view.findViewById(R.id.terminal) terminal = view.findViewById(R.id.terminal)
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)
@ -79,7 +85,33 @@ class MoreFragment : Fragment() {
} }
terminateApp.setOnClickListener { terminateApp.setOnClickListener {
exitProcess(0) if (mainSharedPreferences.getBoolean("ask_terminate_app", true)){
var doNotShowAgain = false
val terminateDialog = MaterialAlertDialogBuilder(requireContext())
terminateDialog.setTitle(getString(R.string.confirm_delete_history))
val dialogView = layoutInflater.inflate(R.layout.dialog_terminate_app, null)
val checkbox = dialogView.findViewById<CheckBox>(R.id.doNotShowAgain)
terminateDialog.setView(dialogView)
checkbox.setOnCheckedChangeListener { compoundButton, b ->
doNotShowAgain = compoundButton.isChecked
}
terminateDialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, _: Int -> dialogInterface.cancel() }
terminateDialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int ->
if (doNotShowAgain){
mainSharedPreferencesEditor.putBoolean("ask_terminate_app", false)
mainSharedPreferencesEditor.commit()
}
exitProcess(0)
}
terminateDialog.show()
}else{
exitProcess(0)
}
} }
settings.setOnClickListener { settings.setOnClickListener {

View file

@ -7,22 +7,40 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.os.Bundle import android.os.Bundle
import android.os.Looper
import android.text.format.DateFormat
import android.util.Log import android.util.Log
import android.view.View import android.view.View
import android.widget.EditText import android.view.ViewGroup
import android.widget.ScrollView import android.view.Window
import android.widget.TextView import android.widget.*
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.work.Data
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import com.deniscerri.ytdlnis.App
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.database.repository.DownloadRepository
import com.deniscerri.ytdlnis.database.viewmodel.CommandTemplateViewModel
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.util.FileUtil import com.deniscerri.ytdlnis.util.FileUtil
import com.deniscerri.ytdlnis.util.NotificationUtil import com.deniscerri.ytdlnis.util.NotificationUtil
import com.deniscerri.ytdlnis.work.DownloadWorker import com.deniscerri.ytdlnis.work.DownloadWorker
import com.google.android.material.appbar.MaterialToolbar import com.google.android.material.appbar.MaterialToolbar
import com.google.android.material.bottomappbar.BottomAppBar
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.button.MaterialButton
import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipGroup
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
import com.google.android.material.progressindicator.LinearProgressIndicator
import com.yausername.youtubedl_android.YoutubeDL import com.yausername.youtubedl_android.YoutubeDL
import com.yausername.youtubedl_android.YoutubeDLRequest import com.yausername.youtubedl_android.YoutubeDLRequest
import io.reactivex.Observable import io.reactivex.Observable
@ -30,8 +48,14 @@ import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import java.io.File import java.io.File
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.TimeUnit
class TerminalActivity : AppCompatActivity() { class TerminalActivity : AppCompatActivity() {
@ -40,8 +64,9 @@ class TerminalActivity : AppCompatActivity() {
private var output: TextView? = null private var output: TextView? = null
private var input: EditText? = null private var input: EditText? = null
private var fab: ExtendedFloatingActionButton? = null private var fab: ExtendedFloatingActionButton? = null
private var cancelFab: ExtendedFloatingActionButton? = null
private var scrollView: ScrollView? = null private var scrollView: ScrollView? = null
private lateinit var bottomAppBar: BottomAppBar
private lateinit var commandTemplateViewModel: CommandTemplateViewModel
var context: Context? = null var context: Context? = null
public override fun onCreate(savedInstanceState: Bundle?) { public override fun onCreate(savedInstanceState: Bundle?) {
@ -51,23 +76,38 @@ class TerminalActivity : AppCompatActivity() {
scrollView = findViewById(R.id.custom_command_scrollview) scrollView = findViewById(R.id.custom_command_scrollview)
topAppBar = findViewById(R.id.custom_command_toolbar) topAppBar = findViewById(R.id.custom_command_toolbar)
topAppBar!!.setNavigationOnClickListener { onBackPressedDispatcher.onBackPressed() } topAppBar!!.setNavigationOnClickListener { onBackPressedDispatcher.onBackPressed() }
commandTemplateViewModel = ViewModelProvider(this)[CommandTemplateViewModel::class.java]
bottomAppBar = findViewById(R.id.bottomAppBar)
bottomAppBar.setOnMenuItemClickListener {
when(it.itemId){
R.id.command_templates -> showCommandTemplates()
R.id.shortcuts -> showShortcuts()
else -> {}
}
true
}
output = findViewById(R.id.custom_command_output) output = findViewById(R.id.custom_command_output)
output!!.setTextIsSelectable(true) output!!.setTextIsSelectable(true)
input = findViewById(R.id.command_edittext) input = findViewById(R.id.command_edittext)
input!!.requestFocus() input!!.requestFocus()
fab = findViewById(R.id.command_fab) fab = findViewById(R.id.command_fab)
fab!!.setOnClickListener { fab!!.setOnClickListener {
input!!.visibility = View.GONE if (fab!!.text == getString(R.string.run_command)){
output!!.text = "${output!!.text}\n~ $ ${input!!.text}\n" input!!.visibility = View.GONE
swapFabs() output!!.text = "${output!!.text}\n~ $ ${input!!.text}\n"
startDownload( showCancelFab()
input!!.text.toString() startDownload(
) input!!.text.toString()
} )
cancelFab = findViewById(R.id.cancel_command_fab) }else {
cancelFab!!.setOnClickListener { cancelDownload()
cancelDownload() input!!.visibility = View.VISIBLE
input!!.visibility = View.VISIBLE hideCancelFab()
}
} }
notificationUtil = NotificationUtil(this) notificationUtil = NotificationUtil(this)
handleIntent(intent) handleIntent(intent)
@ -90,13 +130,73 @@ class TerminalActivity : AppCompatActivity() {
} }
private fun swapFabs() { private fun hideCancelFab() {
val cancel = cancelFab!!.visibility fab!!.text = getString(R.string.run_command)
val start = fab!!.visibility fab!!.setIconResource(R.drawable.ic_baseline_keyboard_arrow_right_24)
cancelFab!!.visibility = start }
fab!!.visibility = cancel private fun showCancelFab() {
fab!!.text = getString(R.string.cancel_download)
fab!!.setIconResource(R.drawable.ic_cancel)
} }
private fun showCommandTemplates(){
lifecycleScope.launch {
val bottomSheet = BottomSheetDialog(this@TerminalActivity)
bottomSheet.requestWindowFeature(Window.FEATURE_NO_TITLE)
bottomSheet.setContentView(R.layout.command_template_list)
val linearLayout = bottomSheet.findViewById<LinearLayout>(R.id.command_list_linear_layout)
val list = withContext(Dispatchers.IO){
commandTemplateViewModel.getAll()
}
linearLayout!!.removeAllViews()
list.forEach {template ->
val item = layoutInflater.inflate(R.layout.command_template_item, linearLayout, false) as ConstraintLayout
item.findViewById<TextView>(R.id.title).text = template.title
item.findViewById<TextView>(R.id.content).text = template.content
item.setOnClickListener {
input!!.text.insert(input!!.selectionStart, template.content + " ")
}
linearLayout.addView(item)
}
bottomSheet.show()
bottomSheet.window!!.setLayout(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
}
}
private fun showShortcuts() {
lifecycleScope.launch {
val bottomSheet = BottomSheetDialog(this@TerminalActivity)
bottomSheet.requestWindowFeature(Window.FEATURE_NO_TITLE)
bottomSheet.setContentView(R.layout.template_shortcuts_list)
val chipGroup = bottomSheet.findViewById<ChipGroup>(R.id.shortcutsChipGroup)
val shortcutList = withContext(Dispatchers.IO){
commandTemplateViewModel.getAllShortcuts()
}
chipGroup!!.removeAllViews()
shortcutList.forEach {shortcut ->
val chip = layoutInflater.inflate(R.layout.suggestion_chip, chipGroup, false) as Chip
chip.text = shortcut.content
chip.setOnClickListener {
input!!.text.insert(input!!.selectionStart, shortcut.content + " ")
}
chipGroup.addView(chip)
}
bottomSheet.show()
bottomSheet.window!!.setLayout(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
}
}
private fun startDownload(command: String?) { private fun startDownload(command: String?) {
val cmd = if (command!!.contains("yt-dlp")) command.replace("yt-dlp", "") val cmd = if (command!!.contains("yt-dlp")) command.replace("yt-dlp", "")
@ -137,10 +237,10 @@ class TerminalActivity : AppCompatActivity() {
}.absolutePath }.absolutePath
) )
//request.addOption("-P", tempFileDir.absolutePath)
cancelFab!!.visibility = View.VISIBLE request.addOption("-P", tempFileDir.absolutePath)
fab!!.visibility = View.GONE
showCancelFab()
val disposable: Disposable = Observable.fromCallable { val disposable: Disposable = Observable.fromCallable {
try{ try{
YoutubeDL.getInstance().execute(request, downloadID.toString()){ progress, _, line -> YoutubeDL.getInstance().execute(request, downloadID.toString()){ progress, _, line ->
@ -167,8 +267,7 @@ class TerminalActivity : AppCompatActivity() {
input!!.visibility = View.VISIBLE input!!.visibility = View.VISIBLE
cancelFab!!.visibility = View.GONE hideCancelFab()
fab!!.visibility = View.VISIBLE
} }
} }
@ -181,15 +280,7 @@ class TerminalActivity : AppCompatActivity() {
input!!.setText("yt-dlp ") input!!.setText("yt-dlp ")
input!!.visibility = View.VISIBLE input!!.visibility = View.VISIBLE
cancelFab!!.visibility = View.GONE hideCancelFab()
fab!!.visibility = View.VISIBLE
//move file from internal to set download directory
try {
moveFile(tempFileDir.absoluteFile, getString(R.string.command_path)){ }
}catch (e: Exception){
Toast.makeText(context, e.message, Toast.LENGTH_SHORT).show()
}
notificationUtil.cancelDownloadNotification(downloadID) notificationUtil.cancelDownloadNotification(downloadID)
}) { e -> }) { e ->
e.printStackTrace() e.printStackTrace()
@ -198,32 +289,19 @@ class TerminalActivity : AppCompatActivity() {
input!!.setText("yt-dlp ") input!!.setText("yt-dlp ")
input!!.visibility = View.VISIBLE input!!.visibility = View.VISIBLE
cancelFab!!.visibility = View.GONE hideCancelFab();
fab!!.visibility = View.VISIBLE
tempFileDir.delete()
Toast.makeText(context, e.message, Toast.LENGTH_SHORT).show() Toast.makeText(context, e.message, Toast.LENGTH_SHORT).show()
Log.e(DownloadWorker.TAG, context?.getString(R.string.failed_download), e) Log.e(DownloadWorker.TAG, context?.getString(R.string.failed_download), e)
notificationUtil.cancelDownloadNotification(downloadID) notificationUtil.cancelDownloadNotification(downloadID)
} }
compositeDisposable.add(disposable) compositeDisposable.add(disposable)
}
@Throws(Exception::class)
private fun moveFile(originDir: File, downLocation: String, progress: (progress: Int) -> Unit){
val fileUtil = FileUtil()
fileUtil.moveFile(originDir, context!!, downLocation){ p ->
progress(p)
}
} }
private fun cancelDownload() { private fun cancelDownload() {
lifecycleScope.launch { YoutubeDL.getInstance().destroyProcessById(downloadID.toString())
compositeDisposable.dispose() WorkManager.getInstance(this).cancelUniqueWork(downloadID.toString())
YoutubeDL.getInstance().destroyProcessById(downloadID.toString()) notificationUtil.cancelDownloadNotification(downloadID)
notificationUtil.cancelDownloadNotification(downloadID)
}
} }
companion object { companion object {

View file

@ -6,64 +6,6 @@
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context="com.deniscerri.ytdlnis.ui.more.TerminalActivity"> tools:context="com.deniscerri.ytdlnis.ui.more.TerminalActivity">
<FrameLayout
android:id="@+id/custom_command_frame_layout"
android:layout_width="match_parent"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_margin="10dp"
android:layout_height="wrap_content"
android:orientation="vertical">
<ScrollView
android:id="@+id/custom_command_scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="100dp"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/custom_command_output"
android:layout_width="match_parent"
android:textIsSelectable="true"
android:fontFamily="monospace"
android:gravity="bottom"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/command_edittext"
android:background="@android:color/transparent"
android:layout_width="match_parent"
android:fontFamily="monospace"
android:text="yt-dlp "
android:textSize="13sp"
android:layout_height="wrap_content"
android:inputType="textMultiLine"
android:gravity="start"
android:maxLines="100" />
</LinearLayout>
</ScrollView>
</LinearLayout>
</FrameLayout>
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -82,25 +24,90 @@
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/command_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:text="@string/run_command"
app:icon="@drawable/ic_baseline_keyboard_arrow_right_24"
/>
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cancel_command_fab" android:layout_width="match_parent"
android:layout_width="wrap_content" app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
android:layout_height="wrap_content" android:layout_height="match_parent">
android:layout_gravity="bottom|end"
android:layout_margin="16dp" <LinearLayout
android:text="@string/cancel_download" android:id="@+id/custom_command_frame_layout"
android:visibility="gone" android:layout_width="match_parent"
app:icon="@drawable/ic_delete_all" android:layout_height="0dp"
/> android:layout_marginHorizontal="10dp"
app:layout_constraintBottom_toTopOf="@+id/coordinatorLayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ScrollView
android:id="@+id/custom_command_scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="100dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/custom_command_output"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="monospace"
android:gravity="bottom"
android:textIsSelectable="true" />
<EditText
android:id="@+id/command_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:fontFamily="monospace"
android:gravity="start"
android:inputType="textMultiLine"
android:maxLines="100"
android:text="yt-dlp "
android:textSize="14sp" />
</LinearLayout>
</ScrollView>
</LinearLayout>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<com.google.android.material.bottomappbar.BottomAppBar
android:id="@+id/bottomAppBar"
style="@style/Widget.Material3.BottomAppBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:menu="@menu/terminal_menu" />
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/command_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/run_command"
app:icon="@drawable/ic_baseline_keyboard_arrow_right_24"
app:layout_anchor="@id/bottomAppBar" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="20dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:orientation="horizontal"
android:paddingTop="20dp">
<TextView
android:id="@+id/bottom_sheet_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/command_templates"
android:textSize="25sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/bottom_sheet_subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/select"
android:textSize="12sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/bottom_sheet_title" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:scrollbars="none"
android:paddingTop="10dp"
android:paddingHorizontal="10dp"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/command_list_linear_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:padding="20dp"
android:orientation="vertical"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/confirm_terminate"
android:textStyle="bold" />
<CheckBox
android:id="@+id/doNotShowAgain"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="@string/dont_ask_again"/>
</LinearLayout>

View file

@ -26,6 +26,9 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/terminal" android:text="@string/terminal"
android:textStyle="bold" android:textStyle="bold"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground"
android:paddingHorizontal="15dp" android:paddingHorizontal="15dp"
android:paddingVertical="15dp" android:paddingVertical="15dp"
android:drawablePadding="35dp" android:drawablePadding="35dp"
@ -38,6 +41,9 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/logs" android:text="@string/logs"
android:textStyle="bold" android:textStyle="bold"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground"
android:paddingHorizontal="15dp" android:paddingHorizontal="15dp"
android:paddingVertical="15dp" android:paddingVertical="15dp"
android:drawablePadding="35dp" android:drawablePadding="35dp"
@ -54,6 +60,9 @@
android:paddingVertical="15dp" android:paddingVertical="15dp"
android:text="@string/command_templates" android:text="@string/command_templates"
android:textStyle="bold" android:textStyle="bold"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground"
android:paddingHorizontal="15dp" android:paddingHorizontal="15dp"
app:drawableLeftCompat="@drawable/ic_baseline_keyboard_arrow_right_24" /> app:drawableLeftCompat="@drawable/ic_baseline_keyboard_arrow_right_24" />
@ -66,6 +75,9 @@
android:paddingVertical="15dp" android:paddingVertical="15dp"
android:text="@string/download_queue" android:text="@string/download_queue"
android:textStyle="bold" android:textStyle="bold"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground"
android:paddingHorizontal="15dp" android:paddingHorizontal="15dp"
app:drawableLeftCompat="@drawable/ic_concurrent_downloads" /> app:drawableLeftCompat="@drawable/ic_concurrent_downloads" />
@ -75,6 +87,9 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:drawablePadding="35dp" android:drawablePadding="35dp"
android:textSize="16sp" android:textSize="16sp"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground"
android:paddingVertical="15dp" android:paddingVertical="15dp"
android:text="@string/kill_app" android:text="@string/kill_app"
android:textStyle="bold" android:textStyle="bold"
@ -93,6 +108,9 @@
android:paddingVertical="15dp" android:paddingVertical="15dp"
android:text="@string/settings" android:text="@string/settings"
android:textStyle="bold" android:textStyle="bold"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground"
android:paddingHorizontal="15dp" android:paddingHorizontal="15dp"
app:drawableLeftCompat="@drawable/ic_settings" /> app:drawableLeftCompat="@drawable/ic_settings" />

View file

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:orientation="horizontal"
android:paddingTop="20dp">
<TextView
android:id="@+id/bottom_sheet_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/shortcuts"
android:textSize="25sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/bottom_sheet_subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/shortcuts_desc"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/bottom_sheet_title" />
</androidx.constraintlayout.widget.ConstraintLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="15dp">
<com.google.android.material.chip.ChipGroup
android:id="@+id/shortcutsChipGroup"
android:layout_width="wrap_content"
app:chipSpacingVertical="0dp"
android:layout_height="wrap_content"
app:singleLine="false">
</com.google.android.material.chip.ChipGroup>
</LinearLayout>
</ScrollView>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,14 @@
<?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"
android:theme="@style/AppDefaultTheme">
<item android:title="@string/command_templates"
android:icon="@drawable/ic_terminal"
app:showAsAction="ifRoom"
android:id="@+id/command_templates"/>
<item android:title="@string/shortcuts"
android:icon="@drawable/ic_shortcut"
app:showAsAction="ifRoom"
android:id="@+id/shortcuts"/>
</menu>

View file

@ -184,4 +184,6 @@
<string name="restrict_filenames">Restrict Filenames</string> <string name="restrict_filenames">Restrict Filenames</string>
<string name="restrict_filenames_summary"><![CDATA[Restrict filenames to only ASCII characters, and avoid \"&\" and spaces in filenames]]></string> <string name="restrict_filenames_summary"><![CDATA[Restrict filenames to only ASCII characters, and avoid \"&\" and spaces in filenames]]></string>
<string name="kill_app">Terminate App</string> <string name="kill_app">Terminate App</string>
<string name="confirm_terminate"><![CDATA[All downloads will be stopped & the app will be force closed]]></string>
<string name="dont_ask_again">Don\'t ask again</string>
</resources> </resources>