Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a1df07dc3 | ||
|
|
75315d92a7 | ||
|
|
95ad3a30cf | ||
|
|
8ce4831efa |
No files matched your search
@@ -5,7 +5,6 @@ import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
@@ -19,9 +18,7 @@ import de.jeanlucmakiola.calendula.data.prefs.CalendarPrefs
|
||||
import de.jeanlucmakiola.calendula.data.prefs.SettingsPrefs
|
||||
import de.jeanlucmakiola.calendula.data.prefs.is24Hour
|
||||
import de.jeanlucmakiola.calendula.data.prefs.resolveFirstDay
|
||||
import de.jeanlucmakiola.calendula.domain.reminders.reminderMapQuery
|
||||
import de.jeanlucmakiola.floret.android.hasPermission
|
||||
import de.jeanlucmakiola.floret.android.resolvableMapsSearchIntent
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.datetime.isoDayNumber
|
||||
import java.time.DayOfWeek
|
||||
@@ -113,11 +110,6 @@ class ReminderNotifier @Inject constructor(
|
||||
context.getString(R.string.reminder_action_dismiss),
|
||||
actionIntent(alert, ReminderActionReceiver.ACTION_DISMISS),
|
||||
)
|
||||
.apply {
|
||||
mapIntent(alert)?.let {
|
||||
addAction(R.drawable.ic_notification_map, context.getString(R.string.event_detail_open_in_maps), it)
|
||||
}
|
||||
}
|
||||
.build()
|
||||
val manager = NotificationManagerCompat.from(context)
|
||||
cancelLegacy(alert)
|
||||
@@ -189,24 +181,6 @@ class ReminderNotifier @Inject constructor(
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
|
||||
/**
|
||||
* Opens [alert]'s location in maps like the detail screen does, started
|
||||
* directly (no receiver trampoline). Leaves the notification up for a later
|
||||
* snooze or dismiss. Null without a place to look up (a bare meeting link
|
||||
* isn't one) or an app to open it.
|
||||
*/
|
||||
private fun mapIntent(alert: ReminderAlert): PendingIntent? {
|
||||
val query = reminderMapQuery(alert.location) ?: return null
|
||||
val intent = context.resolvableMapsSearchIntent(query) ?: return null
|
||||
return PendingIntent.getActivity(
|
||||
context,
|
||||
// An implicit activity intent: filterEquals already keeps it apart from the others.
|
||||
/* requestCode = */ 0,
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
}
|
||||
|
||||
/** Channel creation is idempotent; re-running refreshes the localized name. */
|
||||
private fun ensureChannel() {
|
||||
val channel = NotificationChannel(
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package de.jeanlucmakiola.calendula.domain.reminders
|
||||
|
||||
// Same link shape the detail screen linkifies (ui/detail/WebLinks.kt).
|
||||
private val webLinkRegex = Regex("""https?://[^\s<>"]+""", RegexOption.IGNORE_CASE)
|
||||
|
||||
/**
|
||||
* What a reminder's "Open in maps" button looks up for [location] — the same
|
||||
* text the detail screen's location card opens in maps — or null when there is
|
||||
* no place to find: blank, or nothing but web (meeting) links.
|
||||
*/
|
||||
fun reminderMapQuery(location: String?): String? {
|
||||
val trimmed = location?.trim()?.takeIf { it.isNotEmpty() } ?: return null
|
||||
return trimmed.takeIf { webLinkRegex.replace(it, "").any(Char::isLetterOrDigit) }
|
||||
}
|
||||
@@ -90,7 +90,6 @@ import de.jeanlucmakiola.calendula.domain.timeZoneOptionOf
|
||||
import de.jeanlucmakiola.calendula.domain.zoneDescriptor
|
||||
import de.jeanlucmakiola.calendula.domain.zoneOrNull
|
||||
import de.jeanlucmakiola.calendula.ui.common.orUnnamed
|
||||
import de.jeanlucmakiola.floret.android.mapsSearchIntents
|
||||
import de.jeanlucmakiola.floret.components.IconInfoCard
|
||||
import de.jeanlucmakiola.floret.identity.LocalFloretDarkTheme
|
||||
import de.jeanlucmakiola.floret.identity.predictiveBack
|
||||
@@ -885,6 +884,9 @@ private fun startOrSayNoApp(context: Context, intent: Intent) {
|
||||
|
||||
/** Open a maps intent for [query]; fall back to a web maps URL if no app handles geo:. */
|
||||
private fun openInMaps(context: Context, query: String) {
|
||||
val opened = mapsSearchIntents(query).any { runCatching { context.startActivity(it) }.isSuccess }
|
||||
if (!opened) Toast.makeText(context, R.string.link_open_failed, Toast.LENGTH_SHORT).show()
|
||||
val encoded = Uri.encode(query)
|
||||
val geo = Intent(Intent.ACTION_VIEW, Uri.parse("geo:0,0?q=$encoded"))
|
||||
if (runCatching { context.startActivity(geo) }.isFailure) {
|
||||
openWebLink(context, "https://www.google.com/maps/search/?api=1&query=$encoded")
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Monochrome notification-action mark: Material "place" glyph. -->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13c0,-3.87 -3.13,-7 -7,-7zM12,11.5c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5 2.5,1.12 2.5,2.5 -1.12,2.5 -2.5,2.5z" />
|
||||
</vector>
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
package de.jeanlucmakiola.calendula.domain.reminders
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class ReminderMapQueryTest {
|
||||
|
||||
@Test
|
||||
fun `an address is looked up as written`() {
|
||||
assertThat(reminderMapQuery(" Main St 1, Berlin ")).isEqualTo("Main St 1, Berlin")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `no location means no lookup`() {
|
||||
assertThat(reminderMapQuery(null)).isNull()
|
||||
assertThat(reminderMapQuery(" ")).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `a bare meeting link is not a place`() {
|
||||
assertThat(reminderMapQuery("https://meet.google.com/abc-defg-hij")).isNull()
|
||||
assertThat(reminderMapQuery("HTTP://example.com")).isNull()
|
||||
assertThat(reminderMapQuery("<https://teams.microsoft.com/l/meetup-join/x>")).isNull()
|
||||
assertThat(reminderMapQuery("https://a.example\nhttps://b.example")).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `dotted place names are still places`() {
|
||||
assertThat(reminderMapQuery("Hauptstr. 12/3, Wien")).isEqualTo("Hauptstr. 12/3, Wien")
|
||||
assertThat(reminderMapQuery("St.Gallen/Zentrum")).isEqualTo("St.Gallen/Zentrum")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `a place with a link beside it is still looked up`() {
|
||||
assertThat(reminderMapQuery("Room 4, https://example.com/map")).isEqualTo("Room 4, https://example.com/map")
|
||||
}
|
||||
}
|
||||
+1
-1
Submodule floret-kit updated: aa6398e4d5...a039ab5bd4.
Reference in new issue
Block a user