Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
547
assets/webapps/sms.gaiamobile.org/views/conversation/index.html
Normal file
|
|
@ -0,0 +1,547 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en-US" dir="ltr">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
|
||||
<meta charset="utf-8">
|
||||
<meta name="theme-group" content="theme-communications">
|
||||
<meta name="theme-color" content="var(--header-background)">
|
||||
<title>Messages</title>
|
||||
<!--App Style root.css-->
|
||||
<link rel="stylesheet" type="text/css" href="/views/shared/style/root.css">
|
||||
<!-- Stable Building blocks -->
|
||||
<link rel="stylesheet" type="text/css" href="/shared/style/animations.css">
|
||||
<link rel="stylesheet" type="text/css" href="/shared/style/action_menu.css">
|
||||
<link rel="stylesheet" type="text/css" href="/shared/style/option_menu.css">
|
||||
<link rel="stylesheet" type="text/css" href="/shared/style/buttons.css">
|
||||
<link rel="stylesheet" type="text/css" href="/shared/style/confirm.css">
|
||||
<link rel="stylesheet" type="text/css" href="/shared/style/edit_mode.css">
|
||||
<link rel="stylesheet" type="text/css" href="/shared/style/input_areas.css">
|
||||
<link rel="stylesheet" type="text/css" href="/shared/style/switches.css">
|
||||
<link rel="stylesheet" type="text/css" href="/shared/style/lists.css">
|
||||
<link rel="stylesheet" type="text/css" href="/shared/style/progress_activity.css">
|
||||
<link rel="stylesheet" type="text/css" href="/shared/style/status.css">
|
||||
<link rel="stylesheet" type="text/css" href="/shared/style/tabs.css">
|
||||
<link rel="stylesheet" type="text/css" href="/shared/elements/gaia-icons/gaia-icons.css">
|
||||
<!-- App styles -->
|
||||
<link rel="stylesheet" type="text/css" href="/views/shared/style/sms.css">
|
||||
<link rel="stylesheet" type="text/css" href="/views/shared/style/panel.css">
|
||||
<link rel="stylesheet" type="text/css" href="/views/shared/style/edit-mode.css">
|
||||
<link rel="stylesheet" type="text/css" href="/views/shared/style/notification.css">
|
||||
<link rel="stylesheet" type="text/css" href="/views/shared/style/common.css">
|
||||
<link rel="stylesheet" type="text/css" href="/views/shared/style/composer.css">
|
||||
<link rel="stylesheet" type="text/css" href="/views/conversation/style/message.css">
|
||||
<link rel="stylesheet" type="text/css" href="/views/conversation/style/report_view.css">
|
||||
<link rel="stylesheet" type="text/css" href="/views/conversation/style/attachment.css">
|
||||
<link rel="stylesheet" type="text/css" href="/views/conversation/style/conversation.css">
|
||||
<link rel="stylesheet" type="text/css" href="/views/conversation/style/edit-mode.css">
|
||||
<link rel="stylesheet" type="text/css" href="/views/new_message/style/new_message.css">
|
||||
<link rel="stylesheet" type="text/css" href="/views/new_message/style/recipients.css">
|
||||
<!-- Localization -->
|
||||
<meta name="defaultLanguage" content="en-US">
|
||||
<meta name="availableLanguages" content="ar:201601260729, bg:201601260729, bn-BD:201601260729, ca:201601260729, cs:201601260729, da:201601260729, de:201601260729, el:201601260729, en-US:201601260729, es:201601260729, eu:201601260729, fr:201601260729, gl:201601260729, hr:201601260729, hu:201601260729, it:201601260729, ja:201601260729, km:201601260729, ko:201601260729, lt:201601260729, mk:201601260729, ms:201601260729, ne-NP:201601260729, nl:201601260729, pa:201601260729, pl:201601260729, pt-BR:201601260729, ro:201601260729, ru:201601260729, sk:201601260729, sq:201601260729, sr-Cyrl:201601260729, sr-Latn:201601260729, sv-SE:201601260729, tr:201601260729, zh-CN:201601260729, zh-TW:201601260729">
|
||||
<link rel="localization" href="/locales-obj/views.conversation.index.{locale}.json">
|
||||
|
||||
|
||||
<!-- <script defer="" src="/mocks/navigator_moz_icc_manager.js"></script> -->
|
||||
<!-- Firefox Desktop shims -->
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- Web Components -->
|
||||
<!-- <script defer="" src="/shared/elements/config.js"></script> -->
|
||||
<link rel="stylesheet" type="text/css" href="app://theme.gaiamobile.org/shared/elements/gaia-theme/gaia-theme.css">
|
||||
<script async="" src="/shared/elements/gaia-header/dist/gaia-header.js"></script>
|
||||
|
||||
|
||||
<!--
|
||||
<script defer src="/shared/js/component_utils.js"></script>
|
||||
<script defer src="/shared/elements/gaia_menu/script.js"></script>
|
||||
<script defer src="/shared/elements/gaia_sim_picker/script.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/shared/elements/gaia_menu/style.css">
|
||||
<link rel="stylesheet" type="text/css" href="/shared/elements/gaia_sim_picker/style.css">
|
||||
-->
|
||||
<!-- Shared code -->
|
||||
<!-- <script defer="" src="/shared/js/intl/l20n.js"></script> -->
|
||||
<!-- Should be removed while gecko support navigator.mozHour12 API -->
|
||||
<!-- <script defer="" src="/shared/js/date_time_helper.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/template.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/async_storage.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/lazy_loader.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/contact_photo_helper.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/fb/fb_request.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/fb/fb_data_reader.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/fb/fb_reader_utils.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/event_dispatcher.js"></script> -->
|
||||
<!-- <script defer="" src="/views/shared/js/utils.js"></script> -->
|
||||
<!-- <script defer="" src="/views/shared/js/navigation.js"></script> -->
|
||||
<!-- <script defer="" src="/views/shared/js/inter_instance_event_dispatcher.js"></script> -->
|
||||
<!-- <script defer="" src="/views/shared/js/time_headers.js"></script> -->
|
||||
<!-- <script defer="" src="/views/shared/js/contacts.js"></script> -->
|
||||
<!-- <script defer="" src="/services/js/drafts.js"></script> -->
|
||||
<!-- <script defer="" src="/services/js/threads.js"></script> -->
|
||||
<!-- <script defer="" src="/views/shared/js/settings.js"></script> -->
|
||||
<!-- <script defer="" src="/services/js/message_manager.js"></script> -->
|
||||
<!-- <script defer="" src="/views/shared/js/app.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/multi_sim_action_button.js"></script> -->
|
||||
<!-- <script defer="" src="/views/shared/js/task_runner.js"></script> -->
|
||||
<!-- <script defer="" src="/views/shared/js/wbmp.js"></script> -->
|
||||
<!-- <script defer="" src="/views/shared/js/smil.js"></script> -->
|
||||
<!-- <script defer="" src="/views/shared/js/shared_components.js"></script> -->
|
||||
<!-- <script defer="" src="/views/conversation/js/link_helper.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/image_utils.js"></script> -->
|
||||
<!-- <script defer="" src="/views/conversation/js/attachment.js"></script> -->
|
||||
<!-- <script defer="" src="/views/conversation/js/attachment_renderer.js"></script> -->
|
||||
<!-- <script defer="" src="/views/conversation/js/subject_composer.js"></script> -->
|
||||
<!-- <script defer="" src="/views/conversation/js/compose.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/gesture_detector.js"></script> -->
|
||||
<!-- <script defer="" src="/lib/bridge/client.js"></script> -->
|
||||
<!-- <script defer="" src="/services/js/activity/activity_client.js"></script> -->
|
||||
<!-- <script defer="" src="/views/conversation/js/recipients.js"></script> -->
|
||||
<!-- <script defer="" src="/views/conversation/js/conversation.js"></script> -->
|
||||
<!-- <script defer="" src="/views/conversation/js/startup.js"></script> -->
|
||||
<!-- <script defer="" src="/views/shared/js/bootstrap.js"></script> --><script src="./gaia_build_defer_index.js" defer="" type="text/javascript"></script>
|
||||
<!-- Lazy load scripts
|
||||
<script defer src="/shared/js/settings_url.js"></script>
|
||||
<script defer src="/shared/js/mime_mapper.js"></script>
|
||||
<script defer src="/shared/js/mobile_operator.js"></script>
|
||||
<script defer src="/shared/js/settings_listener.js"></script>
|
||||
<script defer src="/shared/js/option_menu.js"></script>
|
||||
<script defer src="/views/shared/js/errors.js"></script>
|
||||
<script defer src="/views/shared/js/shared_components.js"></script>
|
||||
<script defer src="/views/shared/js/dialog.js"></script>
|
||||
<script defer src="/views/shared/js/error_dialog.js"></script>
|
||||
<script defer src="/views/shared/js/waiting_screen.js"></script>
|
||||
<script defer src="/views/shared/js/activity_picker.js"></script>
|
||||
<script defer src="/views/conversation/js/link_action_handler.js"></script>
|
||||
<script defer src="/views/shared/js/contact_renderer.js"></script>
|
||||
<script defer src="/views/shared/js/localization_helper.js"></script>
|
||||
<script defer src="/views/conversation/js/information.js"></script>
|
||||
<script defer src="/services/js/messaging/messaging_client.js"></script>
|
||||
<script defer src="/services/js/moz_mobile_connections/moz_mobile_connections_client.js"></script>
|
||||
-->
|
||||
<meta content="2.5" name="appVersion"></head>
|
||||
|
||||
<body role="application" class="skin-comms theme-communications">
|
||||
<iframe src="/views/shared/shim_host.html" class="shim-host" hidden=""></iframe>
|
||||
<article id="main-wrapper" class="wrapper">
|
||||
<section class="panel panel-ConversationView editable-select-mode" role="region" aria-hidden="true">
|
||||
<gaia-header id="messages-header" class="view-header regular-header" action="back" no-font-fit="">
|
||||
<h1 id="messages-header-text"></h1>
|
||||
<button aria-label="Call" id="messages-call-number-button" data-icon="call" class="hide" data-l10n-id="callButton"></button>
|
||||
<button aria-label="Actions" id="messages-options-button" data-icon="more" data-l10n-id="actionsButton"></button>
|
||||
</gaia-header>
|
||||
<div id="messages-subheader" class="subheader">
|
||||
<section id="messages-to-field">
|
||||
<section data-l10n-id="to" id="to-label">To:</section>
|
||||
<!-- When overflow occurs in the recipients list, scrolling is
|
||||
commonly triggered automatically through focus and keyboard events.
|
||||
In these cases, white space described by CSS `padding-bottom` will
|
||||
not be automatically scrolled into view (because the element will
|
||||
only scroll far enough to bring the cursor into view). A container
|
||||
element is necessary to consistently render this vertical space
|
||||
(instead realized with CSS `margin-bottom`). -->
|
||||
<div id="messages-recipients-list-container" class="bb-editable" role="group" aria-labelledby="to-label">
|
||||
<section id="messages-recipients-list" class="singleline">
|
||||
</section>
|
||||
</div>
|
||||
<menu type="toolbar">
|
||||
<a id="messages-contact-pick-button">
|
||||
<span class="icon icon-user"></span>
|
||||
</a>
|
||||
</menu>
|
||||
</section>
|
||||
<div id="contact-carrier" class="carrier-wrapper"></div>
|
||||
<!-- Notifications in this container will be rendered on top of the
|
||||
Compose field. These notifications should be hidden automatically so
|
||||
they do not prevent the user from inputting text. -->
|
||||
<div class="overlay">
|
||||
<section id="messages-subject-max-length-notice" role="notification" class="hide">
|
||||
<p data-l10n-id="messages-max-subject-length-text">Maximum length of subject reached.</p>
|
||||
</section>
|
||||
<section id="messages-max-length-notice" role="notification" class="hide">
|
||||
<p></p>
|
||||
</section>
|
||||
<section id="messages-sms-counter-notice" role="notification" class="hide">
|
||||
<p></p>
|
||||
</section>
|
||||
<section id="messages-convert-notice" role="notification" class="hide">
|
||||
<p></p>
|
||||
</section>
|
||||
<section id="messages-resize-notice" role="notification" class="hide">
|
||||
<p data-l10n-id="resize-image">Resizing the attached image</p>
|
||||
</section>
|
||||
<section id="messages-new-message-notice" role="notification" class="hide">
|
||||
<div class="text-container">
|
||||
<div data-l10n-id="new-message-notice-text">New message from</div>
|
||||
<div dir="auto" class="contact">Contact</div>
|
||||
</div>
|
||||
<div class="button-container">
|
||||
<button class="notice-button" data-l10n-id="new-message-notice-a-text">Read it</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<article id="composer-container" class="view-body">
|
||||
<div class="flex-composer">
|
||||
<div id="messages-container" data-type="list" class="article-list"></div>
|
||||
<form id="messages-compose-form" role="search" class="bottom" data-message-type="sms">
|
||||
<section class="mms-label-line">
|
||||
<section class="subject-composer js-subject-composer hide">
|
||||
<div class="subject-composer-input" role="textbox" aria-multiline="false" contenteditable="true">
|
||||
</div>
|
||||
<div class="subject-composer-placeholder" data-l10n-id="messagesSubjectInput_placeholder">Subject</div>
|
||||
</section>
|
||||
<span class="mms-label" data-l10n-id="mms-label">MMS</span>
|
||||
</section>
|
||||
<section class="content-composer">
|
||||
<div class="messages-attach-container">
|
||||
<button id="messages-attach-button" aria-label="Add attachment" data-l10n-id="attach-button" type="button"></button>
|
||||
</div>
|
||||
<div class="composer-message-input-container">
|
||||
<div title="Message" id="messages-input" name="message" x-inputmode="-moz-sms" data-l10n-id="messagesInput" role="textbox" aria-multiline="true" contenteditable="true">
|
||||
</div>
|
||||
</div>
|
||||
<div class="composer-button-container">
|
||||
<span class="message-counter js-message-counter"></span>
|
||||
<button id="messages-send-button" class="icon" aria-label="Send" data-l10n-id="send-button" type="submit">
|
||||
<div aria-label="using SIM {{ n }}" class="js-sim-indication sim-indication" data-l10n-id="send-button-sim-indication">{{ n }}</div>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
</div>
|
||||
</article>
|
||||
<form role="dialog" id="messages-edit-form" data-type="edit">
|
||||
<section role="region" class="theme-settings">
|
||||
<gaia-header id="messages-edit-header" action="close" no-font-fit="">
|
||||
<h1 id="messages-edit-mode" data-l10n-id="deleteMessages-title">Delete messages</h1>
|
||||
<button id="messages-check-uncheck-all-button" class="edit-button" data-l10n-id="select-all">Select all</button>
|
||||
</gaia-header>
|
||||
</section>
|
||||
<div class="bottom-tab" role="region">
|
||||
<ul class="bb-tablist">
|
||||
<li role="presentation">
|
||||
<button id="messages-delete-button" class="disable-when-dialog-animates" data-action="delete-button"></button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</form>
|
||||
<section id="messages-recipient-suggestions" class="article-list hide" data-type="list">
|
||||
<ul class="contact-list recipient-suggestions-list" role="listbox"></ul>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section class="panel panel-GroupView" role="region" aria-hidden="true">
|
||||
<gaia-header id="information-group-header" class="header" action="back" no-font-fit="">
|
||||
<h1 data-l10n-id="participant" class="header-text">participant</h1>
|
||||
</gaia-header>
|
||||
<article class="view-body article-list" data-type="list">
|
||||
<ul class="contact-list"></ul>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="panel panel-ReportView" role="region" aria-hidden="true">
|
||||
<gaia-header id="information-report-header" class="header" action="close" no-font-fit="">
|
||||
<h1 data-l10n-id="message-report">Message report</h1>
|
||||
</gaia-header>
|
||||
<article class="view-body article-list report-view container" data-type="list">
|
||||
<div class="description">
|
||||
<p class="type"></p>
|
||||
<p class="subject">
|
||||
<span data-l10n-id="message-subject">Subject:</span>
|
||||
<span class="detail"></span>
|
||||
</p>
|
||||
<p class="sent-block">
|
||||
<span class="sent-title"></span>
|
||||
<span class="sent-timestamp l10n-contains-date detail"></span>
|
||||
</p>
|
||||
<p class="received-block">
|
||||
<span data-l10n-id="message-received">Received:</span>
|
||||
<span class="received-timestamp l10n-contains-date detail"></span>
|
||||
</p>
|
||||
<p class="lateness-block">
|
||||
<span data-l10n-id="message-lateness">Lateness:</span>
|
||||
<span class="lateness">
|
||||
<span class="lateness-month detail"></span>
|
||||
<span class="lateness-day detail"></span>
|
||||
<span class="lateness-hour detail"></span>
|
||||
<span class="lateness-minute detail"></span>
|
||||
<span class="lateness-second detail"></span>
|
||||
</span>
|
||||
</p>
|
||||
<p class="size-block">
|
||||
<span data-l10n-id="message-size-was">Message size:</span>
|
||||
<span class="size detail"></span>
|
||||
</p>
|
||||
<p class="sim-info hide">
|
||||
<span data-l10n-id="message-via">Via:</span>
|
||||
<span class="sim-detail detail"></span>
|
||||
</p>
|
||||
</div>
|
||||
<span class="contact-title"></span>
|
||||
<ul class="contact-list"></ul>
|
||||
<button class="resend-btn" data-l10n-id="message-resend">Resend</button>
|
||||
</article>
|
||||
</section>
|
||||
</article>
|
||||
|
||||
<article id="loading">
|
||||
<form role="dialog" data-type="confirm" class="loading-container">
|
||||
<section>
|
||||
<p class="loading-header" data-l10n-id="deleting-messages">Deleting…</p>
|
||||
<div role="status">
|
||||
<progress class="small"></progress>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
</article>
|
||||
|
||||
<!--
|
||||
- Templates
|
||||
-->
|
||||
|
||||
<div id="contact-suggestion-tmpl" class="hide">
|
||||
<!--
|
||||
<li role="presentation">
|
||||
<a class="suggestion js-contact-info" role="option"
|
||||
data-number="${number}" data-source="contacts" data-name="${name}"
|
||||
data-type="${type}" data-carrier="${carrier}">
|
||||
${photoHTML}
|
||||
<p class="name"><bdi class="ellipsis-dir-fix">${nameHTML}</bdi></p>
|
||||
<p class="number">${phoneDetailsHTML}</p>
|
||||
</a>
|
||||
</li>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div id="contact-report-tmpl" class="hide">
|
||||
<!--
|
||||
<li>
|
||||
<div class="js-contact-info">
|
||||
${photoHTML}
|
||||
<p class="name"><bdi class="ellipsis-dir-fix">${nameHTML}</bdi></p>
|
||||
<p class="number">${phoneDetailsHTML}</p>
|
||||
</div>
|
||||
</li>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div id="contact-suggestion-unknown-tmpl" class="hide">
|
||||
<!--
|
||||
<li role="presentation">
|
||||
<a class="suggestion" role="option"
|
||||
data-number="${number}" data-source="contacts" data-name="${name}"
|
||||
data-type="${type}" data-carrier="${carrier}">
|
||||
${photoHTML}
|
||||
<p class="name">${phoneDetailsHTML}</p>
|
||||
<p class="number">
|
||||
<span data-l10n-id="unknown-contact-title">Unknown Contact</span>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div id="contact-prompt-tmpl" class="hide">
|
||||
<!--
|
||||
<div class="contact-header">
|
||||
${photoHTML}
|
||||
<p class="name"><bdi class="ellipsis-dir-fix">${name}</bdi></p>
|
||||
<p class="details">${phoneDetailsHTML}</p>
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div id="contact-photo-tmpl" class="hide">
|
||||
<!--
|
||||
<aside role="img" data-l10n-id="contact-photo" aria-label="Contact photo" class="pack-end">
|
||||
<span class="contact-photo" data-type="img"></span>
|
||||
</aside>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div id="contact-highlight-tmpl" class="hide">
|
||||
<!--
|
||||
<span class="highlight">${str}</span>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div id="messages-number-tmpl" class="hide">
|
||||
<!--
|
||||
<a class="suggestion js-contact-info" data-number="${number}" data-source="manual" data-name="${number}">
|
||||
<p class="name"><bdi class="ellipsis-dir-fix">${number}</bdi></p>
|
||||
</a>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div id="information-report-tmpl" class="hide">
|
||||
<!--
|
||||
<span class="icon"></span>
|
||||
<span data-l10n-id="${titleL10n}"></span>
|
||||
<span class="timestamp l10n-contains-date"
|
||||
data-l10n-date="${timestamp}"
|
||||
data-l10n-date-format="${messageL10nDateFormat}"
|
||||
>${reportDateL10n}</span>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div id="messages-not-downloaded-tmpl" class="hide">
|
||||
<!--
|
||||
<span class="not-downloaded-message l10n-contains-date"
|
||||
data-l10n-id="${messageL10nId}"
|
||||
data-l10n-args="${messageL10nArgs}"
|
||||
data-l10n-date="${messageL10nDate}"
|
||||
data-l10n-date-format="${messageL10nDateFormat}"></span>
|
||||
<button type="button" class="download" data-l10n-id="${downloadL10nId}"></button>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div id="messages-date-group-tmpl">
|
||||
<!--
|
||||
<div id="${id}" class="messages-date-group" data-timestamp="${timestamp}">
|
||||
<header
|
||||
class="messages-date-group-header"
|
||||
data-time-update="${headerTimeUpdate}"
|
||||
data-time="${headerTime}"
|
||||
data-date-only="${headerDateOnly}">
|
||||
</header>
|
||||
<ul class="message-list"></ul>
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div id="messages-message-tmpl" class="hide">
|
||||
<!--
|
||||
<label class="pack-checkbox danger">
|
||||
<input type="checkbox" value="${id}">
|
||||
<span></span>
|
||||
</label>
|
||||
<section class="bubble">
|
||||
<h1 class="message-subject">
|
||||
${subject}
|
||||
</h1>
|
||||
<div class="message-content">
|
||||
<p class="message-content-body" tabindex="-1">${bodyHTML}</p>
|
||||
<div class="message-details">
|
||||
${simInformationHTML}
|
||||
<time data-time-update="true" data-time-only="true" data-time="${timestamp}"></time>
|
||||
${messageStatusHTML}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div id="messages-message-sim-information-tmpl" class="hide">
|
||||
<!--
|
||||
<span class="message-sim-information"
|
||||
data-l10n-id="sim-id-label"
|
||||
data-l10n-args="${simNumberL10nArgs}">
|
||||
</span>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div id="messages-message-status-tmpl" class="hide">
|
||||
<!--
|
||||
<div class="message-status" data-l10n-id="${statusL10nId}"
|
||||
aria-label="Message status"
|
||||
role="status">
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div id="messages-late-arrival-notice-tmpl" class="hide">
|
||||
<!--
|
||||
<div class="late-arrival-icon" data-l10n-id="late-notice-label" aria-label="Late arrival"></div>
|
||||
<div class="late-arrival-notice"></div>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div id="messages-recipient-tmpl" class="hide">
|
||||
<!--
|
||||
<span class="${className}" x-inputmode="verbatim"
|
||||
contenteditable="${editable}" role="${role}"
|
||||
data-number="${number}" data-source="${source}" data-name="${name}"
|
||||
data-carrier="${carrier}" data-type="${type}" dir="auto">
|
||||
${name}
|
||||
</span>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div id="attachment-nopreview-tmpl" class="hide">
|
||||
<!--
|
||||
<div class="attachment ${errorClass}" data-attachment-type="${type}">
|
||||
<div class="thumbnail-placeholder ${type}-placeholder">
|
||||
</div>
|
||||
<div class="js-size-indicator size-indicator" data-l10n-id="${sizeL10nId}" data-l10n-args="${sizeL10nArgs}"></div>
|
||||
</div>
|
||||
<div class="file-name" dir="auto"></div>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div id="attachment-preview-tmpl" class="hide">
|
||||
<!--
|
||||
<div class="attachment">
|
||||
<div class="thumbnail"></div>
|
||||
<div class="js-size-indicator size-indicator" data-l10n-id="${sizeL10nId}" data-l10n-args="${sizeL10nArgs}"></div>
|
||||
</div>
|
||||
<div class="file-name" dir="auto"></div>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div id="attachment-draft-tmpl" class="hide">
|
||||
<!--
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
|
||||
<meta charset="utf-8">
|
||||
<base href="${baseURL}">
|
||||
<link rel="stylesheet" type="text/css" href="views/conversation/style/attachment_draft.css">
|
||||
<link rel="stylesheet" type="text/css" href="views/conversation/style/attachment.css">
|
||||
</head>
|
||||
<body class="attachment-draft ${cssClass}">${baseHTML}</body>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<!--
|
||||
Please, don't change template markup alignment, it's done this way to
|
||||
remove any whitespace symbols between inline elements.
|
||||
-->
|
||||
<div id="phone-details-tmpl" class="hide">
|
||||
<!--
|
||||
<span class="${hasTypeClass} ${hasCarrierClass}"><span
|
||||
dir="auto" class="phone-type"
|
||||
data-l10n-id="${type}">${type}</span><span
|
||||
class="phone-type-separator"
|
||||
data-l10n-id="phone-type-separator"></span><span
|
||||
class="phone-number" dir="ltr">${number}</span><span
|
||||
class="phone-carrier-separator"
|
||||
data-l10n-id="phone-carrier-separator"></span><span
|
||||
class="phone-carrier" dir="auto">${carrier}</span>
|
||||
</span>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div id="messages-group-header-tmpl" class="hide">
|
||||
<!--
|
||||
<span class="group-header-title"><bdi class="ellipsis-dir-fix">${name}</bdi> <bdi dir="ltr">(+${participantCount})</bdi></span>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div id="messages-header-tmpl" class="hide">
|
||||
<!--
|
||||
<bdi class="ellipsis-dir-fix">${name}</bdi>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<gaia-sim-picker id="sim-picker" tabindex="-1"></gaia-sim-picker>
|
||||
</article>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
;(function(exports){'use strict';const ATTACHMENT_FOLDER_PATH='sms-attachments/';function getBaseName(filePath){if(!filePath){throw new Error('Filepath is not defined!');}
|
||||
return filePath.substring(filePath.lastIndexOf('/')+1);}
|
||||
function Attachment(blob,options){options=options||{};this.blob=blob;this.isDraft=!!options.isDraft;this.name=blob.name||options.name||'';if(typeof this.name!=='string'){this.name='';}
|
||||
Object.defineProperty(this,'_renderer',{writable:true});}
|
||||
Attachment.prototype={_getAttachmentRenderer:function(){this._renderer=this._renderer||AttachmentRenderer.for(this);return this._renderer;},get size(){return this.blob.size;},get type(){return Utils.typeFromMimeType(this.blob.type);},render:function(readyCallback){var attachmentRenderer=this._getAttachmentRenderer();attachmentRenderer.render().catch(function(e){console.error('Error occurred while rendering attachment.',e);}).then(readyCallback);return attachmentRenderer.getAttachmentContainer();},updateFileSize:function(){var attachmentRenderer=this._getAttachmentRenderer();attachmentRenderer.updateFileSize();},view:function(options){var l10nPromise=this.name?Promise.resolve(this.name):document.l10n.formatValue('unnamed-attachment');return l10nPromise.then(name=>{var mimetype=MimeMapper.guessTypeFromFileProperties(name,this.blob.type.toLowerCase());var filename=MimeMapper.ensureFilenameMatchesType(name,mimetype);filename=ATTACHMENT_FOLDER_PATH+getBaseName(filename);var activity=new MozActivity({name:'open',data:{type:mimetype,filename:filename,blob:this.blob,allowSave:options&&options.allowSave}});activity.onerror=function(){console.error('error with open activity',this.error.name);if(this.error.name==='NO_PROVIDER'){Utils.alert('attachmentOpenError');}};});}};exports.Attachment=Attachment;}(this));
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
;(function(exports){'use strict';const MAX_THUMBNAIL_GENERATION_SIZE=10*1024*1024;const THUMBNAIL_SIZE=100*window.devicePixelRatio;const RENDERERS={draft:{createAttachmentContainer:function(){var container=document.createElement('iframe');container.setAttribute('sandbox','allow-same-origin');return container;},renderTo:function(data,attachmentContainer){attachmentContainer.classList.add(data.cssClass);var template=Template('attachment-draft-tmpl');var markup=template.interpolate({baseURL:location.protocol+'//'+location.host+'/',baseHTML:data.markup,cssClass:data.cssClass},{safe:['baseHTML']});var blob=new Blob([markup],{type:'text/html'});var blobUrl=window.URL.createObjectURL(blob);attachmentContainer.src=blobUrl;return this._whenLoaded(attachmentContainer).then(function onload(){window.URL.revokeObjectURL(blobUrl);var contentDocument=attachmentContainer.contentDocument;var documentElement=contentDocument.documentElement;documentElement.lang=document.documentElement.getAttribute('lang');documentElement.dir=document.documentElement.getAttribute('dir');document.l10n.translateFragment(documentElement);contentDocument.addEventListener('click',()=>attachmentContainer.click());return contentDocument.body;});},_whenLoaded:function(iframe){var innerDocument=iframe.contentDocument;if(innerDocument&&innerDocument.body&&innerDocument.body.classList.contains('attachment-draft')){return Promise.resolve();}
|
||||
return new Promise((resolve)=>{iframe.addEventListener('load',function onload(){this.removeEventListener('load',onload);resolve();});});},getContentNode:function(attachmentContainer){return this._whenLoaded(attachmentContainer).then(()=>attachmentContainer.contentDocument.documentElement);},setL10nAttributes:function(element,l10nId,l10nArgs){document.l10n.setAttributes(element,l10nId,l10nArgs);document.l10n.translateFragment(element);}},base:{createAttachmentContainer:function(){return document.createElement('div');},renderTo:function(data,attachmentContainer){attachmentContainer.classList.add(data.cssClass);attachmentContainer.innerHTML=data.markup;return Promise.resolve(attachmentContainer);},getContentNode:function(attachmentContainer){return Promise.resolve(attachmentContainer);},setL10nAttributes:function(element,l10nId,l10nArgs){document.l10n.setAttributes(element,l10nId,l10nArgs);}}};var AttachmentRenderer=function(attachment){this._attachment=attachment;this._renderer=attachment.isDraft?RENDERERS.draft:RENDERERS.base;this._attachmentContainer=null;};AttachmentRenderer.prototype.getAttachmentContainer=function(){if(!this._attachmentContainer){this._attachmentContainer=this._createAttachmentContainer();}
|
||||
return this._attachmentContainer;};AttachmentRenderer.prototype.render=function(){var attachmentContainer=this.getAttachmentContainer();var thumbnailPromise=this._attachment.type==='img'&&this._attachment.size<MAX_THUMBNAIL_GENERATION_SIZE?this.getThumbnail():Promise.reject();return thumbnailPromise.then((thumbnail)=>{return{markup:this._getBaseMarkup('attachment-preview-tmpl'),cssClass:'preview',thumbnail:thumbnail};}).catch((error)=>{return{markup:this._getBaseMarkup('attachment-nopreview-tmpl',!!error),cssClass:'nopreview'};}).then((data)=>{return this._renderer.renderTo(data,attachmentContainer).then((contentContainer)=>{var thumbnailNode=contentContainer.querySelector('.thumbnail');if(thumbnailNode){thumbnailNode.style.backgroundImage='url("'+data.thumbnail.url+data.thumbnail.fragment+'")';attachmentContainer.dataset.thumbnail=data.thumbnail.url;}
|
||||
var fileNode=contentContainer.querySelector('.file-name');if(this._attachment.name){fileNode.removeAttribute('data-l10n-id');fileNode.textContent=this._attachment.name.slice(this._attachment.name.lastIndexOf('/')+1);}else{fileNode.setAttribute('data-l10n-id','unnamed-attachment');}});});};AttachmentRenderer.prototype.updateFileSize=function(){var attachmentContainer=this.getAttachmentContainer();return this._renderer.getContentNode(attachmentContainer).then((contentNode)=>{var sizeIndicator=contentNode.querySelector('.js-size-indicator');if(!sizeIndicator){throw new Error('updateFileSize should be called after a render().');}
|
||||
var sizeL10n=Utils.getSizeForL10n(this._attachment.size);this._renderer.setL10nAttributes(sizeIndicator,sizeL10n.l10nId,sizeL10n.l10nArgs);});};AttachmentRenderer.prototype.getThumbnail=function(){var blob=this._attachment.blob;return ImageUtils.getSizeAndType(blob).then(function getSizeResolve(data){var fragment=ImageUtils.Downsample.sizeNoMoreThan(THUMBNAIL_SIZE/Math.min(data.width,data.height));return{url:window.URL.createObjectURL(blob),fragment:fragment};});};AttachmentRenderer.prototype._createAttachmentContainer=function(){var attachmentContainer=this._renderer.createAttachmentContainer();attachmentContainer.classList.add('attachment-container');attachmentContainer.dataset.attachmentType=this._attachment.type;return attachmentContainer;};AttachmentRenderer.prototype._getBaseMarkup=function(templateId,hasError){var sizeL10n=Utils.getSizeForL10n(this._attachment.size);return Template(templateId).interpolate({type:this._attachment.type,errorClass:hasError?'corrupted':'',sizeL10nId:sizeL10n.l10nId,sizeL10nArgs:JSON.stringify(sizeL10n.l10nArgs)});};exports.AttachmentRenderer={for:function(attachment){return new AttachmentRenderer(attachment);}};}(this));
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
;'use strict';var Compose=(function(){const TYPES=['image','audio','video'];const UPDATE_DELAY=500;const MIN_AVAILABLE_CHARS_COUNT=20;var placeholderClass='placeholder';var attachmentClass='attachment-container';var attachments=new Map();var dom={form:null,message:null,sendButton:null,attachButton:null,counter:null};var state={empty:true,maxLength:null,size:null,lastScrollPosition:0,resizing:false,type:'sms',lock:{canSend:null,canEdit:null,forceType:null},segmentInfo:{segments:0,charsAvailableInLastSegment:0}};var subject=null;function getContentFromDOM(domElement){var content=[];var node;for(node=domElement.firstChild;node;node=node.nextSibling){var attachment=attachments.get(node);if(attachment){content.push(attachment);continue;}
|
||||
var last=content.length-1;var text=node.textContent;if(text){text=text.replace(/\u00A0/g,' ');}
|
||||
if(node.nodeName=='BR'){if(node===domElement.lastChild){continue;}
|
||||
text='\n';}
|
||||
if(text.length){if(typeof content[last]==='string'){content[last]+=text;}else{content.push(text);}}}
|
||||
return content;}
|
||||
function onContentChanged(duck){if((duck instanceof Attachment&&duck.type==='img')||(duck&&duck.containsImage)){return imageAttachmentsHandling();}
|
||||
var isEmptyMessage=!dom.message.textContent.length&&!hasAttachment();if(isEmptyMessage){var brs=dom.message.getElementsByTagName('br');if(brs.length>1){isEmptyMessage=false;}}
|
||||
var placeholding=dom.message.classList.contains(placeholderClass);if(placeholding&&!isEmptyMessage){dom.message.classList.remove(placeholderClass);}
|
||||
if(!placeholding&&isEmptyMessage){dom.message.classList.add(placeholderClass);}
|
||||
state.emptyMessage=isEmptyMessage;Compose.updateEmptyState();Compose.updateType();Compose.updateSendButton();Compose.updateAttachButton();updateSegmentInfoThrottled();Compose.emit('input');}
|
||||
function onSubjectChanged(){Compose.updateEmptyState();Compose.updateType();Compose.updateSendButton();Compose.updateAttachButton();Compose.emit('subject-change');}
|
||||
function onSubjectVisibilityChanged(){if(subject.isVisible()){dom.form.classList.add('subject-composer-visible');}else{dom.message.focus();dom.form.classList.remove('subject-composer-visible');}}
|
||||
function hasAttachment(){return!!dom.message.querySelector('iframe');}
|
||||
function hasSubject(){return subject.isVisible()&&!!subject.getValue();}
|
||||
function composeKeyEvents(e){if(!compose.canEdit()&&e.which!==8){e.preventDefault();}else{state.size=null;}}
|
||||
function insert(item){var fragment=document.createDocumentFragment();if(!item){return null;}
|
||||
state.size=null;if(item.render){var node=item.render();attachments.set(node,item);fragment.appendChild(node);}else if(item.nodeName==='IFRAME'){fragment.appendChild(item);}else if(typeof item==='string'){item.split('\n').forEach(function(line){fragment.appendChild(document.createTextNode(line));fragment.appendChild(document.createElement('br'));});fragment.lastElementChild.remove();}
|
||||
return fragment;}
|
||||
function imageAttachmentsHandling(){if(Compose.size<Settings.mmsSizeLimitation){onContentChanged();return;}
|
||||
var imgNodes=[];attachments.forEach((attachment,node)=>{if(attachment.type==='img'){imgNodes.push(node);}});var done=0;var images=imgNodes.length;var limit=images>2?Settings.mmsSizeLimitation*0.2:Settings.mmsSizeLimitation*0.4;function imageSized(){if(++done===images){state.resizing=false;onContentChanged();}else{resizedImg(imgNodes[done]);}}
|
||||
function resizedImg(node){var item=attachments.get(node);if(item.blob.size<limit){imageSized();}else{Utils.getResizedImgBlob(item.blob,limit,function(resizedBlob){state.size=null;item.blob=resizedBlob;item.updateFileSize();imageSized();});}}
|
||||
state.resizing=true;resizedImg(imgNodes[0]);onContentChanged();}
|
||||
var segmentInfoTimeout=null;function updateSegmentInfoThrottled(){if(hasAttachment()){return resetSegmentInfo();}
|
||||
if(segmentInfoTimeout===null){segmentInfoTimeout=setTimeout(updateSegmentInfo,UPDATE_DELAY);}}
|
||||
function updateSegmentInfo(){segmentInfoTimeout=null;var value=Compose.getText();var segmentInfoPromise=value?MessageManager.getSegmentInfo(value):Promise.reject();segmentInfoPromise.then(function(segmentInfo){state.segmentInfo=segmentInfo;},resetSegmentInfo).then(compose.updateType.bind(Compose)).then(compose.emit.bind(compose,'segmentinfochange'));}
|
||||
function resetSegmentInfo(){state.segmentInfo={segments:0,charsAvailableInLastSegment:0};}
|
||||
function disposeAttachmentNode(attachmentNode){var thumbnailURL=attachmentNode.dataset.thumbnail;if(thumbnailURL){window.URL.revokeObjectURL(thumbnailURL);}
|
||||
attachments.delete(attachmentNode);}
|
||||
var compose={init:function composeInit(formId){dom.form=document.getElementById(formId);dom.message=document.getElementById('messages-input');dom.sendButton=document.getElementById('messages-send-button');dom.attachButton=document.getElementById('messages-attach-button');dom.counter=dom.form.querySelector('.js-message-counter');dom.messagesAttach=dom.form.querySelector('.messages-attach-container');dom.composerButton=dom.form.querySelector('.composer-button-container');subject=new SubjectComposer(dom.form.querySelector('.js-subject-composer'));subject.on('change',onSubjectChanged);subject.on('visibility-change',onSubjectChanged);subject.on('visibility-change',onSubjectVisibilityChanged);dom.message.addEventListener('input',onContentChanged);dom.message.addEventListener('keydown',composeKeyEvents);dom.message.addEventListener('keypress',composeKeyEvents);dom.message.addEventListener('click',this.onAttachmentClick.bind(this));dom.attachButton.addEventListener('click',this.onAttachClick.bind(this));this.offAll();this.clear();this.on('type',this.onTypeChange.bind(this));this.on('type',this.updateMessageCounter.bind(this));this.on('segmentinfochange',this.updateMessageCounter.bind(this));var onInteracted=this.emit.bind(this,'interact');dom.message.addEventListener('focus',onInteracted);dom.message.addEventListener('click',onInteracted);dom.messagesAttach.addEventListener('click',onInteracted);dom.composerButton.addEventListener('click',onInteracted);subject.on('focus',onInteracted);return this;},getContent:function(){return getContentFromDOM(dom.message);},getSubject:function(){return subject.isVisible()?subject.getValue():null;},setSubject:function(value){return subject.setValue(value);},isSubjectMaxLength:function(){return subject.getValue().length>=subject.getMaxLength();},showSubject:function(){subject.show();subject.focus();},hideSubject:function(){subject.hide();},fromDraft:function(draft){this.clear();if(!draft){return;}
|
||||
if(draft.subject){this.setSubject(draft.subject);subject.show();}
|
||||
if(!draft.content){return;}
|
||||
if(!Array.isArray(draft.content)){throw new Error('If present, the `content` property must be an array.');}
|
||||
draft.content.forEach(function(fragment){if(fragment.blob){fragment=new Attachment(fragment.blob,{name:fragment.name,isDraft:true});}
|
||||
Compose.append(fragment);},Compose);},getText:function(){var out=this.getContent().filter(function(elem){return(typeof elem==='string');});return out.join('');},isEmpty:function(){return state.empty;},setupLock({canSend,canEdit,forceType}){state.lock.canSend=canSend;state.lock.canEdit=canEdit;state.lock.forceType=forceType;},refresh(){this.updateType();this.updateSendButton();this.updateAttachButton();},scrollToTarget:function(target){var targetRect=target.getBoundingClientRect();var containerRect=dom.message.getBoundingClientRect();var offset=(targetRect.top+targetRect.height/2)-
|
||||
(containerRect.top+containerRect.height/2);dom.message.scrollTop+=offset;},scrollMessageContent:function(){if(document.activeElement===dom.message){var range=window.getSelection().getRangeAt(0).cloneRange();if(range.collapsed){range.insertNode(document.createElement('span'));this.scrollToTarget(range);range.deleteContents();}else{this.scrollToTarget(range);}
|
||||
state.lastScrollPosition=dom.message.scrollTop;}else{dom.message.scrollTop=state.lastScrollPosition;}},prepend:function(item){var fragment=insert(item);if(!fragment){return this;}
|
||||
if(dom.message.firstChild&&dom.message.firstChild.nodeName==='BR'){dom.message.insertBefore(fragment,dom.message.childNodes[1]);}else{dom.message.insertBefore(fragment,dom.message.childNodes[0]);}
|
||||
onContentChanged(item);return this;},append:function(item,options){options=options||{};if(Array.isArray(item)){var containsImage=false;item.forEach(function(content){if(content.type==='img'){containsImage=true;}
|
||||
this.append(content,{ignoreChange:true});},this);onContentChanged({containsImage:containsImage});}else{var fragment=insert(item);if(!fragment){return this;}
|
||||
if(document.activeElement===dom.message){var range=window.getSelection().getRangeAt(0);var firstNodes=fragment.firstChild;range.deleteContents();range.insertNode(fragment);this.scrollToTarget(range);dom.message.focus();range.setStartAfter(firstNodes);}else{dom.message.insertBefore(fragment,dom.message.lastChild);this.scrollToTarget(dom.message.lastChild);}
|
||||
if(!options.ignoreChange){onContentChanged(item);}}
|
||||
return this;},clear:function(){state.type='sms';this.onTypeChange();attachments.forEach((attachment,node)=>disposeAttachmentNode(node));dom.message.innerHTML='<br>';subject.reset();state.resizing=false;state.size=0;resetSegmentInfo();segmentInfoTimeout=null;onContentChanged();return this;},focus:function(){dom.message.focus();var selection=window.getSelection();var range=document.createRange();var lastChild=dom.message.lastChild;if(lastChild.tagName==='BR'){range.setStartBefore(lastChild);}else{range.setStartAfter(lastChild);}
|
||||
selection.removeAllRanges();selection.addRange(range);return this;},updateType:function(){var newType=this.getType();if(newType!==state.type){state.type=newType;this.emit('type');}},getType(){var typeForcedByLock=state.lock.forceType&&state.lock.forceType();if(typeForcedByLock){return typeForcedByLock;}
|
||||
var isTextTooLong=state.segmentInfo.segments>Settings.maxConcatenatedMessages;return isTextTooLong||hasSubject()||hasAttachment()?'mms':'sms';},updateEmptyState:function(){state.empty=state.emptyMessage&&!hasSubject();},updateSendButton:function(){dom.sendButton.disabled=!this.canSend();},updateAttachButton:function(){dom.attachButton.disabled=!this.canEdit();},canSend(){var isSendAllowedByLock=!state.lock.canSend||state.lock.canSend();var sizeExceedsLimit=this.type==='mms'&&Settings.mmsSizeLimitation&&this.size>Settings.mmsSizeLimitation;return isSendAllowedByLock&&!sizeExceedsLimit&&!this.isEmpty()&&!this.isResizing;},canEdit(){var isEditAllowedByLock=!state.lock.canEdit||state.lock.canEdit();var sizeExceedsOrEqualToLimit=this.type==='mms'&&Settings.mmsSizeLimitation&&this.size>=Settings.mmsSizeLimitation;return isEditAllowedByLock&&!sizeExceedsOrEqualToLimit;},_onAttachmentRequestError:function c_onAttachmentRequestError(err){var errId=err instanceof DOMError?err.name:err.message;if(errId==='file too large'){Utils.alert({id:'attached-files-too-large',args:{n:1,mmsSize:(Settings.mmsSizeLimitation/1024).toFixed(0)}});}else if(errId!=='ActivityCanceled'&&errId!=='pick cancelled'){console.warn('Unhandled error: ',err);}},onAttachClick:function c_onAttachClick(event){this.requestAttachment().then(this.append.bind(this),this._onAttachmentRequestError);},onAttachmentClick:function c_onAttachmentClick(event){if(!event.target.classList.contains(attachmentClass)||state.resizing){return;}
|
||||
var currentAttachmentDOM=event.target;var currentAttachment=attachments.get(event.target);var name=currentAttachment.name;var blob=currentAttachment.blob;var options={header:name.substr(name.lastIndexOf('/')+1)};var mimeFirstPart=blob.type.substr(0,blob.type.indexOf('/'));var fileType=(TYPES.indexOf(mimeFirstPart)>-1)?mimeFirstPart:'other';var onView=()=>{currentAttachment.view();};function onRemove(){dom.message.removeChild(currentAttachmentDOM);disposeAttachmentNode(currentAttachmentDOM);state.size=null;onContentChanged();}
|
||||
var onReplace=()=>{this.requestAttachment().then((newAttachment)=>{var fragment=insert(newAttachment);dom.message.insertBefore(fragment,currentAttachmentDOM);dom.message.removeChild(currentAttachmentDOM);disposeAttachmentNode(currentAttachmentDOM);onContentChanged(newAttachment);},this._onAttachmentRequestError);};options.items=[{l10nId:`view-attachment-${fileType}`,method:onView},{l10nId:`remove-attachment-${fileType}`,method:onRemove},{l10nId:`replace-attachment-${fileType}`,method:onReplace},{l10nId:'cancel'}];new OptionMenu(options).show();},onTypeChange:function c_onTypeChange(){if(this.type==='sms'){dom.message.setAttribute('x-inputmode','-moz-sms');}else{dom.message.removeAttribute('x-inputmode');}
|
||||
dom.form.dataset.messageType=this.type;},updateMessageCounter:function c_updateMessageCounter(){var counterValue='';if(this.type==='sms'){var segments=state.segmentInfo.segments;var availableChars=state.segmentInfo.charsAvailableInLastSegment;if(segments&&(segments>1||availableChars<=MIN_AVAILABLE_CHARS_COUNT)){counterValue=availableChars+'/'+segments;}}
|
||||
if(counterValue!==dom.counter.textContent){dom.counter.textContent=counterValue;}},requestAttachment:function(){var activityData={type:['image/*','audio/*','video/*','text/vcard']};var activity;var defer=Utils.Promise.defer();if(Settings.mmsSizeLimitation){activityData.maxFileSizeBytes=Settings.mmsSizeLimitation;}
|
||||
activity=new MozActivity({name:'pick',data:activityData});activity.onsuccess=function(){var result=activity.result;if(Settings.mmsSizeLimitation&&result.blob.size>Settings.mmsSizeLimitation&&Utils.typeFromMimeType(result.blob.type)!=='img'){defer.reject(new Error('file too large'));}
|
||||
defer.resolve(new Attachment(result.blob,{name:result.name,isDraft:true}));};activity.onerror=()=>{defer.reject(activity.error);};return defer.promise;}};Object.defineProperty(compose,'type',{get:function composeGetType(){return state.type;}});Object.defineProperty(compose,'size',{get:function composeGetSize(){if(state.size===null){state.size=this.getContent().reduce(function(sum,content){if(typeof content==='string'){return sum+content.length;}else{return sum+content.size;}},0);}
|
||||
return state.size;}});Object.defineProperty(compose,'segmentInfo',{get:function composeGetSegmentInfo(){return state.segmentInfo;}});Object.defineProperty(compose,'isResizing',{get:function composeGetResizeState(){return state.resizing;}});Object.defineProperty(compose,'isSubjectVisible',{get:function composeIsSubjectVisible(){return subject.isVisible();}});return EventDispatcher.mixin(compose,['input','type','segmentinfochange','interact','subject-change']);}());
|
||||
|
|
@ -0,0 +1,582 @@
|
|||
/*global ContactRenderer,
|
||||
Contacts,
|
||||
ConversationView,
|
||||
MessageManager,
|
||||
MobileOperator,
|
||||
Navigation,
|
||||
Settings,
|
||||
Template,
|
||||
Threads,
|
||||
Utils
|
||||
*/
|
||||
|
||||
/*exported Information */
|
||||
|
||||
(function(exports) {
|
||||
'use strict';
|
||||
|
||||
const SECOND = 1000;
|
||||
const MINUTE = 60 * SECOND;
|
||||
const HOUR = 60 * MINUTE;
|
||||
const DAY = 24 * HOUR;
|
||||
const MONTH = 30 * DAY;
|
||||
const LATENESS_DISPLAY_LOWER_LIMIT = 5 * MINUTE;
|
||||
|
||||
/*
|
||||
Information view module is a subpanel belongs to TheadUI panel. This
|
||||
module provide some default method for thiw view module:
|
||||
|
||||
show: Reuse the conversation view for information view. Hiding unrelated icon,
|
||||
reset the header, and render container for showing the view.
|
||||
|
||||
reset: Hide the view container, clean up the contact list and resume the
|
||||
icons/header for ConversationView.
|
||||
|
||||
renderContactList(participants, options): Rendering group-view style contact
|
||||
list inside the page. Participants is an array of contact number and option
|
||||
is for setting additional information for rendering other lock for contact
|
||||
information.
|
||||
*/
|
||||
var TMPL = function createTemplate(tmpls) {
|
||||
for (var key in tmpls) {
|
||||
tmpls[key] = Template(tmpls[key]);
|
||||
}
|
||||
return tmpls;
|
||||
}({
|
||||
number: 'messages-number-tmpl',
|
||||
report: 'information-report-tmpl'
|
||||
});
|
||||
|
||||
/*
|
||||
Summarized single status based on delivery and read status for mms.
|
||||
The 1st level properties represents delivery status and 2nd level properties
|
||||
represents read status.
|
||||
*/
|
||||
const REPORT_MAP = {
|
||||
'not-applicable': {
|
||||
'not-applicable': 'not-applicable',
|
||||
'pending' : 'pending',
|
||||
'success' : 'read',
|
||||
'error' : 'error'
|
||||
},
|
||||
'pending' : {
|
||||
'not-applicable': 'pending',
|
||||
'pending': 'pending',
|
||||
'success' : 'read', // should not possible
|
||||
'error' : 'error'
|
||||
},
|
||||
'success' : {
|
||||
'not-applicable': 'delivered',
|
||||
'pending': 'delivered',
|
||||
'success' : 'read',
|
||||
'error' : 'error'
|
||||
},
|
||||
'error' : {
|
||||
'not-applicable': 'error',
|
||||
'pending': 'error',
|
||||
'success' : 'error', // should not possible
|
||||
'error' : 'error' // should not possible
|
||||
}
|
||||
};
|
||||
|
||||
// Register the message events we wanted for report view refresh
|
||||
const MESSAGE_EVENTS = [
|
||||
'message-failed-to-send',
|
||||
'message-delivered',
|
||||
'message-read',
|
||||
'message-sent',
|
||||
'message-sending'
|
||||
];
|
||||
|
||||
const reportDateTimeFormatOptions = {
|
||||
month: 'long',
|
||||
day: '2-digit',
|
||||
year: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric'
|
||||
};
|
||||
|
||||
function completeLocaleFormat(timestamp) {
|
||||
var options = Object.assign(
|
||||
{ hour12: navigator.mozHour12 },
|
||||
reportDateTimeFormatOptions);
|
||||
|
||||
return new Date(+timestamp).toLocaleString(navigator.languages, options);
|
||||
}
|
||||
|
||||
function l10nContainsDateSetup(element, timestamp) {
|
||||
element.dataset.l10nDate = timestamp;
|
||||
element.dataset.l10nDateFormat = JSON.stringify(reportDateTimeFormatOptions);
|
||||
element.textContent = completeLocaleFormat(timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate report Div contains delivery report and read report for showing
|
||||
* report information within contact list
|
||||
*/
|
||||
function createReportDiv(reports) {
|
||||
var reportDiv = document.createElement('div');
|
||||
reportDiv.className = 'network-status';
|
||||
var data = {
|
||||
titleL10n: '',
|
||||
reportDateL10n: '',
|
||||
messageL10nDateFormat: JSON.stringify(reportDateTimeFormatOptions),
|
||||
timestamp: ''
|
||||
};
|
||||
var status;
|
||||
var deliveryStatus = reports.deliveryStatus;
|
||||
var readStatus = reports.readStatus;
|
||||
|
||||
if (!readStatus) { // sms
|
||||
status = deliveryStatus === 'success' ?
|
||||
'delivered' :
|
||||
deliveryStatus;
|
||||
} else if (deliveryStatus === 'rejected') {
|
||||
// Status = 'rejected' when receiver is not allowed to download any mms
|
||||
status = 'rejected';
|
||||
} else if (deliveryStatus in REPORT_MAP) {
|
||||
status = REPORT_MAP[deliveryStatus][readStatus];
|
||||
} else {
|
||||
console.error('Invalid message report status: ' + deliveryStatus);
|
||||
return reportDiv;
|
||||
}
|
||||
reportDiv.dataset.deliveryStatus = status;
|
||||
|
||||
switch (status) {
|
||||
case 'not-applicable':
|
||||
return reportDiv;
|
||||
case 'delivered':
|
||||
data.timestamp = '' + reports.deliveryTimestamp;
|
||||
data.reportDateL10n = completeLocaleFormat(reports.deliveryTimestamp);
|
||||
break;
|
||||
case 'read':
|
||||
data.timestamp = '' + reports.readTimestamp;
|
||||
data.reportDateL10n = completeLocaleFormat(reports.readTimestamp);
|
||||
break;
|
||||
}
|
||||
data.titleL10n = 'report-status-' + status;
|
||||
reportDiv.innerHTML = TMPL.report.interpolate(data);
|
||||
|
||||
return reportDiv;
|
||||
}
|
||||
|
||||
function showSimInfo(element, iccId) {
|
||||
var iccManager = navigator.mozIccManager;
|
||||
// Hide the element when single SIM or no iccManager/mobileConnections
|
||||
if (!(Settings.hasSeveralSim() && iccId && iccManager)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var simInfoElement = element.querySelector('.sim-detail');
|
||||
var simId = Settings.getServiceIdByIccId(iccId);
|
||||
|
||||
if (simId === null) {
|
||||
document.l10n.setAttributes(
|
||||
simInfoElement,
|
||||
'dsds-unknown-sim'
|
||||
);
|
||||
} else {
|
||||
var operator = getOperatorByServiceId(simId);
|
||||
var icc = iccManager.getIccById(iccId);
|
||||
var number = icc && icc.iccInfo.msisdn;
|
||||
|
||||
var data = {};
|
||||
var l10nId;
|
||||
|
||||
var info = [operator, number].filter(function(value) {
|
||||
return value;
|
||||
});
|
||||
|
||||
var detailString = info.join(', ');
|
||||
l10nId = info.length ? 'sim-detail' : 'sim-id-label';
|
||||
data = { id: simId + 1, detailString: detailString };
|
||||
document.l10n.setAttributes(
|
||||
simInfoElement,
|
||||
l10nId,
|
||||
data
|
||||
);
|
||||
}
|
||||
|
||||
element.classList.remove('hide');
|
||||
}
|
||||
|
||||
/**
|
||||
* Incoming message: return array of sender number string;
|
||||
* Outgoing message: return array of object(number and report div block).
|
||||
*/
|
||||
function createListWithMsgInfo(message) {
|
||||
var list = [];
|
||||
if (message.delivery === 'received' ||
|
||||
message.delivery === 'not-downloaded') { // received message
|
||||
if (message.type === 'mms') {
|
||||
if (message.receivers) {
|
||||
list.push(...message.receivers);
|
||||
}
|
||||
if (!list.includes(message.sender)) {
|
||||
list.push(message.sender);
|
||||
}
|
||||
} else {
|
||||
list.push(message.sender);
|
||||
}
|
||||
} else if (message.type === 'mms') { // sent mms message
|
||||
message.deliveryInfo.forEach(function(info) {
|
||||
list.push({number: info.receiver,
|
||||
infoBlock: createReportDiv(info)});
|
||||
});
|
||||
} else { // sent sms message
|
||||
var info = {};
|
||||
info.deliveryStatus = message.deliveryStatus;
|
||||
info.deliveryTimestamp = message.deliveryTimestamp;
|
||||
list.push({number: message.receiver,
|
||||
infoBlock: createReportDiv(info)});
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will return operator name depending on the iccId.
|
||||
* Will return the empty string in a single SIM scenario.
|
||||
*/
|
||||
function getOperatorByServiceId(index) {
|
||||
var conn = navigator.mozMobileConnections[index];
|
||||
return MobileOperator.userFacingInfo(conn).operator;
|
||||
}
|
||||
|
||||
var VIEWS = {
|
||||
group: {
|
||||
name: 'group-view',
|
||||
selector: '.panel-GroupView',
|
||||
contactFlavor: 'group-view',
|
||||
|
||||
render: function renderGroup() {
|
||||
var participants = Threads.get(this.id).participants;
|
||||
this.renderContactList(participants);
|
||||
document.l10n.setAttributes(
|
||||
this.headerText, 'participant', { n:participants.length }
|
||||
);
|
||||
},
|
||||
|
||||
setEventListener: function setEventListener() {
|
||||
this.contactList.addEventListener('click', (event) => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
var target = event.target;
|
||||
|
||||
ConversationView.promptContact({
|
||||
number: target.dataset.number
|
||||
}).then(
|
||||
() => Navigation.toPanel('thread', { id: this.id })
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
elements: ['contact-list', 'header', 'header-text']
|
||||
},
|
||||
report: {
|
||||
name: 'report-view',
|
||||
selector: '.panel-ReportView',
|
||||
contactFlavor: 'report-view',
|
||||
|
||||
init: function() {
|
||||
this.onStatusChanged = this.onStatusChanged.bind(this);
|
||||
},
|
||||
|
||||
beforeEnter: function() {
|
||||
this.constructor.prototype.beforeEnter.apply(this, arguments);
|
||||
|
||||
MESSAGE_EVENTS.forEach((event) => {
|
||||
MessageManager.on(event, this.onStatusChanged);
|
||||
});
|
||||
},
|
||||
|
||||
afterLeave: function() {
|
||||
this.constructor.prototype.afterLeave.apply(this, arguments);
|
||||
|
||||
MESSAGE_EVENTS.forEach((event) => {
|
||||
MessageManager.off(event, this.onStatusChanged);
|
||||
});
|
||||
},
|
||||
|
||||
render: function renderReport() {
|
||||
var setL10nAttributes = document.l10n.setAttributes;
|
||||
var request = MessageManager.getMessage(this.id);
|
||||
|
||||
// Hide these dynamic fields to avoid incorrect info displayed at first
|
||||
this.subject.classList.add('hide');
|
||||
this.sizeBlock.classList.add('hide');
|
||||
|
||||
request.onsuccess = (function() {
|
||||
var message = request.result;
|
||||
var type = message.type;
|
||||
var delivery = message.delivery;
|
||||
|
||||
var isIncoming = delivery === 'received' ||
|
||||
delivery === 'not-downloaded';
|
||||
|
||||
// Fill in the description/status/size
|
||||
if (type === 'sms') {
|
||||
setL10nAttributes(this.type, 'message-type-sms');
|
||||
} else { //mms
|
||||
setL10nAttributes(this.type, 'message-type-mms');
|
||||
// subject text content
|
||||
var subject = message.subject;
|
||||
|
||||
this.subject.classList.toggle('hide', !subject);
|
||||
if (subject) {
|
||||
this.subject.querySelector('.detail').textContent = subject;
|
||||
}
|
||||
|
||||
// Message total size show/hide
|
||||
if (message.attachments && message.attachments.length > 0) {
|
||||
var size = message.attachments.reduce(function(size, attachment) {
|
||||
return (size += attachment.content.size);
|
||||
}, 0);
|
||||
var params = Utils.getSizeForL10n(size);
|
||||
setL10nAttributes(this.size, params.l10nId, params.l10nArgs);
|
||||
this.sizeBlock.classList.remove('hide');
|
||||
}
|
||||
}
|
||||
this.container.dataset.delivery = delivery;
|
||||
this.container.classList.toggle('incoming-message', isIncoming);
|
||||
this.container.classList.toggle('outgoing-message', !isIncoming);
|
||||
|
||||
// If incoming message is migrated from the database where sentTimestamp
|
||||
// hadn't been supported yet then we won't have valid value for it.
|
||||
this.container.classList.toggle(
|
||||
'no-valid-sent-timestamp',
|
||||
isIncoming && !message.sentTimestamp
|
||||
);
|
||||
|
||||
setL10nAttributes(
|
||||
this.contactTitle,
|
||||
isIncoming ? 'report-from-title' : 'report-to-title'
|
||||
);
|
||||
|
||||
if (isIncoming) {
|
||||
l10nContainsDateSetup(this.receivedTimestamp, message.timestamp);
|
||||
l10nContainsDateSetup(this.sentTimestamp, message.sentTimestamp);
|
||||
setL10nAttributes(this.sentTitle, 'message-sent');
|
||||
this.renderLateArrivalMsg(message);
|
||||
|
||||
} else {
|
||||
if (delivery === 'sending' || delivery === 'sent') {
|
||||
setL10nAttributes(this.sentTitle, 'message-' + delivery);
|
||||
}
|
||||
if (delivery === 'error' || delivery === 'sent') {
|
||||
l10nContainsDateSetup(this.sentTimestamp, message.timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
//show sim information for dual sim device
|
||||
showSimInfo(this.simInfo, message.iccId);
|
||||
|
||||
// Filled in the contact list. Only outgoing message contains detailed
|
||||
// report information.
|
||||
this.renderContactList(createListWithMsgInfo(message));
|
||||
}).bind(this);
|
||||
},
|
||||
|
||||
renderLateArrivalMsg: function report_renderLateArrivalMsg(message) {
|
||||
var latenessBlock = this.panel.querySelector('.lateness-block');
|
||||
var lateness = message.timestamp - message.sentTimestamp;
|
||||
var showLatenessNotice = message.timestamp &&
|
||||
message.sentTimestamp &&
|
||||
lateness >= LATENESS_DISPLAY_LOWER_LIMIT;
|
||||
|
||||
if (showLatenessNotice) {
|
||||
var units = [
|
||||
{ unit: 'month', unitVal: MONTH },
|
||||
{ unit: 'day', unitVal: DAY },
|
||||
{ unit: 'hour', unitVal: HOUR },
|
||||
{ unit: 'minute', unitVal: MINUTE },
|
||||
{ unit: 'second', unitVal: SECOND }
|
||||
];
|
||||
|
||||
units.forEach(({unit, unitVal}) => {
|
||||
var output;
|
||||
var unitElement = this.panel.querySelector(`.lateness-${unit}`);
|
||||
|
||||
if (lateness >= unitVal) {
|
||||
// Compute integer value for the current unit output
|
||||
// and get the rest for the next smaller unit
|
||||
output = Math.floor(lateness / unitVal);
|
||||
lateness = lateness % unitVal;
|
||||
|
||||
document.l10n.setAttributes(
|
||||
unitElement,
|
||||
`duration-${unit}-narrow`,
|
||||
{ value: output }
|
||||
);
|
||||
unitElement.classList.remove('hide');
|
||||
} else {
|
||||
unitElement.classList.add('hide');
|
||||
}
|
||||
});
|
||||
latenessBlock.classList.remove('hide');
|
||||
} else {
|
||||
latenessBlock.classList.add('hide');
|
||||
}
|
||||
},
|
||||
|
||||
// Set this flag to true only when resend is triggered.
|
||||
messageResending: false,
|
||||
|
||||
setEventListener: function report_setEventListener() {
|
||||
this.resendBtn.addEventListener('click', () => {
|
||||
this.messageResending = true;
|
||||
ConversationView.resendMessage(this.id);
|
||||
});
|
||||
},
|
||||
|
||||
isReportForMessage: function report_isReportForMessage(id) {
|
||||
return Navigation.isCurrentPanel('report-view', { id: id }) ||
|
||||
(Navigation.isCurrentPanel('report-view') &&
|
||||
this.id === id);
|
||||
},
|
||||
|
||||
onStatusChanged: function report_onStatusChanged(e) {
|
||||
// If we got sending status change in report view after resend clicked
|
||||
// (messageResending is true), we should change report panel id, reset
|
||||
// messageResending flag and refresh for new message report.
|
||||
if (e.message.delivery === 'sending' && this.messageResending) {
|
||||
this.id = e.message.id;
|
||||
this.messageResending = false;
|
||||
}
|
||||
|
||||
this.isReportForMessage(e.message.id) && this.refresh();
|
||||
},
|
||||
|
||||
elements: ['contact-list', 'size', 'size-block', 'type', 'sent-title',
|
||||
'sent-timestamp', 'received-timestamp', 'subject', 'sim-info',
|
||||
'contact-title', 'resend-btn', 'header', 'container'
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
var Information = function(type) {
|
||||
Object.assign(this, VIEWS[type]);
|
||||
|
||||
if (this.init) {
|
||||
this.init();
|
||||
}
|
||||
|
||||
this.panel = document.querySelector(this.selector);
|
||||
|
||||
this.elements.forEach(function(name) {
|
||||
this[Utils.camelCase(name)] = this.panel.querySelector('.' + name);
|
||||
}, this);
|
||||
|
||||
this.header.addEventListener(
|
||||
'action', this.backOrClose.bind(this)
|
||||
);
|
||||
|
||||
this.setEventListener && this.setEventListener();
|
||||
this.reset();
|
||||
};
|
||||
|
||||
Information.prototype = {
|
||||
constructor: Information,
|
||||
|
||||
beforeEnter: function(args) {
|
||||
this.id = +args.id;
|
||||
this.header.removeAttribute('no-font-fit');
|
||||
this.show();
|
||||
},
|
||||
|
||||
afterLeave: function() {
|
||||
this.reset();
|
||||
this.id = null;
|
||||
},
|
||||
|
||||
show: function() {
|
||||
this.render();
|
||||
},
|
||||
|
||||
refresh: function() {
|
||||
if (Navigation.isCurrentPanel(this.name)) {
|
||||
this.render();
|
||||
}
|
||||
},
|
||||
|
||||
reset: function() {
|
||||
// Remove all LIs
|
||||
if (this.contactList) {
|
||||
this.contactList.textContent = '';
|
||||
}
|
||||
},
|
||||
|
||||
backOrClose: function() {
|
||||
Navigation.back();
|
||||
},
|
||||
|
||||
// Incrementing ID for each rendering request to avoid possible race when next
|
||||
// renderContactList request earlier than list item appended to contact list
|
||||
// ul. Ignoring the rendering/appending request if the rendering ID doesn't
|
||||
// match the latest rendering ID.
|
||||
renderingId: 0,
|
||||
|
||||
// Param participants could be:
|
||||
// - Array of contact number string or
|
||||
// - Array of object({ number: number, infoBlock: infoBlock })
|
||||
// for rendering the contact list.
|
||||
renderContactList: function(participants) {
|
||||
var ul = this.contactList;
|
||||
var renderer = ContactRenderer.flavor(this.contactFlavor);
|
||||
var currentRenderingId = ++this.renderingId;
|
||||
|
||||
ul.textContent = '';
|
||||
participants.forEach((participant) => {
|
||||
var number, infoBlock, selector;
|
||||
|
||||
if (typeof participant === 'object') {
|
||||
number = participant.number;
|
||||
infoBlock = participant.infoBlock;
|
||||
selector = '.js-contact-info';
|
||||
} else {
|
||||
number = participant;
|
||||
}
|
||||
Contacts.findByAddress(number).then((contacts) => {
|
||||
// If the current rendering ID doesn't match the latest ID, skip current
|
||||
// one and only render for ID which matches latest request ID.
|
||||
if (currentRenderingId !== this.renderingId) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (contacts.length > 0) {
|
||||
renderer.render({
|
||||
contact: contacts[0],
|
||||
input: number,
|
||||
infoBlock: infoBlock,
|
||||
infoBlockParentSelector: selector,
|
||||
target: ul
|
||||
});
|
||||
} else {
|
||||
var li = document.createElement('li');
|
||||
li.role = 'presentation';
|
||||
li.innerHTML = TMPL.number.interpolate({
|
||||
number: number
|
||||
});
|
||||
|
||||
var parentBlock = li.querySelector(selector);
|
||||
if (parentBlock && infoBlock) {
|
||||
parentBlock.appendChild(infoBlock);
|
||||
}
|
||||
ul.appendChild(li);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Information.initDefaultViews = function() {
|
||||
// Create group / report information view
|
||||
exports.GroupView = new Information('group');
|
||||
exports.ReportView = new Information('report');
|
||||
};
|
||||
|
||||
exports.Information = Information;
|
||||
|
||||
// end global closure
|
||||
}(this));
|
||||
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*global ActivityPicker, ConversationView */
|
||||
|
||||
(function(exports) {
|
||||
'use strict';
|
||||
/*
|
||||
Centralized event handling for various
|
||||
data-actions url, email, phone in a message
|
||||
*/
|
||||
|
||||
var LinkActionHandler = {
|
||||
onClick: function lah_onClick(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
var dataset = event.target.dataset;
|
||||
var action = dataset.action;
|
||||
|
||||
if (!action) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (action === 'email-link') {
|
||||
ConversationView.prompt({
|
||||
email: dataset.email,
|
||||
inMessage: true
|
||||
});
|
||||
}
|
||||
|
||||
if (action === 'dial-link') {
|
||||
ConversationView.promptContact({
|
||||
number: dataset.dial,
|
||||
inMessage: true
|
||||
});
|
||||
}
|
||||
|
||||
if (action === 'url-link') {
|
||||
|
||||
var type = action.replace('-link', '');
|
||||
|
||||
ActivityPicker[type](
|
||||
dataset[type], this.reset, this.reset
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
exports.LinkActionHandler = LinkActionHandler;
|
||||
}(this));
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
;(function(){'use strict';var KNOWN_TLDS=['aero','asia','biz','cat','com','coop','info','int','jobs','mobi','museum','name','net','org','post','pro','tel','travel','xxx','edu','gov','mil','nyc','ac','ad','ae','af','ag','ai','al','am','an','ao','aq','ar','as','at','au','aw','ax','az','ba','bb','bd','be','bf','bg','bh','bi','bj','bm','bn','bo','br','bs','bt','bv','no','bw','by','bz','ca','cc','cd','cf','cg','ch','ci','ck','cl','cm','cn','co','cr','cs','cu','cv','cx','cy','cz','dd','de','dj','dk','dm','do','dz','ec','ee','eg','eh','er','es','et','eu','fi','fj','fk','fm','fo','fr','ga','gb','gd','ge','gf','gg','gh','gi','gl','gm','gn','gp','gq','gr','gs','gt','gu','gw','gy','hk','hm','hn','hr','ht','hu','id','ie','il','im','in','io','iq','ir','is','it','je','jm','jo','jp','ke','kg','kh','ki','km','kn','kp','kr','kw','ky','kz','la','lb','lc','li','lk','lr','ls','lt','lu','lv','ly','ma','mc','md','me','mg','mh','mk','ml','mm','mn','mn','mo','mp','mq','mr','ms','mt','mu','mv','mw','mx','my','mz','na','nc','ne','nf','ng','ni','nl','no','np','nr','nu','nz','om','pa','pe','pf','pg','ph','pk','pl','pm','pn','pr','ps','pt','pw','py','qa','re','ro','rs','ru','su','рф','rw','sa','sb','sc','sd','se','sg','sh','si','sj','no','sk','sl','sm','sn','so','sr','ss','st','su','sv','sx','sy','sz','tc','td','tf','tg','th','tj','tk','tl','tp','tm','tn','to','tp','tl','tr','tt','tv','tw','tz','ua','ug','uk','us','gov','uy','uz','va','vc','ve','vg','vi','vn','vu','wf','ws','ye','yt','yu','za','zm','zw'];var ipv4part='(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)';var ipv4RegExp=new RegExp('^(?:'+ipv4part+'\\.){3}'+ipv4part+'$');var leadingDigitsRegExp=/^[+0-9]+/;function checkDomain(domain){if(ipv4RegExp.test(domain)){return true;}else{var parts=domain.split('.');var lastPart=parts[parts.length-1];return lastPart.length>1&&!isFinite(lastPart);}}
|
||||
var safeStart=/[\s.,:;\(>\u0080-\uFFFF]/;const MINIMUM_DIGITS_IN_PHONE_NUMBER=5;const LEADING_DIGIT_BREAKPOINT=7;var LINK_TYPES={phone:{regexp:new RegExp(['(?:\\+\\d{1,4}[ \\t.()-]{0,3}|\\()?'+'(?:\\d{1,4}[ \\t.()-]{0,3})?'+'(?:\\d[\\d \\t.()-]{0,12}\\d)'+'\\b'].join(''),'g'),matchFilter:function phoneMatchFilter(phone,link){var onlyDigits=Utils.removeNonDialables(phone);if(onlyDigits.length<MINIMUM_DIGITS_IN_PHONE_NUMBER){return false;}
|
||||
if(onlyDigits.length===MINIMUM_DIGITS_IN_PHONE_NUMBER&&phone.length!==onlyDigits.length){return false;}
|
||||
var leadingDigits=leadingDigitsRegExp.exec(phone);if(leadingDigits&&leadingDigits[0].length>=LEADING_DIGIT_BREAKPOINT){link.end=link.start+leadingDigits[0].length;}
|
||||
return link;},transform:function phoneTransform(phone,link){return'<a dir="ltr" data-dial="'+phone+'" data-action="dial-link">'+phone+'</a>';}},url:{regexp:new RegExp(['(https?://|rtsp://)?','(\\w(?:\\.?[-\\w]){0,255})','(\\.\\w{1,10})','(?::[0-9]{1,5})?','(?:\\.?/','(?:[^\\s.,?:;!]|[.,?:;!](?!\\s|$)){0,2048}',')?'].join(''),'mgi'),matchFilter:function urlMatchFilter(url,linkSpec){var match=linkSpec.match;var scheme,tld;if(!checkDomain(match[2]+match[3])){return false;}
|
||||
scheme=match[1];tld=match[3]&&match[3].slice(1);if(!scheme&&(!isFinite(tld)&&KNOWN_TLDS.indexOf(tld)===-1)){return false;}
|
||||
if(url.slice(-1)===')'&&url.indexOf('(')===-1){linkSpec.end--;}
|
||||
return linkSpec;},transform:function urlTransform(url,linkSpec){var href=url;if(!linkSpec.match[1]){href='http://'+href;}
|
||||
return'<a data-url="'+href+'" data-action="url-link" >'+url+'</a>';}},email:{regexp:/[\w.+-]+@[\w.-]+\.[a-z.]{2,6}/mgi,transform:function emailTransform(email){return['<a data-email="','" data-action="email-link">','</a>'].join(email);}}};var LINK_TYPES_KEYS=Object.keys(LINK_TYPES);function searchForLinks(type,string){var linkSpecs=[];var spec=LINK_TYPES[type];if(!spec){return linkSpecs;}
|
||||
var regexp=spec.regexp;var matchFilter=spec.matchFilter;var match,linkSpec;while((match=regexp.exec(string))){var rest=string.slice(match.index-1);if(match.index&&!safeStart.test(rest.charAt(0))){var nextSafe=safeStart.exec(rest);if(nextSafe){regexp.lastIndex=match.index+nextSafe.index;}
|
||||
continue;}
|
||||
linkSpec={type:type,start:match.index,length:match[0].length,end:match.index+match[0].length,match:match};if(matchFilter){linkSpec=matchFilter(match[0],linkSpec);}
|
||||
if(linkSpec){linkSpecs.push(linkSpec);regexp.lastIndex=linkSpec.end;}}
|
||||
return linkSpecs;}
|
||||
function linkSort(a,b){return(a.start-b.start)||(b.end-a.end)||(LINK_TYPES_KEYS.indexOf(a.type)-LINK_TYPES_KEYS.indexOf(b.type));}
|
||||
function removeOverlapping(linkSpecs){linkSpecs.sort(linkSort);for(var index=0;index<linkSpecs.length-1;index++){var end=linkSpecs[index].end;while(linkSpecs[index+1]&&linkSpecs[index+1].start<end){linkSpecs.splice(index+1,1);}}}
|
||||
var LinkHelper=window.LinkHelper={searchAndLinkUrl:function lh_searchAndLinkUrl(inputText){return LinkHelper.searchAndLinkClickableData(inputText,{url:true});},searchAndLinkEmail:function lh_searchAndLinkEmail(inputText){return LinkHelper.searchAndLinkClickableData(inputText,{email:true});},searchAndLinkPhone:function lh_searchAndLinkPhone(inputText){return LinkHelper.searchAndLinkClickableData(inputText,{phone:true});},searchAndLinkClickableData:function lh_searchAndLinkClickableData(inputText,mode){mode=mode||LINK_TYPES;var linkSpecs=[];var type;for(type in mode){if(mode[type]&&LINK_TYPES[type]){linkSpecs=linkSpecs.concat(searchForLinks(type,inputText));}}
|
||||
removeOverlapping(linkSpecs);var result='';var lastEnd=0;linkSpecs.forEach(function replaceLink(link){result+=inputText.slice(lastEnd,link.start);var replacing=inputText.slice(link.start,link.end);var replaceWith=LINK_TYPES[link.type].transform(replacing,link);result+=replaceWith;lastEnd=link.end;});result+=inputText.slice(lastEnd);return result;}};})();
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
;(function(exports){'use strict';var view=new WeakMap();var priv=new WeakMap();var data=new WeakMap();var events=new WeakMap();var relation=new WeakMap();var rdigit=/^\d/;function Recipient(opts){var number;opts=opts||{};this.name=String(opts.name||opts.number||'');this.number=(opts.number||'')+'';this.email=opts.email||'';this.editable=opts.editable||'true';this.role=this.editable?'textbox':'button';this.source=opts.source||'manual';this.type=opts.type||'';this.carrier=opts.carrier||'';this.className='recipient';this.isEmail=Settings.supportEmailRecipient&&Utils.isEmailAddress(this.number);this.isLookupable=opts.isLookupable||false;this.isInvalid=opts.isInvalid||false;this.isQuestionable=opts.isQuestionable||false;number=this.number[0]==='+'?this.number.slice(1):this.number;if(this.isEmail){this.className+=' email';}else if(this.source==='manual'&&!rdigit.test(number)){this.isQuestionable=true;}
|
||||
if(this.isQuestionable||this.isInvalid){this.className+=' invalid';}}
|
||||
Recipient.prototype.set=function(dict){var length=Recipient.FIELDS.length;var key;for(var i=0;i<length;i++){key=Recipient.FIELDS[i];this[key]=dict[key];}
|
||||
return this;};Recipient.prototype.clone=function(){return new Recipient(this);};Recipient.FIELDS=['name','number','email','editable','source','type','carrier','isQuestionable','isInvalid','isLookupable'];function Recipients(setup){if(!setup){throw new Error('`setup` missing');}
|
||||
if(!setup.template){throw new Error('`setup.template` missing');}
|
||||
if(!setup.outer){throw new Error('`setup.outer` missing');}
|
||||
if(!setup.inner){throw new Error('`setup.inner` missing');}
|
||||
var list=[];Object.defineProperties(this,{length:{get:function(){return list.length;},set:function(value){var oldLength=list.length;list.length=value;if(value<oldLength){this.render();}
|
||||
return value;}},list:{get:function(){return list.slice();}},numbers:{get:function(){return list.reduce(function(unique,recipient){var value=recipient.number||recipient.email;if(!recipient.isInvalid&&unique.indexOf(value)===-1){unique.push(value);}
|
||||
return unique;},[]);}},inputValue:{get:function(){var node=document.getElementById(setup.inner).lastElementChild;return(node&&node.isPlaceholder)?node.textContent.trim():'';}}});data.set(this,list);events.set(this,{add:[],remove:[],modechange:[]});view.set(this,new Recipients.View(this,setup));}
|
||||
Recipients.prototype.on=function(type,handler){var handlers=events.get(this);if(!handlers[type]){throw new Error('Invalid event type: '+type);}
|
||||
handlers[type].push(handler);return this;};Recipients.prototype.off=function(type,handler){var handlers=events.get(this);if(!handlers[type]){throw new Error('Invalid event type: '+type);}
|
||||
if(!handler){handlers[type].length=0;}else{handlers[type].splice(handlers[type].indexOf(handler),1);}
|
||||
return this;};Recipients.prototype.emit=function(type){var handlers=events.get(this);var args=[].slice.call(arguments,1);var handler,stack;if(!handlers[type]){throw new Error('Invalid event type: '+type);}
|
||||
stack=handlers[type].slice();if(stack.length){while((handler=stack.pop())){handler.apply(null,args);}}
|
||||
return this;};Recipients.prototype.add=function(entry){var list=data.get(this);var added;if(entry.number===undefined){throw new Error('recipient entry missing number');}
|
||||
entry.editable=entry.editable||'false';['name','number','email'].forEach(function(field){if(entry[field]){entry[field]=(entry[field]+'').trim();}});list.push(added=new Recipient(entry));this.emit('add',list.length,added.clone());this.render();return this;};Recipients.prototype.update=function(recipOrIndex,entry){var list=data.get(this);var index=typeof recipOrIndex==='number'?recipOrIndex:list.indexOf(recipOrIndex);if(index>-1){list[index].set(new Recipient(entry));}
|
||||
return this.render();};Recipients.prototype.remove=function(recipOrIndex){var list=data.get(this);var index=typeof recipOrIndex==='number'?recipOrIndex:list.indexOf(recipOrIndex);if(index===-1){return this;}
|
||||
list.splice(index,1);this.emit('remove',list.length);return this.render(index);};Recipients.prototype.render=function(){view.get(this).reset();return this;};Recipients.prototype.focus=function(){view.get(this).focus();return this;};Recipients.prototype.visible=function(type,opts){view.get(this).visible(type,opts||{});return this;};Recipients.View=function(owner,setup){var inner=document.getElementById(setup.inner);var outer=document.getElementById(setup.outer);var template=setup.template;var nodes=[];var clone;var outerCss=window.getComputedStyle(outer);priv.set(this,{owner:owner,inner:inner,outer:outer,template:template,active:null,nodes:nodes,state:{isTransitioning:false,visible:'singleline'},minHeight:parseInt(outerCss.getPropertyValue('min-height'),10),mode:'singleline-mode'});clone=inner.cloneNode(true);clone.innerHTML=template.interpolate(new Recipient());clone.firstElementChild.innerHTML='';Object.defineProperties(this,{last:{get:function(){return nodes[nodes.length-1];}},placeholder:{get:function(){var node=clone.firstElementChild.cloneNode(true);node.isPlaceholder=true;return node;}}});this.updateMode=Utils.debounce(this.updateMode,100);['click','keypress','keyup','blur','pan'].forEach(function(type){outer.addEventListener(type,this,false);},this);new GestureDetector(outer).startDetecting();this.reset();};Recipients.View.isFocusable=true;Recipients.View.prototype.reset=function(){this.clear().render();return this;};Recipients.View.prototype.clear=function(){priv.get(this).inner.textContent='';return this;};Recipients.View.prototype.render=function(opts){var view=priv.get(this);var nodes=view.nodes;var inner=view.inner;var template=view.template;var list=view.owner.list;var length=list.length;var html='';opts=opts||{};opts.addPlaceholder=opts.addPlaceholder===undefined?true:opts.addPlaceholder;if(inner.textContent){this.clear();}
|
||||
for(var i=0;i<length;i++){html+=template.interpolate(list[i]);}
|
||||
if(opts.editable){opts.addPlaceholder=false;html+=template.interpolate(opts.editable);}
|
||||
if(html){inner.innerHTML=html;}
|
||||
if(opts.addPlaceholder){inner.appendChild(this.placeholder);}
|
||||
nodes.length=0;if(!list.length){nodes.push.apply(nodes,inner.children[0]);}else{nodes.push.apply(nodes,inner.children);}
|
||||
nodes.forEach(function forEachNode(node,i){node.isPlaceholder=false;node.contentEditable=false;node.setAttribute('role','button');if(i===nodes.length-1){node.isPlaceholder=true;node.contentEditable=true;node.setAttribute('role','textbox');}else{relation.set(node,list[i]);}});if(view.state.visible==='singleline'&&nodes.length){inner.querySelector(':last-child').scrollIntoView(false);}
|
||||
this.updateMode();return this;};Recipients.View.prototype.focus=function(node){var view=priv.get(this);var range=document.createRange();var selection=window.getSelection();if(Recipients.View.isFocusable){if(!node){node=view.inner.lastElementChild;if(!node.isPlaceholder){node=view.inner.appendChild(this.placeholder);}}
|
||||
if(node&&node.isPlaceholder){node.contentEditable=true;node.focus();}
|
||||
range.selectNodeContents(node);range.collapse(false);selection.removeAllRanges();selection.addRange(range);view.inner.scrollTop=view.inner.scrollHeight;}
|
||||
this.updateMode();return this;};Recipients.View.prototype.updateMode=function(){var view=priv.get(this);var mode=view.inner.scrollHeight>view.minHeight?'multiline-mode':'singleline-mode';if(view.mode!==mode){view.mode=mode;if(mode==='singleline-mode'&&view.state.visible==='multiline'){this.visible('singleline',{refocus:this});}
|
||||
view.owner.emit('modechange',mode);}};var rtype=/^(multi|single)line$/;Recipients.View.prototype.visible=function(type,opts){var view=priv.get(this);var state=view.state;var error='visible "type" (multiline or singleline)';opts=opts||{};if(!type){throw new Error('Missing '+error);}
|
||||
if(!rtype.test(type)){throw new Error('Invalid '+error);}
|
||||
if(state.visible!==type){state.isTransitioning=false;}
|
||||
if(state.isTransitioning){return this;}
|
||||
if(state.visible===type){return this;}
|
||||
view.outer.addEventListener('transitionend',function te(){this.removeEventListener('transitionend',te);var last=view.inner.lastElementChild;var previous;if(Navigation.isCurrentPanel('composer')&&state.visible==='singleline'){while(last!==null&&last.isPlaceholder){previous=last.previousElementSibling;if(!last.textContent){last.parentNode.removeChild(last);}
|
||||
last=previous;}
|
||||
if(opts.refocus){opts.refocus.focus();}}else if(state.visible==='multiline'&&last!==null){last.scrollIntoView(true);}
|
||||
state.isTransitioning=false;});state.visible=type;state.isTransitioning=true;view.outer.className=type;view.inner.className=type;return this;};Recipients.View.prototype.handleEvent=function(event){var view=priv.get(this);var owner=view.owner;var isPreventingDefault=false;var isAcceptedRecipient=false;var isEdittingRecipient=false;var isDeletingRecipient=false;var isLookupable=false;var target=event.target;var keyCode=event.keyCode;var editable='false';var lastElement=view.inner.lastElementChild;var typed,recipient,length,previous;Recipients.View.isFocusable=true;if(event.type==='keypress'||event.type==='keyup'){typed=target.textContent.trim();length=typed.length;}
|
||||
switch(event.type){case'pan':if(view.state.visible==='singleline'&&view.inner.scrollHeight>view.minHeight){if(event.detail.absolute.dy>0){this.visible('multiline');}
|
||||
event.preventDefault();event.stopPropagation();return;}
|
||||
break;case'click':if(target.parentNode===view.inner){if(target.isPlaceholder){return;}
|
||||
typed=lastElement&&lastElement.isPlaceholder?lastElement.textContent.trim():'';if(typed){owner.add({name:typed,number:typed,source:'manual'}).focus();}
|
||||
recipient=relation.get(target);if(recipient){if(recipient.source==='contacts'){Recipients.View.prompts.remove(recipient,function(isConfirmed){if(isConfirmed){owner.remove(relation.get(target));this.reset();}
|
||||
Recipients.View.isFocusable=true;this.focus();}.bind(this));}else{isEdittingRecipient=true;typed=recipient.number||recipient.name;editable='true';owner.remove(recipient);target=view.inner.lastElementChild;target.textContent=typed;this.visible('singleline',{refocus:target});}}}else{if(view.state.visible!=='singleline'){this.visible('singleline',{refocus:this});}else{this.focus();}
|
||||
return;}
|
||||
break;case'keyup':if(typed&&(typed[length-1]===';'||typed[length-1]===',')){isAcceptedRecipient=true;isPreventingDefault=true;typed=typed.replace(/[;,]$/,'');target.textContent=typed;}
|
||||
if(!isAcceptedRecipient&&(typed&&typed.length>=1)){this.visible('singleline',{refocus:target});}
|
||||
if(!typed&&keyCode===event.DOM_VK_BACK_SPACE){isPreventingDefault=true;isDeletingRecipient=true;}
|
||||
this.updateMode();break;case'keypress':if(keyCode===event.DOM_VK_BACK_SPACE){previous=target.previousSibling;if(!typed&&previous){recipient=relation.get(previous);if(previous.dataset.source==='contacts'){isPreventingDefault=true;isDeletingRecipient=true;view.owner.remove(recipient);}else if(previous.dataset.source==='manual'){isEdittingRecipient=true;isPreventingDefault=true;target=previous;view.inner.removeChild(view.inner.lastElementChild);data.get(view.owner).pop();view.owner.emit('remove',data.get(view.owner).length);}}}
|
||||
if((keyCode===13||keyCode===event.DOM_VK_ENTER)||(keyCode===event.DOM_VK_TAB)){if(typed){isPreventingDefault=true;if(target.parentNode===view.inner){if(keyCode!==event.DOM_VK_TAB){isAcceptedRecipient=true;isLookupable=true;target.textContent=typed;}}}}
|
||||
break;}
|
||||
if(isAcceptedRecipient){if(typed){view.owner.add({name:typed,number:typed,editable:editable,source:'manual',role:editable?'textbox':'button',isLookupable:isLookupable});this.render().focus();}}
|
||||
if(isDeletingRecipient){this.render().focus();}
|
||||
if(isEdittingRecipient){target.contentEditable=true;target.setAttribute('role','textbox');target.isPlaceholder=true;this.focus(target);}
|
||||
if(isPreventingDefault){event.preventDefault();}};Recipients.View.prompts={remove:function(recipient,callback){callback=typeof callback==='function'?callback:()=>{};var bodyTemplate=SharedComponents.phoneDetails({number:recipient.number,type:recipient.type,carrier:recipient.carrier});var title=document.createElement('bdi');title.textContent=recipient.name||recipient.number;Utils.confirm({raw:bodyTemplate.toDocumentFragment()},{raw:title},{text:'remove',className:'danger'}).then(()=>callback(true),()=>callback(false));Recipients.View.isFocusable=false;}};exports.Recipients=Recipients;}(this));
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
;(function(exports){'use strict';const LAZY_DEPENDENCIES=['/services/js/messaging/messaging_client.js','/services/js/moz_mobile_connections/moz_mobile_connections_client.js','/shared/js/settings_listener.js','/shared/js/mime_mapper.js','/shared/js/option_menu.js','/shared/js/mobile_operator.js','/shared/elements/gaia_sim_picker/script.js','/views/shared/js/waiting_screen.js','/views/shared/js/errors.js','/views/shared/js/dialog.js','/views/shared/js/error_dialog.js','/views/conversation/js/link_action_handler.js','/views/shared/js/contact_renderer.js','/views/shared/js/activity_picker.js','/views/conversation/js/information.js','/views/shared/js/localization_helper.js'];function initLazyDependencies(){return LazyLoader.load(LAZY_DEPENDENCIES).then(()=>{LocalizationHelper.init();TimeHeaders.init();Information.initDefaultViews();Settings.init();MessagingClient.init(App.instanceId);MozMobileConnectionsClient.init(App.instanceId);Navigation.setReady();InterInstanceEventDispatcher.connect();});}
|
||||
function initShims(){exports.InboxView=Object.freeze({markReadUnread:()=>{},updateThread:()=>{}});var deferred=Utils.Promise.defer();MessageManager.getThreads({each:(thread)=>Threads.set(thread.id,thread),done:deferred.resolve});return deferred.promise;}
|
||||
exports.Startup={init(){Utils.initializeShimHost(App.instanceId);MessageManager.init();ConversationView.init();if(Navigation.isDefaultPanel()){ConversationView.once('visually-loaded',initLazyDependencies);}else{initLazyDependencies();}
|
||||
initShims().then(()=>Navigation.init());}};})(window);
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
;(function(exports){'use strict';const MAX_LENGTH=40;const privateMembers=new WeakMap();function onKeyDown(e){var priv=privateMembers.get(this);if(e.keyCode===e.DOM_VK_BACK_SPACE){if(!priv.isHoldingBackspace){priv.isEmptyOnBackspace=!this.getValue();priv.isHoldingBackspace=true;}}else{priv.isHoldingBackspace=false;if(this.getValue().length>=MAX_LENGTH||e.keyCode===e.DOM_VK_RETURN){e.preventDefault();e.stopPropagation();}}}
|
||||
function onKeyUp(e){var priv=privateMembers.get(this);if(e.keyCode===e.DOM_VK_BACK_SPACE&&priv.isHoldingBackspace&&priv.isEmptyOnBackspace){this.hide();}
|
||||
priv.isEmptyOnBackspace=false;priv.isHoldingBackspace=false;}
|
||||
function onInput(e){privateMembers.get(this).updateValue(e.target.textContent);}
|
||||
function updatePlaceholder(){var priv=privateMembers.get(this);if(priv.value){priv.placeholder.remove();}else{priv.node.appendChild(priv.placeholder);}}
|
||||
function updateValue(newValue){var priv=privateMembers.get(this);if(newValue){newValue=newValue.replace(/\n\s*|\u00A0/g,' ');}
|
||||
if(priv.value!==newValue){priv.value=newValue;priv.updatePlaceholder();this.emit('change');}
|
||||
return newValue;}
|
||||
var SubjectComposer=function(node){EventDispatcher.mixin(this,['focus','change','visibility-change']);if(!node){throw new Error('Subject node is required');}
|
||||
var priv={isHoldingBackspace:false,isEmptyOnBackspace:false,isVisible:false,value:'',node:node,input:null,placeholder:null,updateValue:updateValue.bind(this),updatePlaceholder:updatePlaceholder.bind(this),};privateMembers.set(this,priv);priv.input=priv.node.querySelector('.subject-composer-input');priv.placeholder=priv.node.querySelector('.subject-composer-placeholder');priv.input.addEventListener('keydown',onKeyDown.bind(this));priv.input.addEventListener('keyup',onKeyUp.bind(this));priv.input.addEventListener('input',onInput.bind(this));priv.input.addEventListener('focus',this.emit.bind(this,'focus'));};SubjectComposer.prototype.show=function ms_show(){this.toggle(true);};SubjectComposer.prototype.hide=function ms_hide(){this.toggle(false);};SubjectComposer.prototype.toggle=function ms_toggle(toggle){var priv=privateMembers.get(this);priv.node.classList.toggle('hide',!toggle);priv.isVisible=toggle;this.emit('visibility-change');};SubjectComposer.prototype.isVisible=function ms_is_visible(){return privateMembers.get(this).isVisible;};SubjectComposer.prototype.focus=function ms_focus(){privateMembers.get(this).input.focus();};SubjectComposer.prototype.getMaxLength=function ms_get_maxLength(){return MAX_LENGTH;};SubjectComposer.prototype.getValue=function ms_get_value(){return privateMembers.get(this).value;};SubjectComposer.prototype.setValue=function ms_set_value(value){var priv=privateMembers.get(this);if(typeof value!=='string'){throw new Error('Value should be a valid string!');}
|
||||
priv.input.textContent=priv.updateValue(value);};SubjectComposer.prototype.reset=function ms_reset(){var priv=privateMembers.get(this);priv.value=priv.input.textContent='';priv.node.classList.add('hide');priv.isVisible=false;priv.updatePlaceholder();};exports.SubjectComposer=SubjectComposer;})(window);
|
||||
|
|
@ -0,0 +1,214 @@
|
|||
/**
|
||||
* Attachment containers are either:
|
||||
* - <div> elements, in the message thread;
|
||||
* - <iframe> elements, in the Compose area (draft attachments).
|
||||
* Both containers have an `attachment-container' class, but only <iframe>
|
||||
* containers have an `attachment-draft' class.
|
||||
*/
|
||||
.attachment-container {
|
||||
position: relative;
|
||||
margin-bottom: 0.5rem;
|
||||
|
||||
display: block;
|
||||
border: none;
|
||||
height: 10rem;
|
||||
width: 10rem;
|
||||
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
.attachment-draft {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
/* make sure all pointer events are sent to the main container */
|
||||
.attachment-draft *,
|
||||
.attachment-container * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.attachment-container.nopreview { /* 100x100 px placeholder + filename below */
|
||||
height: 12.7rem; /* font-size = 1.7rem + 1rem margin */
|
||||
}
|
||||
|
||||
/* Internal height of the iframe that contains the attachment draft */
|
||||
.attachment-container.nopreview[data-attachment-type="vcard"] {
|
||||
/* 40x40 px placeholder + filename below */
|
||||
height: 6.7rem; /* font-size = 1.7rem + 1rem margin */
|
||||
}
|
||||
|
||||
/* The internal height of the attachment itself */
|
||||
.attachment[data-attachment-type="vcard"] {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Allow to display the filename properly */
|
||||
#messages-input > [data-attachment-type="vcard"] {
|
||||
width: 20rem;
|
||||
}
|
||||
|
||||
.article-list[data-type="list"] .message .attachment-container {
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attachments that occur at the bounds of an MMS message do not need
|
||||
* additional spacing.
|
||||
*/
|
||||
#messages-container[data-type="list"] .message .attachment-container:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
#messages-container[data-type="list"] .message .attachment-container:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.attachment {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
offset-inline-start: 0;
|
||||
|
||||
width: 10rem;
|
||||
height: 10rem;
|
||||
}
|
||||
|
||||
.outgoing .attachment {
|
||||
offset-inline-start: auto;
|
||||
offset-inline-end: 0;
|
||||
}
|
||||
|
||||
.preview .attachment {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
background-color: #ececec;
|
||||
border: 2px solid #fff;
|
||||
}
|
||||
|
||||
.preview .attachment:active,
|
||||
.preview .attachment:hover {
|
||||
background-color: #b2f2ff;
|
||||
}
|
||||
|
||||
.size-indicator {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
|
||||
padding: 0 0.4rem;
|
||||
display: none;
|
||||
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
color: #333;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.attachment-draft > :not([data-attachment-type="vcard"]) .size-indicator {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.file-name {
|
||||
position: absolute;
|
||||
bottom: 0.5rem;
|
||||
|
||||
height: 2rem;
|
||||
display: none;
|
||||
|
||||
line-height: 2rem;
|
||||
font-size: 1.6rem;
|
||||
font-style: italic;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
/* .file-name has a dir="auto". Moreover, sms.css in not included in attachment
|
||||
* iframe, so we cannot leverage the general alignment rules. */
|
||||
html[dir="ltr"] .file-name {
|
||||
text-align: left;
|
||||
left: 1px; /* Avoid issues related to being too much on the left */
|
||||
right: 0;
|
||||
}
|
||||
html[dir="rtl"] .file-name {
|
||||
text-align: right;
|
||||
left: 0;
|
||||
right: 1px;
|
||||
}
|
||||
|
||||
.attachment-draft .file-name {
|
||||
color: #4a4a4a;
|
||||
}
|
||||
|
||||
.nopreview .file-name {
|
||||
display: block;
|
||||
|
||||
unicode-bidi: -moz-plaintext;
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
background: none no-repeat center center / cover;
|
||||
}
|
||||
|
||||
.thumbnail-placeholder {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
/* BiDi-proof: CSS sprites */
|
||||
background: url('images/attachments.png') no-repeat left top / 10rem;
|
||||
}
|
||||
|
||||
.attachment-container .thumbnail,
|
||||
.attachment-container .thumbnail-placeholder {
|
||||
position: absolute;
|
||||
top: 0
|
||||
}
|
||||
|
||||
.attachment-draft:hover .thumbnail-placeholder:not(.vcard-placeholder),
|
||||
.attachment-draft:active .thumbnail-placeholder:not(.vcard-placeholder),
|
||||
.attachment-container:not([data-attachment-type="vcard"]):hover .thumbnail-placeholder,
|
||||
.attachment-container:not([data-attachment-type="vcard"]):active .thumbnail-placeholder {
|
||||
background-color: #33cccc;
|
||||
background-blend-mode: luminosity;
|
||||
}
|
||||
|
||||
.img-placeholder {
|
||||
background-position: left -10rem; /* BiDi proof: CSS sprites */
|
||||
}
|
||||
|
||||
.audio-placeholder {
|
||||
background-position: left -20rem; /* BiDi proof: CSS sprites */
|
||||
}
|
||||
|
||||
.video-placeholder {
|
||||
background-position: left -30rem; /* BiDi proof: CSS sprites */
|
||||
}
|
||||
|
||||
.vcard-placeholder {
|
||||
background: url('images/attachment-vcard.png') no-repeat;
|
||||
background-size: 4rem;
|
||||
}
|
||||
html[dir="ltr"] .vcard-placeholder { background-position: left top; }
|
||||
html[dir="rtl"] .vcard-placeholder { background-position: right top; }
|
||||
|
||||
.incoming.received .vcard-placeholder {
|
||||
background-image: url('images/attachment-vcard-incoming.png');
|
||||
}
|
||||
|
||||
.attachment.corrupted .thumbnail-placeholder:after {
|
||||
display: block;
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
offset-inline-start: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
content: '';
|
||||
background: url('icons/corrupted.png') no-repeat center center / 10rem;
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
html, body {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
font-size: 10px;
|
||||
}
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
#messages-container {
|
||||
/* We'll set flex-basis with a shrink factor of 0 to do min-height.
|
||||
* formula: flex-basis = a % + b)
|
||||
* a = (gap2 - gap1) / keyboard_height
|
||||
* b = gap2 - (gap2 - gap1) * (buri_height - header) / keyboard_height + subheader + time_header
|
||||
*
|
||||
* with :
|
||||
* gap1 = 4rem
|
||||
* minimal visible part of a thread when the keyboard is displayed, on buri
|
||||
* gap2 = 8rem
|
||||
* minimal visible part of a thread when the keyboard is hidden, on a buri
|
||||
* keyboard_height = 26rem
|
||||
* measured on a buri, standard english keyboard with suggestions
|
||||
* header = 5rem
|
||||
* subheader = 2rem
|
||||
* buri_height = 48rem
|
||||
* time_header = 2rem
|
||||
*
|
||||
* See https://bugzilla.mozilla.org/show_bug.cgi?id=1015867#c12 for more
|
||||
* information
|
||||
*/
|
||||
flex: 1 0 calc(15.4% + 5.38rem);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#messages-new-message-notice {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
padding: 1rem;
|
||||
padding-inline-start: 2rem;
|
||||
padding-inline-end: 1.5rem;
|
||||
overflow: hidden;
|
||||
|
||||
white-space: nowrap;
|
||||
line-height: 2rem;
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
#messages-new-message-notice a {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#messages-new-message-notice .contact {
|
||||
overflow: hidden;
|
||||
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#messages-new-message-notice > .text-container {
|
||||
flex: auto;
|
||||
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#messages-new-message-notice > .button-container {
|
||||
flex: none;
|
||||
|
||||
padding: 0.2rem;
|
||||
padding-inline-start: 1.5rem;
|
||||
padding-inline-end: 0;
|
||||
}
|
||||
|
||||
/* remove margin for notice-button class of button */
|
||||
.notice-button {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.group-header-title {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.carrier-wrapper {
|
||||
display: none;
|
||||
|
||||
box-sizing: border-box;
|
||||
height: 2.2rem;
|
||||
padding: 0 1.5rem;
|
||||
|
||||
font-size: 1.4rem;
|
||||
line-height: 2.2rem;
|
||||
text-align: start;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.carrier-wrapper .phone-carrier {
|
||||
color: #008787;
|
||||
}
|
||||
|
||||
.has-carrier .carrier-wrapper {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#messages-container .messages-date-group-header {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
|
||||
height: 2.2rem;
|
||||
margin: 0;
|
||||
padding: 0.6rem 3rem;
|
||||
|
||||
font-size: 1.4rem;
|
||||
line-height: 2.2rem;
|
||||
text-transform: uppercase;
|
||||
|
||||
background: rgba(225, 240, 236, 0.85);
|
||||
color: #008787;
|
||||
}
|
||||
|
||||
/* If has carrier change top position */
|
||||
.has-carrier #messages-container .messages-date-group-header {
|
||||
top: 2.2rem;
|
||||
}
|
||||
|
||||
.has-carrier #messages-container > .messages-date-group:first-child > .messages-date-group-header {
|
||||
margin-top: 2.2rem;
|
||||
}
|
||||
|
||||
/* TODO: check whether we need this rule */
|
||||
#messages-container .messages-date-group-header.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.article-list[data-type="list"] .message {
|
||||
z-index: 0; /* bug 970422 */
|
||||
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
padding-bottom: 1rem;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.article-list[data-type="list"] .message.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#messages-container[data-type="list"] .message.mms .bubble img {
|
||||
height: auto;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
/* transition in and out edit mode, both for LTR and RTL contexts */
|
||||
.message .bubble {
|
||||
transition: transform var(--transition-duration) ease 0s;
|
||||
}
|
||||
|
||||
/* RTL View */
|
||||
#messages-header-text .ellipsis-dir-fix {
|
||||
width: auto;
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* This file contains styles for Conversation view edit mode. They complement
|
||||
* styles from views/shared/style/edit-mode.css that are applied as well.
|
||||
* View edit mode is activated via Options -> Select messages.
|
||||
*/
|
||||
|
||||
|
||||
.edit #messages-container {
|
||||
margin-bottom: 5.5rem;
|
||||
}
|
||||
|
||||
.edit .article-list[data-type="list"] .message {
|
||||
border-color: #e7e7e7;
|
||||
}
|
||||
|
||||
.edit [data-type="list"] .message .bubble {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.edit .message .bubble {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
html[dir="ltr"] .edit .message.incoming .bubble {
|
||||
transform: translateX(2.5rem);
|
||||
}
|
||||
html[dir="rtl"] .edit .message.incoming .bubble {
|
||||
transform: translateX(-2.5rem);
|
||||
}
|
||||
|
||||
.edit #messages-compose-form {
|
||||
display: none;
|
||||
}
|
||||
|
After Width: | Height: | Size: 584 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 454 B |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 411 B |
|
After Width: | Height: | Size: 354 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 398 B |
|
|
@ -0,0 +1,238 @@
|
|||
.message.incoming {
|
||||
padding-inline-start: 1.5rem;
|
||||
padding-inline-end: 4rem;
|
||||
}
|
||||
|
||||
.message.outgoing {
|
||||
padding-inline-start: 4rem;
|
||||
padding-inline-end: 1.5rem;
|
||||
}
|
||||
|
||||
.message .bubble {
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
max-width: 100%;
|
||||
padding: 1rem 1.5rem;
|
||||
overflow: visible;
|
||||
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.bubble .message-content-body:focus {
|
||||
-moz-user-select: text;
|
||||
}
|
||||
|
||||
.message.outgoing .bubble {
|
||||
background: #fff;
|
||||
}
|
||||
html[dir="ltr"] .message.outgoing .bubble {
|
||||
float: right;
|
||||
border-radius: 1.5rem 0 1.5rem 1.5rem;
|
||||
}
|
||||
html[dir="rtl"] .message.outgoing .bubble {
|
||||
float: left;
|
||||
border-radius: 0 1.5rem 1.5rem 1.5rem;
|
||||
}
|
||||
|
||||
|
||||
.message.outgoing .bubble,
|
||||
.message.outgoing a:active {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.message.incoming .bubble {
|
||||
background: #39c3c2;
|
||||
}
|
||||
html[dir="ltr"] .message.incoming .bubble {
|
||||
float: left;
|
||||
border-radius: 0 1.5rem 1.5rem 1.5rem;
|
||||
}
|
||||
html[dir="rtl"] .message.incoming .bubble {
|
||||
float: right;
|
||||
border-radius: 1.5rem 0 1.5rem 1.5rem;
|
||||
}
|
||||
|
||||
.message.incoming .bubble,
|
||||
.message.incoming a:active {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.message p.message-content-body {
|
||||
white-space: pre-wrap;
|
||||
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* BB overrides */
|
||||
.message.outgoing p:first-of-type:last-of-type,
|
||||
.message.incoming p:first-of-type:last-of-type {
|
||||
padding-top: 0.5rem;
|
||||
|
||||
line-height: 2rem;
|
||||
}
|
||||
|
||||
.message.incoming p:first-of-type {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.message.sending p:first-of-type {
|
||||
color: #6e6e6e;
|
||||
}
|
||||
|
||||
/* End of BB overrides */
|
||||
|
||||
.outgoing.error .bubble {
|
||||
background: #fae1df;
|
||||
}
|
||||
|
||||
.incoming.error .bubble {
|
||||
background: #ff9898;
|
||||
}
|
||||
|
||||
.message.sending .bubble,
|
||||
.message.sending a,
|
||||
.message.sending a:active {
|
||||
color: #6e6e6e;
|
||||
}
|
||||
|
||||
.message.sending .message-subject,
|
||||
.message.sending .message-content-body {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* Message Subject */
|
||||
.message .message-subject {
|
||||
display: none;
|
||||
|
||||
margin-bottom: 1rem;
|
||||
|
||||
font-size: 1.4rem;
|
||||
font-style: italic;
|
||||
line-height: 1.7rem;
|
||||
|
||||
unicode-bidi: -moz-plaintext;
|
||||
}
|
||||
|
||||
.message.has-subject .message-subject {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Message content styles */
|
||||
.message-content a {
|
||||
color: #004eff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.message-content > p {
|
||||
unicode-bidi: -moz-plaintext;
|
||||
}
|
||||
|
||||
.message-details {
|
||||
display: flex;
|
||||
|
||||
margin-top: 0.5rem;
|
||||
|
||||
font-size: 1.4rem;
|
||||
line-height: 2rem;
|
||||
}
|
||||
|
||||
.message.sending time,
|
||||
.message.sending .message-sim-information {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.message.outgoing .message-details {
|
||||
color: #858585;
|
||||
}
|
||||
|
||||
.message.outgoing.error .message-details {
|
||||
color: #e97f79;
|
||||
}
|
||||
|
||||
.message.incoming .message-details {
|
||||
color: #d1eeee;
|
||||
}
|
||||
|
||||
.message.incoming .late-arrival-notice {
|
||||
color: #026a69;
|
||||
}
|
||||
|
||||
.message.incoming .late-arrival-icon {
|
||||
margin-inline-start: 1rem;
|
||||
margin-inline-end: 0.1rem;
|
||||
min-width: 1.5rem;
|
||||
height: 2rem;
|
||||
|
||||
background: no-repeat center center / 1.5rem;
|
||||
background-image: url('images/icons/late_clock.png');
|
||||
}
|
||||
|
||||
.message.incoming.error .message-details {
|
||||
color: #ffe0dc;
|
||||
}
|
||||
|
||||
.message-sim-information {
|
||||
margin-inline-end: 0.4rem;
|
||||
}
|
||||
|
||||
.message-sim-information::after {
|
||||
content: ' ‧ ';
|
||||
}
|
||||
|
||||
/* Message status aside panel */
|
||||
.message .message-status {
|
||||
height: 2rem;
|
||||
min-width: 3rem;
|
||||
|
||||
background: no-repeat center center / 1.6rem;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
.message.error .message-status {
|
||||
background-image: url('images/icons/exclamation.png');
|
||||
}
|
||||
|
||||
.message.delivered .message-status {
|
||||
background-image: url('images/icons/deliveredtick.png');
|
||||
}
|
||||
|
||||
.message.read .message-status {
|
||||
background-image: url('images/icons/message_read.png');
|
||||
}
|
||||
|
||||
.message.pending .message-status,
|
||||
.message.sending .message-status {
|
||||
background: none;
|
||||
}
|
||||
|
||||
|
||||
/* Message download button */
|
||||
.message .download {
|
||||
display: block;
|
||||
|
||||
min-height: initial;
|
||||
width: auto;
|
||||
padding: 0;
|
||||
/* Eliminating container paragraph line-height */
|
||||
margin: -1.5rem 0 0;
|
||||
|
||||
background: none;
|
||||
color: #fff;
|
||||
border: none;
|
||||
/* We're using border-bottom instead of just underline style as line is too
|
||||
close to the text and doesn't look similar to visual spec. */
|
||||
border-bottom: 1px solid #fff;
|
||||
}
|
||||
|
||||
.message .download:active {
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
/* hide download button via css on expired messages */
|
||||
.message.expired .download {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.message.pending .download {
|
||||
border-color: transparent;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
/* Message information page for report details*/
|
||||
.report-view {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.report-view > .description {
|
||||
padding-top: 2rem;
|
||||
padding-inline-end: 1.5rem;
|
||||
padding-bottom: 3rem;
|
||||
padding-inline-start: 3rem;
|
||||
}
|
||||
|
||||
.report-view p,
|
||||
.report-view span {
|
||||
font-size: 1.5rem;
|
||||
line-height: 1rem;
|
||||
color: #858585;
|
||||
}
|
||||
|
||||
.report-view p {
|
||||
padding-top: 1.5rem;
|
||||
}
|
||||
|
||||
.report-view .description > .type {
|
||||
padding-top: 0;
|
||||
|
||||
font-size: 1.6rem;
|
||||
color: #ff4e00;
|
||||
}
|
||||
|
||||
.report-view .description .detail {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.report-view .description > .type[data-l10n-id="message-type-sms"] {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/* Hiding some elements for some states */
|
||||
.report-view[data-delivery="error"] .sent-title,
|
||||
.report-view[data-delivery="sending"] .sent-timestamp,
|
||||
.outgoing-message .received-block,
|
||||
.outgoing-message .lateness-block {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/* Hide sent timestamp label if we don't have valid value to display */
|
||||
.report-view.no-valid-sent-timestamp .sent-block {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.report-view .contact-title {
|
||||
color: #008787;
|
||||
font-size: 1.6rem;
|
||||
padding-inline-start: 3rem;
|
||||
}
|
||||
|
||||
.report-view > ul.contact-list {
|
||||
/* Showing 4 complete contacts and part of the contact name if list
|
||||
contains more than 4 contacts */
|
||||
position: static;
|
||||
|
||||
margin-top: 0.5rem;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.report-view > .contact-list > li {
|
||||
height: auto;
|
||||
min-height: 9rem;
|
||||
padding-top: 0.7rem;
|
||||
padding-bottom: 1rem;
|
||||
padding-inline-end: 0;
|
||||
padding-inline-start: 1.5rem;
|
||||
|
||||
border-top: solid 0.1rem #e7e7e7;
|
||||
border-bottom: medium none;
|
||||
}
|
||||
|
||||
.report-view > .contact-list p,
|
||||
.report-view > .contact-list span {
|
||||
font-size: 1.4rem;
|
||||
line-height: 1.6rem;
|
||||
}
|
||||
|
||||
.report-view > .contact-list .name {
|
||||
padding-top: 0;
|
||||
|
||||
font-size: 1.8rem;
|
||||
font-weight: 500;
|
||||
line-height: 2.6rem;
|
||||
}
|
||||
|
||||
.report-view > .contact-list aside {
|
||||
/* margin-top = (li - padding - aside) / 2 = (9rem - 2rem - 5.5rem) / 2 */
|
||||
margin-top: 0.8rem;
|
||||
}
|
||||
|
||||
.report-view > .contact-list .number {
|
||||
padding-top: 0.6rem;
|
||||
}
|
||||
|
||||
.report-view .network-status {
|
||||
padding-top: 0.7rem;
|
||||
}
|
||||
|
||||
.report-view .name + .network-status {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.report-view .network-status,
|
||||
.report-view .network-status span {
|
||||
line-height: 1.4rem;
|
||||
}
|
||||
|
||||
.contact-list p.number .phone-carrier {
|
||||
color: #008787;
|
||||
}
|
||||
|
||||
.report-view > .contact-list .icon {
|
||||
width: 1.6rem;
|
||||
height: 1.6rem;
|
||||
margin: -0.1rem 0 0.1rem;
|
||||
margin-inline-end: 0.7rem;
|
||||
|
||||
background: no-repeat center center / 1.6rem transparent;
|
||||
}
|
||||
html[dir="ltr"] .report-view > .contact-list .icon { float: left; }
|
||||
html[dir="rtl"] .report-view > .contact-list .icon { float: right; }
|
||||
|
||||
.contact-list [data-delivery-status="delivered"] .icon {
|
||||
background-image: url('images/icons/deliveredtick.png');
|
||||
}
|
||||
|
||||
.contact-list [data-delivery-status="read"] .icon {
|
||||
background-image: url('images/icons/message_read.png');
|
||||
}
|
||||
|
||||
.contact-list [data-delivery-status="error"] .icon {
|
||||
background-image: url('images/icons/exclamation.png');
|
||||
}
|
||||
|
||||
.contact-list [data-delivery-status="not-applicable"],
|
||||
.contact-list [data-delivery-status="pending"] .icon,
|
||||
.contact-list [data-delivery-status="pending"] .timestamp,
|
||||
.contact-list [data-delivery-status="error"] .timestamp,
|
||||
.contact-list [data-delivery-status="rejected"] .icon,
|
||||
.contact-list [data-delivery-status="rejected"] .timestamp{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.report-view .resend-btn {
|
||||
display: none;
|
||||
width: calc(100% - 3rem);
|
||||
|
||||
flex-shrink: 0;
|
||||
margin: 0 1.5rem 2rem;
|
||||
|
||||
background-color: #00caf2;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.report-view[data-delivery="error"] .resend-btn {
|
||||
display: block;
|
||||
}
|
||||