Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable Notifications in shared Calendar #733

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
646 changes: 646 additions & 0 deletions app/schemas/at.bitfire.davdroid.db.AppDatabase/14.json

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions app/src/main/kotlin/at/bitfire/davdroid/db/AppDatabase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,12 @@ import javax.inject.Singleton
SyncStats::class,
WebDavDocument::class,
WebDavMount::class
], exportSchema = true, version = 13, autoMigrations = [
], exportSchema = true, version = 14, autoMigrations = [
AutoMigration(from = 9, to = 10),
AutoMigration(from = 10, to = 11),
AutoMigration(from = 11, to = 12, spec = AppDatabase.AutoMigration11_12::class),
AutoMigration(from = 12, to = 13)
AutoMigration(from = 12, to = 13),
AutoMigration(from = 13, to = 14)
])
@TypeConverters(Converters::class)
abstract class AppDatabase: RoomDatabase() {
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/kotlin/at/bitfire/davdroid/db/Collection.kt
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ data class Collection(
// CalDAV only
var color: Int? = null,

/** Whether event alerts should be ignored. Only available on CalDAV */
var ignoreAlerts: Boolean? = null,

/** timezone definition (full VTIMEZONE) - not a TZID! **/
var timezone: String? = null,

Expand Down
3 changes: 3 additions & 0 deletions app/src/main/kotlin/at/bitfire/davdroid/db/CollectionDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ interface CollectionDao {
@Query("UPDATE collection SET forceReadOnly=:forceReadOnly WHERE id=:id")
fun updateForceReadOnly(id: Long, forceReadOnly: Boolean)

@Query("UPDATE collection SET ignoreAlerts=:ignoreAlerts WHERE id=:id")
fun updateIgnoreAlerts(id: Long, ignoreAlerts: Boolean)

@Query("UPDATE collection SET sync=:sync WHERE id=:id")
fun updateSync(id: Long, sync: Boolean)

Expand Down
19 changes: 19 additions & 0 deletions app/src/main/kotlin/at/bitfire/davdroid/resource/LocalCalendar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class LocalCalendar private constructor(

private const val COLUMN_SYNC_STATE = Calendars.CAL_SYNC1

private const val COLUMN_IGNORE_ALERTS = Calendars.CAL_SYNC2

fun create(account: Account, provider: ContentProviderClient, info: Collection): Uri {
val values = valuesFromCollectionInfo(info, true)

Expand All @@ -45,6 +47,8 @@ class LocalCalendar private constructor(
// user is ORGANIZER/ATTENDEE for a certain event.
values.put(Calendars.OWNER_ACCOUNT, account.name)

values.put(COLUMN_IGNORE_ALERTS, info.ignoreAlerts)

// flag as visible & synchronizable at creation, might be changed by user at any time
values.put(Calendars.VISIBLE, 1)
values.put(Calendars.SYNC_EVENTS, 1)
Expand Down Expand Up @@ -77,6 +81,8 @@ class LocalCalendar private constructor(
}
}

values.put(COLUMN_IGNORE_ALERTS, info.ignoreAlerts)

// add base values for Calendars
values.putAll(calendarBaseValues)

Expand Down Expand Up @@ -108,6 +114,19 @@ class LocalCalendar private constructor(
provider.update(calendarSyncURI(), values, null, null)
}

var ignoreAlerts: Boolean?
get() = provider.query(calendarSyncURI(), arrayOf(COLUMN_IGNORE_ALERTS), null, null, null)?.use { cursor ->
if (cursor.moveToNext())
return cursor.getInt(0) == 1
else
null
}
set(state) {
val values = ContentValues(1)
values.put(COLUMN_IGNORE_ALERTS, state)
provider.update(calendarSyncURI(), values, null, null)
}


override fun populate(info: ContentValues) {
super.populate(info)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@ import dagger.hilt.EntryPoint
import dagger.hilt.InstallIn
import dagger.hilt.android.EntryPointAccessors
import dagger.hilt.components.SingletonComponent
import java.io.ByteArrayInputStream
import java.io.ObjectInputStream
import java.util.logging.Level
import net.fortuna.ical4j.model.Property
import net.fortuna.ical4j.model.property.Url
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import org.dmfs.tasks.contract.TaskContract
import java.io.ByteArrayInputStream
import java.io.ObjectInputStream
import java.util.logging.Level

class AccountSettingsMigrations(
val context: Context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ import at.bitfire.davdroid.util.DavUtils
import at.bitfire.ical4android.Event
import at.bitfire.ical4android.InvalidCalendarException
import at.bitfire.ical4android.util.DateUtils
import java.io.ByteArrayOutputStream
import java.io.Reader
import java.io.StringReader
import java.time.Duration
import java.time.ZonedDateTime
import java.util.logging.Level
import net.fortuna.ical4j.model.Component
import net.fortuna.ical4j.model.component.VAlarm
import net.fortuna.ical4j.model.property.Action
Expand All @@ -38,12 +44,6 @@ import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import org.apache.commons.io.FileUtils
import java.io.ByteArrayOutputStream
import java.io.Reader
import java.io.StringReader
import java.time.Duration
import java.time.ZonedDateTime
import java.util.logging.Level

/**
* Synchronization manager for CalDAV collections; handles events (VEVENT)
Expand Down Expand Up @@ -203,6 +203,13 @@ class CalendarSyncManager(
return
}

// remove all alerts if the user has disabled them
if (localCollection.ignoreAlerts == true) {
for (event in events) {
event.alarms.clear()
}
}

if (events.size == 1) {
val event = events.first()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,11 @@ import com.google.accompanist.permissions.isGranted
import com.google.accompanist.permissions.rememberPermissionState
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.lifecycle.HiltViewModel
import java.text.Collator
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.text.Collator
import javax.inject.Inject


@AndroidEntryPoint
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ import at.bitfire.davdroid.util.TaskUtils
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.rememberMultiplePermissionsState
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import javax.inject.Inject
import kotlinx.coroutines.launch

@AndroidEntryPoint
class AccountActivity : AppCompatActivity() {
Expand Down Expand Up @@ -187,6 +187,9 @@ class AccountActivity : AppCompatActivity() {
onChangeForceReadOnly = { id, forceReadOnly ->
model.setCollectionForceReadOnly(id, forceReadOnly)
},
onChangeIgnoreAlerts = { id, ignoreAlerts ->
model.setCollectionIgnoreAlerts(id, ignoreAlerts)
},
onSubscribe = { item ->
installIcsx5 = !subscribeWebcal(item)
},
Expand Down Expand Up @@ -266,6 +269,7 @@ fun AccountOverview(
subscriptions: LazyPagingItems<Collection>?,
onUpdateCollectionSync: (collectionId: Long, sync: Boolean) -> Unit = { _, _ -> },
onChangeForceReadOnly: (collectionId: Long, forceReadOnly: Boolean) -> Unit = { _, _ -> },
onChangeIgnoreAlerts: (collectionId: Long, ignoreAlerts: Boolean) -> Unit = { _, _ -> },
onSubscribe: (Collection) -> Unit = {},
installIcsx5: Boolean = false,
onRefreshCollections: () -> Unit = {},
Expand Down Expand Up @@ -443,7 +447,8 @@ fun AccountOverview(
progress = calDavProgress,
collections = calendars,
onUpdateCollectionSync = onUpdateCollectionSync,
onChangeForceReadOnly = onChangeForceReadOnly
onChangeForceReadOnly = onChangeForceReadOnly,
onChangeIgnoreAlerts = onChangeIgnoreAlerts
)
}

Expand Down Expand Up @@ -699,6 +704,7 @@ fun ServiceTab(
collections: LazyPagingItems<Collection>?,
onUpdateCollectionSync: (collectionId: Long, sync: Boolean) -> Unit = { _, _ -> },
onChangeForceReadOnly: (collectionId: Long, forceReadOnly: Boolean) -> Unit = { _, _ -> },
onChangeIgnoreAlerts: (collectionId: Long, ignoreAlerts: Boolean) -> Unit = { _, _ -> },
onSubscribe: (Collection) -> Unit = {},
) {
val context = LocalContext.current
Expand Down Expand Up @@ -744,6 +750,7 @@ fun ServiceTab(
onChangeSync = onUpdateCollectionSync,
onChangeForceReadOnly = onChangeForceReadOnly,
onSubscribe = onSubscribe,
onChangeIgnoreAlerts = onChangeIgnoreAlerts,
modifier = Modifier.weight(1f)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,13 @@ import at.bitfire.ical4android.util.DateUtils
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import java.io.StringWriter
import java.util.Optional
import java.util.logging.Level
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.launch
import net.fortuna.ical4j.model.Calendar
import java.io.StringWriter
import java.util.Optional
import java.util.logging.Level

class AccountModel @AssistedInject constructor(
val context: Application,
Expand Down Expand Up @@ -561,6 +561,10 @@ class AccountModel @AssistedInject constructor(
db.collectionDao().updateForceReadOnly(id, forceReadOnly)
}

fun setCollectionIgnoreAlerts(id: Long, ignoreAlerts: Boolean) = viewModelScope.launch(Dispatchers.IO) {
db.collectionDao().updateIgnoreAlerts(id, ignoreAlerts)
}


// helpers

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
Expand Down Expand Up @@ -58,6 +59,7 @@ fun CollectionsList(
collections: LazyPagingItems<Collection>,
onChangeSync: (collectionId: Long, sync: Boolean) -> Unit,
onChangeForceReadOnly: (collectionId: Long, forceReadOnly: Boolean) -> Unit,
onChangeIgnoreAlerts: (collectionId: Long, ignoreAlerts: Boolean) -> Unit,
modifier: Modifier = Modifier,
onSubscribe: (collection: Collection) -> Unit = {}
) {
Expand Down Expand Up @@ -86,6 +88,10 @@ fun CollectionsList(
},
onChangeForceReadOnly = { forceReadOnly ->
onChangeForceReadOnly(item.id, forceReadOnly)
},
supportsIgnoreAlerts = item.type == Collection.TYPE_CALENDAR,
onChangeIgnoreAlerts = { ignoreAlerts ->
onChangeIgnoreAlerts(item.id, ignoreAlerts)
}
)
}
Expand All @@ -98,7 +104,9 @@ fun CollectionsList(
fun CollectionList_Item(
collection: Collection,
onChangeSync: (sync: Boolean) -> Unit = {},
onChangeForceReadOnly: (forceReadOnly: Boolean) -> Unit = {}
onChangeForceReadOnly: (forceReadOnly: Boolean) -> Unit = {},
supportsIgnoreAlerts: Boolean = false,
onChangeIgnoreAlerts: (ignoreAlerts: Boolean) -> Unit = {}
) {
val context = LocalContext.current

Expand All @@ -122,7 +130,8 @@ fun CollectionList_Item(
modifier = Modifier
.padding(horizontal = 4.dp)
.semantics {
contentDescription = context.getString(R.string.account_synchronize_this_collection)
contentDescription =
context.getString(R.string.account_synchronize_this_collection)
}
)

Expand Down Expand Up @@ -172,6 +181,35 @@ fun CollectionList_Item(
expanded = showOverflow,
onDismissRequest = { showOverflow = false }
) {
// Ignore alerts (only supported by caldav, obviously)
if (supportsIgnoreAlerts) {
DropdownMenuItem(
onClick = {
onChangeIgnoreAlerts(
if (collection.ignoreAlerts == true) false else true
)
showOverflow = false
}
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth()
) {
Text(
text = stringResource(R.string.collection_ignore_alerts),
modifier = Modifier.weight(1f)
)
Checkbox(
checked = collection.ignoreAlerts == true,
onCheckedChange = { ignoreAlerts ->
onChangeIgnoreAlerts(ignoreAlerts)
showOverflow = false
}
)
}
}
}

// force read-only (only show for collections that are modifiable on the server)
if (collection.privWriteContent)
DropdownMenuItem(
Expand All @@ -180,8 +218,14 @@ fun CollectionList_Item(
showOverflow = false
}
) {
Row(verticalAlignment = Alignment.CenterVertically) {
Text(stringResource(R.string.collection_force_read_only))
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth()
) {
Text(
text = stringResource(R.string.collection_force_read_only),
modifier = Modifier.weight(1f)
)
Checkbox(
checked = collection.readOnly(),
onCheckedChange = { forceReadOnly ->
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@
<string name="delete_collection_confirm_title">Are you sure?</string>
<string name="delete_collection_confirm_warning">This collection (%s) and all its data will be removed permanently.</string>
<string name="delete_collection_data_shall_be_deleted">These data shall be deleted from the server.</string>
<string name="collection_ignore_alerts">Ignore Alerts</string>
<string name="collection_force_read_only">Force read-only</string>
<string name="collection_properties">Properties</string>
<string name="collection_properties_sync_time">Last synced</string>
Expand Down
Loading