diff --git a/app/src/main/java/io/heckel/ntfy/msg/SubscriberConnection.kt b/app/src/main/java/io/heckel/ntfy/msg/SubscriberConnection.kt index 9785aed..6e4e98f 100644 --- a/app/src/main/java/io/heckel/ntfy/msg/SubscriberConnection.kt +++ b/app/src/main/java/io/heckel/ntfy/msg/SubscriberConnection.kt @@ -43,7 +43,9 @@ class SubscriberConnection( val failed = AtomicBoolean(false) val fail = { e: Exception -> failed.set(true) - stateChangeListener(subscriptions.values, ConnectionState.CONNECTING) + if (isActive && serviceActive()) { // Avoid UI update races if we're restarting a connection + stateChangeListener(subscriptions.values, ConnectionState.CONNECTING) + } } // Call /json subscribe endpoint and loop until the call fails, is canceled, @@ -57,8 +59,7 @@ class SubscriberConnection( } } catch (e: Exception) { Log.e(TAG, "[$url] Connection failed: ${e.message}", e) - if (isActive && serviceActive()) { - // Only update if we're not canceled, otherwise this may lead to races + if (isActive && serviceActive()) { // Avoid UI update races if we're restarting a connection stateChangeListener(subscriptions.values, ConnectionState.CONNECTING) } } diff --git a/app/src/main/java/io/heckel/ntfy/ui/AddFragment.kt b/app/src/main/java/io/heckel/ntfy/ui/AddFragment.kt index 83d7d40..7b4d635 100644 --- a/app/src/main/java/io/heckel/ntfy/ui/AddFragment.kt +++ b/app/src/main/java/io/heckel/ntfy/ui/AddFragment.kt @@ -125,4 +125,10 @@ class AddFragment(private val viewModel: SubscriptionsViewModel, private val onS getString(R.string.app_base_url) } } + + companion object { + fun newInstance() { + // ... make it not crash + } + } } 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 0ff3624..df8fa66 100644 --- a/app/src/main/java/io/heckel/ntfy/ui/DetailActivity.kt +++ b/app/src/main/java/io/heckel/ntfy/ui/DetailActivity.kt @@ -232,12 +232,14 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback { val url = topicUrl(subscriptionBaseUrl, subscriptionTopic) Log.d(TAG, "Copying topic URL $url to clipboard ") - val clipboard: ClipboardManager = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager - val clip = ClipData.newPlainText("topic address", url) - clipboard.setPrimaryClip(clip) - Toast - .makeText(this, getString(R.string.detail_copied_to_clipboard_message), Toast.LENGTH_LONG) - .show() + runOnUiThread { + val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager + val clip = ClipData.newPlainText("topic address", url) + clipboard.setPrimaryClip(clip) + Toast + .makeText(this, getString(R.string.detail_copied_to_clipboard_message), Toast.LENGTH_LONG) + .show() + } } private fun refresh() { @@ -345,13 +347,15 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback { } private fun copyToClipboard(notification: Notification) { - val message = notification.message + "\n\n" + Date(notification.timestamp * 1000).toString() - val clipboard: ClipboardManager = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager - val clip = ClipData.newPlainText("notification message", message) - clipboard.setPrimaryClip(clip) - Toast - .makeText(this, getString(R.string.detail_copied_to_clipboard_message), Toast.LENGTH_LONG) - .show() + runOnUiThread { + val message = notification.message + "\n\n" + Date(notification.timestamp * 1000).toString() + val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager + val clip = ClipData.newPlainText("notification message", message) + clipboard.setPrimaryClip(clip) + Toast + .makeText(this, getString(R.string.detail_copied_to_clipboard_message), Toast.LENGTH_LONG) + .show() + } } private fun onNotificationLongClick(notification: Notification) { @@ -407,10 +411,10 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback { it.message + "\n" + Date(it.timestamp * 1000).toString() }.orEmpty() } - val clipboard: ClipboardManager = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager - val clip = ClipData.newPlainText("notifications", content) - clipboard.setPrimaryClip(clip) runOnUiThread { + val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager + val clip = ClipData.newPlainText("notifications", content) + clipboard.setPrimaryClip(clip) Toast .makeText(this@DetailActivity, getString(R.string.detail_copied_to_clipboard_message), Toast.LENGTH_LONG) .show() 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 31fe6d7..ef70fb3 100644 --- a/app/src/main/java/io/heckel/ntfy/ui/MainActivity.kt +++ b/app/src/main/java/io/heckel/ntfy/ui/MainActivity.kt @@ -152,8 +152,9 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback { } private fun onSubscribeButtonClick() { - val newFragment = AddFragment(viewModel) { topic, baseUrl, instant -> onSubscribe(topic, baseUrl, instant) } - newFragment.show(supportFragmentManager, "AddFragment") + val newFragment = AddFragment(viewModel, ::onSubscribe) + newFragment + .show(supportFragmentManager, "AddFragment") } private fun onSubscribe(topic: String, baseUrl: String, instant: Boolean) { diff --git a/app/src/main/java/io/heckel/ntfy/ui/MainAdapter.kt b/app/src/main/java/io/heckel/ntfy/ui/MainAdapter.kt index ade97dd..2086997 100644 --- a/app/src/main/java/io/heckel/ntfy/ui/MainAdapter.kt +++ b/app/src/main/java/io/heckel/ntfy/ui/MainAdapter.kt @@ -12,7 +12,7 @@ import io.heckel.ntfy.R import io.heckel.ntfy.data.ConnectionState import io.heckel.ntfy.data.Subscription import io.heckel.ntfy.data.topicShortUrl -import java.text.SimpleDateFormat +import java.text.DateFormat import java.util.* @@ -62,12 +62,18 @@ class MainAdapter(private val onClick: (Subscription) -> Unit, private val onLon if (subscription.instant && subscription.state == ConnectionState.CONNECTING) { statusMessage += ", " + context.getString(R.string.main_item_status_reconnecting) } + val date = Date(subscription.lastActive * 1000) + val dateStr = DateFormat.getDateInstance(DateFormat.SHORT).format(date) + val moreThanOneDay = System.currentTimeMillis()/1000 - subscription.lastActive > 24 * 60 * 60 + val sameDay = dateStr == DateFormat.getDateInstance(DateFormat.SHORT).format(Date()) // Omg this is horrible val dateText = if (subscription.lastActive == 0L) { "" - } else if (System.currentTimeMillis()/1000 - subscription.lastActive < 24 * 60 * 60) { - SimpleDateFormat("HH:mm").format(Date(subscription.lastActive*1000)) + } else if (sameDay) { + DateFormat.getTimeInstance(DateFormat.SHORT).format(date) + } else if (!moreThanOneDay) { + context.getString(R.string.main_item_date_yesterday) } else { - SimpleDateFormat("M/d/yy").format(Date(subscription.lastActive*1000)) + dateStr } nameView.text = topicShortUrl(subscription.baseUrl, subscription.topic) statusView.text = statusMessage diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f48db4d..0bc89ed 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -35,6 +35,7 @@ %1$d notification %1$d notifications reconnecting … + Yesterday Add subscription It looks like you don\'t have any subscriptions yet. Click the button below to create or subscribe to a topic. After that, you can send messages via PUT or POST and you\'ll receive notifications on your phone.