From d4c01e16fd0b5c2ed24c57942feec56226870f2c Mon Sep 17 00:00:00 2001 From: Alex Baker Date: Tue, 9 Mar 2021 13:55:52 -0600 Subject: [PATCH] Send share invites for Nextcloud and ownCloud --- .../caldav/CaldavCalendarSettingsActivity.kt | 9 +++-- .../tasks/caldav/CaldavCalendarViewModel.kt | 10 +++-- .../java/org/tasks/caldav/CaldavClient.kt | 32 ++++++++------- .../java/org/tasks/compose/ShareInvite.kt | 39 ++++++++++++------- 4 files changed, 55 insertions(+), 35 deletions(-) diff --git a/app/src/main/java/org/tasks/caldav/CaldavCalendarSettingsActivity.kt b/app/src/main/java/org/tasks/caldav/CaldavCalendarSettingsActivity.kt index fe121e71f..7cc1c4fdd 100644 --- a/app/src/main/java/org/tasks/caldav/CaldavCalendarSettingsActivity.kt +++ b/app/src/main/java/org/tasks/caldav/CaldavCalendarSettingsActivity.kt @@ -69,10 +69,13 @@ class CaldavCalendarSettingsActivity : BaseCaldavCalendarSettingsActivity() { .setContent { tasksTheme.TasksTheme { val openDialog = rememberSaveable { mutableStateOf(false) } - ShareInviteDialog(openDialog) { email -> + ShareInviteDialog( + openDialog, + email = caldavAccount.serverType != SERVER_OWNCLOUD + ) { input -> lifecycleScope.launch { // TODO: remove delay hack after beta02 release - email?.let { share(it) } ?: delay(100) + input?.let { share(it) } ?: delay(100) openDialog.value = false } } @@ -152,7 +155,7 @@ class CaldavCalendarSettingsActivity : BaseCaldavCalendarSettingsActivity() { val CaldavAccount.canShare: Boolean get() = when (serverType) { - SERVER_TASKS, SERVER_SABREDAV -> true + SERVER_TASKS, SERVER_OWNCLOUD, SERVER_SABREDAV -> true else -> false } } diff --git a/app/src/main/java/org/tasks/caldav/CaldavCalendarViewModel.kt b/app/src/main/java/org/tasks/caldav/CaldavCalendarViewModel.kt index 05807784d..a668ffa41 100644 --- a/app/src/main/java/org/tasks/caldav/CaldavCalendarViewModel.kt +++ b/app/src/main/java/org/tasks/caldav/CaldavCalendarViewModel.kt @@ -94,14 +94,18 @@ class CaldavCalendarViewModel @Inject constructor( suspend fun addUser( account: CaldavAccount, list: CaldavCalendar, - email: String + input: String ) = doRequest { + val href = if (account.serverType == CaldavAccount.SERVER_OWNCLOUD) + "principal:principals/users/$input" + else + "mailto:$input" withContext(Dispatchers.IO) { - provider.forAccount(account, list.url!!).share(account, email) + provider.forAccount(account, list.url!!).share(account, href) } principalDao.insert(Principal().apply { this.list = list.id - principal = "mailto:$email" + principal = href inviteStatus = INVITE_UNKNOWN access = ACCESS_READ_WRITE }) diff --git a/app/src/main/java/org/tasks/caldav/CaldavClient.kt b/app/src/main/java/org/tasks/caldav/CaldavClient.kt index 6b97bad59..e435c6410 100644 --- a/app/src/main/java/org/tasks/caldav/CaldavClient.kt +++ b/app/src/main/java/org/tasks/caldav/CaldavClient.kt @@ -237,31 +237,35 @@ open class CaldavClient( suspend fun share( account: CaldavAccount, - email: String, - displayName: String? = null, - comment: String? = null + href: String, ) { when (account.serverType) { - SERVER_TASKS, SERVER_SABREDAV -> shareSabredav(email) + SERVER_TASKS, SERVER_SABREDAV -> shareSabredav(href) + SERVER_OWNCLOUD -> shareOwncloud(href) else -> throw IllegalArgumentException() } } - private suspend fun shareSabredav(email: String, displayName: String? = null, comment: String? = null) = + private suspend fun shareOwncloud(href: String) = + withContext(Dispatchers.IO) { + DavCollection(httpClient, httpUrl!!) + .post(""" + + + $href + + + """.trimIndent().toRequestBody(MIME_XML) + ) {} + } + + private suspend fun shareSabredav(href: String) = withContext(Dispatchers.IO) { DavCollection(httpClient, httpUrl!!) .post(""" - mailto:$email - ${displayName?.let { """ - - $it - - """.trimIndent() }} - ${comment?.let { """ - $it - """.trimIndent() }} + $href diff --git a/app/src/main/java/org/tasks/compose/ShareInvite.kt b/app/src/main/java/org/tasks/compose/ShareInvite.kt index 6ead4e027..14566d225 100644 --- a/app/src/main/java/org/tasks/compose/ShareInvite.kt +++ b/app/src/main/java/org/tasks/compose/ShareInvite.kt @@ -13,6 +13,7 @@ import androidx.compose.material.Text import androidx.compose.material.darkColors import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Email +import androidx.compose.material.icons.outlined.Person import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf @@ -29,44 +30,45 @@ import org.tasks.compose.ShareInvite.ShareInvite @Preview(showBackground = true, backgroundColor = 0xFFFFFF) @Composable private fun Invite() = MaterialTheme { - ShareInvite(mutableStateOf("")) + ShareInvite(true, mutableStateOf("")) } @Preview(showBackground = true, backgroundColor = 0x202124) @Composable private fun InviteDark() = MaterialTheme(darkColors()) { - ShareInvite(mutableStateOf("")) + ShareInvite(false, mutableStateOf("")) } @Preview(showBackground = true, backgroundColor = 0xFFFFFF) @Composable private fun InviteFilled() = MaterialTheme { - ShareInvite(mutableStateOf("user@example.com")) + ShareInvite(true, mutableStateOf("user@example.com")) } @Preview(showBackground = true, backgroundColor = 0x202124) @Composable private fun InviteDarkFilled() = MaterialTheme(darkColors()) { - ShareInvite(mutableStateOf("user@example.com")) + ShareInvite(false, mutableStateOf("user@example.com")) } object ShareInvite { @Composable fun ShareInviteDialog( openDialog: MutableState, + email: Boolean, invite: (String?) -> Unit, ) { - val email = rememberSaveable { mutableStateOf("") } + val text = rememberSaveable { mutableStateOf("") } // TODO: remove after beta02 release: https://issuetracker.google.com/issues/181282423 val enableHack = rememberSaveable { mutableStateOf(true) } if (openDialog.value) { AlertDialog( onDismissRequest = {}, - text = { ShareInvite(email, enableHack) }, + text = { ShareInvite(email, text, enableHack) }, confirmButton = { TextButton(text = R.string.invite, onClick = { enableHack.value = false - invite(email.value) + invite(text.value) }) }, dismissButton = { @@ -77,29 +79,36 @@ object ShareInvite { }, ) } else { - email.value = "" + text.value = "" enableHack.value = true } } @Composable - fun ShareInvite(email: MutableState, enableHack: MutableState = mutableStateOf(true)) { + fun ShareInvite( + email: Boolean, + text: MutableState, + enableHack: MutableState = mutableStateOf(true) + ) { Column(modifier = Modifier.fillMaxWidth()) { Text( stringResource(R.string.share_list), style = MaterialTheme.typography.h6, ) Spacer(Modifier.height(Constants.KEYLINE_FIRST)) + val label = stringResource(if (email) R.string.email else R.string.user) OutlinedTextField( modifier = Modifier.fillMaxWidth(), - value = email.value, - label = { Text(stringResource(R.string.email)) }, - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Email), - onValueChange = { email.value = it }, + value = text.value, + label = { Text(label) }, + keyboardOptions = KeyboardOptions( + keyboardType = if (email) KeyboardType.Email else KeyboardType.Text + ), + onValueChange = { text.value = it }, leadingIcon = { Icon( - imageVector = Icons.Outlined.Email, - contentDescription = stringResource(id = R.string.email) + imageVector = if (email) Icons.Outlined.Email else Icons.Outlined.Person, + contentDescription = label ) }, enabled = enableHack.value,