diff --git a/CHANGELOG.md b/CHANGELOG.md
index 49f8808..724bb14 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -32,6 +32,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
Now a bigger widget gets bigger, more readable type and roomier rows, while the
default size looks exactly as before — no new setting; it follows the size you
already chose ([#51]).
+- Calendula now appears under other apps' "Add to calendar" / "Save to calendar"
+ actions. Some apps (e.g. DB Navigator) fire the widely-used "insert event"
+ intent with the singular `vnd.android.cursor.item/event` type, which Calendula
+ didn't advertise — so it was left out of the chooser, and if it was your only
+ calendar app the save silently did nothing. It now accepts that form, plus the
+ `INSERT_OR_EDIT` action, and opens the new event prefilled for review ([#74]).
+- Opening a `.ics`/`.vcs` file now works even when another app hands it over
+ mislabelled as a generic download (`application/octet-stream`), as some mail
+ clients, browsers and file managers do — Calendula recognises it by its file
+ extension instead of relying on the declared type ([#74]).
## [2.16.0] — 2026-07-17
@@ -1079,3 +1089,4 @@ automatically, with zero telemetry and no internet permission.
[#53]: https://codeberg.org/jlmakiola/calendula/issues/53
[#60]: https://codeberg.org/jlmakiola/calendula/issues/60
[#65]: https://codeberg.org/jlmakiola/calendula/issues/65
+[#74]: https://codeberg.org/jlmakiola/calendula/issues/74
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7f73919..8e0df89 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -112,6 +112,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -123,11 +145,13 @@
+ to the same prefilled create form. (The far more common *item*-
+ typed INSERT — the form the Android docs' example and apps like
+ DB Navigator use — is the item filter below, issue #74.) -->
@@ -135,14 +159,31 @@
-
+
+
+
diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/MainActivity.kt b/app/src/main/java/de/jeanlucmakiola/calendula/MainActivity.kt
index 1177165..0a0c20f 100644
--- a/app/src/main/java/de/jeanlucmakiola/calendula/MainActivity.kt
+++ b/app/src/main/java/de/jeanlucmakiola/calendula/MainActivity.kt
@@ -222,10 +222,12 @@ class MainActivity : AppCompatActivity() {
* [buildInsertEventForm].
*/
private fun Intent.insertFormOrNull(): EventForm? {
- // ACTION_EDIT on an existing event routes to the edit form instead
- // ([editEventKeyOrNull]); only an id-less EDIT is a create.
+ // ACTION_EDIT / ACTION_INSERT_OR_EDIT on an existing event route to the
+ // edit form instead ([editEventKeyOrNull]); an id-less one is a create,
+ // as is any plain ACTION_INSERT.
val isCreate = action == Intent.ACTION_INSERT ||
- (action == Intent.ACTION_EDIT && editEventKeyOrNull() == null)
+ ((action == Intent.ACTION_EDIT || action == Intent.ACTION_INSERT_OR_EDIT) &&
+ editEventKeyOrNull() == null)
if (!isCreate) return null
return buildInsertEventForm(
beginMillis = longExtraOrNull(CalendarContract.EXTRA_EVENT_BEGIN_TIME),
@@ -344,10 +346,11 @@ class MainActivity : AppCompatActivity() {
* occurrence's times as `EXTRA_EVENT_BEGIN_TIME` / `EXTRA_EVENT_END_TIME`
* when it has them, otherwise we carry [NO_OCCURRENCE_TIME] and
* [EventEditViewModel.openForEdit] falls back to the event row's own
- * DTSTART/DTEND. An id-less `ACTION_EDIT` is a create instead ([insertFormOrNull]).
+ * DTSTART/DTEND. An id-less `ACTION_EDIT` — or `ACTION_INSERT_OR_EDIT`, which
+ * some apps fire — is a create instead ([insertFormOrNull]).
*/
private fun Intent.editEventKeyOrNull(): LongArray? {
- if (action != Intent.ACTION_EDIT) return null
+ if (action != Intent.ACTION_EDIT && action != Intent.ACTION_INSERT_OR_EDIT) return null
val uri = data ?: return null
if (uri.host != CALENDAR_PROVIDER_HOST) return null
val segments = uri.pathSegments