Commit 2f6321fd authored by Daniel Wolf's avatar Daniel Wolf
Browse files

Show user-defined rules on the top

Implements #282
parent 2b7ac69f
...@@ -155,7 +155,7 @@ dependencies { ...@@ -155,7 +155,7 @@ dependencies {
implementation 'com.frostnerd.utilskt:navigationdraweractivity:1.4.2' // https://git.frostnerd.com/AndroidUtils/navigationdraweractivity implementation 'com.frostnerd.utilskt:navigationdraweractivity:1.4.2' // https://git.frostnerd.com/AndroidUtils/navigationdraweractivity
implementation 'com.frostnerd.utilskt:encrypteddnstunnelproxy:2.1.23' // https://git.frostnerd.com/AndroidUtils/encrypteddnstunnelproxy implementation 'com.frostnerd.utilskt:encrypteddnstunnelproxy:2.1.23' // https://git.frostnerd.com/AndroidUtils/encrypteddnstunnelproxy
implementation 'com.frostnerd.utilskt:general:1.0.25' // https://git.frostnerd.com/AndroidUtils/generalkt implementation 'com.frostnerd.utilskt:general:1.0.25' // https://git.frostnerd.com/AndroidUtils/generalkt
implementation 'com.frostnerd.utilskt:adapters:1.2.0' // https://git.frostnerd.com/AndroidUtils/Adapters implementation 'com.frostnerd.utilskt:adapters:1.3.4' // https://git.frostnerd.com/AndroidUtils/Adapters
implementation 'androidx.work:work-runtime:2.4.0' implementation 'androidx.work:work-runtime:2.4.0'
implementation 'androidx.appcompat:appcompat:1.3.0-alpha02' implementation 'androidx.appcompat:appcompat:1.3.0-alpha02'
......
...@@ -79,6 +79,8 @@ class DnsRuleFragment : Fragment() { ...@@ -79,6 +79,8 @@ class DnsRuleFragment : Fragment() {
private var userRulesJob: Job? = null private var userRulesJob: Job? = null
private var totalRuleCount:Long? = null private var totalRuleCount:Long? = null
private var importSourceSnackbar:Snackbar? = null private var importSourceSnackbar:Snackbar? = null
var showUserRules = false
var userRuleCount = 0
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
...@@ -117,7 +119,8 @@ class DnsRuleFragment : Fragment() { ...@@ -117,7 +119,8 @@ class DnsRuleFragment : Fragment() {
} }
} }
sourceAdapterList.add(insertPos, newSource) sourceAdapterList.add(insertPos, newSource)
sourceAdapter.notifyItemInserted(insertPos) val offset = 1 + if(showUserRules) userRuleCount else 0
sourceAdapter.notifyItemInserted(offset + insertPos)
list.scrollToPosition(insertPos) list.scrollToPosition(insertPos)
newSource.id = getDatabase().hostSourceDao().insert(newSource) newSource.id = getDatabase().hostSourceDao().insert(newSource)
importSourceSnackbar = Snackbar.make(contentFrame, R.string.window_dnsrules_refresh_sources, Snackbar.LENGTH_INDEFINITE) importSourceSnackbar = Snackbar.make(contentFrame, R.string.window_dnsrules_refresh_sources, Snackbar.LENGTH_INDEFINITE)
...@@ -210,9 +213,7 @@ class DnsRuleFragment : Fragment() { ...@@ -210,9 +213,7 @@ class DnsRuleFragment : Fragment() {
sourceRuleCount = sourceAdapterList.map { sourceRuleCount = sourceAdapterList.map {
it to (null as Int?) it to (null as Int?)
}.toMap().toMutableMap() }.toMap().toMutableMap()
adapterDataSource = ListDataSource(sourceAdapterList) adapterDataSource = ListDataSource(sourceAdapterList, listOf(0))
var showUserRules = false
var userRuleCount = 0
sourceAdapter = ModelAdapterBuilder.withModelAndViewHolder({ itemView, type -> sourceAdapter = ModelAdapterBuilder.withModelAndViewHolder({ itemView, type ->
when (type) { when (type) {
0 -> SourceViewHolder(itemView, deleteSource = { 0 -> SourceViewHolder(itemView, deleteSource = {
...@@ -221,9 +222,10 @@ class DnsRuleFragment : Fragment() { ...@@ -221,9 +222,10 @@ class DnsRuleFragment : Fragment() {
getString(R.string.dialog_deletehostsource_message, it.name), getString(R.string.dialog_deletehostsource_message, it.name),
getString(R.string.all_yes) to { dialog, _ -> getString(R.string.all_yes) to { dialog, _ ->
val pos = sourceAdapterList.indexOf(it) val pos = sourceAdapterList.indexOf(it)
if(pos >= 0) { if (pos >= 0) {
val offset = 1 + if (showUserRules) userRuleCount else 0
sourceAdapterList.removeAt(pos) sourceAdapterList.removeAt(pos)
sourceAdapter.notifyItemRemoved(pos) sourceAdapter.notifyItemRemoved(offset + pos)
} }
GlobalScope.launch { GlobalScope.launch {
getDatabase().dnsRuleDao().deleteAllFromSource(it.id) getDatabase().dnsRuleDao().deleteAllFromSource(it.id)
...@@ -248,7 +250,8 @@ class DnsRuleFragment : Fragment() { ...@@ -248,7 +250,8 @@ class DnsRuleFragment : Fragment() {
}?.also { source -> }?.also { source ->
getDatabase().hostSourceDao().update(source) getDatabase().hostSourceDao().update(source)
val index = sourceAdapterList.indexOf(hostSource).takeIf { it >= 0 } ?: sourceAdapterList.indexOfFirst { it.id == hostSource.id } val index = sourceAdapterList.indexOf(hostSource).takeIf { it >= 0 }
?: sourceAdapterList.indexOfFirst { it.id == hostSource.id }
sourceAdapterList[index] = source sourceAdapterList[index] = source
sourceRuleCount[source] = sourceRuleCount[hostSource] sourceRuleCount[source] = sourceRuleCount[hostSource]
sourceRuleCount.remove(hostSource) sourceRuleCount.remove(hostSource)
...@@ -263,7 +266,12 @@ class DnsRuleFragment : Fragment() { ...@@ -263,7 +266,12 @@ class DnsRuleFragment : Fragment() {
}, hostSource = hostSource).show() }, hostSource = hostSource).show()
}, refreshSource = { }, refreshSource = {
importSourceSnackbar?.dismiss() importSourceSnackbar?.dismiss()
requireContext().startService(Intent(requireContext(), RuleImportService::class.java).putExtra("sources", longArrayOf(it.id))) requireContext().startService(
Intent(
requireContext(),
RuleImportService::class.java
).putExtra("sources", longArrayOf(it.id))
)
refreshProgress.show() refreshProgress.show()
refreshProgressShown = true refreshProgressShown = true
}) })
...@@ -280,7 +288,7 @@ class DnsRuleFragment : Fragment() { ...@@ -280,7 +288,7 @@ class DnsRuleFragment : Fragment() {
getDatabase().dnsRuleRepository().deleteAllUserRulesAsync() getDatabase().dnsRuleRepository().deleteAllUserRulesAsync()
userDnsRules = mutableListOf() userDnsRules = mutableListOf()
if (showUserRules) { if (showUserRules) {
sourceAdapter.notifyItemRangeRemoved(sourceAdapterList.size + 1, userRuleCount) sourceAdapter.notifyItemRangeRemoved(1, userRuleCount)
} }
userRuleCount = 0 userRuleCount = 0
notifyRulesChanged() notifyRulesChanged()
...@@ -293,20 +301,22 @@ class DnsRuleFragment : Fragment() { ...@@ -293,20 +301,22 @@ class DnsRuleFragment : Fragment() {
changeRuleVisibility = { changeRuleVisibility = {
val changeVisibility = { val changeVisibility = {
showUserRules = !showUserRules showUserRules = !showUserRules
println("SHOW: $showUserRules")
if (showUserRules) { if (showUserRules) {
userRuleCount = userDnsRules.size userRuleCount = userDnsRules.size
activity?.runOnUiThread { adapterDataSource.nonSourcePositions = (0..userRuleCount).toList()
sourceAdapter.notifyItemRangeInserted(sourceAdapterList.size + 1, userRuleCount) if (userRuleCount > 0) activity?.runOnUiThread {
list.smoothScrollToPosition(sourceAdapterList.size + 1) sourceAdapter.notifyItemRangeInserted(1, userRuleCount)
} }
} else { } else {
activity?.runOnUiThread { adapterDataSource.nonSourcePositions = listOf(0)
sourceAdapter.notifyItemRangeRemoved(sourceAdapterList.size + 1, userRuleCount) if (userRuleCount > 0) activity?.runOnUiThread {
sourceAdapter.notifyItemRangeRemoved(1, userRuleCount)
} }
userRuleCount = 0 userRuleCount = 0
} }
} }
if(userRulesJob == null) changeVisibility() if (userRulesJob == null) changeVisibility()
else launchWithLifecycle { else launchWithLifecycle {
userRulesJob?.join() userRulesJob?.join()
changeVisibility() changeVisibility()
...@@ -337,14 +347,17 @@ class DnsRuleFragment : Fragment() { ...@@ -337,14 +347,17 @@ class DnsRuleFragment : Fragment() {
showUserRules = true showUserRules = true
if (wereRulesShown) { if (wereRulesShown) {
userRuleCount += 1 userRuleCount += 1
adapterDataSource.nonSourcePositions += (1 + insertPos)
activity?.runOnUiThread { activity?.runOnUiThread {
sourceAdapter.notifyItemInserted(sourceAdapterList.size + 1 + insertPos) sourceAdapter.notifyItemInserted(1 + insertPos)
} }
} else { } else {
userRuleCount = userDnsRules.size userRuleCount = userDnsRules.size
activity?.runOnUiThread { activity?.runOnUiThread {
sourceAdapter.notifyItemChanged(sourceAdapterList.size) adapterDataSource.nonSourcePositions =
sourceAdapter.notifyItemRangeInserted(sourceAdapterList.size + 1, userRuleCount) (0..userRuleCount).toList()
sourceAdapter.notifyItemChanged(0)
sourceAdapter.notifyItemRangeInserted(1, userRuleCount)
list.smoothScrollToPosition(insertPos) list.smoothScrollToPosition(insertPos)
} }
} }
...@@ -357,7 +370,7 @@ class DnsRuleFragment : Fragment() { ...@@ -357,7 +370,7 @@ class DnsRuleFragment : Fragment() {
).show() ).show()
} }
} }
if(userRulesJob == null) insert() if (userRulesJob == null) insert()
else GlobalScope.launch { else GlobalScope.launch {
userRulesJob?.join() userRulesJob?.join()
insert() insert()
...@@ -369,8 +382,8 @@ class DnsRuleFragment : Fragment() { ...@@ -369,8 +382,8 @@ class DnsRuleFragment : Fragment() {
userDnsRules.remove(it) userDnsRules.remove(it)
getDatabase().dnsRuleRepository().removeAsync(it) getDatabase().dnsRuleRepository().removeAsync(it)
userRuleCount -= 1 userRuleCount -= 1
sourceAdapter.notifyItemRemoved(sourceAdapterList.size + 1 + index) sourceAdapter.notifyItemRemoved(1 + index)
if(totalRuleCount != null) { if (totalRuleCount != null) {
totalRuleCount = totalRuleCount!! - 1 totalRuleCount = totalRuleCount!! - 1
updateRuleCountTitle() updateRuleCountTitle()
} }
...@@ -381,7 +394,7 @@ class DnsRuleFragment : Fragment() { ...@@ -381,7 +394,7 @@ class DnsRuleFragment : Fragment() {
if (rows > 0) { if (rows > 0) {
val index = userDnsRules.indexOf(it) val index = userDnsRules.indexOf(it)
userDnsRules[index] = newRule userDnsRules[index] = newRule
sourceAdapter.notifyItemChanged(sourceAdapterList.size + 1 + index) sourceAdapter.notifyItemChanged(1 + index)
} else { } else {
Snackbar.make( Snackbar.make(
requireActivity().findViewById(android.R.id.content), requireActivity().findViewById(android.R.id.content),
...@@ -405,7 +418,7 @@ class DnsRuleFragment : Fragment() { ...@@ -405,7 +418,7 @@ class DnsRuleFragment : Fragment() {
) )
} }
getItemCount = { getItemCount = {
sourceAdapterList.size + 1 + userRuleCount sourceAdapterList.size + 1 + if(showUserRules) userRuleCount else 0
} }
bindModelView = { viewHolder, position, data -> bindModelView = { viewHolder, position, data ->
(viewHolder as SourceViewHolder).display(data) (viewHolder as SourceViewHolder).display(data)
...@@ -426,8 +439,11 @@ class DnsRuleFragment : Fragment() { ...@@ -426,8 +439,11 @@ class DnsRuleFragment : Fragment() {
data.enabled -> launchWithLifecycle { data.enabled -> launchWithLifecycle {
val prev = sourceRuleCount[data] val prev = sourceRuleCount[data]
sourceRuleCount[data] = getDatabase().dnsRuleDao().getCountForHostSource(data.id) sourceRuleCount[data] = getDatabase().dnsRuleDao().getCountForHostSource(data.id)
if(prev != sourceRuleCount[data]) runOnUiThread { if(prev != sourceRuleCount[data]) {
sourceAdapter.notifyItemChanged(position) val offset = 1 + if(showUserRules) userRuleCount else 0
runOnUiThread {
sourceAdapter.notifyItemChanged(offset + position)
}
} }
} }
else -> viewHolder.ruleCount.text = getString(R.string.window_dnsrules_customhosts_hostsource_rulecount_pending) else -> viewHolder.ruleCount.text = getString(R.string.window_dnsrules_customhosts_hostsource_rulecount_pending)
...@@ -441,20 +457,19 @@ class DnsRuleFragment : Fragment() { ...@@ -441,20 +457,19 @@ class DnsRuleFragment : Fragment() {
viewHolder.elementsShown = true viewHolder.elementsShown = true
} }
} else if(viewHolder is CustomRuleHostViewHolder) { } else if(viewHolder is CustomRuleHostViewHolder) {
viewHolder.display(userDnsRules[position - sourceAdapterList.size - 1]) viewHolder.display(userDnsRules[position - 1])
} }
} }
getViewType = { position -> getViewType = { position ->
when { when {
position < sourceAdapterList.size -> 0 position == 0 -> 1
position == sourceAdapterList.size -> 1 showUserRules && position <= userRuleCount -> 2
else -> 2 else -> 0
} }
} }
runOnUiThread = { runOnUiThread = {
activity?.runOnUiThread(it) activity?.runOnUiThread(it)
} }
}.build() }.build()
list.layoutManager = LinearLayoutManager(requireContext()) list.layoutManager = LinearLayoutManager(requireContext())
list.recycledViewPool.setMaxRecycledViews(1, 1) list.recycledViewPool.setMaxRecycledViews(1, 1)
...@@ -495,10 +510,11 @@ class DnsRuleFragment : Fragment() { ...@@ -495,10 +510,11 @@ class DnsRuleFragment : Fragment() {
launchWithLifecycle { launchWithLifecycle {
sourceRuleCount.keys.forEach { sourceRuleCount.keys.forEach {
val index = sourceAdapterList.indexOf(it) val index = sourceAdapterList.indexOf(it)
val offset = 1 + if(showUserRules) userRuleCount else 0
if(index >= 0 && (sourceAdapterList[index].enabled || sourceRuleCount[it] != null)) { if(index >= 0 && (sourceAdapterList[index].enabled || sourceRuleCount[it] != null)) {
sourceRuleCount[it] = null sourceRuleCount[it] = null
launchUi { launchUi {
sourceAdapter.notifyItemChanged(index) sourceAdapter.notifyItemChanged(offset + index)
} }
} else sourceRuleCount[it] = null } else sourceRuleCount[it] = null
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
app:cardElevation="0dp" app:cardElevation="0dp"
app:cardCornerRadius="6dp" app:cardCornerRadius="6dp"
android:layout_marginBottom="12dp" android:layout_marginBottom="8dp"
app:cardBackgroundColor="?inputElementColor" app:cardBackgroundColor="?inputElementColor"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment