Skip to content
Merged
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
3 changes: 3 additions & 0 deletions app/src/main/java/com/gatecontrol/android/mail/MailModels.kt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ data class MMe(
const val FEATURE_DRIVE = "drive"
const val FEATURE_FAMILY_CALENDAR = "familyCalendar"
const val FEATURE_IMAGES = "images"
/** Since Mail 1.2.0: calendars and contacts (the administrator switched them on). */
const val FEATURE_CALENDAR = "calendar"
const val FEATURE_CONTACTS = "contacts"
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ private class MailNavigation(private val navController: NavHostController) {
draft = { go(Screen.MailCompose.create(draft = it)) },
search = { go(Screen.MailSearch.route) },
filing = { go(Screen.MailFiling.route) },
addAccount = { go(Screen.MailAddAccount.create()) },
addAccount = {
// an account is added in the settings: back from adding leads there
go(Screen.MailSettings.route)
go(Screen.MailAddAccount.create())
},
settings = { go(Screen.MailSettings.route) },
account = { go(Screen.MailAccount.create(it)) },
outbox = { go(Screen.MailOutbox.route) },
Expand Down
70 changes: 56 additions & 14 deletions app/src/main/java/com/gatecontrol/android/ui/mail/MailHomeScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ data class MailNav(
val draft: (Long) -> Unit,
val search: () -> Unit,
val filing: () -> Unit,
/** "Konto hinzufügen" of the empty tab: the settings with "Konto hinzufügen" on top (the menu has no "+"). */
val addAccount: () -> Unit,
val settings: () -> Unit,
val account: (Long) -> Unit,
Expand Down Expand Up @@ -172,7 +173,6 @@ fun MailHomeScreen(nav: MailNav, viewModel: MailHomeViewModel = hiltViewModel())
onBox = { close(); viewModel.selectBox(it) },
onFiling = { close(); nav.filing() },
onOutbox = { close(); nav.outbox() },
onAdd = { close(); nav.addAccount() },
onSettings = { close(); nav.settings() },
)
}
Expand Down Expand Up @@ -576,10 +576,11 @@ internal object MailFolders {
}

/**
* The menu (mockup "Seitenmenü"): "Mail", "Alle Posteingänge", "Zum Ablegen" (with Drive), "Postausgang" (when
* something waits), the accounts with their folders and below "Konto hinzufügen" and the settings. A tap on an
* account opens or closes its folders (the menu stays, [folds] keeps it for the session); picking its "Posteingang"
* or a folder closes the menu. Calendar and resources come later (phase 2/3).
* The menu (mockups "Seitenmenü" and "Seitenmenü neu"): "Mail", "Alle Posteingänge", "Zum Ablegen" (with Drive),
* "Postausgang" (when something waits), the accounts with their folders, the storage bar and the foot: the settings
* on the left, contacts and calendar on the right ([MailDrawerFoot]). A tap on an account opens or closes its folders
* (the menu stays, [folds] keeps it for the session); picking its "Posteingang" or a folder closes the menu. An
* account is added in the settings only (no "+" here since phase 2).
*/
@Composable
private fun MailDrawer(
Expand All @@ -593,8 +594,10 @@ private fun MailDrawer(
onBox: (MailLogic.Box) -> Unit,
onFiling: () -> Unit,
onOutbox: () -> Unit,
onAdd: () -> Unit,
onSettings: () -> Unit,
onContacts: (() -> Unit)? = null,
onCalendar: (() -> Unit)? = null,
area: String = MailDrawerFoot.MAIL,
) {
val extra = GateControlTheme.extraColors
Column(Modifier.fillMaxHeight().padding(start = 12.dp, end = 12.dp, top = 8.dp, bottom = 16.dp)) {
Expand Down Expand Up @@ -653,13 +656,50 @@ private fun MailDrawer(
}
}
}
Row(Modifier.padding(horizontal = 12.dp, vertical = 8.dp), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
DrawerIcon(GcIcons.Plus, stringResource(R.string.mail_add_account), onAdd)
DrawerIcon(GcIcons.Settings, stringResource(R.string.mail_settings), onSettings)
MailDrawerFoot(me = me, area = area, onSettings = onSettings, onContacts = onContacts, onCalendar = onCalendar)
}
}

/**
* The menu's foot (mockup "Seitenmenü neu"): the settings on the left; contacts and calendar on the right, each only
* when the server offers it (`features.contacts` / `features.calendar`) and the app can open it, the active area in the
* accent. A tap on the active one goes back to the mail.
*/
@Composable
internal fun MailDrawerFoot(
me: MMe?,
area: String,
onSettings: () -> Unit,
onContacts: (() -> Unit)?,
onCalendar: (() -> Unit)?,
) {
Row(
Modifier.fillMaxWidth().padding(horizontal = 12.dp, vertical = 8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically,
) {
DrawerIcon(GcIcons.Settings, stringResource(R.string.mail_settings), on = false, onClick = onSettings)
Spacer(Modifier.weight(1f))
if (onContacts != null && MailDrawerFoot.contacts(me)) {
DrawerIcon(GcIcons.User, stringResource(R.string.mail_contacts), on = area == MailDrawerFoot.CONTACTS, onClick = onContacts)
}
if (onCalendar != null && MailDrawerFoot.calendar(me)) {
DrawerIcon(GcIcons.Calendar, stringResource(R.string.mail_calendar), on = area == MailDrawerFoot.CALENDAR, onClick = onCalendar)
}
}
}

/** What the menu's foot shows (pure, unit-tested). */
internal object MailDrawerFoot {
const val MAIL = "mail"
const val CALENDAR = "calendar"
const val CONTACTS = "contacts"

fun calendar(me: MMe?): Boolean = me?.has(MMe.FEATURE_CALENDAR) == true

fun contacts(me: MMe?): Boolean = me?.has(MMe.FEATURE_CONTACTS) == true
}

@Composable
private fun DrawerLabel(text: String) {
Text(
Expand Down Expand Up @@ -740,18 +780,20 @@ private fun DrawerAccount(a: MAccount, count: Int, on: Boolean, open: Boolean, o
}
}

/** A square button of the menu's foot (44×44); [on]: the area shown now, in the accent (`aria-pressed`). */
@Composable
private fun DrawerIcon(icon: androidx.compose.ui.graphics.vector.ImageVector, label: String, onClick: () -> Unit) {
private fun DrawerIcon(icon: androidx.compose.ui.graphics.vector.ImageVector, label: String, on: Boolean, onClick: () -> Unit) {
val extra = GateControlTheme.extraColors
val shape = RoundedCornerShape(12.dp)
Box(
Modifier
.size(44.dp)
.clip(RoundedCornerShape(12.dp))
.border(1.dp, extra.border, RoundedCornerShape(12.dp))
.clickable(role = Role.Button, onClick = onClick)
.clip(shape)
.then(if (on) Modifier.background(extra.accentBg) else Modifier.border(1.dp, extra.border, shape))
.selectable(selected = on, role = Role.Button, onClick = onClick)
.semantics { contentDescription = label },
contentAlignment = Alignment.Center,
) {
Icon(icon, contentDescription = null, tint = extra.muted, modifier = Modifier.size(20.dp))
Icon(icon, contentDescription = null, tint = if (on) extra.accentText else extra.muted, modifier = Modifier.size(20.dp))
}
}
2 changes: 2 additions & 0 deletions app/src/main/res/values-de/strings_mail.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
<string name="mail_accounts">Konten</string>
<string name="mail_add_account">Konto hinzufügen</string>
<string name="mail_settings">Mail-Einstellungen</string>
<string name="mail_calendar">Kalender</string>
<string name="mail_contacts">Kontakte</string>
<string name="mail_quota">%1$s von %2$s belegt</string>
<string name="mail_offline_copy">Offline – du siehst den zuletzt geladenen Stand.</string>
<string name="mail_account_auth_failed">%1$s: Anmeldung abgelehnt. Tippen, um dich neu anzumelden.</string>
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings_mail.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
<string name="mail_accounts">Accounts</string>
<string name="mail_add_account">Add account</string>
<string name="mail_settings">Mail settings</string>
<string name="mail_calendar">Calendar</string>
<string name="mail_contacts">Contacts</string>
<string name="mail_quota">%1$s of %2$s used</string>
<string name="mail_offline_copy">Offline – showing what was loaded last.</string>
<string name="mail_account_auth_failed">%1$s: sign-in refused. Tap to sign in again.</string>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.gatecontrol.android.ui.mail

import com.gatecontrol.android.mail.MLimits
import com.gatecontrol.android.mail.MMe
import com.gatecontrol.android.mail.MMicrosoft
import com.gatecontrol.android.mail.MSettings
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test

class MailDrawerFootTest {

private fun me(vararg features: String) = MMe(
features = features.toSet(),
limits = MLimits(5, 0, 0, 12),
microsoft = MMicrosoft(null, "https://login.microsoftonline.com/common", emptyList()),
accounts = emptyList(),
unreadAll = 0,
unreadByAccount = emptyMap(),
settings = MSettings.DEFAULT,
)

@Test
fun `contacts and calendar only with the server's features`() {
assertFalse(MailDrawerFoot.calendar(null))
assertFalse(MailDrawerFoot.contacts(null))
assertFalse(MailDrawerFoot.calendar(me("mail")))
assertFalse(MailDrawerFoot.contacts(me("mail", "calendar")))
assertTrue(MailDrawerFoot.calendar(me("mail", "calendar")))
assertTrue(MailDrawerFoot.contacts(me("mail", "contacts")))
}
}
Loading