Files
inbuxa-webmail/web/src/views/DelegatedBar.tsx
T
jcoffey-dev 722a68432c
ci / version (pull_request) Skipped
ci / github (pull_request) Skipped
ci / node (pull_request) Successful in 1m29s
ci / publish (pull_request) Skipped
ci / announce (pull_request) Skipped
ci / docker-build (pull_request) Successful in 41s
github/ci (branch) GitHub Actions
Open a group's mailbox, or folders someone shared, from the account menu
A group's members, and anyone a folder was shared with, could reach that
mail over IMAP but not here: Mail read only the reader's own account.
Calendar, Contacts and Files already list other people's shares; Mail
now does too (multi-account spec, MA-A).

Such an account is listed under "Mail to show" in the account menu,
after any locked account handed to the reader, and opens in place of
the reader's own mail through the same switch AL-7 uses. Only accounts
whose Mailbox/get answers with a mailbox are offered: the server
advertises every capability on any shared account, so a colleague who
shared one calendar would otherwise appear with mail.

While one is in view:

- a bar in the palette's accent (not the locked account's red) names
  it, with "Back to my mail"; the tab title names it without a padlock;
- calendars, contacts and files stay the reader's own (viewAccountFor
  follows only a delegation now);
- writing a message uses the viewed account's identities, so a reply in
  support@ goes out as support@ and is saved in its Drafts and Sent.

Losing the account (removed from the group, share withdrawn) takes the
reader back to their own mail with the existing "You no longer have
access" notice.

New string: "Shared mailbox:" (1, English only in the other ten
catalogs). Checked in Chrome against a scratch server with a support@
group and two members. typecheck and vitest (174 files, 1533 tests)
pass.
2026-10-05 14:49:28 -07:00

64 lines
2.2 KiB
TypeScript

import { Lock, Users } from "lucide-react";
import { useLocation } from "wouter";
import { useSession, useViewingDelegation, useViewingShared } from "@/store/session";
import { t } from "@/lib/i18n";
import type { DelegationAccess } from "@/lib/delegation";
export function accessText(access: DelegationAccess): string {
switch (access) {
case "read":
return t("Read only");
case "organize":
return t("Read and organize");
case "full":
return t("Full access");
}
}
/**
* inbuxa AL-7: while a locked account's mail is in view, a red bar across
* the whole app says so, with the way back. Red, not the palette's accent: a
* fixed color that reads the same in every palette and in dark mode, so it
* can't be mistaken for part of a theme.
*/
export function DelegatedBar() {
const viewing = useSession((s) => s.viewing);
const name = useSession((s) => (s.viewing ? s.session?.accounts[s.viewing]?.name : undefined));
const delegation = useViewingDelegation();
const shared = useViewingShared();
const [, navigate] = useLocation();
const back = () => {
useSession.getState().view(null);
navigate("/mail");
};
// MA-A: a shared or group mailbox in view says whose it is, with the same way back
if (viewing && shared) {
return (
<div className="delegated-bar shared" role="status">
<Users size={15} aria-hidden />
<span className="grow truncate">
{t("Shared mailbox:")} <strong className="notranslate" translate="no">{shared.name}</strong>
</span>
<button type="button" onClick={back}>
{t("Back to my mail")}
</button>
</div>
);
}
if (!viewing || !delegation) return null;
return (
<div className="delegated-bar" role="status">
<Lock size={15} aria-hidden />
<span className="grow truncate">
{t("Locked account:")} <strong className="notranslate" translate="no">{name}</strong>
{" · "}
{accessText(delegation.access)}
{delegation.sendAs ? ` · ${t("You can send as this account")}` : ""}
</span>
<button type="button" onClick={back}>
{t("Back to my mail")}
</button>
</div>
);
}