Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds option to exclude file/folder patterns #224

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,13 @@
<activity
android:name=".Activities.TriggerActivity"
android:label="@string/title_activity_trigger"
android:theme="@style/AppTheme.NoActionBar" /> <!-- Auto Language Generation -->
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".Activities.FilterActivity"
android:label="@string/title_activity_filter"
android:theme="@style/AppTheme.NoActionBar" />

<!-- Auto Language Generation -->
<service
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
android:enabled="false"
Expand Down
141 changes: 141 additions & 0 deletions app/src/main/java/ca/pkay/rcloneexplorer/Activities/FilterActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package ca.pkay.rcloneexplorer.Activities

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.core.view.size
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import ca.pkay.rcloneexplorer.Database.DatabaseHandler
import ca.pkay.rcloneexplorer.Items.Filter
import ca.pkay.rcloneexplorer.Items.FilterEntry
import ca.pkay.rcloneexplorer.R
import ca.pkay.rcloneexplorer.Rclone
import ca.pkay.rcloneexplorer.RecyclerViewAdapters.FilterEntryRecyclerViewAdapter
import ca.pkay.rcloneexplorer.util.ActivityHelper
import com.google.android.material.floatingactionbutton.FloatingActionButton
import es.dmoral.toasty.Toasty
import jp.wasabeef.recyclerview.animators.LandingAnimator

class FilterActivity : AppCompatActivity() {


private lateinit var rcloneInstance: Rclone
private lateinit var dbHandler: DatabaseHandler

private lateinit var filterTitle: EditText
private lateinit var filterList: RecyclerView


private var existingFilter: Filter? = null
private var filters: ArrayList<FilterEntry> = arrayListOf()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ActivityHelper.applyTheme(this)
setContentView(R.layout.activity_filter)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a "close" icon in the toolbar would be better instead of the "back"-one that is default. In the future i might change views like this to a Full Screen Dialog

setSupportActionBar(toolbar)
val actionBar = supportActionBar
actionBar?.setDisplayHomeAsUpEnabled(true)

filterTitle = findViewById(R.id.filter_title_textfield)
filterList = findViewById(R.id.filter_filterlist)
val newFilterEntry = findViewById<Button>(R.id.filter_add_filterentry_button)
newFilterEntry.setOnClickListener {
filters.add(FilterEntry(FilterEntry.FILTER_EXCLUDE, ""))
filterList.adapter?.notifyItemInserted(filterList.size)
}


rcloneInstance = Rclone(this)
dbHandler = DatabaseHandler(this)
val extras = intent.extras
val filterId: Long
if (extras != null) {
filterId = extras.getLong(ID_EXTRA)
if (filterId != 0L) {
existingFilter = dbHandler.getFilter(filterId)
if (existingFilter == null) {
Toasty.error(
this,
this.resources.getString(R.string.filteractivity_filter_not_found)
).show()
finish()
}
}
}
val fab = findViewById<FloatingActionButton>(R.id.saveButton)
fab.setOnClickListener {
if (existingFilter == null) {
saveFilter()
} else {
persistFilterChanges()
}
}

if(existingFilter != null) {
filters = existingFilter!!.getFilters()
}
filterTitle.setText(existingFilter?.title)
prepareFilterList()
}

override fun onSupportNavigateUp(): Boolean {
finish()
return true
}

private fun persistFilterChanges() {
val updatedFilter = getFilterValues(existingFilter!!.id)
if (updatedFilter != null) {
dbHandler.updateFilter(updatedFilter)
val resultIntent = Intent()
resultIntent.putExtra(SAVED_FILTER_ID_EXTRA, updatedFilter.id)
setResult(Activity.RESULT_OK, resultIntent)
finish()
}
}

private fun saveFilter() {
val newFilter = getFilterValues(0)
if (newFilter != null) {
val filter = dbHandler.createFilter(newFilter)
val resultIntent = Intent()
resultIntent.putExtra(SAVED_FILTER_ID_EXTRA, filter.id)
setResult(Activity.RESULT_OK, resultIntent)
finish()
}
}

private fun getFilterValues(id: Long): Filter? {
val filterToPopulate = Filter(id)
filterToPopulate.title = filterTitle.text.toString()
filterToPopulate.setFilters(filters)
if (filterTitle.text.toString() == "") {
Toasty.error(
this.applicationContext,
getString(R.string.filter_data_validation_error_no_title),
Toast.LENGTH_SHORT,
true
).show()
return null
}
return filterToPopulate
}
private fun prepareFilterList() {
val adapter = FilterEntryRecyclerViewAdapter(filters, this)
filterList.layoutManager = LinearLayoutManager(this)
filterList.itemAnimator = LandingAnimator()
filterList.adapter = adapter
}
companion object {
const val ID_EXTRA = "FILTER_EDIT_ID"
const val SAVED_FILTER_ID_EXTRA = "filterId"
}
}
135 changes: 132 additions & 3 deletions app/src/main/java/ca/pkay/rcloneexplorer/Activities/TaskActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,39 @@ package ca.pkay.rcloneexplorer.Activities
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.MenuItem
import android.view.View
import android.widget.*
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.EditText
import android.widget.ImageButton
import android.widget.Spinner
import android.widget.Switch
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.PopupMenu
import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.Fragment
import ca.pkay.rcloneexplorer.Database.DatabaseHandler
import ca.pkay.rcloneexplorer.FilePicker
import ca.pkay.rcloneexplorer.Fragments.FolderSelectorCallback
import ca.pkay.rcloneexplorer.Fragments.RemoteFolderPickerFragment
import ca.pkay.rcloneexplorer.Items.Filter
import ca.pkay.rcloneexplorer.Items.RemoteItem
import ca.pkay.rcloneexplorer.Items.SyncDirectionObject
import ca.pkay.rcloneexplorer.Items.Task
import ca.pkay.rcloneexplorer.R
import ca.pkay.rcloneexplorer.Rclone
import ca.pkay.rcloneexplorer.SpinnerAdapters.FilterSpinnerAdapter
import ca.pkay.rcloneexplorer.util.ActivityHelper
import com.google.android.material.floatingactionbutton.FloatingActionButton
import es.dmoral.toasty.Toasty
import java.io.UnsupportedEncodingException
import java.net.URLDecoder

class TaskActivity : AppCompatActivity(), FolderSelectorCallback {
class TaskActivity : AppCompatActivity(), FolderSelectorCallback{


private lateinit var rcloneInstance: Rclone
Expand All @@ -40,8 +52,18 @@ class TaskActivity : AppCompatActivity(), FolderSelectorCallback {
private lateinit var switchMD5sum: Switch


private lateinit var filterDropdown: Spinner
private lateinit var createNewFilterButton: Button
private lateinit var switchDeleteExcluded: Switch


private lateinit var filterOptionsButton: ImageButton


private var existingTask: Task? = null
private var remotePathHolder = ""
private var selectedFilter: Filter? = null



override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
Expand Down Expand Up @@ -77,6 +99,12 @@ class TaskActivity : AppCompatActivity(), FolderSelectorCallback {
Toasty.error(this, "This Remote is not a RCX-Remote.").show()
}
}
REQUEST_CODE_FILTER -> if (data != null) {
val filterId = data.getLongExtra(FilterActivity.SAVED_FILTER_ID_EXTRA, -1)
if(filterId >= 0) {
selectFilter(filterId)
}
}
}
fab.visibility = View.VISIBLE
}
Expand All @@ -95,6 +123,8 @@ class TaskActivity : AppCompatActivity(), FolderSelectorCallback {
remoteDropdown = findViewById(R.id.task_remote_spinner)
syncDirection = findViewById(R.id.task_direction_spinner)
syncDescription = findViewById(R.id.descriptionSyncDirection)
filterDropdown = findViewById(R.id.task_filter_spinner)
switchDeleteExcluded = findViewById(R.id.task_exclude_delete_toggle)
fab = findViewById(R.id.saveButton)
switchWifi = findViewById(R.id.task_wifionly)
switchMD5sum = findViewById(R.id.task_md5sum)
Expand Down Expand Up @@ -126,13 +156,24 @@ class TaskActivity : AppCompatActivity(), FolderSelectorCallback {
}
}

filterOptionsButton = findViewById(R.id.task_edit_filter_options_button)
filterOptionsButton.setOnClickListener {
val filter = if(filterDropdown.selectedItemPosition > 0 && filterDropdown.selectedItemPosition < filterDropdown.count) filterItems[filterDropdown.selectedItemPosition - 1] else null
showFilterMenu(filterOptionsButton, filter)
}
createNewFilterButton = findViewById<Button>(R.id.task_edit_filter_add_button)
createNewFilterButton.setOnClickListener {
openFilterActivity()
}

findViewById<TextView>(R.id.task_title_textfield).text = existingTask?.title
switchWifi.isChecked = existingTask?.wifionly ?: false
switchMD5sum.isChecked = existingTask?.md5sum ?: false
switchDeleteExcluded.isChecked = existingTask?.deleteExcluded ?: false
prepareSyncDirectionDropdown()
prepareLocal()
prepareRemote()

prepareFilterDropdown()
}

private val remoteItems: Array<String?>
Expand All @@ -143,6 +184,10 @@ class TaskActivity : AppCompatActivity(), FolderSelectorCallback {
}
return remotes
}
private val filterItems: List<Filter>
get() {
return dbHandler.allFilters
}


override fun onSupportNavigateUp(): Boolean {
Expand Down Expand Up @@ -183,6 +228,8 @@ class TaskActivity : AppCompatActivity(), FolderSelectorCallback {

taskToPopulate.wifionly = switchWifi.isChecked
taskToPopulate.md5sum = switchMD5sum.isChecked
taskToPopulate.deleteExcluded = switchDeleteExcluded.isChecked
taskToPopulate.filterId = if(filterDropdown.selectedItemPosition == 0) null else filterItems[filterDropdown.selectedItemPosition - 1].id

// Verify if data is completed
if (localPath.text.toString() == "") {
Expand Down Expand Up @@ -220,6 +267,15 @@ class TaskActivity : AppCompatActivity(), FolderSelectorCallback {
remotePath.setText(remotePathHolder)
fab.visibility = View.VISIBLE
}
private fun selectFilter(filterId: Long) {
prepareFilterDropdown()

for ((i, filter) in filterItems.withIndex()) {
if (filter.id == filterId) {
filterDropdown.setSelection(i + 1)
}
}
}

private fun prepareLocal() {
existingTask.let {
Expand Down Expand Up @@ -271,6 +327,78 @@ class TaskActivity : AppCompatActivity(), FolderSelectorCallback {
}
}
}
private fun prepareFilterDropdown() {
val filterList = filterItems.toMutableList()

if(filterList.isEmpty()) {
createNewFilterButton.visibility = View.VISIBLE
filterDropdown.visibility = View.INVISIBLE
}
else {
val titles = mutableListOf<String?>().apply {
add(getString(R.string.task_edit_filter_nofilter))
addAll(filterList.map { it.title })
}

val adapter = FilterSpinnerAdapter(this, android.R.layout.simple_spinner_dropdown_item, titles)
filterDropdown.adapter = adapter
createNewFilterButton.visibility = View.INVISIBLE
filterDropdown.visibility = View.VISIBLE

if (existingTask != null) {
for ((i, filter) in filterList.withIndex()) {
if (filter.id == existingTask!!.filterId) {
filterDropdown.setSelection(i + 1)
}
}
}

filterDropdown.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parentView: AdapterView<*>?, selectedItemView: View, position: Int, id: Long) {
selectedFilter = if (position > 0 && position < titles.size) filterItems[position - 1] else null
}
override fun onNothingSelected(parentView: AdapterView<*>?) {}
}
}
}

private fun showFilterMenu(view: View, filter: Filter?) {
val popupMenu = PopupMenu(this, view)
popupMenu.menuInflater.inflate(R.menu.filter_item_menu, popupMenu.menu)
val menu = popupMenu.menu
for (i in 0 until menu.size()) {
val menuItem = menu.getItem(i)
if (menuItem.itemId == R.id.action_edit_filter ||
menuItem.itemId == R.id.action_delete_filter) {
menuItem.isVisible = filter != null
}
}
popupMenu.setOnMenuItemClickListener { item: MenuItem ->
when (item.itemId) {
R.id.action_create_new_filter -> {
openFilterActivity()
}
R.id.action_edit_filter -> {
openFilterActivity(filter)
}
R.id.action_delete_filter -> {
dbHandler.deleteFilter(filter!!.id)
filterDropdown.setSelection(0)
prepareFilterDropdown()
}
else -> return@setOnMenuItemClickListener false
}
true
}
popupMenu.show()
}
private fun openFilterActivity(filter: Filter? = null) {
val intent = Intent(this, FilterActivity::class.java)
if(filter != null) {
intent.putExtra(FilterActivity.ID_EXTRA, filter.id)
}
startActivityForResult(intent, REQUEST_CODE_FILTER)
}

private fun prepareSyncDirectionDropdown() {
val options = SyncDirectionObject.getOptionsArray(this)
Expand Down Expand Up @@ -313,6 +441,7 @@ class TaskActivity : AppCompatActivity(), FolderSelectorCallback {
const val ID_EXTRA = "TASK_EDIT_ID"
const val REQUEST_CODE_FP_LOCAL = 500
const val REQUEST_CODE_FP_REMOTE = 444
const val REQUEST_CODE_FILTER = 333

}
}
Loading