diff --git a/app/build.gradle b/app/build.gradle index 2911aac..3862f4e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -41,11 +41,14 @@ dependencies { implementation "androidx.activity:activity-ktx:$rootProject.activityVersion" implementation 'com.google.code.gson:gson:2.8.8' - // Room + // Room (SQLite) def roomVersion = "2.3.0" implementation "androidx.room:room-ktx:$roomVersion" kapt "androidx.room:room-compiler:$roomVersion" + // Volley (HTTP library) + implementation 'com.android.volley:volley:1.2.1' + // Firebase, sigh ... implementation 'com.google.firebase:firebase-messaging:22.0.0' diff --git a/app/src/main/java/io/heckel/ntfy/data/Util.kt b/app/src/main/java/io/heckel/ntfy/data/Util.kt index e4394b7..fca51f7 100644 --- a/app/src/main/java/io/heckel/ntfy/data/Util.kt +++ b/app/src/main/java/io/heckel/ntfy/data/Util.kt @@ -1,6 +1,7 @@ package io.heckel.ntfy.data +fun topicUrl(baseUrl: String, topic: String) = "${baseUrl}/${topic}" fun topicShortUrl(baseUrl: String, topic: String) = - "${baseUrl}/${topic}" + topicUrl(baseUrl, topic) .replace("http://", "") .replace("https://", "") diff --git a/app/src/main/java/io/heckel/ntfy/ui/DetailActivity.kt b/app/src/main/java/io/heckel/ntfy/ui/DetailActivity.kt index c25adca..a385613 100644 --- a/app/src/main/java/io/heckel/ntfy/ui/DetailActivity.kt +++ b/app/src/main/java/io/heckel/ntfy/ui/DetailActivity.kt @@ -3,22 +3,36 @@ package io.heckel.ntfy.ui import android.app.AlertDialog import android.content.Intent import android.os.Bundle +import android.util.Log import android.view.Menu import android.view.MenuItem import android.view.View +import android.widget.Toast import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.RecyclerView +import com.android.volley.Request +import com.android.volley.toolbox.StringRequest +import com.android.volley.toolbox.Volley import io.heckel.ntfy.R import io.heckel.ntfy.app.Application import io.heckel.ntfy.data.Notification import io.heckel.ntfy.data.topicShortUrl +import io.heckel.ntfy.data.topicUrl +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import java.io.OutputStreamWriter +import java.net.HttpURLConnection +import java.util.* + class DetailActivity : AppCompatActivity() { private val viewModel by viewModels { DetailViewModelFactory((application as Application).repository) } private var subscriptionId: Long = 0L // Set in onCreate() + private var subscriptionBaseUrl: String = "" // Set in onCreate() private var subscriptionTopic: String = "" // Set in onCreate() override fun onCreate(savedInstanceState: Bundle?) { @@ -28,6 +42,7 @@ class DetailActivity : AppCompatActivity() { // Get extras required for the return to the main activity subscriptionId = intent.getLongExtra(MainActivity.EXTRA_SUBSCRIPTION_ID, 0) + subscriptionBaseUrl = intent.getStringExtra(MainActivity.EXTRA_SUBSCRIPTION_BASE_URL) ?: return subscriptionTopic = intent.getStringExtra(MainActivity.EXTRA_SUBSCRIPTION_TOPIC) ?: return // Set title @@ -61,6 +76,10 @@ class DetailActivity : AppCompatActivity() { override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { + R.id.detail_menu_test -> { + onTestClick() + true + } R.id.detail_menu_delete -> { onDeleteClick() true @@ -69,7 +88,31 @@ class DetailActivity : AppCompatActivity() { } } + private fun onTestClick() { + val url = topicUrl(subscriptionBaseUrl, subscriptionTopic) + Log.d(TAG, "Sending test notification to $url") + + val queue = Volley.newRequestQueue(this) // This should be a Singleton :-O + val stringRequest = object : StringRequest( + Method.PUT, + url, + { _ -> /* Do nothing */ }, + { error -> + Toast + .makeText(this, getString(R.string.detail_test_message_error, error.message), Toast.LENGTH_LONG) + .show() + } + ) { + override fun getBody(): ByteArray { + return getString(R.string.detail_test_message, Date().toString()).toByteArray() + } + } + queue.add(stringRequest) + } + private fun onDeleteClick() { + Log.d(TAG, "Deleting subscription ${topicShortUrl(subscriptionBaseUrl, subscriptionTopic)}") + val builder = AlertDialog.Builder(this) builder .setMessage(R.string.detail_delete_dialog_message) @@ -90,6 +133,10 @@ class DetailActivity : AppCompatActivity() { } private fun onNotificationClick(notification: Notification) { - println("clicked " + notification.id) + // TODO Do something + } + + companion object { + const val TAG = "NtfyDetailActivity" } } diff --git a/app/src/main/java/io/heckel/ntfy/ui/MainActivity.kt b/app/src/main/java/io/heckel/ntfy/ui/MainActivity.kt index 5772fe8..9dfb94a 100644 --- a/app/src/main/java/io/heckel/ntfy/ui/MainActivity.kt +++ b/app/src/main/java/io/heckel/ntfy/ui/MainActivity.kt @@ -3,20 +3,18 @@ package io.heckel.ntfy.ui import android.content.Intent import android.net.Uri import android.os.Bundle +import android.util.Log import android.view.Menu import android.view.MenuItem import android.view.View import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity -import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.RecyclerView import com.google.firebase.messaging.FirebaseMessaging import io.heckel.ntfy.R import io.heckel.ntfy.app.Application import io.heckel.ntfy.data.Subscription import io.heckel.ntfy.data.topicShortUrl -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch import java.util.* import kotlin.random.Random @@ -29,6 +27,8 @@ class MainActivity : AppCompatActivity() { super.onCreate(savedInstanceState) setContentView(R.layout.main_activity) + // TODO implement multi-select delete - https://enoent.fr/posts/recyclerview-basics/ + // Action bar title = getString(R.string.main_action_bar_title) @@ -65,11 +65,11 @@ class MainActivity : AppCompatActivity() { override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { - R.id.menu_action_source -> { + R.id.main_menu_source -> { startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.main_menu_source_url)))) true } - R.id.detail_menu_delete -> { + R.id.main_menu_website -> { startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.app_base_url)))) true } @@ -83,12 +83,16 @@ class MainActivity : AppCompatActivity() { } private fun onSubscribe(topic: String, baseUrl: String) { + Log.d(TAG, "Adding subscription ${topicShortUrl(baseUrl, topic)}") + val subscription = Subscription(id = Random.nextLong(), baseUrl = baseUrl, topic = topic, notifications = 0, lastActive = Date().time/1000) viewModel.add(subscription) FirebaseMessaging.getInstance().subscribeToTopic(topic) // FIXME ignores baseUrl } private fun onSubscriptionItemClick(subscription: Subscription) { + Log.d(TAG, "Entering detail view for subscription $subscription") + val intent = Intent(this, DetailActivity::class.java) intent.putExtra(EXTRA_SUBSCRIPTION_ID, subscription.id) intent.putExtra(EXTRA_SUBSCRIPTION_BASE_URL, subscription.baseUrl) @@ -100,6 +104,8 @@ class MainActivity : AppCompatActivity() { if (requestCode == REQUEST_CODE_DELETE_SUBSCRIPTION && resultCode == RESULT_OK) { val subscriptionId = data?.getLongExtra(EXTRA_SUBSCRIPTION_ID, 0) val subscriptionTopic = data?.getStringExtra(EXTRA_SUBSCRIPTION_TOPIC) + Log.d(TAG, "Deleting subscription with subscription ID $subscriptionId (topic: $subscriptionTopic)") + subscriptionId?.let { id -> viewModel.remove(id) } subscriptionTopic?.let { topic -> FirebaseMessaging.getInstance().unsubscribeFromTopic(topic) } // FIXME This only works for ntfy.sh } else { diff --git a/app/src/main/res/menu/detail_action_bar_menu.xml b/app/src/main/res/menu/detail_action_bar_menu.xml index 9b62583..ead0031 100644 --- a/app/src/main/res/menu/detail_action_bar_menu.xml +++ b/app/src/main/res/menu/detail_action_bar_menu.xml @@ -1,3 +1,4 @@ - + + diff --git a/app/src/main/res/menu/main_action_bar_menu.xml b/app/src/main/res/menu/main_action_bar_menu.xml index 4a5c360..a6e655f 100644 --- a/app/src/main/res/menu/main_action_bar_menu.xml +++ b/app/src/main/res/menu/main_action_bar_menu.xml @@ -1,5 +1,4 @@ - - + + diff --git a/app/src/main/res/menu/main_item_popup_menu.xml b/app/src/main/res/menu/main_item_popup_menu.xml deleted file mode 100644 index 313c9b1..0000000 --- a/app/src/main/res/menu/main_item_popup_menu.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 43c27ff..99c09f3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -18,7 +18,6 @@ reconnecting … %1$d notification received %1$d notifications received - Unsubscribe Add subscription It looks like you don\'t have any subscriptions yet. @@ -34,7 +33,10 @@ Do you really want to permanently delete this subscription and all its messages? Permanently delete Cancel + This is a test notification from the Ntfy Android app. It was sent at %1$s. + Could not send test message: %1$s + Send test notification Delete topic