Add dialog instead of activity
This commit is contained in:
parent
0c3a14d528
commit
170bdc2485
10 changed files with 141 additions and 124 deletions
|
@ -63,4 +63,5 @@ dependencies {
|
|||
|
||||
// LiveData
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$rootProject.liveDataVersion"
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
}
|
||||
|
|
|
@ -1,20 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2020 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="io.heckel.ntfy">
|
||||
|
||||
|
@ -36,5 +20,4 @@
|
|||
<activity android:name="io.heckel.ntfy.add.AddTopicActivity" />
|
||||
<activity android:name="io.heckel.ntfy.detail.DetailActivity" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
80
app/src/main/java/io/heckel/ntfy/AddFragment.kt
Normal file
80
app/src/main/java/io/heckel/ntfy/AddFragment.kt
Normal file
|
@ -0,0 +1,80 @@
|
|||
package io.heckel.ntfy
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.View
|
||||
import android.widget.CheckBox
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
|
||||
class AddFragment(private val listener: Listener) : DialogFragment() {
|
||||
interface Listener {
|
||||
fun onAddClicked(topic: String, baseUrl: String)
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
return activity?.let {
|
||||
// Build root view
|
||||
val view = requireActivity().layoutInflater.inflate(R.layout.fragment_add, null)
|
||||
val topicNameText = view.findViewById(R.id.add_dialog_topic_text) as TextInputEditText
|
||||
val baseUrlText = view.findViewById(R.id.add_dialog_base_url_text) as TextInputEditText
|
||||
val useAnotherServerCheckbox = view.findViewById(R.id.add_dialog_use_another_server_checkbox) as CheckBox
|
||||
useAnotherServerCheckbox.setOnCheckedChangeListener { buttonView, isChecked ->
|
||||
if (isChecked) baseUrlText.visibility = View.VISIBLE
|
||||
else baseUrlText.visibility = View.GONE
|
||||
}
|
||||
|
||||
// Build dialog
|
||||
val alert = AlertDialog.Builder(it)
|
||||
.setView(view)
|
||||
.setPositiveButton(R.string.add_dialog_button_subscribe) { _, _ ->
|
||||
val topic = topicNameText.text.toString()
|
||||
val baseUrl = if (useAnotherServerCheckbox.isChecked) {
|
||||
baseUrlText.text.toString()
|
||||
} else {
|
||||
getString(R.string.add_dialog_base_url_default)
|
||||
}
|
||||
listener.onAddClicked(topic, baseUrl)
|
||||
}
|
||||
.setNegativeButton(R.string.add_dialog_button_cancel) { _, _ ->
|
||||
dialog?.cancel()
|
||||
}
|
||||
.create()
|
||||
|
||||
// Add logic to disable "Subscribe" button on invalid input
|
||||
alert.setOnShowListener {
|
||||
val dialog = it as AlertDialog
|
||||
|
||||
val subscribeButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE)
|
||||
subscribeButton.isEnabled = false
|
||||
|
||||
val textWatcher = object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable?) {
|
||||
if (useAnotherServerCheckbox.isChecked) {
|
||||
subscribeButton.isEnabled = topicNameText.text.toString().isNotBlank()
|
||||
&& "[-_A-Za-z0-9]+".toRegex().matches(topicNameText.text.toString())
|
||||
&& baseUrlText.text.toString().isNotBlank()
|
||||
&& "^https?://.+".toRegex().matches(baseUrlText.text.toString())
|
||||
} else {
|
||||
subscribeButton.isEnabled = topicNameText.text.toString().isNotBlank()
|
||||
&& "[-_A-Za-z0-9]+".toRegex().matches(topicNameText.text.toString())
|
||||
}
|
||||
}
|
||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
||||
// Nothing
|
||||
}
|
||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
|
||||
// Nothing
|
||||
}
|
||||
}
|
||||
topicNameText.addTextChangedListener(textWatcher)
|
||||
baseUrlText.addTextChangedListener(textWatcher)
|
||||
}
|
||||
|
||||
alert
|
||||
} ?: throw IllegalStateException("Activity cannot be null")
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package io.heckel.ntfy
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
|
@ -13,17 +12,16 @@ import androidx.appcompat.app.AppCompatActivity
|
|||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.heckel.ntfy.add.AddTopicActivity
|
||||
import io.heckel.ntfy.data.*
|
||||
import io.heckel.ntfy.data.Notification
|
||||
import io.heckel.ntfy.data.Status
|
||||
import io.heckel.ntfy.data.Subscription
|
||||
import io.heckel.ntfy.data.topicShortUrl
|
||||
import io.heckel.ntfy.detail.DetailActivity
|
||||
import kotlin.random.Random
|
||||
|
||||
const val SUBSCRIPTION_ID = "topic_id"
|
||||
const val TOPIC_NAME = "topic_name"
|
||||
const val SERVICE_BASE_URL = "base_url"
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
private val newSubscriptionActivityRequestCode = 1
|
||||
class MainActivity : AppCompatActivity(), AddFragment.Listener {
|
||||
private val subscriptionViewModel by viewModels<SubscriptionsViewModel> {
|
||||
SubscriptionsViewModelFactory()
|
||||
}
|
||||
|
@ -64,21 +62,13 @@ class MainActivity : AppCompatActivity() {
|
|||
|
||||
/* Adds topic to topicList when FAB is clicked. */
|
||||
private fun fabOnClick() {
|
||||
val intent = Intent(this, AddTopicActivity::class.java)
|
||||
startActivityForResult(intent, newSubscriptionActivityRequestCode)
|
||||
val newFragment = AddFragment(this)
|
||||
newFragment.show(supportFragmentManager, "AddFragment")
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, intentData: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, intentData)
|
||||
|
||||
if (requestCode == newSubscriptionActivityRequestCode && resultCode == Activity.RESULT_OK) {
|
||||
intentData?.let { data ->
|
||||
val name = data.getStringExtra(TOPIC_NAME) ?: return
|
||||
val baseUrl = data.getStringExtra(SERVICE_BASE_URL) ?: return
|
||||
val subscription = Subscription(Random.nextLong(), name, baseUrl, Status.CONNECTING, 0)
|
||||
subscriptionViewModel.add(subscription)
|
||||
}
|
||||
}
|
||||
override fun onAddClicked(topic: String, baseUrl: String) {
|
||||
val subscription = Subscription(Random.nextLong(), topic, baseUrl, Status.CONNECTING, 0)
|
||||
subscriptionViewModel.add(subscription)
|
||||
}
|
||||
|
||||
private fun displayNotification(n: Notification) {
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
package io.heckel.ntfy.add
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.widget.Button
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import io.heckel.ntfy.R
|
||||
import io.heckel.ntfy.SERVICE_BASE_URL
|
||||
import io.heckel.ntfy.TOPIC_NAME
|
||||
|
||||
class AddTopicActivity : AppCompatActivity() {
|
||||
private lateinit var topicName: TextInputEditText
|
||||
private lateinit var baseUrl: TextInputEditText
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.add_topic_layout)
|
||||
|
||||
findViewById<Button>(R.id.subscribe_button).setOnClickListener {
|
||||
addTopic()
|
||||
}
|
||||
topicName = findViewById(R.id.add_topic_name)
|
||||
baseUrl = findViewById(R.id.add_topic_base_url)
|
||||
baseUrl.setText(R.string.topic_base_url_default_value)
|
||||
}
|
||||
|
||||
/* The onClick action for the done button. Closes the activity and returns the new topic name
|
||||
and description as part of the intent. If the name or description are missing, the result is set
|
||||
to cancelled. */
|
||||
|
||||
private fun addTopic() {
|
||||
val resultIntent = Intent()
|
||||
|
||||
// TODO don't allow this
|
||||
|
||||
if (baseUrl.text.isNullOrEmpty()) {
|
||||
setResult(Activity.RESULT_CANCELED, resultIntent)
|
||||
} else {
|
||||
resultIntent.putExtra(TOPIC_NAME, topicName.text.toString())
|
||||
resultIntent.putExtra(SERVICE_BASE_URL, baseUrl.text.toString())
|
||||
setResult(Activity.RESULT_OK, resultIntent)
|
||||
}
|
||||
finish()
|
||||
}
|
||||
}
|
|
@ -47,7 +47,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:hint="@string/topic_base_url_edit_text"
|
||||
android:hint="@string/add_dialog_base_url_layout"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp">
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
|
|
32
app/src/main/res/layout/fragment_add.xml
Normal file
32
app/src/main/res/layout/fragment_add.xml
Normal file
|
@ -0,0 +1,32 @@
|
|||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/add_dialog_title_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp"
|
||||
android:text="@string/add_dialog_title"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large"/>
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/add_dialog_topic_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" android:hint="@string/add_dialog_topic_name_hint"/>
|
||||
<CheckBox
|
||||
android:text="@string/add_dialog_use_another_server"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" android:id="@+id/add_dialog_use_another_server_checkbox"/>
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/add_dialog_base_url_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" android:visibility="gone"
|
||||
android:hint="@string/add_dialog_base_url_hint"/>
|
||||
</LinearLayout>
|
|
@ -1,22 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2020 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<color name="colorPrimary">#6200EE</color>
|
||||
<color name="colorPrimaryDark">#3700B3</color>
|
||||
<color name="colorAccent">#03DAC5</color>
|
||||
<color name="colorPrimary">#3949ab</color>
|
||||
<color name="colorPrimaryDark">#3949ab</color>
|
||||
<!--<color name="colorAccent">#03DAC5</color>-->
|
||||
</resources>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
|
||||
<string name="topic_name_edit_text">Topic Name</string>
|
||||
<string name="topic_base_url_edit_text">Service URL</string>
|
||||
<string name="add_dialog_base_url_layout">Service URL</string>
|
||||
<string name="topic_base_url_default_value">https://ntfy.sh</string>
|
||||
<string name="subscribe_button_text">Subscribe</string>
|
||||
<string name="status_connected">Connected</string>
|
||||
|
@ -14,6 +14,16 @@
|
|||
<string name="fab_content_description">fab</string>
|
||||
<string name="remove_topic">Unsubscribe</string>
|
||||
|
||||
<!-- Notifications -->
|
||||
<string name="notification_channel_name">Ntfy</string>
|
||||
<string name="notification_channel_id">ntfy</string>
|
||||
|
||||
<!-- Add dialog -->
|
||||
<string name="add_dialog_title">Subscribe to topic</string>
|
||||
<string name="add_dialog_topic_name_hint">Topic name, e.g. phils_alerts</string>
|
||||
<string name="add_dialog_use_another_server">Use another server</string>
|
||||
<string name="add_dialog_base_url_hint">https://ntfy.sh</string>
|
||||
<string name="add_dialog_base_url_default">https://ntfy.sh</string>
|
||||
<string name="add_dialog_button_cancel">Cancel</string>
|
||||
<string name="add_dialog_button_subscribe">Subscribe</string>
|
||||
</resources>
|
||||
|
|
|
@ -1,28 +1,12 @@
|
|||
<!--
|
||||
Copyright (C) 2020 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<!-- Base application theme. -->
|
||||
<!-- No action bar, https://stackoverflow.com/a/36236700 -->
|
||||
<style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryVariant">@color/colorPrimaryDark</item>
|
||||
<item name="colorSecondary">@color/colorAccent</item>
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
<!--<item name="colorSecondary">@color/colorAccent</item>-->
|
||||
<!--<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>-->
|
||||
<!--<item name="android:windowFullscreen">true</item>-->
|
||||
</style>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in a new issue