Commit b10b5495 authored by Daniel Wolf's avatar Daniel Wolf
Browse files

Merge branch '115-add-auto-updating-to-the-dns-rules' into 'master'

Resolve "Add auto-updating to the dns rules"

Closes #115

See merge request !36
parents 6a472bfa 59248475
Pipeline #5074 passed with stage
in 1 minute and 50 seconds
......@@ -111,6 +111,7 @@ dependencies {
implementation 'com.frostnerd.utilskt:general:1.0.16' // https://git.frostnerd.com/AndroidUtils/generalkt (Accessible after logging in [free of charge])
implementation 'com.frostnerd.utilskt:adapters:1.1.1' // https://git.frostnerd.com/AndroidUtils/Adapters (Accessible after logging in [free of charge])
implementation 'androidx.work:work-runtime:2.2.0-rc01'
implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
implementation "androidx.preference:preference:1.1.0-rc01"
implementation "com.google.android.material:material:1.1.0-alpha09"
......
package com.frostnerd.smokescreen.dialog
import android.content.Context
import android.content.DialogInterface
import android.view.View
import android.widget.ArrayAdapter
import androidx.annotation.Keep
import androidx.appcompat.app.AlertDialog
import com.frostnerd.smokescreen.R
import com.frostnerd.smokescreen.getPreferences
import kotlinx.android.synthetic.main.dialog_host_source_refresh.view.*
/*
* Copyright (C) 2019 Daniel Wolf (Ch4t4r)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* You can contact the developer at daniel.wolf@frostnerd.com.
*/
class HostSourceRefreshDialog(context:Context,
runRefresh:() -> Unit,
refreshConfigChanged:() -> Unit):AlertDialog(context, context.getPreferences().theme.dialogStyle) {
init {
setTitle(R.string.dialog_hostsourcerefresh_title)
val view = layoutInflater.inflate(R.layout.dialog_host_source_refresh, null, false)
setView(view)
view.refreshNow.setOnClickListener {
runRefresh()
}
val changeAutomaticRefreshStatus:(Boolean) -> Unit = { isChecked ->
view.refreshWifiOnly.isEnabled = isChecked
view.timeAmountTil.isEnabled = isChecked
view.timeUnit.isEnabled = isChecked
view.refreshTimeWrap.visibility = if(isChecked) View.VISIBLE else View.INVISIBLE
}
view.automaticRefresh.setOnCheckedChangeListener { _, isChecked ->
changeAutomaticRefreshStatus(isChecked)
}
changeAutomaticRefreshStatus(view.automaticRefresh.isChecked)
val adapter: ArrayAdapter<CharSequence> = ArrayAdapter.createFromResource(
context,
R.array.dialog_hostsourcerefresh_timeunits,
R.layout.item_tasker_action_spinner_item
)
adapter.setDropDownViewResource(R.layout.item_tasker_action_spinner_dropdown_item)
view.timeUnit.adapter = adapter
view.automaticRefresh.isChecked = context.getPreferences().automaticHostRefresh
view.refreshWifiOnly.isChecked = context.getPreferences().automaticHostRefreshWifiOnly
view.timeAmount.setText(context.getPreferences().automaticHostRefreshTimeAmount.toString())
view.timeUnit.setSelection(context.getPreferences().automaticHostRefreshTimeUnit.ordinal)
setButton(DialogInterface.BUTTON_NEUTRAL, context.getString(android.R.string.cancel)) { dialog, _ ->
dialog.dismiss()
}
setButton(DialogInterface.BUTTON_POSITIVE, context.getString(android.R.string.ok)) { dialog, _ ->
dialog.dismiss()
context.getPreferences().automaticHostRefresh = view.automaticRefresh.isChecked
context.getPreferences().automaticHostRefreshWifiOnly = view.refreshWifiOnly.isChecked
context.getPreferences().automaticHostRefreshTimeAmount = view.timeAmount.text.toString().toIntOrNull() ?: 1
context.getPreferences().automaticHostRefreshTimeUnit = TimeUnit.values().find { it.ordinal == view.timeUnit.selectedItemPosition }!!
refreshConfigChanged()
}
}
@Keep
enum class TimeUnit {
MINUTES, HOURS, DAYS, WEEKS
}
}
\ No newline at end of file
......@@ -12,6 +12,10 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.work.Constraints
import androidx.work.NetworkType
import androidx.work.PeriodicWorkRequest
import androidx.work.WorkManager
import com.frostnerd.cacheadapter.ListDataSource
import com.frostnerd.cacheadapter.ModelAdapterBuilder
import com.frostnerd.general.service.isServiceRunning
......@@ -23,12 +27,15 @@ import com.frostnerd.smokescreen.database.entities.HostSource
import com.frostnerd.smokescreen.database.getDatabase
import com.frostnerd.smokescreen.dialog.DnsRuleDialog
import com.frostnerd.smokescreen.dialog.ExportDnsRulesDialog
import com.frostnerd.smokescreen.dialog.HostSourceRefreshDialog
import com.frostnerd.smokescreen.dialog.NewHostSourceDialog
import com.frostnerd.smokescreen.service.RuleExportService
import com.frostnerd.smokescreen.service.RuleImportService
import com.frostnerd.smokescreen.util.SpaceItemDecorator
import com.frostnerd.smokescreen.util.worker.RuleImportStartWorker
import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.activity_dns_rules.*
import kotlinx.android.synthetic.main.dialog_host_source_refresh.*
import kotlinx.android.synthetic.main.item_datasource.view.*
import kotlinx.android.synthetic.main.item_datasource.view.cardContent
import kotlinx.android.synthetic.main.item_datasource.view.delete
......@@ -39,6 +46,8 @@ import kotlinx.android.synthetic.main.item_dnsrule_host.view.*
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import java.time.Duration
import java.util.concurrent.TimeUnit
/*
* Copyright (C) 2019 Daniel Wolf (Ch4t4r)
......@@ -118,13 +127,46 @@ class DnsRuleFragment : Fragment() {
}).show()
}
refresh.setOnClickListener {
if(context!!.isServiceRunning(RuleImportService::class.java)) {
context!!.startService(Intent(context!!, RuleImportService::class.java).putExtra("abort", true))
} else {
context!!.startService(Intent(context!!, RuleImportService::class.java))
refreshProgress.show()
refreshProgressShown = true
}
HostSourceRefreshDialog(context!!,runRefresh = {
if(context!!.isServiceRunning(RuleImportService::class.java)) {
context!!.startService(Intent(context!!, RuleImportService::class.java).putExtra("abort", true))
} else {
context!!.startService(Intent(context!!, RuleImportService::class.java))
refreshProgress.show()
refreshProgressShown = true
}
}, refreshConfigChanged = {
getPreferences().apply {
val constraints = Constraints.Builder()
.setRequiresStorageNotLow(true)
.setRequiresBatteryNotLow(true)
.setRequiredNetworkType(if (this.automaticHostRefreshWifiOnly) NetworkType.UNMETERED else NetworkType.CONNECTED)
.build()
val mappedTimeAmount = automaticHostRefreshTimeAmount.let {
if (automaticHostRefreshTimeUnit == HostSourceRefreshDialog.TimeUnit.WEEKS) it * 7
else it
}.toLong()
val mappedTimeUnit = automaticHostRefreshTimeUnit.let {
when (it) {
HostSourceRefreshDialog.TimeUnit.WEEKS -> TimeUnit.DAYS
HostSourceRefreshDialog.TimeUnit.DAYS -> TimeUnit.DAYS
HostSourceRefreshDialog.TimeUnit.HOURS -> TimeUnit.HOURS
HostSourceRefreshDialog.TimeUnit.MINUTES -> TimeUnit.MINUTES
}
}
val workRequest = PeriodicWorkRequest.Builder(RuleImportStartWorker::class.java,
mappedTimeAmount,
mappedTimeUnit)
.setConstraints(constraints)
.setInitialDelay(mappedTimeAmount, mappedTimeUnit)
.addTag("hostSourceRefresh")
WorkManager.getInstance(context!!).apply {
cancelAllWorkByTag("hostSourceRefresh")
enqueue(workRequest.build())
}
}
}).show()
}
export.setOnClickListener {
if (context!!.isServiceRunning(RuleExportService::class.java)) {
......
......@@ -11,6 +11,7 @@ import com.frostnerd.preferenceskt.typedpreferences.cache.ExpirationCacheControl
import com.frostnerd.preferenceskt.typedpreferences.cache.buildCacheStrategy
import com.frostnerd.preferenceskt.typedpreferences.types.*
import com.frostnerd.smokescreen.BuildConfig
import com.frostnerd.smokescreen.dialog.HostSourceRefreshDialog
import java.util.*
/*
......@@ -243,6 +244,11 @@ class AppSettingsSharedPreferences(context: Context) : AppSettings, SimpleTypedP
var vpnServiceState:VpnServiceState by enumPref("vpn_service_state", VpnServiceState.STOPPED)
var ignoreServiceKilled:Boolean by booleanPref("ignore_service_killed", false)
var automaticHostRefresh:Boolean by booleanPref("automatic_host_refresh", false)
var automaticHostRefreshWifiOnly:Boolean by booleanPref("automatic_host_refresh_wifi_only", true)
var automaticHostRefreshTimeUnit:HostSourceRefreshDialog.TimeUnit by enumPref("automatic_host_refresh_timeunit", HostSourceRefreshDialog.TimeUnit.HOURS)
var automaticHostRefreshTimeAmount:Int by intPref("automatic_host_refresh_timeamount", 12)
}
fun AppSettings.Companion.fromSharedPreferences(context: Context): AppSettingsSharedPreferences {
......
package com.frostnerd.smokescreen.util.worker
import android.content.Context
import android.content.Intent
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.frostnerd.smokescreen.service.RuleImportService
import com.frostnerd.smokescreen.startForegroundServiceCompat
/*
* Copyright (C) 2019 Daniel Wolf (Ch4t4r)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* You can contact the developer at daniel.wolf@frostnerd.com.
*/
class RuleImportStartWorker(appContext: Context, workerParams: WorkerParameters)
: Worker(appContext, workerParams) {
override fun doWork(): Result {
applicationContext.startForegroundServiceCompat(Intent(applicationContext, RuleImportService::class.java))
return Result.success()
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
android:layout_width="match_parent"
android:paddingLeft="@dimen/dialog_horizontal_margin"
android:paddingRight="@dimen/dialog_horizontal_margin"
android:paddingTop="@dimen/dialog_vertical_margin"
android:paddingBottom="@dimen/dialog_vertical_margin"
android:layout_height="match_parent">
<CheckBox
android:layout_width="wrap_content"
android:text="@string/dialog_hostsourcerefresh_automatic_refresh"
android:textColor="?android:attr/textColor"
android:id="@+id/automaticRefresh"
android:layout_height="wrap_content"/>
<CheckBox
android:layout_width="wrap_content"
android:text="@string/dialog_hostsourcerefresh_wifi_only"
android:textColor="?android:attr/textColor"
android:id="@+id/refreshWifiOnly"
android:layout_height="wrap_content"/>
<LinearLayout
android:layout_width="match_parent"
android:id="@+id/refreshTimeWrap"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/dialog_hostsourcerefresh_refresh_every"
android:layout_height="wrap_content"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.textfield.TextInputLayout
android:layout_width="wrap_content"
android:id="@+id/timeAmountTil"
android:layout_alignParentTop="true"
android:minWidth="48dp"
android:layout_height="wrap_content">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:id="@+id/timeAmount"
android:inputType="numberSigned"
android:imeOptions="actionNext"
android:text="12"
android:maxLines="1"
android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout>
<Spinner
android:layout_width="wrap_content"
android:layout_alignParentEnd="true"
android:layout_toEndOf="@id/timeAmountTil"
android:id="@+id/timeUnit"
android:layout_marginStart="8dp"
android:layout_alignBaseline="@id/timeAmountTil"
android:layout_height="wrap_content"/>
</RelativeLayout>
</LinearLayout>
<Button
android:layout_width="match_parent"
android:background="@drawable/main_roundbuttons"
android:id="@+id/refreshNow"
android:layout_marginTop="16dp"
android:text="@string/dialog_hostsourcerefresh_refresh_now"
style="@style/Base.Widget.AppCompat.Button.Borderless.Colored"
android:layout_height="wrap_content"/>
</LinearLayout>
\ No newline at end of file
......@@ -157,4 +157,21 @@
<string name="dialog_overlaydetected_title">System-wide overlay detected</string>
<string name="dialog_overlaydetected_message">There seems to be a system-wide overlay (e.g. a chat bubble, color- or nightfilter) active. Most device don\'t allow you to enable a VPN in this case.\n\nIf you can\'t click OK in the next dialog please disable the overlay.</string>
<string name="dialog_hostsourcerefresh_title">Refresh host sources</string>
<string name="dialog_hostsourcerefresh_automatic_refresh">Automatically refresh host sources</string>
<string name="dialog_hostsourcerefresh_wifi_only">Refresh on WIFI only</string>
<string name="dialog_hostsourcerefresh_refresh_every">Refresh every</string>
<string name="dialog_hostsourcerefresh_refresh_now">Refresh now</string>
<string name="dialog_hostsourcerefresh_timeunit_minutes">Minutes</string>
<string name="dialog_hostsourcerefresh_timeunit_hours">Hours</string>
<string name="dialog_hostsourcerefresh_timeunit_days">Days</string>
<string name="dialog_hostsourcerefresh_timeunit_weeks">Weeks</string>
<string-array name="dialog_hostsourcerefresh_timeunits">
<item>@string/dialog_hostsourcerefresh_timeunit_minutes</item>
<item>@string/dialog_hostsourcerefresh_timeunit_hours</item>
<item>@string/dialog_hostsourcerefresh_timeunit_days</item>
<item>@string/dialog_hostsourcerefresh_timeunit_weeks</item>
</string-array>
</resources>
Markdown is supported
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