Migrate from kotlin-android-extensions (synthetics) to data binding
This commit is contained in:
parent
3164bee01b
commit
53cd8c7312
18 changed files with 213 additions and 148 deletions
|
@ -1,6 +1,22 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<JetCodeStyleSettings>
|
||||
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
||||
<value>
|
||||
<package name="java.util" alias="false" withSubpackages="false" />
|
||||
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
|
||||
<package name="io.ktor" alias="false" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="PACKAGES_IMPORT_LAYOUT">
|
||||
<value>
|
||||
<package name="" alias="false" withSubpackages="true" />
|
||||
<package name="java" alias="false" withSubpackages="true" />
|
||||
<package name="javax" alias="false" withSubpackages="true" />
|
||||
<package name="kotlin" alias="false" withSubpackages="true" />
|
||||
<package name="" alias="true" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</JetCodeStyleSettings>
|
||||
<codeStyleSettings language="XML">
|
||||
|
|
6
.idea/compiler.xml
Normal file
6
.idea/compiler.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="1.8" />
|
||||
</component>
|
||||
</project>
|
|
@ -15,6 +15,7 @@
|
|||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
<option name="useQualifiedModuleNames" value="true" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
|
|
25
.idea/jarRepositories.xml
Normal file
25
.idea/jarRepositories.xml
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RemoteRepositoriesConfiguration">
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Maven Central repository" />
|
||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="jboss.community" />
|
||||
<option name="name" value="JBoss Community repository" />
|
||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="BintrayJCenter" />
|
||||
<option name="name" value="BintrayJCenter" />
|
||||
<option name="url" value="https://jcenter.bintray.com/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="Google" />
|
||||
<option name="name" value="Google" />
|
||||
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
9
.idea/kotlinScripting.xml
Normal file
9
.idea/kotlinScripting.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KotlinScriptingSettings">
|
||||
<scriptDefinition className="org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate" definitionName="KotlinBuildScript">
|
||||
<order>2147483647</order>
|
||||
<autoReloadConfigurations>true</autoReloadConfigurations>
|
||||
</scriptDefinition>
|
||||
</component>
|
||||
</project>
|
|
@ -5,7 +5,7 @@
|
|||
<configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" />
|
||||
</configurations>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
def keystoreProperties = new Properties()
|
||||
try {
|
||||
|
@ -47,6 +46,9 @@ android {
|
|||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
@ -54,17 +56,17 @@ dependencies {
|
|||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
||||
implementation "org.koin:koin-androidx-viewmodel:$koin_version"
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.core:core-ktx:1.2.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation 'com.google.android.material:material:1.2.0-alpha06'
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
implementation 'androidx.core:core-ktx:1.3.2'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||
implementation 'com.google.android.material:material:1.3.0-alpha04'
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
implementation 'androidx.security:security-crypto:1.0.0-rc01'
|
||||
implementation 'androidx.preference:preference:1.1.1'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
def navigation_version = '2.2.2'
|
||||
implementation 'androidx.preference:preference-ktx:1.1.1'
|
||||
testImplementation 'junit:junit:4.13.1'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||
def navigation_version = '2.3.2'
|
||||
implementation "androidx.navigation:navigation-fragment-ktx:$navigation_version"
|
||||
implementation "androidx.navigation:navigation-ui-ktx:$navigation_version"
|
||||
def lifecycle_version = '2.2.0'
|
||||
|
|
|
@ -10,45 +10,47 @@ import android.view.animation.LinearInterpolator
|
|||
import android.view.animation.RotateAnimation
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.FragmentNavigatorExtras
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import kotlinx.android.synthetic.main.fragment_add_pi_hole.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import com.wbrawner.pihelper.databinding.FragmentAddPiHoleBinding
|
||||
import org.koin.android.ext.android.inject
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class AddPiHoleFragment : Fragment(), CoroutineScope {
|
||||
class AddPiHoleFragment : Fragment() {
|
||||
|
||||
override val coroutineContext: CoroutineContext = Dispatchers.Main
|
||||
private val viewModel: AddPiHelperViewModel by inject()
|
||||
private var _binding: FragmentAddPiHoleBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? = inflater.inflate(R.layout.fragment_add_pi_hole, container, false)
|
||||
): View {
|
||||
_binding = FragmentAddPiHoleBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
val navController = findNavController()
|
||||
scanNetworkButton.setOnClickListener {
|
||||
binding.scanNetworkButton.setOnClickListener {
|
||||
navController.navigate(
|
||||
R.id.action_addPiHoleFragment_to_scanNetworkFragment,
|
||||
null,
|
||||
null,
|
||||
FragmentNavigatorExtras(piHelperLogo to "piHelperLogo")
|
||||
FragmentNavigatorExtras(binding.piHelperLogo to "piHelperLogo")
|
||||
)
|
||||
}
|
||||
ipAddress.setOnEditorActionListener { _, _, _ ->
|
||||
connectButton.performClick()
|
||||
binding.ipAddress.setOnEditorActionListener { _, _, _ ->
|
||||
binding.connectButton.performClick()
|
||||
}
|
||||
connectButton.setSuspendingOnClickListener(this) {
|
||||
binding.connectButton.setSuspendingOnClickListener(lifecycleScope) {
|
||||
showProgress(true)
|
||||
if (viewModel.connectToIpAddress(ipAddress.text.toString())) {
|
||||
if (viewModel.connectToIpAddress(binding.ipAddress.text.toString())) {
|
||||
navController.navigate(
|
||||
R.id.action_addPiHoleFragment_to_retrieveApiKeyFragment,
|
||||
null,
|
||||
null,
|
||||
FragmentNavigatorExtras(piHelperLogo to "piHelperLogo")
|
||||
FragmentNavigatorExtras(binding.piHelperLogo to "piHelperLogo")
|
||||
)
|
||||
} else {
|
||||
AlertDialog.Builder(view.context)
|
||||
|
@ -63,7 +65,7 @@ class AddPiHoleFragment : Fragment(), CoroutineScope {
|
|||
|
||||
private fun showProgress(show: Boolean) {
|
||||
if (show) {
|
||||
piHelperLogo.startAnimation(
|
||||
binding.piHelperLogo.startAnimation(
|
||||
RotateAnimation(
|
||||
0f,
|
||||
360f,
|
||||
|
@ -81,13 +83,13 @@ class AddPiHoleFragment : Fragment(), CoroutineScope {
|
|||
}
|
||||
)
|
||||
} else {
|
||||
piHelperLogo.clearAnimation()
|
||||
binding.piHelperLogo.clearAnimation()
|
||||
}
|
||||
connectionForm.visibility = if (show) View.GONE else View.VISIBLE
|
||||
binding.connectionForm.visibility = if (show) View.GONE else View.VISIBLE
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
cancel()
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,16 +15,13 @@ import androidx.appcompat.app.AppCompatActivity
|
|||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.wbrawner.pihelper.MainActivity.Companion.ACTION_FORGET_PIHOLE
|
||||
import kotlinx.android.synthetic.main.fragment_info.*
|
||||
import kotlinx.android.synthetic.main.fragment_main.toolbar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import com.wbrawner.pihelper.databinding.FragmentInfoBinding
|
||||
import org.koin.android.ext.android.inject
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class InfoFragment : Fragment(), CoroutineScope {
|
||||
override val coroutineContext: CoroutineContext = Dispatchers.Main
|
||||
class InfoFragment : Fragment() {
|
||||
private val viewModel: AddPiHelperViewModel by inject()
|
||||
private var _binding: FragmentInfoBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
@ -34,20 +31,23 @@ class InfoFragment : Fragment(), CoroutineScope {
|
|||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? = inflater.inflate(R.layout.fragment_info, container, false)
|
||||
): View {
|
||||
_binding = FragmentInfoBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
(activity as? AppCompatActivity)?.setSupportActionBar(toolbar)
|
||||
(activity as? AppCompatActivity)?.setSupportActionBar(binding.toolbar)
|
||||
(activity as? AppCompatActivity)?.supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
(activity as? AppCompatActivity)?.supportActionBar?.setTitle(R.string.action_settings)
|
||||
val html = getString(R.string.content_info)
|
||||
@Suppress("DEPRECATION")
|
||||
infoContent?.text = if (Build.VERSION.SDK_INT < 24)
|
||||
binding.infoContent.text = if (Build.VERSION.SDK_INT < 24)
|
||||
Html.fromHtml(html)
|
||||
else
|
||||
Html.fromHtml(html, 0)
|
||||
infoContent.movementMethod = LinkMovementMethod.getInstance()
|
||||
forgetPiHoleButton?.setOnClickListener {
|
||||
binding.infoContent.movementMethod = LinkMovementMethod.getInstance()
|
||||
binding.forgetPiHoleButton.setOnClickListener {
|
||||
AlertDialog.Builder(view.context)
|
||||
.setTitle(R.string.confirm_forget_pihole)
|
||||
.setMessage(R.string.warning_cannot_be_undone)
|
||||
|
@ -77,4 +77,9 @@ class InfoFragment : Fragment(), CoroutineScope {
|
|||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import androidx.navigation.findNavController
|
|||
import com.wbrawner.pihelper.MainFragment.Companion.ACTION_DISABLE
|
||||
import com.wbrawner.pihelper.MainFragment.Companion.ACTION_ENABLE
|
||||
import com.wbrawner.pihelper.MainFragment.Companion.EXTRA_DURATION
|
||||
import com.wbrawner.pihelper.databinding.ActivityMainBinding
|
||||
import org.koin.android.ext.android.inject
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
@ -19,10 +20,9 @@ class MainActivity : AppCompatActivity() {
|
|||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
val binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
window.setBackgroundDrawable(ColorDrawable(getColor(R.color.colorSurface)))
|
||||
val analyticsBundle = Bundle()
|
||||
analyticsBundle.putString("intent_action", intent.action)
|
||||
val args = when (intent.action) {
|
||||
ACTION_ENABLE -> {
|
||||
if (addPiHoleViewModel.apiKey == null) {
|
||||
|
|
|
@ -11,32 +11,28 @@ import android.view.*
|
|||
import android.view.animation.Animation
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.view.animation.RotateAnimation
|
||||
import android.widget.EditText
|
||||
import android.widget.RadioGroup
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat.getColor
|
||||
import androidx.core.text.set
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.wbrawner.pihelper.databinding.DialogDisableCustomTimeBinding
|
||||
import com.wbrawner.pihelper.databinding.FragmentMainBinding
|
||||
import com.wbrawner.piholeclient.Status
|
||||
import kotlinx.android.synthetic.main.fragment_main.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.android.ext.android.inject
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class MainFragment : Fragment(), CoroutineScope {
|
||||
override val coroutineContext: CoroutineContext = Dispatchers.Main
|
||||
class MainFragment : Fragment() {
|
||||
private val viewModel: PiHelperViewModel by inject()
|
||||
private var _binding: FragmentMainBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
launch {
|
||||
lifecycleScope.launch {
|
||||
if (arguments?.getBoolean(ACTION_ENABLE) == true) {
|
||||
viewModel.enablePiHole()
|
||||
} else if (arguments?.getBoolean(ACTION_DISABLE) == true) {
|
||||
|
@ -44,52 +40,53 @@ class MainFragment : Fragment(), CoroutineScope {
|
|||
}
|
||||
viewModel.monitorSummary()
|
||||
}
|
||||
viewModel.status.observe(this, Observer {
|
||||
viewModel.status.observe(this, {
|
||||
showProgress(false)
|
||||
val (statusColor, statusText) = when (it) {
|
||||
Status.DISABLED -> {
|
||||
enableButton?.visibility = View.VISIBLE
|
||||
disableButtons?.visibility = View.GONE
|
||||
binding.enableButton.visibility = View.VISIBLE
|
||||
binding.disableButtons.visibility = View.GONE
|
||||
Pair(R.color.colorDisabled, R.string.status_disabled)
|
||||
}
|
||||
Status.ENABLED -> {
|
||||
enableButton?.visibility = View.GONE
|
||||
disableButtons?.visibility = View.VISIBLE
|
||||
binding.enableButton.visibility = View.GONE
|
||||
binding.disableButtons.visibility = View.VISIBLE
|
||||
Pair(R.color.colorEnabled, R.string.status_enabled)
|
||||
}
|
||||
else -> {
|
||||
enableButton?.visibility = View.GONE
|
||||
disableButtons?.visibility = View.GONE
|
||||
binding.enableButton.visibility = View.GONE
|
||||
binding.disableButtons.visibility = View.GONE
|
||||
Pair(R.color.colorUnknown, R.string.status_unknown)
|
||||
}
|
||||
}
|
||||
status?.let { textView ->
|
||||
val status = getString(statusText)
|
||||
val statusLabel = getString(R.string.label_status, status)
|
||||
val start = statusLabel.indexOf(status)
|
||||
val end = start + status.length
|
||||
val statusSpan = SpannableString(statusLabel)
|
||||
statusSpan[start, end] = StyleSpan(Typeface.BOLD)
|
||||
statusSpan[start, end] =
|
||||
ForegroundColorSpan(getColor(textView.context, statusColor))
|
||||
textView.text = statusSpan
|
||||
}
|
||||
val status = getString(statusText)
|
||||
val statusLabel = getString(R.string.label_status, status)
|
||||
val start = statusLabel.indexOf(status)
|
||||
val end = start + status.length
|
||||
val statusSpan = SpannableString(statusLabel)
|
||||
statusSpan[start, end] = StyleSpan(Typeface.BOLD)
|
||||
statusSpan[start, end] =
|
||||
ForegroundColorSpan(getColor(binding.status.context, statusColor))
|
||||
binding.status.text = statusSpan
|
||||
})
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? = inflater.inflate(R.layout.fragment_main, container, false)
|
||||
): View {
|
||||
_binding = FragmentMainBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
inflater.inflate(R.menu.main, menu)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
(activity as? AppCompatActivity)?.setSupportActionBar(toolbar)
|
||||
(activity as? AppCompatActivity)?.setSupportActionBar(binding.toolbar)
|
||||
showProgress(true)
|
||||
enableButton?.setSuspendingOnClickListener(this) {
|
||||
binding.enableButton.setSuspendingOnClickListener(lifecycleScope) {
|
||||
showProgress(true)
|
||||
try {
|
||||
viewModel.enablePiHole()
|
||||
|
@ -97,7 +94,7 @@ class MainFragment : Fragment(), CoroutineScope {
|
|||
Log.e("Pi-helper", "Failed to enable Pi-Hole", ignored)
|
||||
}
|
||||
}
|
||||
disable10SecondsButton?.setSuspendingOnClickListener(this) {
|
||||
binding.disable10SecondsButton.setSuspendingOnClickListener(lifecycleScope) {
|
||||
showProgress(true)
|
||||
try {
|
||||
viewModel.disablePiHole(10)
|
||||
|
@ -105,7 +102,7 @@ class MainFragment : Fragment(), CoroutineScope {
|
|||
Log.e("Pi-helper", "Failed to disable Pi-Hole", ignored)
|
||||
}
|
||||
}
|
||||
disable30SecondsButton?.setSuspendingOnClickListener(this) {
|
||||
binding.disable30SecondsButton.setSuspendingOnClickListener(lifecycleScope) {
|
||||
showProgress(true)
|
||||
try {
|
||||
viewModel.disablePiHole(30)
|
||||
|
@ -113,7 +110,7 @@ class MainFragment : Fragment(), CoroutineScope {
|
|||
Log.e("Pi-helper", "Failed to disable Pi-Hole", ignored)
|
||||
}
|
||||
}
|
||||
disable5MinutesButton?.setSuspendingOnClickListener(this) {
|
||||
binding.disable5MinutesButton.setSuspendingOnClickListener(lifecycleScope) {
|
||||
showProgress(true)
|
||||
try {
|
||||
viewModel.disablePiHole(300)
|
||||
|
@ -121,40 +118,43 @@ class MainFragment : Fragment(), CoroutineScope {
|
|||
Log.e("Pi-helper", "Failed to disable Pi-Hole", ignored)
|
||||
}
|
||||
}
|
||||
disableCustomTimeButton?.setOnClickListener {
|
||||
val dialogView = LayoutInflater.from(it.context)
|
||||
.inflate(R.layout.dialog_disable_custom_time, view as ViewGroup, false)
|
||||
binding.disableCustomTimeButton.setOnClickListener {
|
||||
val dialogView = DialogDisableCustomTimeBinding.inflate(
|
||||
LayoutInflater.from(it.context),
|
||||
view as ViewGroup,
|
||||
false
|
||||
)
|
||||
AlertDialog.Builder(it.context)
|
||||
.setTitle(R.string.action_disable_custom)
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ -> }
|
||||
.setPositiveButton(R.string.action_disable, null)
|
||||
.setView(dialogView)
|
||||
.setView(dialogView.root)
|
||||
.create()
|
||||
.apply {
|
||||
setOnShowListener {
|
||||
getButton(AlertDialog.BUTTON_POSITIVE).setSuspendingOnClickListener(this@MainFragment) {
|
||||
getButton(AlertDialog.BUTTON_POSITIVE).setSuspendingOnClickListener(
|
||||
lifecycleScope
|
||||
) {
|
||||
try {
|
||||
val rawTime = dialogView.findViewById<EditText>(R.id.time)
|
||||
val rawTime = dialogView.time
|
||||
.text
|
||||
.toString()
|
||||
.toLong()
|
||||
val checkedId =
|
||||
dialogView.findViewById<RadioGroup>(R.id.timeUnit)
|
||||
.checkedRadioButtonId
|
||||
dialogView.timeUnit.checkedRadioButtonId
|
||||
val computedTime = if (checkedId == R.id.seconds) rawTime
|
||||
else rawTime * 60
|
||||
viewModel.disablePiHole(computedTime)
|
||||
dismiss()
|
||||
} catch (e: Exception) {
|
||||
dialogView.findViewById<EditText>(R.id.time)
|
||||
.error = "Failed to disable Pi-hole"
|
||||
dialogView.time.error = "Failed to disable Pi-hole"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.show()
|
||||
}
|
||||
disablePermanentlyButton?.setSuspendingOnClickListener(this) {
|
||||
binding.disablePermanentlyButton.setSuspendingOnClickListener(lifecycleScope) {
|
||||
showProgress(true)
|
||||
try {
|
||||
viewModel.disablePiHole()
|
||||
|
@ -173,8 +173,8 @@ class MainFragment : Fragment(), CoroutineScope {
|
|||
}
|
||||
|
||||
private fun showProgress(show: Boolean) {
|
||||
progressBar?.visibility = if (show) {
|
||||
progressBar?.startAnimation(RotateAnimation(
|
||||
binding.progressBar.visibility = if (show) {
|
||||
binding.progressBar.startAnimation(RotateAnimation(
|
||||
0f,
|
||||
360f,
|
||||
Animation.RELATIVE_TO_SELF,
|
||||
|
@ -190,10 +190,10 @@ class MainFragment : Fragment(), CoroutineScope {
|
|||
})
|
||||
View.VISIBLE
|
||||
} else {
|
||||
progressBar?.clearAnimation()
|
||||
binding.progressBar.clearAnimation()
|
||||
View.GONE
|
||||
}
|
||||
statusContent?.visibility = if (show) {
|
||||
binding.statusContent.visibility = if (show) {
|
||||
View.GONE
|
||||
} else {
|
||||
View.VISIBLE
|
||||
|
@ -201,7 +201,7 @@ class MainFragment : Fragment(), CoroutineScope {
|
|||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
coroutineContext[Job]?.cancel()
|
||||
_binding = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
|
|
|
@ -11,17 +11,16 @@ import android.view.animation.LinearInterpolator
|
|||
import android.view.animation.RotateAnimation
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.transition.TransitionInflater
|
||||
import kotlinx.android.synthetic.main.fragment_retrieve_api_key.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import com.wbrawner.pihelper.databinding.FragmentRetrieveApiKeyBinding
|
||||
import org.koin.android.ext.android.inject
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class RetrieveApiKeyFragment : Fragment(), CoroutineScope {
|
||||
override val coroutineContext: CoroutineContext = Dispatchers.Main
|
||||
class RetrieveApiKeyFragment : Fragment() {
|
||||
private val viewModel: AddPiHelperViewModel by inject()
|
||||
private var _binding: FragmentRetrieveApiKeyBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
@ -36,32 +35,35 @@ class RetrieveApiKeyFragment : Fragment(), CoroutineScope {
|
|||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? = inflater.inflate(R.layout.fragment_retrieve_api_key, container, false)
|
||||
): View {
|
||||
_binding = FragmentRetrieveApiKeyBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
password.setOnEditorActionListener { _, _, _ ->
|
||||
connectWithPasswordButton.performClick()
|
||||
binding.password.setOnEditorActionListener { _, _, _ ->
|
||||
binding.connectWithPasswordButton.performClick()
|
||||
}
|
||||
connectWithPasswordButton.setSuspendingOnClickListener(this) {
|
||||
binding.connectWithPasswordButton.setSuspendingOnClickListener(lifecycleScope) {
|
||||
showProgress(true)
|
||||
try {
|
||||
viewModel.authenticateWithPassword(password.text.toString())
|
||||
viewModel.authenticateWithPassword(binding.password.text.toString())
|
||||
} catch (ignored: Exception) {
|
||||
Log.e("Pi-helper", "Failed to authenticate with password", ignored)
|
||||
password.error = "Failed to authenticate with given password. Please verify " +
|
||||
binding.password.error = "Failed to authenticate with given password. Please verify " +
|
||||
"you've entered it correctly and try again."
|
||||
showProgress(false)
|
||||
}
|
||||
}
|
||||
apiKey.setOnEditorActionListener { _, _, _ ->
|
||||
connectWithApiKeyButton.performClick()
|
||||
binding.apiKey.setOnEditorActionListener { _, _, _ ->
|
||||
binding.connectWithApiKeyButton.performClick()
|
||||
}
|
||||
connectWithApiKeyButton.setSuspendingOnClickListener(this) {
|
||||
binding.connectWithApiKeyButton.setSuspendingOnClickListener(lifecycleScope) {
|
||||
showProgress(true)
|
||||
try {
|
||||
viewModel.authenticateWithApiKey(apiKey.text.toString())
|
||||
viewModel.authenticateWithApiKey(binding.apiKey.text.toString())
|
||||
} catch (ignored: Exception) {
|
||||
apiKey.error = "Failed to authenticate with given API key. Please verify " +
|
||||
binding.apiKey.error = "Failed to authenticate with given API key. Please verify " +
|
||||
"you've entered it correctly and try again."
|
||||
showProgress(false)
|
||||
}
|
||||
|
@ -70,7 +72,7 @@ class RetrieveApiKeyFragment : Fragment(), CoroutineScope {
|
|||
|
||||
private fun showProgress(show: Boolean) {
|
||||
if (show) {
|
||||
piHelperLogo.startAnimation(
|
||||
binding.piHelperLogo.startAnimation(
|
||||
RotateAnimation(
|
||||
0f,
|
||||
360f,
|
||||
|
@ -88,13 +90,13 @@ class RetrieveApiKeyFragment : Fragment(), CoroutineScope {
|
|||
}
|
||||
)
|
||||
} else {
|
||||
piHelperLogo.clearAnimation()
|
||||
binding.piHelperLogo.clearAnimation()
|
||||
}
|
||||
authenticationForm.visibility = if (show) View.GONE else View.VISIBLE
|
||||
binding.authenticationForm.visibility = if (show) View.GONE else View.VISIBLE
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
cancel()
|
||||
_binding = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,23 +16,23 @@ import android.view.animation.RotateAnimation
|
|||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.FragmentNavigatorExtras
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.transition.Transition
|
||||
import androidx.transition.TransitionInflater
|
||||
import kotlinx.android.synthetic.main.fragment_scan_network.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import com.wbrawner.pihelper.databinding.FragmentScanNetworkBinding
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.android.ext.android.inject
|
||||
import java.net.Inet4Address
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class ScanNetworkFragment : Fragment(), CoroutineScope {
|
||||
class ScanNetworkFragment : Fragment() {
|
||||
|
||||
override val coroutineContext: CoroutineContext = Dispatchers.Main
|
||||
private val viewModel: AddPiHelperViewModel by inject()
|
||||
private var _binding: FragmentScanNetworkBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
@ -60,12 +60,15 @@ class ScanNetworkFragment : Fragment(), CoroutineScope {
|
|||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? = inflater.inflate(R.layout.fragment_scan_network, container, false)
|
||||
): View {
|
||||
_binding = FragmentScanNetworkBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
viewModel.scanningIp.observe(viewLifecycleOwner, Observer {
|
||||
ipAddress?.text = it
|
||||
binding.ipAddress.text = it
|
||||
})
|
||||
viewModel.piHoleIpAddress.observe(viewLifecycleOwner, Observer { ipAddress ->
|
||||
if (ipAddress == null) {
|
||||
|
@ -78,7 +81,7 @@ class ScanNetworkFragment : Fragment(), CoroutineScope {
|
|||
.show()
|
||||
return@Observer
|
||||
}
|
||||
piHelperLogo?.animation?.let {
|
||||
binding.piHelperLogo.animation?.let {
|
||||
it.setAnimationListener(object : Animation.AnimationListener {
|
||||
override fun onAnimationRepeat(animation: Animation?) {
|
||||
}
|
||||
|
@ -93,7 +96,7 @@ class ScanNetworkFragment : Fragment(), CoroutineScope {
|
|||
it.repeatCount = 0
|
||||
} ?: navigateToApiKeyScreen()
|
||||
})
|
||||
launch(Dispatchers.IO) {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
if (BuildConfig.DEBUG && Build.MODEL == "Android SDK built for x86") {
|
||||
// For emulators, just begin scanning the host machine directly
|
||||
viewModel.beginScanning("10.0.2.2")
|
||||
|
@ -120,9 +123,9 @@ class ScanNetworkFragment : Fragment(), CoroutineScope {
|
|||
}
|
||||
}
|
||||
}
|
||||
launch {
|
||||
lifecycleScope.launch {
|
||||
delay(500)
|
||||
if (piHelperLogo?.animation == null) {
|
||||
if (binding.piHelperLogo.animation == null) {
|
||||
animatePiHelperLogo()
|
||||
}
|
||||
}
|
||||
|
@ -130,7 +133,7 @@ class ScanNetworkFragment : Fragment(), CoroutineScope {
|
|||
|
||||
private fun navigateToApiKeyScreen() {
|
||||
val extras = FragmentNavigatorExtras(
|
||||
piHelperLogo to "piHelperLogo"
|
||||
binding.piHelperLogo to "piHelperLogo"
|
||||
)
|
||||
|
||||
findNavController().navigate(
|
||||
|
@ -142,13 +145,13 @@ class ScanNetworkFragment : Fragment(), CoroutineScope {
|
|||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
piHelperLogo.clearAnimation()
|
||||
cancel()
|
||||
binding.piHelperLogo.clearAnimation()
|
||||
_binding = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
private fun animatePiHelperLogo() {
|
||||
piHelperLogo?.startAnimation(
|
||||
binding.piHelperLogo.startAnimation(
|
||||
RotateAnimation(
|
||||
0f,
|
||||
360f,
|
||||
|
|
|
@ -1,17 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<fragment 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:id="@+id/content_main"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:background="@color/colorSurface">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/content_main"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
app:defaultNavHost="true"
|
||||
app:navGraph="@navigation/nav_graph" />
|
||||
</merge>
|
||||
android:fitsSystemWindows="true"
|
||||
app:defaultNavHost="true"
|
||||
app:navGraph="@navigation/nav_graph"
|
||||
tools:background="@color/colorSurface" />
|
||||
|
|
|
@ -23,6 +23,6 @@
|
|||
</style>
|
||||
|
||||
<style name="AppTheme.Button.Red" parent="AppTheme.Button">
|
||||
<item name="backgroundTint">@color/colorRedDark</item>
|
||||
<item name="backgroundTint">@color/colorAccent</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
buildscript {
|
||||
ext.kotlin_version = '1.3.61'
|
||||
ext.kotlin_version = '1.4.20'
|
||||
ext.coroutines_version = '1.3.2'
|
||||
ext.koin_version = '2.0.1'
|
||||
ext.okhttp_version = '4.2.2'
|
||||
|
@ -8,7 +8,7 @@ buildscript {
|
|||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.6.2'
|
||||
classpath 'com.android.tools.build:gradle:4.1.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
|||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
|
||||
android {
|
||||
|
|
Loading…
Reference in a new issue