mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-01 08:12:43 +00:00
@@ -0,0 +1,131 @@
|
||||
import { fireEvent, render, screen, within } from '@testing-library/react';
|
||||
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||
import type { Mailbox } from '@/lib/jmap/types';
|
||||
|
||||
// #1342: with compact shared mailboxes, each shared account is one row that is
|
||||
// its inbox, its folders below it and its empty standard folders left out.
|
||||
|
||||
vi.mock('@/components/plugins/plugin-slot', () => ({ PluginSlot: () => null }));
|
||||
vi.mock('@/components/tour/tour-provider', () => ({
|
||||
useTour: () => ({ startTour: vi.fn(), resetTourCompletion: vi.fn(), activeTour: null, endTour: vi.fn(), registerStep: vi.fn() }),
|
||||
}));
|
||||
vi.mock('@/contexts/drag-drop-context', () => ({
|
||||
useDragDropContext: () => ({ isDragging: false }),
|
||||
}));
|
||||
vi.mock('@/hooks/use-mailbox-drop', () => ({
|
||||
useMailboxDrop: () => ({ dropHandlers: {}, isValidDropTarget: false, isInvalidDropTarget: false }),
|
||||
}));
|
||||
vi.mock('@/hooks/use-tag-drop', () => ({
|
||||
useTagDrop: () => ({ dropHandlers: {}, isValidDropTarget: false }),
|
||||
}));
|
||||
vi.mock('../account-switcher', () => ({ AccountSwitcher: () => null }));
|
||||
|
||||
const { Sidebar } = await import('../sidebar');
|
||||
const { useAuthStore } = await import('@/stores/auth-store');
|
||||
const { useSettingsStore } = await import('@/stores/settings-store');
|
||||
|
||||
function shared(accountId: string, accountName: string, id: string, extra: Partial<Mailbox>): Mailbox {
|
||||
return {
|
||||
id: `${accountId}-${id}`, name: id, role: undefined, parentId: null, totalEmails: 0, unreadEmails: 0,
|
||||
myRights: { mayAddItems: true }, accountId, accountName, isShared: true, ...extra,
|
||||
} as unknown as Mailbox;
|
||||
}
|
||||
|
||||
const mailboxes: Mailbox[] = [
|
||||
{ id: 'inbox', name: 'Inbox', role: 'inbox', parentId: null, totalEmails: 0, unreadEmails: 0, myRights: { mayAddItems: true } } as unknown as Mailbox,
|
||||
shared('g1', 'sales@example.com', 'inbox', { name: 'Inbox', role: 'inbox', totalEmails: 340, unreadEmails: 5 }),
|
||||
shared('g1', 'sales@example.com', 'requests', { name: 'Requests', parentId: 'g1-inbox', totalEmails: 120, unreadEmails: 3 }),
|
||||
shared('g1', 'sales@example.com', 'drafts', { name: 'Drafts', role: 'drafts' }),
|
||||
shared('g1', 'sales@example.com', 'sent', { name: 'Sent', role: 'sent', totalEmails: 512 }),
|
||||
shared('g1', 'sales@example.com', 'junk', { name: 'Junk', role: 'junk', totalEmails: 1, unreadEmails: 1 }),
|
||||
shared('g1', 'sales@example.com', 'trash', { name: 'Trash', role: 'trash' }),
|
||||
shared('g2', 'support@example.com', 'inbox', { name: 'Inbox', role: 'inbox', totalEmails: 38 }),
|
||||
];
|
||||
|
||||
const compactRows = () => screen.queryAllByTestId('compact-shared-mailbox');
|
||||
const sales = () => compactRows()[0];
|
||||
const folderNames = (el: HTMLElement) =>
|
||||
within(el).getAllByTestId('folder-row').map((row) => row.getAttribute('data-folder-name'));
|
||||
|
||||
describe('Sidebar compact shared mailboxes (#1342)', () => {
|
||||
beforeEach(() => {
|
||||
localStorage.setItem('sidebarSharedExpanded', 'true');
|
||||
// Without a stored state the sidebar opens every folder that has some.
|
||||
localStorage.setItem('expandedMailboxes', '[]');
|
||||
useAuthStore.setState({ activeAccountId: 'login-a' } as never);
|
||||
useSettingsStore.setState({
|
||||
hideAccountSwitcher: true,
|
||||
showSharedMailAccounts: true,
|
||||
hiddenSharedMailAccounts: {},
|
||||
compactSharedMailboxes: true,
|
||||
} as never);
|
||||
});
|
||||
|
||||
it('keeps the header rows while the setting is off', () => {
|
||||
useSettingsStore.setState({ compactSharedMailboxes: false } as never);
|
||||
render(<Sidebar mailboxes={mailboxes} selectedMailbox="inbox" />);
|
||||
|
||||
expect(screen.getAllByTestId('section-shared-account')).toHaveLength(2);
|
||||
expect(compactRows()).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('shows each shared account as one row named after it, with its inbox counter', () => {
|
||||
render(<Sidebar mailboxes={mailboxes} selectedMailbox="inbox" />);
|
||||
|
||||
expect(screen.queryAllByTestId('section-shared-account')).toHaveLength(0);
|
||||
expect(compactRows().map((el) => el.textContent)).toEqual([
|
||||
expect.stringContaining('sales@example.com'),
|
||||
expect.stringContaining('support@example.com'),
|
||||
]);
|
||||
const counts = within(sales()).getByTestId('folder-counts');
|
||||
expect(counts.getAttribute('data-unread')).toBe('5');
|
||||
});
|
||||
|
||||
it('opens the inbox when the row is clicked', () => {
|
||||
const onMailboxSelect = vi.fn();
|
||||
render(<Sidebar mailboxes={mailboxes} selectedMailbox="inbox" onMailboxSelect={onMailboxSelect} />);
|
||||
|
||||
fireEvent.click(within(sales()).getByText('sales@example.com'));
|
||||
|
||||
expect(onMailboxSelect).toHaveBeenCalledWith('g1-inbox');
|
||||
});
|
||||
|
||||
it('lists the folders below it and leaves out its empty Drafts and Trash', () => {
|
||||
render(<Sidebar mailboxes={mailboxes} selectedMailbox="inbox" />);
|
||||
|
||||
fireEvent.click(within(sales()).getByTestId('folder-expand-toggle'));
|
||||
|
||||
expect(folderNames(sales())).toEqual(['Inbox', 'Requests', 'Sent', 'Junk']);
|
||||
});
|
||||
|
||||
it('offers the account entries on the row, and hides the account from there', () => {
|
||||
render(<Sidebar mailboxes={mailboxes} selectedMailbox="inbox" />);
|
||||
|
||||
fireEvent.contextMenu(within(sales()).getAllByTestId('folder-row')[0]);
|
||||
expect(screen.getByTitle('sales@example.com')).toBeTruthy();
|
||||
expect(screen.getByTestId('mailbox-new-subfolder')).toBeTruthy();
|
||||
fireEvent.click(screen.getByTestId('mailbox-hide-shared-account'));
|
||||
|
||||
expect(useSettingsStore.getState().hiddenSharedMailAccounts).toEqual({ 'login-a': ['g1'] });
|
||||
expect(compactRows().map((el) => el.textContent)).toEqual([expect.stringContaining('support@example.com')]);
|
||||
});
|
||||
|
||||
it('keeps the account entries off the folders below the row', () => {
|
||||
render(<Sidebar mailboxes={mailboxes} selectedMailbox="inbox" />);
|
||||
|
||||
fireEvent.click(within(sales()).getByTestId('folder-expand-toggle'));
|
||||
fireEvent.contextMenu(within(sales()).getAllByTestId('folder-row')[1]);
|
||||
|
||||
expect(screen.getByTestId('mailbox-new-subfolder')).toBeTruthy();
|
||||
expect(screen.queryByTestId('mailbox-hide-shared-account')).toBeNull();
|
||||
});
|
||||
|
||||
it('keeps the shared mailboxes behind More in Mountain View', () => {
|
||||
useSettingsStore.setState({ interfaceLayout: 'mountain-view' } as never);
|
||||
render(<Sidebar mailboxes={mailboxes} selectedMailbox="inbox" mvShell />);
|
||||
|
||||
expect(compactRows()).toHaveLength(0);
|
||||
fireEvent.click(screen.getByText('show_more'));
|
||||
expect(compactRows()).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
@@ -35,7 +35,10 @@ interface Position {
|
||||
}
|
||||
|
||||
export type MailboxContextTarget =
|
||||
| { kind: "mailbox"; mailbox: Mailbox; hasChildren: boolean }
|
||||
/** `sharedAccountId`: the folder is a shared account's inbox standing for the
|
||||
* whole account (compact shared mailboxes, #1342), so the account's entries
|
||||
* are added. */
|
||||
| { kind: "mailbox"; mailbox: Mailbox; hasChildren: boolean; sharedAccountId?: string }
|
||||
| { kind: "folders-section"; accountId?: string };
|
||||
|
||||
const PATH_SEPARATOR = " › ";
|
||||
@@ -145,6 +148,46 @@ export function MailboxContextMenu({
|
||||
|
||||
if (!target) return null;
|
||||
|
||||
// An account's notifications and, for a shared one, hiding it: on the
|
||||
// account's heading, and on a compact shared mailbox's row.
|
||||
const accountItems = (accountId?: string) => (
|
||||
<>
|
||||
{notifications && (() => {
|
||||
const accountMuted = notifications.isAccountMuted(accountId);
|
||||
return (
|
||||
<>
|
||||
<ContextMenuSeparator />
|
||||
<ContextMenuItem
|
||||
icon={accountMuted ? Bell : BellOff}
|
||||
label={accountMuted ? t("unmute_account_notifications") : t("mute_account_notifications")}
|
||||
onClick={() => handleAction(() => notifications.setAccountMuted(accountId, !accountMuted))}
|
||||
testId="mailbox-mute-account"
|
||||
/>
|
||||
{notifications.hasFolderSettings(accountId) && (
|
||||
<ContextMenuItem
|
||||
icon={RotateCcw}
|
||||
label={t("reset_folder_notifications")}
|
||||
onClick={() => handleAction(() => notifications.resetFolderSettings(accountId))}
|
||||
testId="mailbox-reset-folder-mutes"
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
})()}
|
||||
{accountId && onHideSharedAccount && (
|
||||
<>
|
||||
<ContextMenuSeparator />
|
||||
<ContextMenuItem
|
||||
icon={EyeOff}
|
||||
label={t("hide_shared_account")}
|
||||
onClick={() => handleAction(() => onHideSharedAccount(accountId))}
|
||||
testId="mailbox-hide-shared-account"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
if (target.kind === "folders-section") {
|
||||
return (
|
||||
<ContextMenu ref={menuRef} isOpen={isOpen} position={position} onClose={onClose}>
|
||||
@@ -172,39 +215,7 @@ export function MailboxContextMenu({
|
||||
onClick={() => handleAction(onRefresh!)}
|
||||
disabled={!onRefresh}
|
||||
/>
|
||||
{notifications && (() => {
|
||||
const accountMuted = notifications.isAccountMuted(target.accountId);
|
||||
return (
|
||||
<>
|
||||
<ContextMenuSeparator />
|
||||
<ContextMenuItem
|
||||
icon={accountMuted ? Bell : BellOff}
|
||||
label={accountMuted ? t("unmute_account_notifications") : t("mute_account_notifications")}
|
||||
onClick={() => handleAction(() => notifications.setAccountMuted(target.accountId, !accountMuted))}
|
||||
testId="mailbox-mute-account"
|
||||
/>
|
||||
{notifications.hasFolderSettings(target.accountId) && (
|
||||
<ContextMenuItem
|
||||
icon={RotateCcw}
|
||||
label={t("reset_folder_notifications")}
|
||||
onClick={() => handleAction(() => notifications.resetFolderSettings(target.accountId))}
|
||||
testId="mailbox-reset-folder-mutes"
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
})()}
|
||||
{target.accountId && onHideSharedAccount && (
|
||||
<>
|
||||
<ContextMenuSeparator />
|
||||
<ContextMenuItem
|
||||
icon={EyeOff}
|
||||
label={t("hide_shared_account")}
|
||||
onClick={() => handleAction(() => onHideSharedAccount(target.accountId!))}
|
||||
testId="mailbox-hide-shared-account"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{accountItems(target.accountId)}
|
||||
</ContextMenu>
|
||||
);
|
||||
}
|
||||
@@ -224,7 +235,10 @@ export function MailboxContextMenu({
|
||||
// someone else shared with us, their permission to re-share it.
|
||||
const canShare = !!onShareFolder && (!mailbox.isShared || mailbox.myRights?.mayShare === true);
|
||||
|
||||
const fullPath = getMailboxPath(mailbox, mailboxes);
|
||||
// A compact shared mailbox's row is named after its account, so is its menu.
|
||||
const fullPath = target.sharedAccountId && mailbox.accountName
|
||||
? mailbox.accountName
|
||||
: getMailboxPath(mailbox, mailboxes);
|
||||
|
||||
return (
|
||||
<ContextMenu ref={menuRef} isOpen={isOpen} position={position} onClose={onClose}>
|
||||
@@ -285,6 +299,20 @@ export function MailboxContextMenu({
|
||||
);
|
||||
})()}
|
||||
|
||||
{target.sharedAccountId && (
|
||||
<>
|
||||
<ContextMenuSeparator />
|
||||
<ContextMenuItem
|
||||
icon={FolderPlus}
|
||||
label={t("new_folder")}
|
||||
onClick={() => handleAction(() => onCreateFolder?.(target.sharedAccountId))}
|
||||
disabled={!onCreateFolder}
|
||||
testId="mailbox-new-folder"
|
||||
/>
|
||||
{accountItems(target.sharedAccountId)}
|
||||
</>
|
||||
)}
|
||||
|
||||
<ContextMenuSeparator />
|
||||
|
||||
<ContextMenuItem
|
||||
|
||||
@@ -87,6 +87,7 @@ import { buildSettingsPath, SCHEDULED_MAILBOX_ID, scopedScheduledMailboxId } fro
|
||||
import { useTour } from "@/components/tour/tour-provider";
|
||||
import { toUnicodeEmail } from "@/lib/idn";
|
||||
import { hiddenSharedMailIds, isSharedMailAccountVisible, setSharedMailAccountHidden } from "@/lib/shared-mail-visibility";
|
||||
import { compactSharedMailbox } from "@/lib/compact-shared-mailbox";
|
||||
import {
|
||||
isAccountMuted,
|
||||
isMailboxMuted,
|
||||
@@ -676,6 +677,7 @@ function MailboxTreeItem({
|
||||
colorful,
|
||||
onContextMenu,
|
||||
dragAccountId = null,
|
||||
sharedAccountName,
|
||||
}: {
|
||||
node: MailboxNode;
|
||||
selectedMailbox: string;
|
||||
@@ -690,15 +692,19 @@ function MailboxTreeItem({
|
||||
* Travels in the folder-drag payload so a folder tab fetches through the
|
||||
* right client, and tells a message drop which login the folder is in. */
|
||||
dragAccountId?: string | null;
|
||||
/** Set when this node is a shared account's inbox standing for the whole
|
||||
* account (compact shared mailboxes, #1342): the row is named after the
|
||||
* account and carries its icon. */
|
||||
sharedAccountName?: string;
|
||||
}) {
|
||||
const tNotifications = useTranslations('notifications');
|
||||
const tSidebar = useTranslations('sidebar');
|
||||
const hasChildren = node.children.length > 0;
|
||||
const isExpanded = expandedFolders.has(node.id);
|
||||
const Icon = getIconForMailbox(node.role, hasChildren, isExpanded, node.id);
|
||||
const Icon = sharedAccountName ? User : getIconForMailbox(node.role, hasChildren, isExpanded, node.id);
|
||||
const isVirtualNode = node.id.startsWith('shared-');
|
||||
const isSelected = selectedMailbox === node.id;
|
||||
const label = localizeMailboxName(node.role, node.name, (k) => tSidebar(`mailboxes.${k}`));
|
||||
const label = sharedAccountName ?? localizeMailboxName(node.role, node.name, (k) => tSidebar(`mailboxes.${k}`));
|
||||
// Only for the active login's folders: its client tells a missing
|
||||
// accountId (own mailbox) apart.
|
||||
const muted = useMutedMailbox(isVirtualNode || dragAccountId ? null : node);
|
||||
@@ -740,7 +746,7 @@ function MailboxTreeItem({
|
||||
return (
|
||||
<>
|
||||
<SidebarRow
|
||||
icon={<Icon className={getIconClass(isSelected, isVirtualNode, colorful, node.role)} />}
|
||||
icon={<Icon className={getIconClass(isSelected, isVirtualNode, colorful, sharedAccountName ? undefined : node.role)} />}
|
||||
label={label}
|
||||
testRole={node.role}
|
||||
testName={node.name}
|
||||
@@ -1198,6 +1204,7 @@ function SidebarImpl({
|
||||
const enableUnifiedMailbox = useSettingsStore(s => s.enableUnifiedMailbox);
|
||||
const includeGroupInUnified = useSettingsStore(s => s.includeGroupInUnified);
|
||||
const showSharedMailAccounts = useSettingsStore(s => s.showSharedMailAccounts);
|
||||
const compactSharedMailboxes = useSettingsStore(s => s.compactSharedMailboxes);
|
||||
const hiddenSharedMailAccounts = useSettingsStore(s => s.hiddenSharedMailAccounts);
|
||||
// Mountain View draws its navigation icons in the text colour.
|
||||
const colorfulSidebarIcons = useSettingsStore(s => s.colorfulSidebarIcons) && !mvShell;
|
||||
@@ -1656,6 +1663,19 @@ function SidebarImpl({
|
||||
openMailboxContextMenu(e, { kind: "folders-section", accountId });
|
||||
};
|
||||
|
||||
// A compact shared mailbox's row is its inbox and stands for the account, so
|
||||
// its menu is the inbox's plus what the account's header row offered.
|
||||
const handleCompactSharedContextMenu = (e: React.MouseEvent, node: MailboxNode, inboxId: string, accountId?: string) => {
|
||||
const mailbox = mailboxes.find(mb => mb.id === node.id);
|
||||
if (!mailbox) return;
|
||||
openMailboxContextMenu(e, {
|
||||
kind: "mailbox",
|
||||
mailbox,
|
||||
hasChildren: node.children.length > 0,
|
||||
sharedAccountId: node.id === inboxId ? accountId : undefined,
|
||||
});
|
||||
};
|
||||
|
||||
const hideSharedAccount = activeAccountId
|
||||
? (accountId: string) => {
|
||||
const { hiddenSharedMailAccounts: hidden, updateSetting } = useSettingsStore.getState();
|
||||
@@ -2034,6 +2054,28 @@ function SidebarImpl({
|
||||
{sharedAccounts.map((account) => {
|
||||
const accountExpanded = expandedSharedAccounts.has(account.id);
|
||||
const menuAccountId = sharedAccountMenuId(account.accountId);
|
||||
const compact = compactSharedMailboxes ? compactSharedMailbox(account) : null;
|
||||
if (compact) {
|
||||
const scheduledCount = menuAccountId ? (scheduledTotalByAccount?.[menuAccountId] ?? 0) : 0;
|
||||
return (
|
||||
<div key={account.id} data-testid="compact-shared-mailbox">
|
||||
<MailboxTreeItem
|
||||
node={compact}
|
||||
sharedAccountName={account.name}
|
||||
selectedMailbox={selectedKeyword ? "" : selectedMailbox}
|
||||
expandedFolders={expandedFolders}
|
||||
onMailboxSelect={onMailboxSelect}
|
||||
onToggleExpand={handleToggleExpand}
|
||||
isCollapsed={isCollapsed}
|
||||
onUnreadFilterClick={onUnreadFilterClick}
|
||||
colorful={colorfulSidebarIcons}
|
||||
onContextMenu={(e, node) => handleCompactSharedContextMenu(e, node, compact.id, menuAccountId)}
|
||||
/>
|
||||
{expandedFolders.has(compact.id) && !isCollapsed && scheduledCount > 0
|
||||
&& renderScheduledRow(`${account.id}-scheduled`, { accountId: menuAccountId, depth: 1 })}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div key={account.id}>
|
||||
<SidebarSectionHeader
|
||||
|
||||
@@ -245,6 +245,7 @@ export function MultipleAccountsSection() {
|
||||
const mailboxes = useEmailStore(s => s.mailboxes);
|
||||
const hasGroupInboxes = useMemo(() => mailboxes.some(m => m.isShared), [mailboxes]);
|
||||
const showSharedMailAccounts = useSettingsStore(s => s.showSharedMailAccounts);
|
||||
const compactSharedMailboxes = useSettingsStore(s => s.compactSharedMailboxes);
|
||||
const hiddenSharedMailAccounts = useSettingsStore(s => s.hiddenSharedMailAccounts);
|
||||
const hiddenSharedIds = hiddenSharedMailIds(hiddenSharedMailAccounts, activeAccountId);
|
||||
const sharedMailAccounts = useMemo(() => {
|
||||
@@ -447,6 +448,19 @@ export function MultipleAccountsSection() {
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{sharedMailAccounts.length > 0 && showSharedMailAccounts && !isSettingHidden('compactSharedMailboxes') && (
|
||||
<SettingItem
|
||||
label={t('compact_shared_mailboxes.label')}
|
||||
description={t('compact_shared_mailboxes.description')}
|
||||
locked={isSettingLocked('compactSharedMailboxes')}
|
||||
>
|
||||
<ToggleSwitch
|
||||
checked={compactSharedMailboxes}
|
||||
onChange={(v) => updateSetting('compactSharedMailboxes', v)}
|
||||
/>
|
||||
</SettingItem>
|
||||
)}
|
||||
</SettingsSection>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { compactSharedMailbox } from '../compact-shared-mailbox';
|
||||
import type { MailboxNode } from '../utils';
|
||||
|
||||
// #1342: a shared account's mail as one row that is its inbox.
|
||||
|
||||
function node(id: string, extra: Partial<MailboxNode> = {}): MailboxNode {
|
||||
return {
|
||||
id, name: id, role: undefined, totalEmails: 0, unreadEmails: 0, children: [], depth: 0,
|
||||
...extra,
|
||||
} as unknown as MailboxNode;
|
||||
}
|
||||
|
||||
function account(children: MailboxNode[]): MailboxNode {
|
||||
return node('shared-account-g1', { name: 'sales@example.com', children, isShared: true });
|
||||
}
|
||||
|
||||
const names = (nodes: MailboxNode[]) => nodes.map((n) => n.name);
|
||||
|
||||
describe('compactSharedMailbox', () => {
|
||||
it('puts the inbox at the top, its subfolders, the own folders, then the standard folders', () => {
|
||||
const inbox = node('inbox', { role: 'inbox', children: [node('Requests', { depth: 1 })] });
|
||||
const compact = compactSharedMailbox(account([
|
||||
inbox,
|
||||
node('Sent', { role: 'sent', totalEmails: 3 }),
|
||||
node('Trade fairs', { children: [node('Fair 2027', { depth: 1 })] }),
|
||||
]));
|
||||
|
||||
expect(compact?.id).toBe('inbox');
|
||||
expect(compact?.depth).toBe(0);
|
||||
expect(names(compact!.children)).toEqual(['Requests', 'Trade fairs', 'Sent']);
|
||||
expect(compact!.children.map((n) => n.depth)).toEqual([1, 1, 1]);
|
||||
expect(compact!.children[1].children[0].depth).toBe(2);
|
||||
});
|
||||
|
||||
it('lists Drafts, Scheduled, Junk and Trash only while they hold mail, Sent always', () => {
|
||||
const compact = compactSharedMailbox(account([
|
||||
node('inbox', { role: 'inbox' }),
|
||||
node('Drafts', { role: 'drafts' }),
|
||||
node('Scheduled', { role: 'scheduled' }),
|
||||
node('Sent', { role: 'sent' }),
|
||||
node('Junk', { role: 'junk', totalEmails: 1, unreadEmails: 1 }),
|
||||
node('Trash', { role: 'trash' }),
|
||||
node('Archive', { role: 'archive' }),
|
||||
]));
|
||||
|
||||
expect(names(compact!.children)).toEqual(['Sent', 'Junk', 'Archive']);
|
||||
});
|
||||
|
||||
it('leaves an account without an inbox as it is', () => {
|
||||
expect(compactSharedMailbox(account([node('Invoices')]))).toBeNull();
|
||||
});
|
||||
|
||||
it('does not change the tree it is given', () => {
|
||||
const requests = node('Requests', { depth: 0 });
|
||||
const tree = account([node('inbox', { role: 'inbox' }), requests]);
|
||||
compactSharedMailbox(tree);
|
||||
|
||||
expect(requests.depth).toBe(0);
|
||||
expect(tree.children).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
import type { MailboxNode } from "@/lib/utils";
|
||||
|
||||
/** Standard folders a compact shared mailbox lists only while they hold mail. */
|
||||
const LISTED_WHEN_FILLED = new Set(["drafts", "scheduled", "junk", "trash"]);
|
||||
|
||||
const withDepths = (nodes: MailboxNode[], depth: number): MailboxNode[] =>
|
||||
nodes.map((node) => ({ ...node, depth, children: withDepths(node.children, depth + 1) }));
|
||||
|
||||
/**
|
||||
* A shared account's mail as one row (#1342): the account's inbox, with the
|
||||
* inbox's own subfolders below it, then the folders the account's owners made,
|
||||
* then Sent and the other standard folders, Drafts, Scheduled, Junk and Trash
|
||||
* only while they hold mail. The inbox sits at depth 0, where the account's
|
||||
* header row was, and everything below it one level further in.
|
||||
*
|
||||
* Returns null for an account without an inbox; it keeps its header row.
|
||||
*/
|
||||
export function compactSharedMailbox(account: MailboxNode): MailboxNode | null {
|
||||
const inbox = account.children.find((node) => node.role === "inbox");
|
||||
if (!inbox) return null;
|
||||
const others = account.children.filter((node) => node !== inbox);
|
||||
const own = others.filter((node) => !node.role);
|
||||
const standard = others.filter(
|
||||
(node) => node.role && !(LISTED_WHEN_FILLED.has(node.role) && node.totalEmails === 0),
|
||||
);
|
||||
return {
|
||||
...inbox,
|
||||
depth: 0,
|
||||
children: withDepths([...inbox.children, ...own, ...standard], 1),
|
||||
};
|
||||
}
|
||||
@@ -1542,6 +1542,10 @@
|
||||
"label": "إظهار حسابات البريد المشتركة",
|
||||
"description": "عرض مجلدات صناديق البريد المشتركة معك تحت \"مشترك\" في الشريط الجانبي. أوقفه لإخفائها كلها، أو أخفِ حسابات بعينها أدناه. تبقى تقاويمها وجهات اتصالها ظاهرة."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "صناديق البريد المشتركة بشكل مضغوط",
|
||||
"description": "عرض كل صندوق بريد مشترك كسطر واحد يفتح البريد الوارد الخاص به، مع مجلداته أسفله. تُحذف المجلدات الفارغة مثل المسودات أو المهملات."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "الواجهة الاحترافية (تجريبي)",
|
||||
"description": "تخطيط للمستخدمين المتقدمين لسطح المكتب فقط، مع تصفح رسائل بعلامات تبويب متعددة وسير عمل عبر الحسابات. الواجهة القياسية لا تتأثر؛ يمكنك العودة إليها في أي وقت.",
|
||||
|
||||
@@ -1542,6 +1542,10 @@
|
||||
"label": "Mostra els comptes de correu compartits",
|
||||
"description": "Mostra les carpetes de les bústies compartides amb tu a Compartit, a la barra lateral. Desactiva-ho per amagar-les totes, o amaga comptes concrets a sota. Els calendaris i contactes es mantenen."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "Bústies compartides compactes",
|
||||
"description": "Mostra cada bústia compartida com una sola fila que obre la seva safata d'entrada, amb les seves carpetes a sota. Les buides, com Esborranys o Paperera, no es mostren."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Interfície Pro (experimental)",
|
||||
"description": "Disposició avançada només per a escriptori amb navegació de missatges en diverses pestanyes i fluxos de treball entre comptes. La interfície estàndard no es veu afectada; podeu tornar-hi en qualsevol moment.",
|
||||
|
||||
@@ -1539,6 +1539,10 @@
|
||||
"label": "Zobrazit sdílené poštovní účty",
|
||||
"description": "Zobrazit složky schránek sdílených s vámi v postranním panelu pod Sdílené. Vypnutím skryjete všechny, nebo níže skryjte jednotlivé účty. Jejich kalendáře a kontakty zůstanou."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "Kompaktní sdílené schránky",
|
||||
"description": "Zobrazit každou sdílenou schránku jako jeden řádek, který otevře její Doručené, se složkami pod ním. Prázdné složky jako Koncepty nebo Koš se vynechají."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Pro rozhraní (experimentální)",
|
||||
"description": "Rozložení pro pokročilé uživatele pouze pro stolní počítače s prohlížením zpráv na více kartách a pracovními postupy napříč účty. Standardní rozhraní zůstává nedotčeno; kdykoli se můžete vrátit.",
|
||||
|
||||
@@ -1542,6 +1542,10 @@
|
||||
"label": "Vis delte mailkonti",
|
||||
"description": "Vis mapperne fra postkasser, der er delt med dig, under Delt i sidepanelet. Slå fra for at skjule dem alle, eller skjul enkelte konti nedenfor. Deres kalendere og kontakter bliver."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "Kompakte delte postkasser",
|
||||
"description": "Vis hver delt postkasse som én række, der åbner dens indbakke, med dens mapper nedenunder. Tomme mapper som Kladder eller Papirkurv udelades."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Pro-grænseflade (eksperimentel)",
|
||||
"description": "Power user-layout kun til skrivebordet med beskedvisning på flere faner og arbejdsforløb på tværs af konti. Standardgrænsefladen påvirkes ikke; du kan skifte tilbage når som helst.",
|
||||
|
||||
@@ -1539,6 +1539,10 @@
|
||||
"label": "Geteilte E-Mail-Konten anzeigen",
|
||||
"description": "Die Ordner von Postfächern, die mit Ihnen geteilt wurden, in der Seitenleiste unter „Geteilt“ anzeigen. Ausschalten, um alle auszublenden, oder einzelne Konten unten ausblenden. Kalender und Kontakte bleiben sichtbar."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "Geteilte Postfächer kompakt",
|
||||
"description": "Jedes geteilte Postfach als eine Zeile anzeigen, die seinen Posteingang öffnet, mit seinen Ordnern darunter. Leere wie Entwürfe oder Papierkorb werden ausgelassen."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Pro-Oberfläche (experimentell)",
|
||||
"description": "Desktop-Power-User-Layout mit Multi-Tab-Nachrichtenansicht und kontoübergreifenden Workflows. Die Standardoberfläche bleibt unverändert; Sie können jederzeit zurückwechseln.",
|
||||
|
||||
@@ -1542,6 +1542,10 @@
|
||||
"label": "Show shared mail accounts",
|
||||
"description": "List the folders of mailboxes shared with you under Shared in the sidebar. Turn off to hide them all, or hide single accounts below. Their calendars and contacts stay."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "Compact shared mailboxes",
|
||||
"description": "Show each shared mailbox as one row that opens its inbox, with its folders below it. Empty ones such as Drafts or Trash are left out."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Pro interface (experimental)",
|
||||
"description": "Desktop-only power-user layout with multi-tab message browsing and cross-account workflows. The standard interface is unaffected; you can switch back at any time.",
|
||||
|
||||
@@ -1539,6 +1539,10 @@
|
||||
"label": "Mostrar cuentas de correo compartidas",
|
||||
"description": "Muestra las carpetas de los buzones compartidos contigo en Compartido, en la barra lateral. Desactívalo para ocultarlas todas, u oculta cuentas concretas abajo. Sus calendarios y contactos se mantienen."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "Buzones compartidos compactos",
|
||||
"description": "Muestra cada buzón compartido como una sola fila que abre su bandeja de entrada, con sus carpetas debajo. Las vacías, como Borradores o Papelera, se omiten."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Interfaz Pro (experimental)",
|
||||
"description": "Diseño de escritorio para usuarios avanzados con exploración de mensajes en varias pestañas y flujos de trabajo entre cuentas. La interfaz estándar no se ve afectada; puedes volver en cualquier momento.",
|
||||
|
||||
@@ -1542,6 +1542,10 @@
|
||||
"label": "Näita jagatud meilikontosid",
|
||||
"description": "Näita sinuga jagatud postkastide kaustu külgribal jaotises Jagatud. Lülita välja, et peita kõik, või peida allpool üksikud kontod. Nende kalendrid ja kontaktid jäävad alles."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "Kompaktsed jagatud postkastid",
|
||||
"description": "Näita iga jagatud postkasti ühe reana, mis avab selle saabunud kirjad, kaustad selle all. Tühjad kaustad, nagu Mustandid või Prügikast, jäetakse välja."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Pro liides (eksperimentaalne)",
|
||||
"description": "Ainult lauaarvutile mõeldud kogenud kasutaja paigutus mitme vahekaardiga kirjade sirvimiseks ja kontodeüleseks töövooks. Standardliidest see ei mõjuta ning saad igal ajal tagasi lülituda.",
|
||||
|
||||
@@ -1542,6 +1542,10 @@
|
||||
"label": "نمایش حسابهای ایمیل اشتراکی",
|
||||
"description": "پوشههای صندوقهایی که با شما به اشتراک گذاشته شدهاند در نوار کناری زیر «اشتراکی» نمایش داده شوند. برای پنهان کردن همه خاموش کنید، یا حسابهای جداگانه را در پایین پنهان کنید. تقویمها و مخاطبان آنها باقی میمانند."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "صندوقهای پستی اشتراکی فشرده",
|
||||
"description": "هر صندوق پستی اشتراکی را بهصورت یک ردیف نشان میدهد که صندوق ورودی آن را باز میکند و پوشههایش زیر آن قرار دارند. پوشههای خالی مانند پیشنویسها یا زبالهدان نمایش داده نمیشوند."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "رابط حرفهای (آزمایشی)",
|
||||
"description": "چیدمان قدرت-کاربری فقط دسکتاپ",
|
||||
|
||||
@@ -1539,6 +1539,10 @@
|
||||
"label": "Afficher les comptes de messagerie partagés",
|
||||
"description": "Afficher les dossiers des boîtes partagées avec vous sous Partagé dans la barre latérale. Désactivez pour les masquer tous, ou masquez des comptes un par un ci-dessous. Leurs agendas et contacts restent visibles."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "Boîtes partagées compactes",
|
||||
"description": "Afficher chaque boîte aux lettres partagée sur une seule ligne qui ouvre sa boîte de réception, avec ses dossiers en dessous. Les dossiers vides, comme Brouillons ou Corbeille, sont masqués."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Interface Pro (expérimental)",
|
||||
"description": "Disposition pour utilisateurs avancés (bureau uniquement) avec navigation des messages multi-onglets et flux de travail multi-comptes. L'interface standard n'est pas affectée ; vous pouvez revenir à tout moment.",
|
||||
|
||||
@@ -1504,6 +1504,10 @@
|
||||
"label": "הצגת חשבונות דואר משותפים",
|
||||
"description": "הצגת התיקיות של תיבות דואר ששותפו איתך תחת \"משותף\" בסרגל הצד. כבה כדי להסתיר את כולן, או הסתר חשבונות בודדים למטה. לוחות השנה ואנשי הקשר שלהם נשארים."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "תיבות דואר משותפות בתצוגה מצומצמת",
|
||||
"description": "הצגת כל תיבת דואר משותפת כשורה אחת שפותחת את הדואר הנכנס שלה, עם התיקיות שלה מתחתיה. תיקיות ריקות כמו טיוטות או אשפה מוסתרות."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "ממשק Pro (ניסיוני)",
|
||||
"description": "פריסה של משתמש כוח לשולחן עבודה בלבד עם גלישה מרובת-הודעות וזרימות עבודה חוצות-חשבונות. הממשק הסטנדרטי אינו מושפע; תוכל להחזור בכל עת.",
|
||||
|
||||
@@ -1542,6 +1542,10 @@
|
||||
"label": "Megosztott levelezőfiókok megjelenítése",
|
||||
"description": "A veled megosztott postafiókok mappáinak megjelenítése az oldalsávon, a Megosztott alatt. Kapcsold ki az összes elrejtéséhez, vagy rejts el egyes fiókokat lent. A naptárak és névjegyek megmaradnak."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "Tömör megosztott postafiókok",
|
||||
"description": "Minden megosztott postafiók egyetlen sorként jelenik meg, amely a beérkező leveleit nyitja meg, alatta a mappáival. Az üres mappák, például a Piszkozatok vagy a Kuka, rejtve maradnak."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Pro felület (Kísérleti)",
|
||||
"description": "Asztali számítógépes erőfelhasználói elrendezés több lapos üzenetböngészéssel és fiókok közötti munkafolyamatokkal. A szabványos felületet nem érinti; bármikor visszaválthatsz.",
|
||||
|
||||
@@ -1539,6 +1539,10 @@
|
||||
"label": "Mostra account di posta condivisi",
|
||||
"description": "Mostra le cartelle delle caselle condivise con te sotto Condiviso nella barra laterale. Disattiva per nasconderle tutte, oppure nascondi singoli account qui sotto. Calendari e contatti restano visibili."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "Caselle condivise compatte",
|
||||
"description": "Mostra ogni casella condivisa come una sola riga che apre la sua posta in arrivo, con le sue cartelle sotto. Quelle vuote, come Bozze o Cestino, vengono omesse."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Interfaccia Pro (sperimentale)",
|
||||
"description": "Layout per utenti esperti solo desktop con esplorazione messaggi a più schede e flussi tra account. L'interfaccia standard non è influenzata; puoi tornare indietro in qualsiasi momento.",
|
||||
|
||||
@@ -1539,6 +1539,10 @@
|
||||
"label": "共有メールアカウントを表示",
|
||||
"description": "共有されたメールボックスのフォルダーをサイドバーの「共有」に表示します。オフにするとすべて非表示になります。下で個別のアカウントだけを非表示にすることもできます。カレンダーと連絡先は表示されたままです。"
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "共有メールボックスをコンパクトに表示",
|
||||
"description": "各共有メールボックスを、受信トレイを開く1行として表示し、その下にフォルダを並べます。下書きやゴミ箱などの空のフォルダは表示しません。"
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Pro インターフェイス(実験的)",
|
||||
"description": "デスクトップ専用のパワーユーザー向けレイアウトで、マルチタブのメッセージ閲覧やアカウント横断のワークフローに対応します。標準インターフェイスには影響せず、いつでも元に戻せます。",
|
||||
|
||||
@@ -1539,6 +1539,10 @@
|
||||
"label": "공유 메일 계정 표시",
|
||||
"description": "나와 공유된 메일함의 폴더를 사이드바의 '공유됨' 아래에 표시합니다. 끄면 모두 숨겨지며, 아래에서 계정별로 숨길 수도 있습니다. 캘린더와 연락처는 그대로 유지됩니다."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "공유 메일함 간단히 보기",
|
||||
"description": "각 공유 메일함을 받은편지함을 여는 한 줄로 표시하고, 그 아래에 폴더를 표시합니다. 임시보관함이나 휴지통 같은 빈 폴더는 숨깁니다."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Pro 인터페이스 (실험적)",
|
||||
"description": "데스크톱 전용 파워 유저 레이아웃으로, 다중 탭 메시지 탐색과 계정 간 워크플로우를 지원합니다. 표준 인터페이스에는 영향이 없으며 언제든지 되돌릴 수 있습니다.",
|
||||
|
||||
@@ -1539,6 +1539,10 @@
|
||||
"label": "Rādīt koplietotos pasta kontus",
|
||||
"description": "Rādīt ar jums koplietoto pastkastīšu mapes sānjoslā sadaļā Koplietots. Izslēdziet, lai paslēptu visas, vai paslēpiet atsevišķus kontus zemāk. To kalendāri un kontakti paliek redzami."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "Kompaktas koplietotās pastkastes",
|
||||
"description": "Rādīt katru koplietoto pastkasti kā vienu rindu, kas atver tās iesūtni, ar tās mapēm zem tās. Tukšas mapes, piemēram, Melnraksti, netiek rādītas."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Pro saskarne (eksperimentāla)",
|
||||
"description": "Tikai darbvirsmas pieredzējušu lietotāju izkārtojums ar ziņojumu pārlūkošanu vairākās cilnēs un kontu pārvaldību. Standarta saskarne netiek ietekmēta; varat jebkurā brīdī pārslēgties atpakaļ.",
|
||||
|
||||
@@ -1542,6 +1542,10 @@
|
||||
"label": "Хуваалцсан шуудангийн бүртгэлийг харуулах",
|
||||
"description": "Тантай хуваалцсан шуудангийн хайрцгийн хавтаснуудыг хажуугийн самбарын \"Хуваалцсан\" хэсэгт харуулна. Бүгдийг нуухын тулд унтраана уу, эсвэл доор тус тусад нь нууна уу. Тэдний хуанли, харилцагчид хэвээр үлдэнэ."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "Хуваалцсан шуудангийн хайрцгийг товч харуулах",
|
||||
"description": "Хуваалцсан шуудангийн хайрцаг бүрийг ирсэн имэйлийг нь нээх нэг мөрөөр, доор нь хавтаснуудтай нь харуулна. Ноорог, Хогийн сав зэрэг хоосон хавтаснуудыг харуулахгүй."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Pro интерфейс (туршилтын)",
|
||||
"description": "Зөвхөн ширээний компьютерт зориулагдсан, олон цонхтой мессеж үзэх, данс хоорондын ажлын урсгалтай. Стандарт интерфэйс нь нөлөөлөлд өртөөгүй; та хүссэн үедээ буцааж сольж болно.",
|
||||
|
||||
@@ -1542,6 +1542,10 @@
|
||||
"label": "Vis delte e-postkontoer",
|
||||
"description": "Vis mappene fra postbokser som er delt med deg under Delt i sidepanelet. Slå av for å skjule alle, eller skjul enkeltkontoer nedenfor. Kalendere og kontakter blir værende."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "Kompakte delte postbokser",
|
||||
"description": "Vis hver delte postboks som én rad som åpner innboksen, med mappene under. Tomme mapper som Utkast eller Papirkurv utelates."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Pro-grensesnitt (eksperimentelt)",
|
||||
"description": "Skrivebordsoppsett for erfarne brukere, med meldinger i flere faner og arbeidsflyter på tvers av kontoer. Standardgrensesnittet påvirkes ikke, og du kan bytte tilbake når som helst.",
|
||||
|
||||
@@ -1539,6 +1539,10 @@
|
||||
"label": "Gedeelde mailaccounts tonen",
|
||||
"description": "Toon de mappen van postvakken die met je zijn gedeeld onder Gedeeld in de zijbalk. Zet uit om ze allemaal te verbergen, of verberg hieronder losse accounts. Hun agenda's en contacten blijven zichtbaar."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "Compacte gedeelde postvakken",
|
||||
"description": "Toon elk gedeeld postvak als één regel die het Postvak IN opent, met de mappen eronder. Lege mappen zoals Concepten of Prullenbak worden weggelaten."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Pro-interface (experimenteel)",
|
||||
"description": "Power user-indeling alleen voor desktop met meertabs berichtweergave en accountoverschrijdende workflows. De standaardinterface blijft onveranderd; u kunt op elk moment terugkeren.",
|
||||
|
||||
@@ -1539,6 +1539,10 @@
|
||||
"label": "Pokaż udostępnione konta pocztowe",
|
||||
"description": "Pokazuj foldery skrzynek udostępnionych Ci w sekcji Udostępnione na pasku bocznym. Wyłącz, aby ukryć wszystkie, lub ukryj poszczególne konta poniżej. Ich kalendarze i kontakty pozostaną."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "Kompaktowe udostępnione skrzynki",
|
||||
"description": "Pokazuj każdą udostępnioną skrzynkę jako jeden wiersz, który otwiera jej Odebrane, z folderami pod spodem. Puste foldery, takie jak Szkice czy Kosz, są pomijane."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Interfejs Pro (eksperymentalny)",
|
||||
"description": "Układ dla zaawansowanych użytkowników (tylko na komputerze) z przeglądaniem wiadomości w wielu kartach i obiegami pracy między kontami. Standardowy interfejs pozostaje nietknięty; możesz wrócić w dowolnej chwili.",
|
||||
|
||||
@@ -1539,6 +1539,10 @@
|
||||
"label": "Mostrar contas de e-mail compartilhadas",
|
||||
"description": "Mostra as pastas das caixas compartilhadas com você em Compartilhado, na barra lateral. Desative para ocultar todas, ou oculte contas individuais abaixo. Os calendários e contatos continuam visíveis."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "Caixas compartilhadas compactas",
|
||||
"description": "Mostra cada caixa de correio compartilhada como uma única linha que abre sua caixa de entrada, com suas pastas abaixo. As vazias, como Rascunhos ou Lixeira, são omitidas."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Interface Pro (experimental)",
|
||||
"description": "Layout para utilizadores avançados apenas em desktop com navegação de mensagens em múltiplos separadores e fluxos entre contas. A interface padrão não é afetada; pode voltar a qualquer momento.",
|
||||
|
||||
@@ -1542,6 +1542,10 @@
|
||||
"label": "Afișează conturile de e-mail partajate",
|
||||
"description": "Afișează folderele cutiilor poștale partajate cu tine la Partajat, în bara laterală. Dezactivează pentru a le ascunde pe toate sau ascunde conturi individuale mai jos. Calendarele și contactele lor rămân."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "Căsuțe partajate compacte",
|
||||
"description": "Afișează fiecare căsuță poștală partajată ca un singur rând care îi deschide mesajele primite, cu dosarele dedesubt. Dosarele goale, precum Ciorne sau Coș de gunoi, sunt omise."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Interfață Pro (experimentală)",
|
||||
"description": "Aspect destinat utilizatorilor avansați, disponibil doar pe desktop, cu navigare prin mesaje în mai multe file și fluxuri de lucru între conturi. Interfața standard nu este afectată; puteți reveni la aceasta în orice moment.",
|
||||
|
||||
@@ -1539,6 +1539,10 @@
|
||||
"label": "Показывать общие почтовые аккаунты",
|
||||
"description": "Показывать папки ящиков, к которым вам открыт доступ, в разделе «Общие» на боковой панели. Выключите, чтобы скрыть все, или скройте отдельные аккаунты ниже. Их календари и контакты останутся."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "Компактные общие ящики",
|
||||
"description": "Показывать каждый общий почтовый ящик одной строкой, которая открывает его «Входящие», с папками под ней. Пустые папки, например «Черновики» или «Корзина», скрываются."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Pro-интерфейс (экспериментальный)",
|
||||
"description": "Макет для опытных пользователей только для настольных устройств с просмотром сообщений в нескольких вкладках и работой между аккаунтами. Стандартный интерфейс не меняется; вы можете вернуться в любое время.",
|
||||
|
||||
@@ -1542,6 +1542,10 @@
|
||||
"label": "Zobraziť zdieľané poštové účty",
|
||||
"description": "Zobraziť priečinky schránok zdieľaných s vami v bočnom paneli pod Zdieľané. Vypnutím skryjete všetky, alebo nižšie skryte jednotlivé účty. Ich kalendáre a kontakty zostanú."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "Kompaktné zdieľané schránky",
|
||||
"description": "Zobraziť každú zdieľanú schránku ako jeden riadok, ktorý otvorí jej Doručené, s priečinkami pod ním. Prázdne priečinky ako Koncepty alebo Koš sa vynechajú."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Pro rozhranie (experimentálne)",
|
||||
"description": "Rozloženie pre pokročilých používateľov iba pre stolné počítače.",
|
||||
|
||||
@@ -3983,6 +3983,10 @@
|
||||
"label": "แสดงบัญชีอีเมลที่แชร์",
|
||||
"description": "แสดงรายการโฟลเดอร์ของกล่องข้อความที่ผู้อื่นแชร์กับคุณภายใต้ส่วน ที่แชร์ ในแถบด้านข้าง ปิดใช้งานเพื่อซ่อนทั้งหมด หรือซ่อนทีละบัญชีด้านล่าง โดยปฏิทินและผู้ติดต่อของบัญชีเหล่านั้นจะยังคงอยู่"
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "กล่องจดหมายที่แชร์แบบกะทัดรัด",
|
||||
"description": "แสดงกล่องจดหมายที่แชร์แต่ละกล่องเป็นแถวเดียวที่เปิดกล่องขาเข้า โดยมีโฟลเดอร์อยู่ด้านล่าง โฟลเดอร์ที่ว่าง เช่น ฉบับร่างหรือถังขยะ จะไม่แสดง"
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "ส่วนต่อประสานระดับโปร (ทดลองใช้)",
|
||||
"description": "เค้าโครงสำหรับผู้ใช้ระดับสูงบนคอมพิวเตอร์เดสก์ท็อป พร้อมการเรียกดูข้อความหลายแท็บและขั้นตอนการทำงานข้ามบัญชี ส่วนต่อประสานมาตรฐานจะไม่ได้รับผลกระทบ คุณสามารถสลับกลับมาได้ตลอดเวลา",
|
||||
|
||||
@@ -1539,6 +1539,10 @@
|
||||
"label": "Paylaşılan posta hesaplarını göster",
|
||||
"description": "Sizinle paylaşılan posta kutularının klasörlerini kenar çubuğunda Paylaşılan altında göster. Hepsini gizlemek için kapatın veya aşağıdan tek tek hesapları gizleyin. Takvimleri ve kişileri görünür kalır."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "Kompakt paylaşılan posta kutuları",
|
||||
"description": "Her paylaşılan posta kutusunu, gelen kutusunu açan tek bir satır olarak ve klasörleri altında olacak şekilde göster. Taslaklar veya Çöp Kutusu gibi boş klasörler gösterilmez."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Pro Arayüz (Deneysel)",
|
||||
"description": "Yalnızca masaüstü için güçlü kullanıcı düzeni: çoklu sekmede ileti gezme ve hesaplar arası iş akışları. Standart arayüz etkilenmez; istediğiniz zaman geri dönebilirsiniz.",
|
||||
|
||||
@@ -1539,6 +1539,10 @@
|
||||
"label": "Показувати спільні поштові акаунти",
|
||||
"description": "Показувати папки скриньок, до яких вам надано доступ, у розділі «Спільні» на бічній панелі. Вимкніть, щоб приховати всі, або приховайте окремі акаунти нижче. Їхні календарі та контакти залишаться."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "Компактні спільні скриньки",
|
||||
"description": "Показувати кожну спільну поштову скриньку одним рядком, що відкриває її «Вхідні», з теками під ним. Порожні теки, як-от «Чернетки» чи «Кошик», приховуються."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Pro-інтерфейс (експериментальний)",
|
||||
"description": "Розкладка для досвідчених користувачів лише для настільного комп'ютера з переглядом повідомлень у кількох вкладках і робочими процесами між обліковими записами. Стандартний інтерфейс не змінюється; ви можете повернутися будь-коли.",
|
||||
|
||||
@@ -1554,6 +1554,10 @@
|
||||
"label": "Hiển thị tài khoản thư được chia sẻ",
|
||||
"description": "Liệt kê thư mục của các hộp thư được chia sẻ với bạn trong mục Được chia sẻ ở thanh bên. Tắt để ẩn tất cả hoặc ẩn riêng từng tài khoản bên dưới. Lịch và danh bạ của chúng vẫn được giữ lại."
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "Thu gọn hộp thư được chia sẻ",
|
||||
"description": "Hiển thị mỗi hộp thư được chia sẻ thành một dòng mở hộp thư đến, các thư mục của nó nằm bên dưới. Các thư mục trống như Thư nháp hoặc Thùng rác được ẩn đi."
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Giao diện Pro (thử nghiệm)",
|
||||
"description": "Bố cục chỉ dành cho máy tính, dành cho người dùng nâng cao, hỗ trợ duyệt thư bằng nhiều tab và thao tác giữa các tài khoản. Giao diện tiêu chuẩn không bị ảnh hưởng; bạn có thể chuyển lại bất cứ lúc nào.",
|
||||
|
||||
@@ -1542,6 +1542,10 @@
|
||||
"label": "顯示共用郵件帳號",
|
||||
"description": "在側邊欄的「共用」下顯示與你共用的信箱資料夾。關閉可全部隱藏,也可以在下方逐一隱藏帳號。它們的行事曆和聯絡人仍會顯示。"
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "精簡顯示共用信箱",
|
||||
"description": "將每個共用信箱顯示為一列,點選即開啟其收件匣,資料夾列在下方。草稿、垃圾桶等空資料夾不會顯示。"
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Pro 介面(實驗性)",
|
||||
"description": "適合進階使用者的桌面版配置,支援多分頁郵件瀏覽與跨帳號工作流程。標準介面不受影響,您可隨時切換回來。",
|
||||
|
||||
@@ -1539,6 +1539,10 @@
|
||||
"label": "显示共享邮件账户",
|
||||
"description": "在侧边栏的“共享”下显示与你共享的邮箱的文件夹。关闭可全部隐藏,也可以在下方逐个隐藏账户。它们的日历和联系人仍会显示。"
|
||||
},
|
||||
"compact_shared_mailboxes": {
|
||||
"label": "紧凑显示共享邮箱",
|
||||
"description": "将每个共享邮箱显示为一行,点击即打开其收件箱,文件夹列在下方。草稿、已删除等空文件夹不显示。"
|
||||
},
|
||||
"pro_interface": {
|
||||
"label": "Pro 界面(实验性)",
|
||||
"description": "仅限桌面的高级用户布局,支持多标签消息浏览和跨账户工作流。标准界面不受影响,您可以随时切换回来。",
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import { beforeEach, describe, expect, it } from 'vitest';
|
||||
import { useSettingsStore } from '../settings-store';
|
||||
import { usePolicyStore } from '../policy-store';
|
||||
import { DEFAULT_POLICY } from '@/lib/admin/types';
|
||||
|
||||
// #1342: compact shared mailboxes is the user's choice, off until the user or
|
||||
// the admin's policy default turns it on.
|
||||
|
||||
const settings = () => useSettingsStore.getState();
|
||||
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
usePolicyStore.setState({ policy: { ...DEFAULT_POLICY }, loaded: false });
|
||||
settings().resetToDefaults();
|
||||
});
|
||||
|
||||
describe('settings-store compactSharedMailboxes', () => {
|
||||
it('is off by default', () => {
|
||||
expect(settings().compactSharedMailboxes).toBe(false);
|
||||
});
|
||||
|
||||
it('is synced', () => {
|
||||
settings().updateSetting('compactSharedMailboxes', true);
|
||||
expect(JSON.parse(settings().exportSettings()).compactSharedMailboxes).toBe(true);
|
||||
|
||||
settings().importSettings(JSON.stringify({ compactSharedMailboxes: false }));
|
||||
expect(settings().compactSharedMailboxes).toBe(false);
|
||||
});
|
||||
|
||||
it('takes the admin\'s default', () => {
|
||||
usePolicyStore.setState({ policy: { ...DEFAULT_POLICY, defaults: { compactSharedMailboxes: true } }, loaded: true });
|
||||
expect(settings().compactSharedMailboxes).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -724,6 +724,9 @@ interface SettingsState extends AccessibilitySettings {
|
||||
// Turning it off hides every shared account's folders; their calendars,
|
||||
// contacts and files stay. (#1228)
|
||||
showSharedMailAccounts: boolean;
|
||||
// Each shared account's mail as one row that is its inbox, its folders
|
||||
// below it and its empty Drafts, Scheduled, Junk and Trash left out (#1342).
|
||||
compactSharedMailboxes: boolean;
|
||||
// Shared accounts whose mail folders are hidden one by one, keyed by
|
||||
// AccountEntry.id -> JMAP accountIds, since those ids are per server.
|
||||
hiddenSharedMailAccounts: Record<string, string[]>;
|
||||
@@ -1011,6 +1014,7 @@ const DEFAULT_SETTINGS = {
|
||||
showAccountDot: true,
|
||||
showFolderTotalCount: true,
|
||||
showSharedMailAccounts: true,
|
||||
compactSharedMailboxes: false,
|
||||
hiddenSharedMailAccounts: {} as Record<string, string[]>,
|
||||
|
||||
// Folders
|
||||
@@ -1404,6 +1408,7 @@ export const useSettingsStore = create<SettingsState>()(
|
||||
showAccountDot: state.showAccountDot,
|
||||
showFolderTotalCount: state.showFolderTotalCount,
|
||||
showSharedMailAccounts: state.showSharedMailAccounts,
|
||||
compactSharedMailboxes: state.compactSharedMailboxes,
|
||||
hiddenSharedMailAccounts: state.hiddenSharedMailAccounts,
|
||||
folderIcons: state.folderIcons,
|
||||
folderCountModes: state.folderCountModes,
|
||||
|
||||
Reference in New Issue
Block a user