Files

818 lines
41 KiB
Plaintext

import { ScrollFade } from "scroll-fade.slint";
import { ListView, VerticalBox } from "std-widgets.slint";
import { MailProfileRow, SidebarRow, SidebarRowKind } from "../models.slint";
import { SidebarItem, SidebarSectionHeader } from "sidebar-controls.slint";
import { SidebarStyle } from "sidebar-row.slint";
import { Button } from "button.slint";
import { IconButton, LineEdit } from "controls.slint";
import { ProfileSwitcher } from "profile-switcher.slint";
import {
CollapsibleWorkspaceSidebar,
WorkspaceMiniHeading,
} from "workspace-layout.slint";
import { LayoutMetrics, MailIconPalette, MotionSettings } from "../design-system.slint";
import { LocalMailUi } from "../local-mail.slint";
import { Updates } from "../updates.slint";
import { TypeScale } from "../typography.slint";
// The profile switcher across a sidebar, as tall as its buttons.
component SidebarProfileSwitcher inherits Rectangle {
in property <[MailProfileRow]> profiles;
in property <MailProfileRow> active;
in property <int> account-count;
callback choose(string);
callback create-profile();
callback manage-profiles();
height: LayoutMetrics.sidebar-action-height;
ProfileSwitcher {
x: 0px;
y: 0px;
height: parent.height;
fill-width: true;
widest: parent.width;
profiles: root.profiles;
active: root.active;
account-count: root.account-count;
choose(id) => { root.choose(id); }
create-profile => { root.create-profile(); }
manage-profiles => { root.manage-profiles(); }
}
}
// A newer release is out: a quiet line at the foot of the sidebar that leads
// to its page, until the user puts it away (src/updates.rs).
component UpdateNotice inherits Rectangle {
in property <bool> touch-mode;
in property <color> background-color;
in property <color> hover-background;
in property <color> accent-color;
in property <color> title-color;
in property <color> muted-color;
height: max(root.touch-mode ? 52px : 44px, labels.preferred-height + 14px);
border-radius: 8px;
background: open.has-hover ? root.hover-background : root.background-color;
Image {
x: 12px;
y: (parent.height - self.height) / 2;
width: LayoutMetrics.icon-size;
height: LayoutMetrics.icon-size;
source: @image-url("../icons/lucide/outline/download.svg");
colorize: root.accent-color;
image-fit: contain;
accessible-role: none;
}
labels := VerticalLayout {
x: 12px + LayoutMetrics.icon-size + 10px;
width: parent.width - self.x - 38px;
alignment: center;
Text {
text: @tr("New version available");
color: root.title-color;
font-size: TypeScale.caption;
font-weight: 600;
overflow: elide;
}
Text {
text: @tr("Version {}", Updates.version);
color: root.muted-color;
font-size: TypeScale.caption;
overflow: elide;
}
}
open := TouchArea {
width: parent.width - 38px;
accessible-role: button;
accessible-label: @tr("Flectar Mail {} is out. Open its release page.", Updates.version);
accessible-action-default => { Updates.open-release(); }
mouse-cursor: pointer;
clicked => { Updates.open-release(); }
}
IconButton {
x: parent.width - 34px;
y: (parent.height - self.height) / 2;
width: 28px;
height: 28px;
icon: @image-url("../icons/lucide/outline/x.svg");
icon-size: 12px;
icon-color: root.muted-color;
hover-background: root.hover-background;
tooltip-text: @tr("Hide until the next version");
clicked => { Updates.dismiss(); }
}
}
export component MailSidebar inherits CollapsibleWorkspaceSidebar {
in property <bool> touch-mode: false;
in property <[SidebarRow]> rows: [];
in-out property <length> scroll-y: 0px;
in-out property <string> filter-query: "";
private property <bool> filter-open: root.filter-query != "";
in property <string> unified-count;
in property <bool> sync-in-progress: false;
in property <string> selected-scope;
in property <bool> monochrome-icons: false;
in property <color> background-color;
in property <color> hover-background;
in property <color> selection-background;
in property <color> accent-color;
in property <color> title-color;
in property <color> body-color;
in property <color> muted-color;
// Without the tab bar, the profile pill heads the sidebar once there
// are profiles to choose from.
in property <bool> show-profiles: false;
in property <[MailProfileRow]> profiles: [];
in property <MailProfileRow> active-profile;
in property <int> account-count;
callback select-scope(string);
callback compose;
callback manage-accounts;
callback sync-account(int);
callback choose-profile(string);
callback create-profile();
callback manage-profiles();
callback toggle-folder(int, bool);
callback toggle-section(string, bool);
callback filter-folders(string);
callback request-create-folder(int, int, string);
callback request-create-label(int, string, int, string);
callback request-rename-folder(int, string);
callback request-delete-folder(int, string);
callback request-empty-trash(int);
callback request-rename-label(int, string, color, string, bool);
callback request-delete-label(int, string, string, bool, bool);
surface-color: root.background-color;
clip: true;
// Account rows hold a name and an address; both keep their 12px design
// and grow with the platform font.
private property <length> account-row-height: 10px
+ max(20px, account-name-probe.preferred-height)
+ max(15px, account-detail-probe.preferred-height);
account-name-probe := Text { visible: false; text: "Ag"; font-size: SidebarStyle.label-size; font-weight: SidebarStyle.selected-weight; }
account-detail-probe := Text { visible: false; text: "Ag"; font-size: TypeScale.caption; }
if !root.collapsed: VerticalBox {
x: LayoutMetrics.sidebar-inset;
y: LayoutMetrics.sidebar-action-top;
width: parent.width - 2 * LayoutMetrics.sidebar-inset;
height: parent.height - LayoutMetrics.sidebar-action-top;
padding: 0px;
spacing: 8px;
// The phone drawer opens on the profile, once there are profiles.
if root.show-profiles && root.touch-mode && root.profiles.length > 0 : SidebarProfileSwitcher {
width: parent.width;
profiles: root.profiles;
active: root.active-profile;
account-count: root.account-count;
choose(id) => { root.choose-profile(id); }
create-profile => { root.create-profile(); }
manage-profiles => { root.manage-profiles(); }
}
// With only local mail, nothing could send; adding an account comes
// first.
Button {
height: LayoutMetrics.sidebar-action-height;
horizontal-stretch: 1;
text: LocalMailUi.can-send ? @tr("New email") : @tr("Add an account");
icon: LocalMailUi.can-send ? @image-url("../icons/lucide/filled/compose.svg") : @image-url("../icons/lucide/filled/person-add.svg");
has-icon: true;
primary: true;
clicked => {
if LocalMailUi.can-send {
root.compose();
} else {
root.manage-accounts();
}
}
}
// A desktop sidebar stands in for the top bar's pill, which is always
// there, below the sidebar's main action.
if root.show-profiles && !root.touch-mode : SidebarProfileSwitcher {
width: parent.width;
profiles: root.profiles;
active: root.active-profile;
account-count: root.account-count;
choose(id) => { root.choose-profile(id); }
create-profile => { root.create-profile(); }
manage-profiles => { root.manage-profiles(); }
}
Rectangle {
height: 32px;
horizontal-stretch: 1;
background: transparent;
Rectangle {
visible: !root.filter-open;
x: 0px;
width: parent.width - 36px;
height: parent.height;
border-radius: 6px;
background: find-hit.has-hover ? root.hover-background : transparent;
Image {
x: 13px - self.width / 2;
y: (parent.height - self.height) / 2;
width: LayoutMetrics.icon-size;
height: LayoutMetrics.icon-size;
source: @image-url("../icons/lucide/outline/search.svg");
colorize: root.muted-color;
image-fit: contain;
accessible-role: none;
}
Text {
x: 28px;
width: parent.width - 28px;
height: parent.height;
text: @tr("Find folder or label");
color: root.muted-color;
font-size: TypeScale.caption;
vertical-alignment: center;
overflow: elide;
}
find-hit := TouchArea {
accessible-role: button;
accessible-label: @tr("Find folder or label");
accessible-action-default => {
root.filter-open = true;
filter-field.focus();
}
clicked => {
root.filter-open = true;
filter-field.focus();
}
mouse-cursor: pointer;
}
}
filter-field := LineEdit {
visible: root.filter-open;
x: 0px;
width: parent.width - 36px;
height: parent.height;
text <=> root.filter-query;
placeholder-text: @tr("Find folder or label");
input-label: @tr("Find folder or label");
show-leading-icon: true;
leading-icon: @image-url("../icons/lucide/outline/search.svg");
leading-icon-color: root.muted-color;
trailing-content-width: 32px;
edited(value) => { root.filter-folders(value); }
}
IconButton {
visible: root.filter-open;
x: parent.width - 68px;
width: 32px;
height: 32px;
icon: @image-url("../icons/lucide/outline/x.svg");
icon-size: 14px;
icon-color: root.muted-color;
hover-background: root.hover-background;
tooltip-text: @tr("Clear folder filter");
clicked => {
root.filter-query = "";
root.filter-open = false;
root.filter-folders("");
}
}
IconButton {
x: parent.width - 32px;
width: 32px;
height: 32px;
icon: @image-url("../icons/lucide/outline/plus.svg");
icon-size: 16px;
icon-color: root.muted-color;
hover-background: root.hover-background;
tooltip-text: @tr("Add account");
clicked => { root.manage-accounts(); }
}
}
Rectangle {
vertical-stretch: 1;
width: parent.width;
background: transparent;
mailbox-scroll := ListView {
// Keep a direct ListView repeater; Slint does not
// virtualize through a wrapper or inherited ListView.
content-width: self.visible-width;
horizontal-scrollbar-policy: always-off;
x: 0px;
y: 0px;
width: parent.width;
height: parent.height;
content-y <=> root.scroll-y;
mouse-drag-pan-enabled: root.touch-mode;
// The repeater must be a direct ListView child: nesting it in
// a layout disables virtualization. Rust supplies only expanded rows.
for entry in root.rows: Rectangle {
private property <bool> reveal-ready: !entry.reveal_row;
width: max(0px, mailbox-scroll.visible-width - LayoutMetrics.sidebar-scrollbar-gutter);
height: !entry.show_row || (entry.reveal_row && !self.reveal-ready && MotionSettings.enabled) ? 0px
: entry.kind == SidebarRowKind.unified-heading ? 21px
: entry.kind == SidebarRowKind.accounts-heading ? 25px
: entry.kind == SidebarRowKind.account ? (entry.mailbox.detail == "" ? 35px : root.account-row-height)
: entry.kind == SidebarRowKind.unified-section || entry.kind == SidebarRowKind.unified-inbox ? 35px
: entry.kind == SidebarRowKind.folder && entry.mailbox.label == "Inbox" ? 35px
: 31px;
background: transparent;
clip: true;
animate height { duration: 230ms; easing: spring(0); enabled: MotionSettings.enabled; }
Timer {
interval: 16ms;
running: entry.reveal_row && !parent.reveal-ready && MotionSettings.enabled;
triggered => { parent.reveal-ready = true; }
}
if entry.kind == SidebarRowKind.unified-heading: WorkspaceMiniHeading {
x: 0px;
y: 0px;
width: parent.width;
label: @tr("ALL ACCOUNTS");
label-color: root.muted-color;
}
if entry.kind == SidebarRowKind.unified-section: SidebarSectionHeader {
x: 0px;
interactive: entry.show_row;
y: 0px;
width: parent.width;
label: @tr("All Inboxes");
icon: @image-url("../icons/lucide/filled/stack.svg");
sidebar-background: root.background-color;
hover-background: root.hover-background;
body-color: root.title-color;
muted-color: root.muted-color;
icon-color: root.monochrome-icons ? root.body-color : MailIconPalette.inbox;
open: entry.open;
toggled(open) => { root.toggle-section(entry.key, open); }
}
if entry.kind == SidebarRowKind.unified-inbox: SidebarItem {
x: 0px;
interactive: entry.show_row;
y: 0px;
width: parent.width;
label: @tr("Inbox");
count: root.unified-count;
scope: "Unified Inbox";
account-id: 0;
folder-id: -1;
mail-drop-enabled: true;
icon: @image-url("../icons/lucide/filled/inbox-flectar.svg");
selected: root.selected-scope == "Unified Inbox";
row-height: 32px;
sidebar-background: root.background-color;
selection-background: root.selection-background;
accent-color: root.accent-color;
body-color: root.body-color;
muted-color: root.muted-color;
icon-color: root.monochrome-icons ? (root.selected-scope == "Unified Inbox" ? root.accent-color : root.muted-color) : MailIconPalette.inbox;
clicked(scope) => { root.select-scope(scope); }
}
if entry.kind == SidebarRowKind.unified-mailbox: SidebarItem {
x: 0px;
interactive: entry.show_row;
y: 0px;
width: parent.width;
label: entry.mailbox.label;
count: entry.mailbox.count;
scope: entry.mailbox.scope;
account-id: entry.mailbox.account_id;
can-empty-trash: entry.mailbox.scope == "Unified Trash";
folder-id: entry.mailbox.folder_id;
mail-drop-enabled: entry.mailbox.scope == "Unified Starred"
|| entry.mailbox.scope == "Unified Archive"
|| entry.mailbox.scope == "Unified Spam"
|| entry.mailbox.scope == "Unified Trash";
mail-drop-copies: entry.mailbox.scope == "Unified Starred";
icon: entry.mailbox.scope == "Unified Starred" ? @image-url("../icons/lucide/filled/star.svg")
: entry.mailbox.scope == "Unified Sent" ? @image-url("../icons/lucide/filled/paper-airplane.svg")
: entry.mailbox.scope == "Unified Spam" ? @image-url("../icons/lucide/filled/alert.svg")
: entry.mailbox.scope == "Unified Trash" ? @image-url("../icons/lucide/filled/trash.svg")
: entry.mailbox.scope == "Unified Archive" ? @image-url("../icons/lucide/filled/archive.svg")
: @image-url("../icons/lucide/filled/draft.svg");
selected: entry.mailbox.scope == root.selected-scope;
sidebar-background: root.background-color;
selection-background: root.selection-background;
accent-color: root.accent-color;
body-color: root.body-color;
muted-color: root.muted-color;
icon-color: root.monochrome-icons ? (entry.mailbox.scope == root.selected-scope ? root.accent-color : root.muted-color)
: entry.mailbox.scope == "Unified Starred" ? MailIconPalette.starred
: entry.mailbox.scope == "Unified Sent" ? MailIconPalette.sent
: entry.mailbox.scope == "Unified Spam" ? MailIconPalette.spam
: entry.mailbox.scope == "Unified Trash" ? MailIconPalette.trash
: entry.mailbox.scope == "Unified Archive" ? MailIconPalette.archive
: MailIconPalette.drafts;
clicked(scope) => { root.select-scope(scope); }
empty-trash(account-id) => { root.request-empty-trash(account-id); }
}
if entry.kind == SidebarRowKind.categories-section: SidebarSectionHeader {
x: 0px;
interactive: entry.show_row;
y: 0px;
width: parent.width;
label: @tr("Categories");
label-font-weight: 500;
folder-row-style: true;
sidebar-background: root.background-color;
hover-background: root.hover-background;
body-color: root.body-color;
muted-color: root.muted-color;
icon: @image-url("../icons/lucide/filled/tag.svg");
icon-color: root.monochrome-icons ? root.body-color : MailIconPalette.inbox;
open: entry.open;
toggled(open) => { root.toggle-section(entry.key, open); }
}
if entry.kind == SidebarRowKind.important: SidebarItem {
x: 0px;
interactive: entry.show_row;
y: 0px;
width: parent.width;
label: @tr("Important");
count: entry.mailbox.count;
left-padding: SidebarStyle.icon-left + SidebarStyle.branch-indent;
scope: "Important";
mail-drop-enabled: true;
icon: @image-url("../icons/lucide/filled/tag.svg");
selected: root.selected-scope == "Important";
sidebar-background: root.background-color;
selection-background: root.selection-background;
accent-color: root.accent-color;
body-color: root.body-color;
muted-color: root.muted-color;
icon-color: root.monochrome-icons ? (root.selected-scope == "Important" ? root.accent-color : root.muted-color) : MailIconPalette.inbox;
clicked(scope) => { root.select-scope(scope); }
}
if entry.kind == SidebarRowKind.other: SidebarItem {
x: 0px;
interactive: entry.show_row;
y: 0px;
width: parent.width;
label: @tr("Other");
count: entry.mailbox.count;
left-padding: SidebarStyle.icon-left + SidebarStyle.branch-indent;
scope: "Other";
mail-drop-enabled: true;
icon: @image-url("../icons/lucide/filled/tag.svg");
selected: root.selected-scope == "Other";
sidebar-background: root.background-color;
selection-background: root.selection-background;
accent-color: root.accent-color;
body-color: root.body-color;
muted-color: root.muted-color;
icon-color: root.monochrome-icons ? (root.selected-scope == "Other" ? root.accent-color : root.muted-color) : MailIconPalette.other;
clicked(scope) => { root.select-scope(scope); }
}
if entry.kind == SidebarRowKind.category: SidebarItem {
x: 0px;
interactive: entry.show_row;
y: 0px;
width: parent.width;
label: entry.label.name;
count: entry.label.count;
label-has-emoji: entry.label.name_has_emoji;
left-padding: SidebarStyle.icon-left + SidebarStyle.branch-indent;
scope: "Category:" + entry.label.id;
mail-drop-enabled: true;
icon: @image-url("../icons/lucide/filled/tag.svg");
selected: root.selected-scope == "Category:" + entry.label.id;
sidebar-background: root.background-color;
selection-background: root.selection-background;
accent-color: root.accent-color;
body-color: root.body-color;
muted-color: root.muted-color;
icon-color: root.monochrome-icons
? (root.selected-scope == "Category:" + entry.label.id ? root.accent-color : root.muted-color)
: entry.label.color;
clicked(scope) => { root.select-scope(scope); }
}
if entry.kind == SidebarRowKind.global-labels-section: SidebarSectionHeader {
x: 0px;
interactive: entry.show_row;
y: 0px;
width: parent.width;
label: @tr("Labels");
label-font-weight: 500;
folder-row-style: true;
sidebar-background: root.background-color;
hover-background: root.hover-background;
body-color: root.body-color;
muted-color: root.muted-color;
icon: @image-url("../icons/lucide/filled/tag.svg");
icon-color: root.monochrome-icons ? root.body-color : MailIconPalette.folders;
open: entry.open;
toggled(open) => { root.toggle-section(entry.key, open); }
}
if entry.kind == SidebarRowKind.global-label: SidebarItem {
x: 0px;
interactive: entry.show_row;
y: 0px;
width: parent.width;
label: entry.label.name;
accessible-name: @tr("Global label {}", entry.label.name);
count: entry.label.count;
label-has-emoji: entry.label.name_has_emoji;
left-padding: SidebarStyle.icon-left + SidebarStyle.branch-indent;
label-id: entry.label.id;
editable-color: entry.label.color;
scope: "GlobalLabel:" + entry.label.id;
label-manageable: true;
label-is-global: true;
mail-drop-enabled: true;
mail-drop-copies: true;
icon: @image-url("../icons/lucide/filled/tag.svg");
selected: root.selected-scope == "GlobalLabel:" + entry.label.id;
sidebar-background: root.background-color;
selection-background: root.selection-background;
accent-color: root.accent-color;
body-color: root.body-color;
muted-color: root.muted-color;
icon-color: root.monochrome-icons
? (root.selected-scope == "GlobalLabel:" + entry.label.id ? root.accent-color : root.muted-color)
: entry.label.color;
clicked(scope) => { root.select-scope(scope); }
rename-label(id, name, color, account, global) => { root.request-rename-label(id, name, color, account, global); }
delete-label(id, name, account, global, has-children) => {
root.request-delete-label(id, name, account, global, has-children);
}
}
if entry.kind == SidebarRowKind.accounts-heading: WorkspaceMiniHeading {
x: 0px;
y: 0px;
width: parent.width;
height: 22px;
label: @tr("ACCOUNTS");
label-color: root.muted-color;
vertical-alignment: bottom;
}
// Local mail is listed like an account, under its own
// name and a folders icon.
if entry.kind == SidebarRowKind.account: SidebarSectionHeader {
private property <bool> local: entry.mailbox.account_id == LocalMailUi.account-id;
x: 0px;
interactive: entry.show_row;
y: 0px;
width: parent.width;
label: self.local ? @tr("On this device") : entry.mailbox.label;
detail: entry.mailbox.detail;
avatar: entry.mailbox.avatar;
avatar-image: entry.mailbox.avatar_image;
has-avatar-image: entry.mailbox.has_avatar;
has-avatar: !self.local;
count: entry.mailbox.count;
icon: @image-url("../icons/lucide/filled/folders.svg");
sidebar-background: root.background-color;
hover-background: root.hover-background;
body-color: root.title-color;
muted-color: root.muted-color;
icon-color: self.local && !root.monochrome-icons ? MailIconPalette.folders : root.body-color;
open: entry.open;
// Mail on this device has no server or settings page.
account-menu: !self.local;
can-check-mail: !root.sync-in-progress;
toggled(open) => { root.toggle-section(entry.key, open); }
check-mail => { root.sync-account(entry.mailbox.account_id); }
account-settings => { root.manage-accounts(); }
}
if entry.kind == SidebarRowKind.folder: SidebarItem {
x: 0px;
interactive: entry.show_row;
y: 0px;
width: parent.width;
label: entry.mailbox.label;
label-has-emoji: entry.mailbox.label_has_emoji;
count: entry.mailbox.count;
scope: entry.mailbox.scope;
account-id: entry.mailbox.account_id;
folder-id: entry.mailbox.folder_id;
has-children: entry.mailbox.has_children;
expanded: entry.mailbox.expanded;
folder-menu-enabled: entry.mailbox.folder_id >= 0
&& !(entry.mailbox.is_standard && entry.mailbox.label == "Trash")
&& (entry.mailbox.can_create_children
|| (!entry.mailbox.is_standard && entry.mailbox.can_rename)
|| (!entry.mailbox.is_standard && entry.mailbox.can_delete));
can-create-child: entry.mailbox.can_create_children;
can-rename: !entry.mailbox.is_standard && entry.mailbox.can_rename;
can-delete: !entry.mailbox.is_standard && entry.mailbox.can_delete;
can-empty-trash: entry.mailbox.is_standard
&& entry.mailbox.label == "Trash"
&& entry.mailbox.folder_id >= 0;
mail-drop-enabled: entry.mailbox.is_selectable
&& ((entry.mailbox.folder_id >= 0
&& entry.mailbox.label != "Sent"
&& entry.mailbox.label != "Drafts")
|| entry.mailbox.label == "Starred");
mail-drop-copies: entry.mailbox.label == "Starred";
left-padding: SidebarStyle.icon-left + entry.mailbox.depth * SidebarStyle.branch-indent;
icon: entry.mailbox.label == "Inbox" ? @image-url("../icons/lucide/filled/inbox-flectar.svg")
: entry.mailbox.label == "Starred" ? @image-url("../icons/lucide/filled/star.svg")
: entry.mailbox.label == "Sent" ? @image-url("../icons/lucide/filled/paper-airplane.svg")
: entry.mailbox.label == "Archive" ? @image-url("../icons/lucide/filled/archive.svg")
: entry.mailbox.label == "Spam" ? @image-url("../icons/lucide/filled/alert.svg")
: entry.mailbox.label == "Trash" ? @image-url("../icons/lucide/filled/trash.svg")
: entry.mailbox.label == "Drafts" ? @image-url("../icons/lucide/filled/draft.svg")
: entry.mailbox.scope == root.selected-scope ? @image-url("../icons/lucide/filled/folder-open.svg")
: @image-url("../icons/lucide/filled/file-directory.svg");
selected: entry.mailbox.scope == root.selected-scope;
row-height: entry.mailbox.label == "Inbox" ? 32px : 28px;
sidebar-background: root.background-color;
selection-background: root.selection-background;
accent-color: root.accent-color;
body-color: root.body-color;
muted-color: root.muted-color;
icon-color: root.monochrome-icons ? (entry.mailbox.scope == root.selected-scope ? root.accent-color : root.muted-color)
: entry.mailbox.label == "Inbox" ? MailIconPalette.inbox
: entry.mailbox.label == "Starred" ? MailIconPalette.starred
: entry.mailbox.label == "Sent" ? MailIconPalette.sent
: entry.mailbox.label == "Archive" ? MailIconPalette.archive
: entry.mailbox.label == "Spam" ? MailIconPalette.spam
: entry.mailbox.label == "Trash" ? MailIconPalette.trash
: entry.mailbox.label == "Drafts" ? MailIconPalette.drafts
: entry.mailbox.has_custom_color ? entry.mailbox.color
: MailIconPalette.folders;
clicked(scope) => {
if (entry.mailbox.is_selectable || entry.mailbox.is_standard) {
root.select-scope(scope);
} else if (entry.mailbox.has_children) {
root.toggle-folder(entry.mailbox.folder_id, !entry.mailbox.expanded);
}
}
toggled(folder-id, expanded) => { root.toggle-folder(folder-id, expanded); }
new-subfolder(account-id, folder-id, name) => {
root.request-create-folder(account-id, folder-id, name);
}
rename-folder(folder-id, name) => { root.request-rename-folder(folder-id, name); }
delete-folder(folder-id, name) => { root.request-delete-folder(folder-id, name); }
empty-trash(account-id) => { root.request-empty-trash(account-id); }
}
if entry.kind == SidebarRowKind.account-labels-section: SidebarSectionHeader {
x: 0px;
interactive: entry.show_row;
y: 0px;
width: parent.width;
label: @tr("Labels");
label-font-weight: 500;
folder-row-style: true;
sidebar-background: root.background-color;
hover-background: root.hover-background;
body-color: root.body-color;
muted-color: root.muted-color;
icon: @image-url("../icons/lucide/filled/tag.svg");
icon-color: root.monochrome-icons ? root.body-color : MailIconPalette.folders;
open: entry.open;
toggled(open) => { root.toggle-section(entry.key, open); }
}
if entry.kind == SidebarRowKind.account-label: SidebarItem {
x: 0px;
interactive: entry.show_row;
y: 0px;
width: parent.width;
label: entry.label.display_name;
label-path: entry.label.name;
accessible-name: @tr("{} label, {} account", entry.label.name, entry.label.account_name);
count: entry.label.count;
label-has-emoji: entry.label.name_has_emoji;
left-padding: SidebarStyle.icon-left + SidebarStyle.branch-indent
+ entry.label.depth * SidebarStyle.branch-indent;
label-id: entry.label.id;
has-children: entry.label.has_children;
expanded: entry.label.expanded;
label-tree-node: true;
editable-color: entry.label.color;
scope: "AccountLabel:" + entry.label.id;
account-id: entry.label.account_id;
label-manageable: true;
label-can-create-child: entry.label.can_create_children;
label-account-name: entry.label.account_name;
mail-drop-enabled: true;
mail-drop-copies: true;
icon: @image-url("../icons/lucide/filled/tag.svg");
selected: root.selected-scope == "AccountLabel:" + entry.label.id;
sidebar-background: root.background-color;
selection-background: root.selection-background;
accent-color: root.accent-color;
body-color: root.body-color;
muted-color: root.muted-color;
icon-color: root.monochrome-icons
? (root.selected-scope == "AccountLabel:" + entry.label.id ? root.accent-color : root.muted-color)
: entry.label.color;
clicked(scope) => { root.select-scope(scope); }
toggled(label-id, expanded) => { root.toggle-section(entry.key, expanded); }
new-child-label(account-id, label-id, path, account) => {
root.request-create-label(account-id, account, label-id, path);
}
rename-label(id, name, color, account, global) => { root.request-rename-label(id, name, color, account, global); }
delete-label(id, name, account, global, has-children) => {
root.request-delete-label(id, name, account, global, has-children);
}
}
if entry.kind == SidebarRowKind.new-folder: SidebarItem {
x: 0px;
interactive: entry.show_row;
y: 0px;
width: parent.width;
label: @tr("New folder");
scope: "";
icon: @image-url("../icons/lucide/outline/plus.svg");
sidebar-background: root.background-color;
selection-background: root.selection-background;
accent-color: root.accent-color;
body-color: root.body-color;
muted-color: root.muted-color;
icon-color: root.muted-color;
clicked(scope) => { root.request-create-folder(entry.mailbox.account_id, -1, ""); }
}
if entry.kind == SidebarRowKind.new-label: SidebarItem {
x: 0px;
interactive: entry.show_row;
y: 0px;
width: parent.width;
label: @tr("New label");
scope: "";
left-padding: SidebarStyle.icon-left + SidebarStyle.branch-indent;
icon: @image-url("../icons/lucide/outline/plus.svg");
sidebar-background: root.background-color;
selection-background: root.selection-background;
accent-color: root.accent-color;
body-color: root.body-color;
muted-color: root.muted-color;
icon-color: root.muted-color;
clicked(scope) => { root.request-create-label(entry.mailbox.account_id, entry.mailbox.context, -1, ""); }
}
}
}
if root.filter-query != "" && root.rows.length == 0 : Text {
x: 12px;
y: 12px;
width: parent.width - 24px;
text: @tr("No folders found");
color: root.muted-color;
font-size: TypeScale.caption;
horizontal-alignment: center;
wrap: word-wrap;
}
ScrollFade {
x: mailbox-scroll.x;
y: mailbox-scroll.y;
width: mailbox-scroll.visible-width;
height: mailbox-scroll.visible-height;
surface-color: root.background-color;
content-y: mailbox-scroll.content-y;
content-height: mailbox-scroll.content-height;
visible-height: mailbox-scroll.visible-height;
}
}
if Updates.offered && Updates.enabled && Updates.version != "" && !Updates.dismissed : VerticalLayout {
padding-bottom: 10px;
UpdateNotice {
touch-mode: root.touch-mode;
background-color: root.hover-background;
hover-background: root.selection-background;
accent-color: root.accent-color;
title-color: root.title-color;
muted-color: root.muted-color;
}
}
}
}