// Shared UI-facing data types live outside app.slint so feature components can // consume the same models without depending on the application window. import "../resources/fonts/noto-emoji/NotoEmoji[wght].ttf"; export struct LocalizedMessage { key: string, argument: string, second_argument: string, third_argument: string, } // Computed only while the Storage settings page is open. `offset` and // `fraction` let the view paint one proportional bar without doing byte math // in Slint's 32-bit integer type. export struct StorageUsageRow { kind: string, size: string, fraction: float, offset: float, color: color, } // Drag payloads are opaque to Slint and stay application-internal. Keeping // the transfer construction, validation, and mutation on one shared global // lets the list and every responsive sidebar use the same DnD contract. export global MailDragApi { pure callback make-transfer(int, int) -> data-transfer; pure callback can-drop-on-mailbox(data-transfer, string, int, int) -> bool; callback drop-on-mailbox(data-transfer, string, int, int) -> bool; } export struct MailboxRow { account_id: int, folder_id: int, parent_folder_id: int, depth: int, has_children: bool, expanded: bool, is_standard: bool, is_selectable: bool, can_create_children: bool, can_rename: bool, can_delete: bool, label_has_emoji: bool, label: string, scope: string, context: string, detail: string, avatar: string, avatar_image: image, has_avatar: bool, is_account: bool, count: string, color: color, has_custom_color: bool, } // Provider labels and local auto-categories share one presentation model. // `applied` is projected for the currently selected thread so menus and chips // update from the same source of truth after every action. export struct MailLabelRow { id: int, account_id: int, account_name: string, name: string, display_name: string, depth: int, has_children: bool, expanded: bool, can_create_children: bool, name_has_emoji: bool, color: color, applied: bool, is_auto: bool, is_global: bool, // Unread mail the label's list shows, as the sidebar badge shows it. count: string, } // One visible navigation entry per list row; stable keys also identify sections. export enum SidebarRowKind { unified-heading, unified-section, unified-inbox, unified-mailbox, categories-section, important, other, category, global-labels-section, global-label, accounts-heading, account, folder, account-labels-section, account-label, new-folder, new-label, } export struct SidebarRow { key: string, kind: SidebarRowKind, mailbox: MailboxRow, label: MailLabelRow, open: bool, show_row: bool, reveal_row: bool, } // A file shown on a message-list row. export struct ListAttachment { id: string, // The name before its extension, which stays whole when the name is cut. stem: string, extension: string, // The file's type, as for MailAttachment. kind: string, previewable: bool, } export struct EmailRow { id: int, account_id: int, account: string, account_color: color, account_profile: string, show_account_marker: bool, folder: string, sender: string, address: string, initials: string, favicon: image, favicon_small: image, has_favicon: bool, subject: string, preview: string, time: string, unread: bool, starred: bool, has_attachments: bool, has_replied: bool, message_count: int, label_summary: string, labels: [MailLabelRow], // Gmail labels are tags; other accounts file labels like folders. account_uses_labels: bool, // The one-time code the message asks its reader to enter, if any, and // the same code spelled out for screen readers. verification_code: string, verification_code_spelled: string, // The conversation's first file, and how many files it holds. attachment: ListAttachment, attachment_total: int, selected: bool, checked: bool, } // Section controls and messages share a virtualized ListView. Closing rows // stay in the model briefly at zero height so the accordion can settle. export struct MailListEntry { is_header: bool, group_key: string, group_kind: string, group_count: int, expanded: bool, show_row: bool, reveal_row: bool, email_index: int, email: EmailRow, } // Resolve keyboard movement against the entire model, including messages // outside the virtualized viewport. Geometry stays in the Slint component. export struct MailNavigationTarget { id: int, entry_index: int, preceding_headers: int, preceding_messages: int, checked: bool, } export global MailListNavigation { pure callback target([MailListEntry], int, string, int) -> MailNavigationTarget; } export struct MailProfileRow { id: string, name: string, color: color, account_count: int, } // An account in the profile editor's checklist; checked accounts belong to // the profile being edited. export struct ProfileMemberRow { id: int, name: string, email: string, initials: string, avatar: image, has_avatar: bool, // The other profile the account is in now; empty when none. other_profile: string, checked: bool, } // Messages remain separate inside a conversation. The native side keeps the // bodies and renderer state; this lightweight model is safe to virtualize even // for long threads. export struct ThreadMessageRow { index: int, sender: string, address: string, initials: string, favicon: image, favicon_small: image, has_favicon: bool, preview: string, time: string, to: string, unread: bool, outgoing: bool, body_pending: bool, selected: bool, } // A calendar server an account syncs; mirrors // flectar_mail_core::models::CalendarConnection. export struct CalendarConnectionRow { id: int, // google | generic | microsoft kind: string, base_url: string, host: string, username: string, // The calendar's name when the connection syncs exactly one. calendar_name: string, calendar_count: int, enabled: bool, // "needs_reauth", "offline" or an error message; empty while it syncs. error: string, } export struct AccountRow { id: int, drag_key: string, name: string, email: string, provider: string, mail_protocol: string, status: string, sync_error: string, initials: string, avatar: image, avatar_small: image, has_avatar: bool, profile_id: string, profile_name: string, profile_color: color, has_profile: bool, has_account_color: bool, username: string, jmap_url: string, incoming_security: string, smtp_security: string, trusted_certificate_pem: string, incoming_host: string, incoming_port: string, smtp_host: string, smtp_port: string, mail_history: string, sent_copy_policy: string, keep_on_server: string, // Days a POP3 server keeps downloaded mail on its own; -1 when it // keeps it or hasn't said. server_keeps_mail_days: int, // Calendar servers the account syncs: its provider's first, then CalDAV. calendar_connections: [CalendarConnectionRow], // Gmail and Outlook accounts sync their provider's calendar at most once. provider_calendar_connected: bool, // Why connecting the provider's calendar last failed. provider_calendar_error: string, carddav_connected: bool, carddav_enabled: bool, carddav_status: string, carddav_url: string, carddav_username: string, } export struct EmailLink { x: float, y: float, width: float, height: float, url: string, name: string } // Email HTML is rasterized into bounded vertical tiles. Coordinates are // normalized against the reading-pane width so HiDPI scaling stays in Slint // and no single full-message bitmap has to move on every scroll frame. export struct EmailTile { image: image, y: float, height: float, } // The composer uses the same bounded-tile strategy as the message renderer, // but these coordinates are logical pixels because cosmic-text owns the // editor's exact wrapping and caret geometry. export struct ComposeEditorTile { image: image, y: float, height: float, } export struct EmailTemplateRow { id: int, name: string, shortcut: string, subject: string, body_text: string, } export struct CalendarDay { day: string, iso_date: string, date_label: string, outside_month: bool, is_today: bool, is_selected: bool, has_events: bool, } export struct CalendarWeekDay { weekday: string, day: string, iso_date: string, date_label: string, is_today: bool, } export struct CalendarEventRow { id: int, editable: bool, title: string, detail: string, iso_date: string, date_label: string, day_index: int, month_index: int, start_minutes: int, duration_minutes: int, color_index: int, all_day: bool, provider: string, account: string, calendar: string, location: string, organizer: string, description: string, attendees: string, join_url: string, rsvp_status: string, recurrence: string, status: string, source: string, } // A flat model lets ListView virtualize individual events, including busy days. export struct CalendarAgendaRow { key: string, kind: string, iso_date: string, date_label: string, is_today: bool, count: int, time_label: string, end_label: string, offset: float, previous_event: int, next_event: int, event: CalendarEventRow, } export struct CalendarAgendaFilterRow { id: int, name: string, account: string, color_index: int, checked: bool, } // Provider calendar collections are kept separate from events so the // calendar sidebar can mirror mail's account-aware navigation without // inventing local placeholder rows. export struct CalendarSourceRow { id: int, account_id: int, group_start: bool, name: string, account_name: string, email: string, provider: string, color: string, color_index: int, read_only: bool, enabled: bool, is_default: bool, last_synced: string, } // Compose attachments intentionally expose display metadata only. Absolute // paths stay in Rust so the UI cannot accidentally render or persist local // filesystem details in a message. export struct ComposeAttachment { name: string, detail: string, } // A deliberately small contact shape for compose autocomplete. The core // keeps affinity/account scoping private and only exposes what the menu needs. export struct ComposeContact { name: string, email: string, initials: string, } // Mirrors flectar_mail_core::models::ContactSync. export enum ContactSyncState { local, detached, synced, pending, conflict, unavailable, failed } export struct ContactValueRow { key: string, value: string, label: string, preference: int, } export struct ContactRow { avatar: image, has-avatar: bool, source: string, id: int, name: string, email: string, initials: string, avatar_tone: int, company: string, detail: string, last_contacted: string, favorite: bool, suggested: bool, selected: bool, } // Account-aware contact navigation is projected separately from ContactRow so // list rows stay small and the sidebar can update counts independently. export struct ContactAccountRow { id: int, name: string, email: string, initials: string, avatar: image, has_avatar: bool, count: string, selected: bool, } export enum ContactSidebarRowKind { unified-heading, unified-section, all, favorites, suggestions, accounts-heading, account, contacts, hint } export struct ContactSidebarRow { key: string, kind: ContactSidebarRowKind, account: ContactAccountRow, open: bool, } // Email document controls are shared directly with the native renderer. export struct ReaderItem { name: string, url: string, kind: string, y: float } export struct ReaderImage { x: float, y: float, width: float, height: float, alt: string, state: string } export struct ReaderCaret { x: float, y: float, height: float, valid: bool } export global EmailReader { in-out property available: false; in-out property body-pending: false; in-out property selection-start; in-out property selection-end; in-out property <[ReaderImage]> images; in-out property revision: -1; in-out property message-id: -1; callback ensure-body(int); callback retry-images(); in-out property failed-images; pure callback link-at(float, float) -> string; callback command(string); callback find(string, int); in-out property auto-fit: true; in-out property zoom: 1; in-out property zoom-revision: 0; in-out property width-ratio: 1; in-out property destination; in-out property context-link; in-out property query; in-out property find-status; in-out property notice; in-out property find-open: false; in-out property reader-mode: false; in-out property caret-mode: false; in-out property <[ReaderItem]> items; in-out property authored-text; in-out property use-authored-text: false; } export struct MailAttachment { id: string, name: string, detail: string, previewable: bool, // pdf, document, spreadsheet, presentation, image, video, audio, // archive, code, calendar or file. kind: string, thumbnail: image, has_thumbnail: bool, } export global MailAttachments { callback deliver(); in-out property <[MailAttachment]> rows; in-out property open: false; in-out property busy: false; in-out property name; in-out property status; in-out property image; in-out property text; in-out property is-image: false; in-out property page: 0; in-out property pages: 0; in-out property revision: 0; callback command(string, string); }