Send share invites for Nextcloud and ownCloud

pull/1401/head
Alex Baker 5 years ago
parent 5513d42777
commit d4c01e16fd

@ -69,10 +69,13 @@ class CaldavCalendarSettingsActivity : BaseCaldavCalendarSettingsActivity() {
.setContent { .setContent {
tasksTheme.TasksTheme { tasksTheme.TasksTheme {
val openDialog = rememberSaveable { mutableStateOf(false) } val openDialog = rememberSaveable { mutableStateOf(false) }
ShareInviteDialog(openDialog) { email -> ShareInviteDialog(
openDialog,
email = caldavAccount.serverType != SERVER_OWNCLOUD
) { input ->
lifecycleScope.launch { lifecycleScope.launch {
// TODO: remove delay hack after beta02 release // TODO: remove delay hack after beta02 release
email?.let { share(it) } ?: delay(100) input?.let { share(it) } ?: delay(100)
openDialog.value = false openDialog.value = false
} }
} }
@ -152,7 +155,7 @@ class CaldavCalendarSettingsActivity : BaseCaldavCalendarSettingsActivity() {
val CaldavAccount.canShare: Boolean val CaldavAccount.canShare: Boolean
get() = when (serverType) { get() = when (serverType) {
SERVER_TASKS, SERVER_SABREDAV -> true SERVER_TASKS, SERVER_OWNCLOUD, SERVER_SABREDAV -> true
else -> false else -> false
} }
} }

@ -94,14 +94,18 @@ class CaldavCalendarViewModel @Inject constructor(
suspend fun addUser( suspend fun addUser(
account: CaldavAccount, account: CaldavAccount,
list: CaldavCalendar, list: CaldavCalendar,
email: String input: String
) = doRequest { ) = doRequest {
val href = if (account.serverType == CaldavAccount.SERVER_OWNCLOUD)
"principal:principals/users/$input"
else
"mailto:$input"
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
provider.forAccount(account, list.url!!).share(account, email) provider.forAccount(account, list.url!!).share(account, href)
} }
principalDao.insert(Principal().apply { principalDao.insert(Principal().apply {
this.list = list.id this.list = list.id
principal = "mailto:$email" principal = href
inviteStatus = INVITE_UNKNOWN inviteStatus = INVITE_UNKNOWN
access = ACCESS_READ_WRITE access = ACCESS_READ_WRITE
}) })

@ -237,31 +237,35 @@ open class CaldavClient(
suspend fun share( suspend fun share(
account: CaldavAccount, account: CaldavAccount,
email: String, href: String,
displayName: String? = null,
comment: String? = null
) { ) {
when (account.serverType) { when (account.serverType) {
SERVER_TASKS, SERVER_SABREDAV -> shareSabredav(email) SERVER_TASKS, SERVER_SABREDAV -> shareSabredav(href)
SERVER_OWNCLOUD -> shareOwncloud(href)
else -> throw IllegalArgumentException() 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("""
<x4:share xmlns:x4="$NS_OWNCLOUD">
<x4:set>
<x0:href xmlns:x0="$NS_WEBDAV">$href</x0:href>
</x4:set>
</x4:share>
""".trimIndent().toRequestBody(MIME_XML)
) {}
}
private suspend fun shareSabredav(href: String) =
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
DavCollection(httpClient, httpUrl!!) DavCollection(httpClient, httpUrl!!)
.post(""" .post("""
<D:share-resource xmlns:D="$NS_WEBDAV"> <D:share-resource xmlns:D="$NS_WEBDAV">
<D:sharee> <D:sharee>
<D:href>mailto:$email</D:href> <D:href>$href</D:href>
${displayName?.let { """
<D:prop>
<D:displayname>$it</D:displayname>
</D:prop>
""".trimIndent() }}
${comment?.let { """
<D:comment>$it</D:comment>
""".trimIndent() }}
<D:share-access> <D:share-access>
<D:read-write /> <D:read-write />
</D:share-access> </D:share-access>

@ -13,6 +13,7 @@ import androidx.compose.material.Text
import androidx.compose.material.darkColors import androidx.compose.material.darkColors
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Email import androidx.compose.material.icons.outlined.Email
import androidx.compose.material.icons.outlined.Person
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
@ -29,44 +30,45 @@ import org.tasks.compose.ShareInvite.ShareInvite
@Preview(showBackground = true, backgroundColor = 0xFFFFFF) @Preview(showBackground = true, backgroundColor = 0xFFFFFF)
@Composable @Composable
private fun Invite() = MaterialTheme { private fun Invite() = MaterialTheme {
ShareInvite(mutableStateOf("")) ShareInvite(true, mutableStateOf(""))
} }
@Preview(showBackground = true, backgroundColor = 0x202124) @Preview(showBackground = true, backgroundColor = 0x202124)
@Composable @Composable
private fun InviteDark() = MaterialTheme(darkColors()) { private fun InviteDark() = MaterialTheme(darkColors()) {
ShareInvite(mutableStateOf("")) ShareInvite(false, mutableStateOf(""))
} }
@Preview(showBackground = true, backgroundColor = 0xFFFFFF) @Preview(showBackground = true, backgroundColor = 0xFFFFFF)
@Composable @Composable
private fun InviteFilled() = MaterialTheme { private fun InviteFilled() = MaterialTheme {
ShareInvite(mutableStateOf("user@example.com")) ShareInvite(true, mutableStateOf("user@example.com"))
} }
@Preview(showBackground = true, backgroundColor = 0x202124) @Preview(showBackground = true, backgroundColor = 0x202124)
@Composable @Composable
private fun InviteDarkFilled() = MaterialTheme(darkColors()) { private fun InviteDarkFilled() = MaterialTheme(darkColors()) {
ShareInvite(mutableStateOf("user@example.com")) ShareInvite(false, mutableStateOf("user@example.com"))
} }
object ShareInvite { object ShareInvite {
@Composable @Composable
fun ShareInviteDialog( fun ShareInviteDialog(
openDialog: MutableState<Boolean>, openDialog: MutableState<Boolean>,
email: Boolean,
invite: (String?) -> Unit, invite: (String?) -> Unit,
) { ) {
val email = rememberSaveable { mutableStateOf("") } val text = rememberSaveable { mutableStateOf("") }
// TODO: remove after beta02 release: https://issuetracker.google.com/issues/181282423 // TODO: remove after beta02 release: https://issuetracker.google.com/issues/181282423
val enableHack = rememberSaveable { mutableStateOf(true) } val enableHack = rememberSaveable { mutableStateOf(true) }
if (openDialog.value) { if (openDialog.value) {
AlertDialog( AlertDialog(
onDismissRequest = {}, onDismissRequest = {},
text = { ShareInvite(email, enableHack) }, text = { ShareInvite(email, text, enableHack) },
confirmButton = { confirmButton = {
TextButton(text = R.string.invite, onClick = { TextButton(text = R.string.invite, onClick = {
enableHack.value = false enableHack.value = false
invite(email.value) invite(text.value)
}) })
}, },
dismissButton = { dismissButton = {
@ -77,29 +79,36 @@ object ShareInvite {
}, },
) )
} else { } else {
email.value = "" text.value = ""
enableHack.value = true enableHack.value = true
} }
} }
@Composable @Composable
fun ShareInvite(email: MutableState<String>, enableHack: MutableState<Boolean> = mutableStateOf(true)) { fun ShareInvite(
email: Boolean,
text: MutableState<String>,
enableHack: MutableState<Boolean> = mutableStateOf(true)
) {
Column(modifier = Modifier.fillMaxWidth()) { Column(modifier = Modifier.fillMaxWidth()) {
Text( Text(
stringResource(R.string.share_list), stringResource(R.string.share_list),
style = MaterialTheme.typography.h6, style = MaterialTheme.typography.h6,
) )
Spacer(Modifier.height(Constants.KEYLINE_FIRST)) Spacer(Modifier.height(Constants.KEYLINE_FIRST))
val label = stringResource(if (email) R.string.email else R.string.user)
OutlinedTextField( OutlinedTextField(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
value = email.value, value = text.value,
label = { Text(stringResource(R.string.email)) }, label = { Text(label) },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Email), keyboardOptions = KeyboardOptions(
onValueChange = { email.value = it }, keyboardType = if (email) KeyboardType.Email else KeyboardType.Text
),
onValueChange = { text.value = it },
leadingIcon = { leadingIcon = {
Icon( Icon(
imageVector = Icons.Outlined.Email, imageVector = if (email) Icons.Outlined.Email else Icons.Outlined.Person,
contentDescription = stringResource(id = R.string.email) contentDescription = label
) )
}, },
enabled = enableHack.value, enabled = enableHack.value,

Loading…
Cancel
Save