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.
|
|
@ -0,0 +1,34 @@
|
|||
<element name="call-info-view" extends="form">
|
||||
<template>
|
||||
|
||||
<gaia-header id="call-info-gaia-header" action="back">
|
||||
<h1><bdi class="ellipsis-dir-fix" id="call-info-title" dir="auto"></bdi></h1>
|
||||
</gaia-header>
|
||||
|
||||
<div class="ci__wrapper">
|
||||
<div class="ci__calls-wrapper">
|
||||
<div class="ci__group-info">
|
||||
<p id="call-info-day" class="ci__grow"></p>
|
||||
<p id="call-info-direction" class="ci__direction-icon"></p>
|
||||
</div>
|
||||
|
||||
<div id="call-durations">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ci__contact-wrapper">
|
||||
<div id="contact-detail">
|
||||
<section id="phone-details-stub"></section>
|
||||
<section id="email-details-stub"></section>
|
||||
<ul id="call-info-list-details"></ul>
|
||||
</div>
|
||||
|
||||
<div id="contact-actions">
|
||||
<button id="call-info-details" class="activity" data-l10n-id="contactDetails" hidden></button>
|
||||
<button id="call-info-add" class="activity" data-l10n-id="addToExistingContact" hidden></button>
|
||||
<button id="call-info-create" class="activity" data-l10n-id="createNewContact" hidden></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</element>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<element name="edit-mode" extends="form">
|
||||
<template>
|
||||
|
||||
<section role="region" class="theme-settings">
|
||||
<gaia-header id="edit-mode-header" action="close">
|
||||
<h1 id="header-edit-mode-text" data-l10n-id="edit"></h1>
|
||||
<button id="delete-button" data-l10n-id="delete" disabled>Delete</button>
|
||||
</gaia-header>
|
||||
</section>
|
||||
<menu>
|
||||
<button id="deselect-all-threads" class="edit-button" disabled data-l10n-id="deselectAll">Deselect all</button>
|
||||
<button id="select-all-threads" class="edit-button" data-l10n-id="selectAll">Select all</button>
|
||||
</menu>
|
||||
|
||||
</template>
|
||||
</element>
|
||||
402
assets/webapps/communications.gaiamobile.org/dialer/index.html
Normal file
|
|
@ -0,0 +1,402 @@
|
|||
<!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>Dialer</title>
|
||||
|
||||
<!-- 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/dialer.index.{locale}.json">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- CSS -->
|
||||
<link rel="stylesheet" type="text/css" href="/shared/style/animations.css">
|
||||
<link rel="stylesheet" type="text/css" href="/shared/style/dialer/dialer.css">
|
||||
<link rel="stylesheet" type="text/css" href="style/toolbar.css">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/shared/style/dialer/keypad.css">
|
||||
<link rel="stylesheet" type="text/css" href="/dialer/style/call_log.css">
|
||||
<link rel="stylesheet" type="text/css" href="/dialer/style/suggestion.css">
|
||||
<link rel="stylesheet" type="text/css" href="/shared/style/contacts/contact_in_overlay.css">
|
||||
<link rel="stylesheet" type="text/css" href="/shared/style/dialer/overlay.css">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/shared/style/tabs.css">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="app://theme.gaiamobile.org/shared/elements/gaia-theme/gaia-theme.css">
|
||||
<link rel="stylesheet" type="text/css" href="/shared/elements/gaia-icons/gaia-icons.css">
|
||||
<link rel="stylesheet" type="text/css" href="/shared/elements/gaia-icons/bidi-helper.css">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/shared/style/option_menu.css">
|
||||
|
||||
<!-- JS -->
|
||||
<!-- <script defer="" src="/shared/js/l10n.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/lazy_loader.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/font_size_utils.js"></script> -->
|
||||
<!-- <script defer="" src="/dialer/js/index.js"></script> -->
|
||||
|
||||
<!-- <script defer="" src="/shared/js/dialer/contacts.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/dialer/dtmf_tone.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/dialer/font_size_manager.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/dialer/keypad.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/dialer/tone_player.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/dialer/utils.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/dialer/voicemail.js"></script> -->
|
||||
|
||||
<!-- <script defer="" src="/dialer/js/navigation.js"></script> -->
|
||||
<!-- <script defer="" src="/dialer/js/dialer.js"></script> -->
|
||||
<!-- <script defer="" src="/dialer/js/call_log.js"></script> -->
|
||||
<!-- <script defer="" src="/dialer/js/call_log_db.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/accessibility_helper.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/async_storage.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/contact_photo_helper.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/multi_sim_action_button.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/notification_helper.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/simple_phone_matcher.js"></script> --><script src="./gaia_build_defer_index.js" defer="" type="text/javascript"></script>
|
||||
|
||||
<!-- Lazy load all the things:
|
||||
<link rel="stylesheet" type="text/css" href="/shared/style/action_menu.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/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/input_areas.css">
|
||||
<link rel="stylesheet" type="text/css" href="/dialer/style/mmi.css">
|
||||
<link rel="stylesheet" type="text/css" href="/shared/style/contacts/contacts_buttons.css">
|
||||
<link rel="stylesheet" type="text/css" href="/shared/style/contacts.css">
|
||||
<link rel="stylesheet" type="text/css" href="/dialer/style/buttons.css">
|
||||
<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">
|
||||
<script defer src="/shared/elements/gaia_menu/script.js"></script>
|
||||
<script defer src="/shared/elements/gaia_sim_picker/script.js"></script>
|
||||
<script defer src="/shared/js/component_utils.js"></script>
|
||||
<script defer src="/shared/js/mobile_operator.js"></script>
|
||||
<script defer src="/shared/js/option_menu.js"></script>
|
||||
<script defer src="/shared/js/settings_listener.js"></script>
|
||||
<script defer src="/shared/js/confirm.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/fb/fb_tel_index.js"></script>
|
||||
<script defer src="/shared/js/binary_search.js"></script>
|
||||
<script defer src="/shared/js/sticky_header.js"></script>
|
||||
<script defer src="/shared/js/sim_settings_helper.js"></script>
|
||||
<script defer src="/shared/js/dialer/telephony_messages.js"></script>
|
||||
<script defer src="/shared/js/contacts/contacts_buttons.js"></script>
|
||||
<script defer src="/shared/js/custom_dialog.js"></script>
|
||||
<script defer src="/dialer/js/contact_data_manager.js"></script>
|
||||
<script defer src="/dialer/js/suggestion_bar.js"></script>
|
||||
<script defer src="/dialer/js/telephony_helper.js"></script>
|
||||
<script defer src="/dialer/js/mmi.js"></script>
|
||||
<script defer src="/dialer/js/mmi_ui.js"></script>
|
||||
<script defer src="/shared/js/icc_helper.js"></script>
|
||||
<script defer src="/shared/elements/config.js"></script>
|
||||
<script defer src="/shared/elements/gaia-header/dist/gaia-header.js"></script>
|
||||
<script defer src="/shared/js/text_normalizer.js"></script>
|
||||
<script defer src="/shared/js/contacts/utilities/templates.js"></script>
|
||||
<script defer src="/shared/js/contacts/sms_integration.js"></script>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<meta content="2.5" name="appVersion"></head>
|
||||
<body role="application" class="skin-comms theme-communications">
|
||||
<section id="views" role="tablist" class="bb-tablist">
|
||||
<li role="presentation" class="view hidden" id="call-log-view">
|
||||
<a aria-label="Recent calls" id="option-recents" role="tab" aria-controls="recents-panel" class="icon icon-recents" data-l10n-id="recents" aria-selected="false" data-destination="recents"></a>
|
||||
<div id="recents-panel" role="tabpanel" class="bb-tabpanel" aria-labelledby="option-recents">
|
||||
<section role="region">
|
||||
<gaia-header>
|
||||
<h1 data-l10n-id="callLog">Call log</h1>
|
||||
<button aria-label="Edit call log" id="call-log-icon-edit" data-icon="edit" disabled="" data-l10n-id="callLogEditButton"></button>
|
||||
</gaia-header>
|
||||
<nav id="call-log-filter" class="recents-filter-container">
|
||||
<ul role="tablist" class="bb-tablist" data-type="filter" aria-controls="call-log-container">
|
||||
<li id="all-filter" role="presentation"><a aria-label="All" id="all-filter-tab" role="tab" aria-selected="true" data-action="all" data-l10n-id="all">All</a></li>
|
||||
<li id="missed-filter" role="presentation"><a aria-label="Missed" id="missed-filter-tab" role="tab" aria-selected="false" data-action="missed" data-l10n-id="missed">Missed</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="view-body">
|
||||
<article id="call-log-container" role="tabpanel" class="view-body-inner active" data-type="list">
|
||||
<div id="no-result-container" hidden="">
|
||||
<div id="no-result-message">
|
||||
<p id="no-result-msg1" data-l10n-id="no-logs-msg-1">No calls recorded</p>
|
||||
<p id="no-result-msg2" data-l10n-id="no-logs-msg-4">Start a conversation now</p>
|
||||
<p id="no-result-msg3" data-l10n-id="no-logs-msg-3" hidden="">No missed calls</p>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<div id="sticky"></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="call-info-view" role="region" hidden=""><!--
|
||||
|
||||
<gaia-header id="call-info-gaia-header" action="back">
|
||||
<h1><bdi class="ellipsis-dir-fix" id="call-info-title" dir="auto"></bdi></h1>
|
||||
</gaia-header>
|
||||
|
||||
<div class="ci__wrapper">
|
||||
<div class="ci__calls-wrapper">
|
||||
<div class="ci__group-info">
|
||||
<p id="call-info-day" class="ci__grow"></p>
|
||||
<p id="call-info-direction" class="ci__direction-icon"></p>
|
||||
</div>
|
||||
|
||||
<div id="call-durations">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ci__contact-wrapper">
|
||||
<div id="contact-detail">
|
||||
<section id="phone-details-stub"></section>
|
||||
<section id="email-details-stub"></section>
|
||||
<ul id="call-info-list-details"></ul>
|
||||
</div>
|
||||
|
||||
<div id="contact-actions">
|
||||
<button id="call-info-details" class="activity" data-l10n-id="contactDetails" hidden=""></button>
|
||||
<button id="call-info-add" class="activity" data-l10n-id="addToExistingContact" hidden=""></button>
|
||||
<button id="call-info-create" class="activity" data-l10n-id="createNewContact" hidden=""></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
--></section>
|
||||
</div>
|
||||
</li>
|
||||
<li role="presentation" class="view" id="contacts-view">
|
||||
<a aria-label="Contacts" id="option-contacts" role="tab" aria-controls="iframe-contacts-container" class="icon icon-contacts" data-l10n-id="contacts" aria-selected="false" data-destination="contacts"></a>
|
||||
<div id="iframe-contacts-container" role="tabpanel" class="bb-tabpanel" aria-labelledby="option-contacts">
|
||||
</div>
|
||||
</li>
|
||||
<li role="presentation" id="keyboard-view">
|
||||
<a aria-label="Keypad" id="option-keypad" role="tab" aria-controls="keypad-panel" class="icon icon-keypad" data-l10n-id="keypad" aria-selected="true" data-destination="keypad"></a>
|
||||
<div id="keypad-panel" role="tabpanel" class="bb-tabpanel" aria-labelledby="option-keypad">
|
||||
<div id="phone-number-view-container" dir="ltr">
|
||||
<div class="phone-number-view-wrapper-input">
|
||||
<input aria-label="Phone number" id="phone-number-view" class="phone-number-font font-light textfield" readonly="readonly" data-l10n-id="phoneNumberInput" type="text">
|
||||
</div>
|
||||
<button aria-label="Delete" role="key" id="keypad-delete" class="reset-button" data-value="delete" data-l10n-id="keypadDelete">
|
||||
</button>
|
||||
</div>
|
||||
<section id="suggestion-bar" class="suggestion-bar hide">
|
||||
<div role="button" class="js-suggestion-item contact-item bb-button"><!--
|
||||
|
||||
<div class="js-name ci__name ellipsis" dir="auto"></div>
|
||||
<div class="ci__details">
|
||||
<span class="js-tel-type ci__tel-type ellipsis" dir="auto"></span>
|
||||
<span class="js-separator"></span>
|
||||
<span class="js-tel ellipsis" dir="ltr"></span>
|
||||
</div>
|
||||
|
||||
--></div>
|
||||
<div role="button" id="suggestion-count" class="suggestion-count more bb-button"></div>
|
||||
</section>
|
||||
<button role="button" id="contact-in-overlay-template" class="js-suggestion-item contact-item bb-button" hidden=""><!--
|
||||
|
||||
<div class="js-name ci__name ellipsis" dir="auto"></div>
|
||||
<div class="ci__details">
|
||||
<span class="js-tel-type ci__tel-type ellipsis" dir="auto"></span>
|
||||
<span class="js-separator"></span>
|
||||
<span class="js-tel ellipsis" dir="ltr"></span>
|
||||
</div>
|
||||
|
||||
--></button>
|
||||
|
||||
<article id="keyboard-container" dir="ltr">
|
||||
<section id="keypad">
|
||||
<div class="keypad-row">
|
||||
<div class="keypad-key" role="key" data-value="1">
|
||||
<span>1</span>
|
||||
<em aria-label="Voicemail" class="keypad-subicon voicemail" data-l10n-id="voiceMailKey"></em>
|
||||
</div>
|
||||
<div class="keypad-key" role="key" data-value="2">
|
||||
<span>2</span>
|
||||
<em>ABC</em>
|
||||
</div>
|
||||
<div class="keypad-key" role="key" data-value="3">
|
||||
<span>3</span>
|
||||
<em>DEF</em>
|
||||
</div>
|
||||
</div>
|
||||
<div class="keypad-row">
|
||||
<div class="keypad-key" role="key" data-value="4">
|
||||
<span>4</span>
|
||||
<em>GHI</em>
|
||||
</div>
|
||||
<div class="keypad-key" role="key" data-value="5">
|
||||
<span>5</span>
|
||||
<em>JKL</em>
|
||||
</div>
|
||||
<div class="keypad-key" role="key" data-value="6">
|
||||
<span>6</span>
|
||||
<em>MNO</em>
|
||||
</div>
|
||||
</div>
|
||||
<div class="keypad-row">
|
||||
<div class="keypad-key" role="key" data-value="7">
|
||||
<span>7</span>
|
||||
<em>PQRS</em>
|
||||
</div>
|
||||
<div class="keypad-key" role="key" data-value="8">
|
||||
<span>8</span>
|
||||
<em>TUV</em>
|
||||
</div>
|
||||
<div class="keypad-key" role="key" data-value="9">
|
||||
<span>9</span>
|
||||
<em>WXYZ</em>
|
||||
</div>
|
||||
</div>
|
||||
<div class="keypad-row">
|
||||
<div aria-label="Asterisk" class="keypad-key" role="key" data-value="*" data-l10n-id="asterisk">
|
||||
<span class="asterisk">*</span>
|
||||
<em>’</em>
|
||||
</div>
|
||||
<div class="keypad-key" role="key" data-value="0">
|
||||
<span>0</span>
|
||||
<em class="font-size-plus">+</em>
|
||||
</div>
|
||||
<div aria-label="Hash sign" class="keypad-key" role="key" data-type="dial" data-value="#" data-l10n-id="hashSign">
|
||||
<div class="sharp">#</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="keypad-callbar">
|
||||
<button aria-label="Add contact" id="keypad-callbar-add-contact" data-value="add-contact" class="reset-button keypad-callbar-button icon-add-contact disable-when-dialog-animates" data-l10n-id="dialerAddContact" disabled=""></button>
|
||||
<button aria-label="Make call" id="keypad-callbar-call-action" class="reset-button" data-value="make-call" data-l10n-id="makeCall">
|
||||
<div class="js-sim-indication"></div>
|
||||
</button>
|
||||
</section>
|
||||
</article>
|
||||
</div>
|
||||
</li>
|
||||
</section>
|
||||
|
||||
<form aria-label="Edit call log dialog" id="edit-mode" role="dialog" data-l10n-id="callLogEditDialog" data-type="edit" hidden=""><!--
|
||||
|
||||
<section role="region" class="theme-settings">
|
||||
<gaia-header id="edit-mode-header" action="close">
|
||||
<h1 id="header-edit-mode-text" data-l10n-id="edit"></h1>
|
||||
<button id="delete-button" data-l10n-id="delete" disabled="">Delete</button>
|
||||
</gaia-header>
|
||||
</section>
|
||||
<menu>
|
||||
<button id="deselect-all-threads" class="edit-button" disabled="" data-l10n-id="deselectAll">Deselect all</button>
|
||||
<button id="select-all-threads" class="edit-button" data-l10n-id="selectAll">Select all</button>
|
||||
</menu>
|
||||
|
||||
--></form>
|
||||
|
||||
<form aria-label="Add Contact Dialog" id="add-contact-action-menu" role="dialog" data-l10n-id="dialerAddContactDialog" data-type="action" hidden=""><!--undefined--></form>
|
||||
|
||||
<gaia-sim-picker id="sim-picker" tabindex="-1"></gaia-sim-picker>
|
||||
|
||||
<form id="confirmation-message" class="hide no-opacity" role="dialog" data-type="confirm"><!--
|
||||
|
||||
<section>
|
||||
<h1>Confirmation title</h1>
|
||||
<p>Confirmation message</p>
|
||||
</section>
|
||||
<menu>
|
||||
<button>Action 1</button>
|
||||
<button>Action 2</button>
|
||||
</menu>
|
||||
|
||||
--></form>
|
||||
|
||||
<form id="contact-list-overlay" role="dialog" data-type="action" class="overlay" aria-hidden="true"><!--
|
||||
|
||||
<header></header>
|
||||
<menu id="contact-list">
|
||||
<button id="contact-list-overlay-cancel" data-l10n-id="cancel">Cancel</button>
|
||||
</menu>
|
||||
|
||||
--></form>
|
||||
|
||||
<section id="phone-details" hidden=""><!--
|
||||
<li data-phone="" id="phone-details-template-#i#" data-template="" role="region" aria-label="Phone" data-l10n-id="phoneDetail">
|
||||
<h2>
|
||||
<span data-l10n-id="#type_l10n_id#">#type#</span>
|
||||
<span class="carrier-wrapper" hidden="">
|
||||
<span data-l10n-id="separator"></span>
|
||||
<span class="carrier">#carrier#</span>
|
||||
</span>
|
||||
</h2>
|
||||
<div class="item">
|
||||
<div class="item-body-exp">
|
||||
<div class="button activity call-action icon icon-call" id="call-or-pick-#i#">
|
||||
<b aria-label="Call" data-l10n-id="makeCall"><bdi class="ellipsis-dir-fix">#value#</bdi></b>
|
||||
<span class="js-sim-indication"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-media pull-right">
|
||||
<button id="send-sms-button-#i#" class="activity send-sms icon icon-message" data-l10n-id="send-sms-button" aria-label="SMS"></button>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
--></section>
|
||||
<section id="email-details" hidden=""><!--
|
||||
<li data-mail="" id="email-details-template-#i#" data-template="" role="region" aria-label="Email" data-l10n-id="emailDetail">
|
||||
<h2 data-l10n-id="#type_l10n_id#">#type#</h2>
|
||||
<div class="item">
|
||||
<div class="item-body-exp">
|
||||
<button id="email-or-pick-#i#" class="activity icon icon-email">
|
||||
<b aria-label="Email" data-l10n-id="composeEmail" dir="ltr">#value#</b>
|
||||
</button>
|
||||
</div>
|
||||
<div class="item-media pull-right">
|
||||
<button id="send-sms-to-email-button-#i#" class="activity send-sms icon icon-message" data-l10n-id="send-sms-button" aria-label="SMS"></button>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
--></section>
|
||||
|
||||
<article id="mmi-screen" role="region" hidden="">
|
||||
<section role="region">
|
||||
<gaia-header id="mmi-header" action="close">
|
||||
<h1 id="header-title">USSD</h1>
|
||||
<button id="send" data-l10n-id="send" disabled="">Send</button>
|
||||
</gaia-header>
|
||||
</section>
|
||||
<section id="mmi-container" role="region">
|
||||
<div id="message">
|
||||
</div>
|
||||
</section>
|
||||
<form id="response" role="region">
|
||||
<p>
|
||||
<input id="response-text" data-l10n-id="type-your-response" placeholder="Type your response…" required="" disabled="" type="text">
|
||||
<button id="response-text-reset" type="reset" data-l10n-id="clear-all-text">Clear all text</button>
|
||||
</p>
|
||||
</form>
|
||||
</article>
|
||||
|
||||
<form data-type="confirm" role="dialog" id="loading-overlay" class="hide">
|
||||
<section>
|
||||
<h1 data-l10n-id="sending">Sending…</h1>
|
||||
<p role="status">
|
||||
<progress class="pack-activity" value="0" max="100"></progress>
|
||||
</p>
|
||||
</section>
|
||||
<menu>
|
||||
<button class="full" id="cancel" data-l10n-id="cancel">Cancel</button>
|
||||
</menu>
|
||||
</form>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
'use strict';
|
||||
|
||||
/* exported AddContactMenu */
|
||||
|
||||
/* globals LazyLoader, MozActivity, OptionMenu */
|
||||
|
||||
var AddContactMenu = (function() {
|
||||
|
||||
var _createNewContact = function(phoneNumber) {
|
||||
launchActivity('new', phoneNumber);
|
||||
};
|
||||
|
||||
var _addToExistingContact = function(phoneNumber) {
|
||||
launchActivity('update', phoneNumber);
|
||||
};
|
||||
|
||||
var launchActivity = function(name, phoneNumber) {
|
||||
try {
|
||||
/* jshint nonew: false */
|
||||
new MozActivity({
|
||||
name: name,
|
||||
data: {
|
||||
type: 'webcontacts/contact',
|
||||
params: {
|
||||
'tel': phoneNumber
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('Error while creating activity');
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
show: function(phoneNumber) {
|
||||
var params = {
|
||||
items: [{
|
||||
l10nId: 'createNewContact',
|
||||
method: _createNewContact,
|
||||
params: [phoneNumber]
|
||||
},{
|
||||
l10nId: 'addToExistingContact',
|
||||
method: _addToExistingContact,
|
||||
params: [phoneNumber]
|
||||
},{ // Last item is the Cancel button
|
||||
l10nId: 'cancel',
|
||||
incomplete: true
|
||||
}],
|
||||
header: phoneNumber
|
||||
};
|
||||
|
||||
LazyLoader.load(['/shared/js/option_menu.js',
|
||||
'/shared/style/action_menu.css'], function() {
|
||||
/* jshint nonew: false */
|
||||
new OptionMenu(params).show();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
}());
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
'use strict';
|
||||
|
||||
/* exported CallGroupMenu */
|
||||
|
||||
/* globals CallInfo, LazyLoader, MozActivity, OptionMenu */
|
||||
|
||||
var CallGroupMenu = (function() {
|
||||
|
||||
var _showCallInfo = function(phoneNumber, date, type, status) {
|
||||
LazyLoader.load(['/dialer/js/call_info.js',
|
||||
'/dialer/style/call_info.css'], function() {
|
||||
CallInfo.show(phoneNumber, date, type, status);
|
||||
});
|
||||
};
|
||||
|
||||
var _sendSms = function(phoneNumber) {
|
||||
/* jshint nonew: false */
|
||||
try {
|
||||
new MozActivity({
|
||||
name: 'new',
|
||||
data: {
|
||||
type: 'websms/sms',
|
||||
number: phoneNumber
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('Error while creating activity: ' + e);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
show: function(groupPrimaryInfo, phoneNumber, date, type, status) {
|
||||
var span = document.createElement('span');
|
||||
span.dir = 'auto';
|
||||
span.textContent = groupPrimaryInfo;
|
||||
var params = {
|
||||
items: [{
|
||||
l10nId: 'callInformation',
|
||||
method: _showCallInfo,
|
||||
params: [phoneNumber, date, type, status]
|
||||
},{
|
||||
l10nId: 'sendSms',
|
||||
method: _sendSms,
|
||||
params: [phoneNumber]
|
||||
},{ // Last item is the Cancel button
|
||||
l10nId: 'cancel',
|
||||
incomplete: true
|
||||
}],
|
||||
header: span,
|
||||
classes: ['call-group-menu']
|
||||
};
|
||||
|
||||
LazyLoader.load(['/shared/js/option_menu.js',
|
||||
'/shared/style/action_menu.css'], function() {
|
||||
new OptionMenu(params).show();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
}());
|
||||
|
|
@ -0,0 +1,295 @@
|
|||
'use strict';
|
||||
|
||||
/* global CallLog, CallLogDBManager, Contacts, ContactsButtons, LazyLoader,
|
||||
MozActivity, SimplePhoneMatcher, Utils */
|
||||
|
||||
(function(exports) {
|
||||
var currentGroup;
|
||||
var detailsButton;
|
||||
var addToContactButton;
|
||||
var createContactButton;
|
||||
var callInfoView;
|
||||
var phoneDetailsElt;
|
||||
var emailDetailsElt;
|
||||
var listDetailsElt;
|
||||
|
||||
function updateViewIfNeeded(evt) {
|
||||
if (evt.detail.group.id !== currentGroup.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateView(evt.detail.group);
|
||||
}
|
||||
|
||||
function updateView(group) {
|
||||
currentGroup = group;
|
||||
updateGroupInformation(group);
|
||||
updateCallDurations(group);
|
||||
updateActionButtons(group);
|
||||
callInfoView.hidden = false;
|
||||
CallLog.hideEditModeButton();
|
||||
}
|
||||
|
||||
function isMissedCall(group) {
|
||||
return group.type === 'incoming' && group.status !== 'connected';
|
||||
}
|
||||
|
||||
function updateGroupInformation(group) {
|
||||
var titleElt = document.getElementById('call-info-title');
|
||||
if (group.contact) {
|
||||
titleElt.textContent = group.contact.primaryInfo;
|
||||
} else if (group.voicemail) {
|
||||
titleElt.setAttribute('data-l10n-id', 'voiceMail');
|
||||
} else if (group.emergency) {
|
||||
titleElt.setAttribute('data-l10n-id', 'emergencyNumber');
|
||||
} else {
|
||||
titleElt.textContent = group.number;
|
||||
}
|
||||
|
||||
Utils.setHeaderDate(
|
||||
document.getElementById('call-info-day'), parseInt(group.date));
|
||||
|
||||
var classList = document.getElementById('call-info-direction').classList;
|
||||
classList.remove('icon-outgoing', 'icon-incoming', 'icon-missed');
|
||||
if (isMissedCall(group)) {
|
||||
classList.add('icon-missed');
|
||||
} else if (group.type === 'dialing' || group.type === 'alerting') {
|
||||
classList.add('icon-outgoing');
|
||||
} else if (group.type === 'incoming'){
|
||||
classList.add('icon-incoming');
|
||||
}
|
||||
}
|
||||
|
||||
function updateCallDurations(group) {
|
||||
var callDurationsElt = document.getElementById('call-durations');
|
||||
callDurationsElt.innerHTML = '';
|
||||
|
||||
/* Old groups did not record call durations */
|
||||
if (!group.calls) {
|
||||
return;
|
||||
}
|
||||
|
||||
group.calls.forEach(function(call) {
|
||||
var startTime = document.createElement('p');
|
||||
startTime.classList.add('ci__grow');
|
||||
startTime.classList.add('js-ci-start-times');
|
||||
startTime.dataset.date = call.date;
|
||||
startTime.textContent = Utils.prettyDate(call.date);
|
||||
|
||||
var durationElt = document.createElement('p');
|
||||
durationElt.classList.add('cd__duration');
|
||||
navigator.mozL10n.once(function() {
|
||||
if (call.duration === 0) {
|
||||
if (group.type === 'incoming') {
|
||||
durationElt.setAttribute('data-l10n-id', 'info-missed');
|
||||
} else {
|
||||
durationElt.setAttribute('data-l10n-id', 'canceled');
|
||||
}
|
||||
} else {
|
||||
Utils.prettyDuration(durationElt, call.duration,
|
||||
'callDurationTextFormat');
|
||||
}
|
||||
});
|
||||
|
||||
var row = document.createElement('div');
|
||||
row.classList.add('call-duration');
|
||||
row.appendChild(startTime);
|
||||
row.appendChild(durationElt);
|
||||
|
||||
callDurationsElt.appendChild(row);
|
||||
});
|
||||
}
|
||||
|
||||
function updateStartTimes() {
|
||||
var startTimeElts = document.querySelectorAll('.js-ci-start-times');
|
||||
for (var i=0, il=startTimeElts.length; i<il; i++) {
|
||||
var startTimeElt = startTimeElts[i];
|
||||
var date = parseInt(startTimeElt.dataset.date, 10);
|
||||
startTimeElt.textContent = Utils.prettyDate(date);
|
||||
}
|
||||
}
|
||||
|
||||
function renderPhones(group, contact) {
|
||||
var contactTels = contact.tel.map(function(tel) {
|
||||
return tel.value;
|
||||
});
|
||||
|
||||
if (!contactTels.some((tel) => tel != null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LazyLoader.load(['/shared/js/simple_phone_matcher.js'], function() {
|
||||
ContactsButtons.renderPhones(contact);
|
||||
|
||||
// Highlight the contact number that the call info page was opened for,
|
||||
// with a color depending on whether the call was missed or not.
|
||||
var remark = isMissedCall(group) ? 'remark-missed' : 'remark';
|
||||
|
||||
var groupTel = SimplePhoneMatcher.sanitizedNumber(
|
||||
group.number || group.contact.matchingTel.number);
|
||||
var groupTelVariants = SimplePhoneMatcher.generateVariants(groupTel);
|
||||
|
||||
// SimplePhoneMatch expects a series of contacts, so we pass it an array
|
||||
// containing only the relevant contact.
|
||||
contactTels = [contactTels];
|
||||
|
||||
var matchingTels = SimplePhoneMatcher.bestMatch(groupTelVariants,
|
||||
contactTels);
|
||||
var matchingTel = {value: ''};
|
||||
if (matchingTels.totalMatchNum) {
|
||||
matchingTel = contact.tel[matchingTels.allMatches[0][0]];
|
||||
}
|
||||
ContactsButtons.reMark('tel', matchingTel.value, remark);
|
||||
});
|
||||
}
|
||||
|
||||
function updateActionButtons(group) {
|
||||
listDetailsElt.innerHTML = '';
|
||||
|
||||
detailsButton.hidden = true;
|
||||
addToContactButton.hidden = true;
|
||||
createContactButton.hidden = true;
|
||||
|
||||
if (group.contact) {
|
||||
detailsButton.hidden = false;
|
||||
|
||||
Contacts.findByNumber(group.contact.matchingTel.number,
|
||||
function(contact, matchingTel) {
|
||||
ContactsButtons.renderEmails(contact);
|
||||
renderPhones(group, contact);
|
||||
});
|
||||
} else {
|
||||
addToContactButton.hidden = false;
|
||||
createContactButton.hidden = false;
|
||||
|
||||
var contact = {
|
||||
tel: [
|
||||
{
|
||||
value: group.number,
|
||||
type: 'mobile'
|
||||
}
|
||||
]
|
||||
};
|
||||
renderPhones(group, contact);
|
||||
}
|
||||
}
|
||||
|
||||
function close(evt) {
|
||||
if (evt.detail.type !== 'back') {
|
||||
return;
|
||||
}
|
||||
|
||||
window.removeEventListener('CallLogDbNewCall', updateViewIfNeeded);
|
||||
callInfoView.hidden = true;
|
||||
CallLog.showEditModeButton();
|
||||
}
|
||||
|
||||
function viewContact() {
|
||||
/*jshint nonew: false */
|
||||
new MozActivity({
|
||||
name: 'open',
|
||||
data: {
|
||||
type: 'webcontacts/contact',
|
||||
params: {id: currentGroup.contact.id}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function createNewContact() {
|
||||
launchActivity('new', currentGroup.number);
|
||||
}
|
||||
|
||||
function addToExistingContact() {
|
||||
launchActivity('update', currentGroup.number);
|
||||
}
|
||||
|
||||
function launchActivity(name, phoneNumber) {
|
||||
try {
|
||||
/* jshint nonew: false */
|
||||
new MozActivity({
|
||||
name: name,
|
||||
data: {
|
||||
type: 'webcontacts/contact',
|
||||
params: {
|
||||
'tel': phoneNumber
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('Error while creating activity');
|
||||
}
|
||||
}
|
||||
|
||||
function initListeners() {
|
||||
detailsButton = document.getElementById('call-info-details');
|
||||
detailsButton.addEventListener('click', viewContact);
|
||||
addToContactButton = document.getElementById('call-info-add');
|
||||
addToContactButton.addEventListener('click', addToExistingContact);
|
||||
createContactButton = document.getElementById('call-info-create');
|
||||
createContactButton.addEventListener('click', createNewContact);
|
||||
var header = document.getElementById('call-info-gaia-header');
|
||||
header.addEventListener('action', close);
|
||||
|
||||
window.addEventListener('timeformatchange', updateStartTimes);
|
||||
}
|
||||
|
||||
// FIXME/bug 1060290: The build system doesn't allow nested fragments, so we
|
||||
// can work around this for now by loading all elements at the root level and
|
||||
// then resolving them to the correct location, e.g. fragment-name-stub, on
|
||||
// runtime.
|
||||
function replaceFragmentStub(stub, fragment) {
|
||||
var parent = stub.parentNode;
|
||||
parent.insertBefore(fragment, stub);
|
||||
parent.removeChild(stub);
|
||||
fragment.hidden = false;
|
||||
}
|
||||
|
||||
function initFragments() {
|
||||
var phoneDetailsStub = document.getElementById('phone-details-stub');
|
||||
phoneDetailsElt = document.getElementById('phone-details');
|
||||
|
||||
var emailDetailsStub = document.getElementById('email-details-stub');
|
||||
emailDetailsElt = document.getElementById('email-details');
|
||||
|
||||
var contactDetailsElt = document.getElementById('contact-detail');
|
||||
listDetailsElt = document.getElementById('call-info-list-details');
|
||||
|
||||
LazyLoader.load([phoneDetailsElt, emailDetailsElt], function() {
|
||||
replaceFragmentStub(phoneDetailsStub, phoneDetailsElt);
|
||||
replaceFragmentStub(emailDetailsStub, emailDetailsElt);
|
||||
|
||||
ContactsButtons.init(listDetailsElt, contactDetailsElt);
|
||||
});
|
||||
}
|
||||
|
||||
var CallInfo = {
|
||||
_initialised: false,
|
||||
show: function(number, date, type, status) {
|
||||
callInfoView = document.getElementById('call-info-view');
|
||||
var self = this;
|
||||
LazyLoader.load([callInfoView,
|
||||
'/shared/js/dialer/contacts.js',
|
||||
'/shared/js/dialer/utils.js',
|
||||
'/shared/js/contacts/contacts_buttons.js',
|
||||
'/shared/js/contacts/utilities/templates.js',
|
||||
'/shared/js/contacts/sms_integration.js',
|
||||
'/shared/js/text_normalizer.js',
|
||||
'/dialer/js/telephony_helper.js',
|
||||
'/shared/style/contacts/contacts_buttons.css',
|
||||
'/shared/style/contacts.css',
|
||||
'/dialer/style/buttons.css'], function() {
|
||||
if (!self._initialised) {
|
||||
self._initialised = true;
|
||||
initListeners();
|
||||
initFragments();
|
||||
}
|
||||
date = parseInt(date, 10);
|
||||
CallLogDBManager.getGroup(number, date, type, status)
|
||||
.then(updateView);
|
||||
|
||||
window.addEventListener('CallLogDbNewCall', updateViewIfNeeded);
|
||||
});
|
||||
}
|
||||
};
|
||||
exports.CallInfo = CallInfo;
|
||||
})(window);
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
;'use strict';var CallLog={_initialized:false,_headersInterval:null,_empty:true,_contactCache:false,init:function cl_init(){if(this._initialized){this.becameVisible();return;}
|
||||
window.performance.mark('callLogStart');this._initialized=true;var lazyFiles=['/shared/style/confirm.css','/shared/style/switches.css','/shared/style/lists.css','/shared/js/confirm.js','/shared/js/dialer/utils.js','/shared/js/sticky_header.js','/shared/js/sim_settings_helper.js','/shared/js/date_time_helper.js'];var self=this;var validContactsCachePromise=this._validateContactsCache();LazyLoader.load(lazyFiles,function resourcesLoaded(){var mainNodes=['all-filter','call-log-container','call-log-edit-mode','call-log-filter','call-log-icon-edit','call-log-view','deselect-all-threads','delete-button','edit-mode-header','header-edit-mode-text','missed-filter','select-all-threads','edit-mode'];mainNodes.forEach(function(id){this[Utils.toCamelCase(id)]=document.getElementById(id);},self);var dualSim=!!navigator.mozIccManager&&navigator.mozIccManager.iccIds.length>1;self.callLogContainer.classList.toggle('dual-sim',dualSim);validContactsCachePromise.then(function(){self.render();window.addEventListener('timeformatchange',self._updateCallTimes.bind(self));self.callLogIconEdit.addEventListener('click',self.showEditMode.bind(self));self.editModeHeader.addEventListener('action',self.hideEditMode.bind(self));self.missedFilter.addEventListener('click',self.filter.bind(self));self.allFilter.addEventListener('click',self.unfilter.bind(self));self.callLogContainer.addEventListener('click',self);self.callLogContainer.addEventListener('contextmenu',self);self.selectAllThreads.addEventListener('click',self.selectAll.bind(self));self.deselectAllThreads.addEventListener('click',self.deselectAll.bind(self));self.deleteButton.addEventListener('click',self.deleteLogGroups.bind(self));document.addEventListener('visibilitychange',function(){if(document.hidden){self.pauseHeaders();}else{self.updateHeadersContinuously();if(Navigation.currentView==='recents'){self.becameVisible();}}});self.sticky=new StickyHeader(self.callLogContainer,document.getElementById('sticky'));self.becameVisible();});});},_validateContactsCache:function cl_validateContactsCache(){var self=this;return new Promise(function(resolve,reject){window.asyncStorage.getItem('contactCacheRevision',function onItem(cacheRevision){Contacts.getRevision(function(contactsRevision){if(cacheRevision>contactsRevision){window.asyncStorage.setItem('contactCacheRevision',contactsRevision);self._contactCache=true;resolve();return;}
|
||||
self._contactCache=(cacheRevision>=contactsRevision);if(self._contactCache){resolve();return;}
|
||||
CallLogDBManager.invalidateContactsCache(function(error){if(!error){self._contactCache=true;resolve();}});});});});},_updateCallTimes:function cl_updateCallTimes(){var logItemElts=this.callLogContainer.querySelectorAll('.log-item');for(var i=0;i<logItemElts.length;i++){var logItemElt=logItemElts[i];var timestamp=logItemElt.getAttribute('data-timestamp');var formattedTime=Utils.prettyDate(parseInt(timestamp,10));var callTimeElt=logItemElt.querySelector('.call-time');callTimeElt.textContent=formattedTime;}},becameVisible:function cl_becameVisible(){this.updateHeaders();this.cleanNotifications();},updateHeaders:function cl_updateHeaders(){var headers=this.callLogContainer.getElementsByTagName('header');for(var i=0,l=headers.length;i<l;i++){var current=headers[i];Utils.setHeaderDate(current,parseInt(current.dataset.timestamp));}},updateHeadersContinuously:function cl_updateHeaders(){var updater=this.updateHeaders.bind(this);this._headersInterval=setInterval(updater,60000);},pauseHeaders:function cl_pauseHeaders(){clearInterval(this._headersInterval);},render:function cl_render(){var self=this;var daysToRender=[];var chunk=[];var prevDate;var screenRendered=false;var MAX_GROUPS_FOR_FIRST_RENDER=8;var MAX_GROUPS_TO_BATCH_RENDER=100;var batchGroupCounter=0;CallLogDBManager.getGroupList(function logGroupsRetrieved(cursor){if(!cursor.value){if(chunk.length===0){self.renderEmptyCallLog();self.disableEditModeButton();}else{daysToRender.push(chunk);self.renderSeveralDays(daysToRender);if(!screenRendered){window.performance.mark('firstChunkReady');}
|
||||
self.enableEditModeButton();self.sticky.refresh();self.updateHeadersContinuously();}
|
||||
window.performance.measure('callLogReady','callLogStart');return;}
|
||||
self._empty=false;var currDate=new Date(cursor.value.date);batchGroupCounter++;if(!prevDate||(currDate.getTime()==prevDate.getTime())){chunk.push(cursor.value);}else{daysToRender.push(chunk);chunk=[cursor.value];var renderNow=false;if(batchGroupCounter>=MAX_GROUPS_FOR_FIRST_RENDER&&!screenRendered){renderNow=true;screenRendered=true;window.performance.mark('firstChunkReady');}else if(batchGroupCounter>=MAX_GROUPS_TO_BATCH_RENDER){renderNow=true;}
|
||||
if(renderNow){self.renderSeveralDays(daysToRender);daysToRender=[];batchGroupCounter=0;}}
|
||||
prevDate=currDate;cursor.continue();},'lastEntryDate',true,true);},renderSeveralDays:function cl_renderSeveralDays(chunks){for(var i=0,l=chunks.length;i<l;i++){this.renderChunk(chunks[i]);}},renderChunk:function cl_renderChunk(chunk){var callLogSection=this.createSectionForGroup(chunk[0]);var phoneNumbers=[];var logGroupContainer=callLogSection.getElementsByTagName('ol')[0];for(var i=0;i<chunk.length;i++){var current=chunk[i];var logGroupDOM=this.createGroup(current);logGroupContainer.appendChild(logGroupDOM);phoneNumbers.push(current.number);}
|
||||
this.callLogContainer.appendChild(callLogSection);if(!this._contactCache){this.updateListWithContactInfo(null,null,phoneNumbers,logGroupContainer);}},renderEmptyCallLog:function cl_renderEmptyCallLog(isEmptyMissedCallsGroup){this.disableEditModeButton();if(!isEmptyMissedCallsGroup){this._empty=true;}
|
||||
var noResultContainer=document.getElementById('no-result-container');noResultContainer.hidden=false;var allCallsMsg1=document.getElementById('no-result-msg1');var allCallsMsg2=document.getElementById('no-result-msg2');var noMissedCallsMsg=document.getElementById('no-result-msg3');allCallsMsg1.hidden=isEmptyMissedCallsGroup||false;allCallsMsg2.hidden=isEmptyMissedCallsGroup||false;noMissedCallsMsg.hidden=!isEmptyMissedCallsGroup;if(!isEmptyMissedCallsGroup){var noResultContainerClone=noResultContainer.cloneNode(true);this.callLogContainer.innerHTML='';this.callLogContainer.appendChild(noResultContainerClone);}},appendGroup:function cl_appendGroup(group){if(!this._initialized){return;}
|
||||
this.unfilter();this.enableEditModeButton();var logGroupDOM=this.createGroup(group);var dayIndex=group.date;var container=this.callLogContainer;var previousLogGroup=document.getElementById(group.id);if(previousLogGroup){var parent=previousLogGroup.parentNode;parent.removeChild(previousLogGroup);this.insertInSection(logGroupDOM,parent);return logGroupDOM;}
|
||||
var groupSelector='[data-timestamp="'+dayIndex+'"]';var sectionExists=container.querySelector(groupSelector);if(sectionExists){var section=sectionExists.getElementsByTagName('ol')[0];this.insertInSection(logGroupDOM,section);return logGroupDOM;}
|
||||
var callLogSection=this.createSectionForGroup(group);var logGroupContainer=callLogSection.getElementsByTagName('ol')[0];logGroupContainer.appendChild(logGroupDOM);var previousSections=container.getElementsByTagName('section');var referenceSection;var previousSectionsLength=previousSections.length;for(var i=0;i<previousSectionsLength;i++){var current=previousSections[i];if(dayIndex>current.dataset.timestamp){referenceSection=current;break;}}
|
||||
if(referenceSection){container.insertBefore(callLogSection,referenceSection);}else{if(this._empty){var noResultContainer=document.getElementById('no-result-container').cloneNode(true);container.innerHTML='';noResultContainer.hidden=true;container.appendChild(noResultContainer);this._empty=false;}
|
||||
container.appendChild(callLogSection);}
|
||||
this.sticky.refresh();return logGroupDOM;},insertInSection:function cl_insertInSect(group,section){var groups=section.getElementsByTagName('li');var groupsLength=groups.length;var referenceGroup;var date=group.dataset.timestamp;for(var i=0;i<groupsLength;i++){var current=groups[i];if(parseInt(date)>parseInt(current.dataset.timestamp)){referenceGroup=current;break;}}
|
||||
if(referenceGroup){section.insertBefore(group,referenceGroup);}else{section.appendChild(group);}},createGroup:function cl_createGroup(group){var date=group.lastEntryDate;var number=group.number;var type=group.type;var emergency=group.emergency;var voicemail=group.voicemail;var status=group.status||'';var contact=group.contact;var groupDOM=document.createElement('li');groupDOM.classList.add('log-item');groupDOM.dataset.timestamp=date;groupDOM.dataset.phoneNumber=number;groupDOM.dataset.type=type;groupDOM.setAttribute('role','option');groupDOM.setAttribute('aria-selected',false);if(contact&&contact.id){groupDOM.dataset.contactId=contact.id;}
|
||||
groupDOM.id=group.id;var iconStyle='icon ';switch(type){case'dialing':case'alerting':iconStyle+='icon-outgoing';break;case'incoming':groupDOM.dataset.status=status;if(status==='connected'){iconStyle+='icon-incoming';}else{iconStyle+='icon-missed';groupDOM.classList.add('missed-call');}
|
||||
break;}
|
||||
if(typeof group.serviceId!=='undefined'){var serviceClass=(parseInt(group.serviceId)===0)?'first-sim':'second-sim';iconStyle+=' '+serviceClass;}
|
||||
var label=document.createElement('label');label.setAttribute('aria-hidden',true);label.className='pack-checkbox call-log-selection danger';var input=document.createElement('input');input.setAttribute('type','checkbox');input.value=group.id;var span=document.createElement('span');label.appendChild(input);label.appendChild(span);var main=document.createElement('a');main.setAttribute('role','presentation');var icon=document.createElement('aside');icon.className='icon call-type-icon '+iconStyle;var primInfo=document.createElement('p');primInfo.className='primary-info';var primInfoMain=document.createElement('span');primInfoMain.className='primary-info-main';var bdi=document.createElement('bdi');if(contact&&contact.primaryInfo){bdi.textContent=contact.primaryInfo;}else{if(number){bdi.textContent=number;}else{bdi.setAttribute('data-l10n-id','withheld-number');}}
|
||||
primInfoMain.appendChild(bdi);primInfo.appendChild(primInfoMain);if(group.retryCount&&group.retryCount>1){var retryCount=document.createElement('span');retryCount.className='retry-count';retryCount.textContent='('+group.retryCount+')';primInfo.appendChild(retryCount);}
|
||||
var phoneNumberAdditionalInfo='';var phoneNumberTypeL10nId=null;if(contact&&contact.matchingTel){phoneNumberAdditionalInfo=Utils.getPhoneNumberAdditionalInfo(contact.matchingTel);}else if(voicemail||emergency){phoneNumberAdditionalInfo={raw:number};phoneNumberTypeL10nId=voicemail?'voiceMail':(emergency?'emergencyNumber':null);}else{phoneNumberAdditionalInfo={id:'unknown'};}
|
||||
var addInfo=document.createElement('p');addInfo.className='additional-info';addInfo.setAttribute('aria-hidden','true');var typeAndCarrier=document.createElement('span');typeAndCarrier.className='type-carrier';if(phoneNumberAdditionalInfo){if(phoneNumberAdditionalInfo.raw){typeAndCarrier.removeAttribute('data-l10n-id');typeAndCarrier.textContent=phoneNumberAdditionalInfo.raw;}else{navigator.mozL10n.setAttributes(typeAndCarrier,phoneNumberAdditionalInfo.id,phoneNumberAdditionalInfo.args);}}
|
||||
addInfo.appendChild(typeAndCarrier);var callTime=document.createElement('span');callTime.className='call-time';callTime.textContent=Utils.prettyDate(date)+' ';addInfo.appendChild(callTime);main.appendChild(icon);main.appendChild(primInfo);main.appendChild(addInfo);if(phoneNumberTypeL10nId){var bdiPrim=primInfoMain.querySelector('bdi');primInfoMain.removeChild(bdiPrim);primInfoMain.setAttribute('data-l10n-id',phoneNumberTypeL10nId);var primElem=primInfoMain.parentNode;var parent=primElem.parentNode;parent.insertBefore(addInfo,primElem.nextElementSibling);}
|
||||
groupDOM.appendChild(label);groupDOM.appendChild(main);return groupDOM;},createSectionForGroup:function cl_createSectionForGroup(group){var referenceTimestamp=group.date;var groupContainer=document.createElement('section');groupContainer.dataset.timestamp=referenceTimestamp;var header=document.createElement('header');Utils.setHeaderDate(header,referenceTimestamp);header.dataset.timestamp=referenceTimestamp;header.id='header-'+referenceTimestamp;header.dataset.update=true;var ol=document.createElement('ol');ol.classList.add('log-group');ol.setAttribute('role','listbox');ol.setAttribute('aria-multiselectable',true);ol.id='group-container-'+referenceTimestamp;groupContainer.appendChild(header);groupContainer.appendChild(ol);return groupContainer;},enableEditModeButton:function cl_enableEditModeButton(){CallLog.callLogIconEdit.removeAttribute('disabled');},disableEditModeButton:function cl_disableEditModeButton(){CallLog.callLogIconEdit.setAttribute('disabled','disabled');},showEditModeButton:function cl_showEditModeButton(){CallLog.callLogIconEdit.hidden=false;},hideEditModeButton:function cl_hideEditModeButton(){CallLog.callLogIconEdit.hidden=true;},showEditMode:function cl_showEditMode(event){if(this.callLogIconEdit.hasAttribute('disabled')){event.preventDefault();event.stopPropagation();return;}
|
||||
this.editMode.removeAttribute('hidden');this.headerEditModeText.setAttribute('data-l10n-id','edit');this.deleteButton.setAttribute('disabled','disabled');this.selectAllThreads.removeAttribute('disabled');this.selectAllThreads.setAttribute('data-l10n-id','selectAll');this.deselectAllThreads.setAttribute('disabled','disabled');document.body.classList.add('recents-edit');},hideEditMode:function cl_hideEditMode(){document.body.classList.remove('recents-edit');var cont=this.callLogContainer;var inputs=cont.querySelectorAll('input[type="checkbox"]');var logItems=cont.querySelectorAll('.log-item');var i,l;for(i=0,l=inputs.length;i<l;i++){inputs[i].checked=false;}
|
||||
for(i=0,l=logItems.length;i<l;i++){logItems[i].setAttribute('aria-selected',false);}
|
||||
if(this.callLogContainer.classList.contains('filter')){this.filter();}else{this.unfilter();}
|
||||
this.editMode.setAttribute('hidden','');},handleEvent:function cl_handleEvent(evt){var logItem=evt.target;if(document.body.classList.contains('recents-edit')){if(logItem.dataset.phoneNumber){var checkbox=logItem.getElementsByTagName('input')[0];var toggleChecked=!checkbox.checked;checkbox.checked=toggleChecked;logItem.setAttribute('aria-selected',toggleChecked);}
|
||||
this.updateHeaderCount();return;}
|
||||
var dataset=logItem.dataset;var phoneNumber=dataset.phoneNumber;if(!phoneNumber){return;}
|
||||
if(evt.type=='click'){if(navigator.mozIccManager&&navigator.mozIccManager.iccIds.length>1){KeypadManager.updatePhoneNumber(phoneNumber);Navigation.showKeypad();}else{SimSettingsHelper.getCardIndexFrom('outgoingCall',function(ci){CallHandler.call(phoneNumber,ci);});}}else{evt.preventDefault();var primaryInfo=logItem.querySelector('.primary-info-main').textContent;LazyLoader.load(['/dialer/js/call_group_menu.js'],function(){CallGroupMenu.show(primaryInfo,phoneNumber,dataset.timestamp,dataset.type,dataset.status);});}},filter:function cl_filter(){this.callLogContainer.classList.add('filter');AccessibilityHelper.setAriaSelected(this.missedFilter.firstElementChild,[this.allFilter.firstElementChild,this.missedFilter.firstElementChild]);this.callLogContainer.setAttribute('aria-labelledby','missed-filter-tab');var containers=this.callLogContainer.getElementsByTagName('ol');var totalMissedCalls=0;for(var i=0,l=containers.length;i<l;i++){var noMissedCalls=containers[i].getElementsByClassName('missed-call');if(noMissedCalls.length===0){containers[i].parentNode.classList.add('groupFiltered');}
|
||||
totalMissedCalls+=noMissedCalls.length;}
|
||||
if(totalMissedCalls===0){this.renderEmptyCallLog(true);}else{var noResultContainer=document.getElementById('no-result-container');noResultContainer.hidden=true;this.enableEditModeButton();}},unfilter:function cl_unfilter(){var logItems=this.callLogContainer.querySelectorAll('.log-item');if(logItems.length===0){this.renderEmptyCallLog();}else{var noResultContainer=document.getElementById('no-result-container');noResultContainer.hidden=true;this.enableEditModeButton();}
|
||||
this.callLogContainer.classList.remove('filter');AccessibilityHelper.setAriaSelected(this.allFilter.firstElementChild,[this.allFilter.firstElementChild,this.missedFilter.firstElementChild]);this.callLogContainer.setAttribute('aria-labelledby','all-filter-tab');var hiddenContainers=document.getElementsByClassName('groupFiltered');for(var i=(hiddenContainers.length-1);i>=0;i--){hiddenContainers[i].classList.remove('groupFiltered');}},updateHeaderCount:function cl_updateHeaderCount(){var selector=this.callLogContainer.classList.contains('filter')?'li.missed-call input[type="checkbox"]:checked':'input[type="checkbox"]:checked';var allSelector=this.callLogContainer.classList.contains('filter')?'li.missed-call input[type="checkbox"]':'input[type="checkbox"]';var selected=this.callLogContainer.querySelectorAll(selector).length;var allInputs=this.callLogContainer.querySelectorAll(allSelector).length;if(selected===0){this.headerEditModeText.setAttribute('data-l10n-id','edit');this.selectAllThreads.removeAttribute('disabled');this.selectAllThreads.setAttribute('data-l10n-id','selectAll');this.deselectAllThreads.setAttribute('disabled','disabled');this.deleteButton.setAttribute('disabled','disabled');return;}
|
||||
navigator.mozL10n.setAttributes(this.headerEditModeText,'edit-selected',{n:selected});this.deleteButton.removeAttribute('disabled');if(selected===allInputs){this.deselectAllThreads.removeAttribute('disabled');this.selectAllThreads.setAttribute('disabled','disabled');}else{this.selectAllThreads.removeAttribute('disabled');this.selectAllThreads.setAttribute('data-l10n-id','selectAll');this.deselectAllThreads.removeAttribute('disabled');}},selectAll:function cl_selectAll(){var selector=this.callLogContainer.classList.contains('filter')?'li.missed-call input[type="checkbox"]:not(:checked)':'input[type="checkbox"]:not(:checked)';var inputs=this.callLogContainer.querySelectorAll(selector);for(var i=0,l=inputs.length;i<l;i++){inputs[i].checked=true;}
|
||||
this.updateHeaderCount();},deselectAll:function cl_selectAll(){var selector='input[type="checkbox"]:checked';var inputs=this.callLogContainer.querySelectorAll(selector);for(var i=0,l=inputs.length;i<l;i++){inputs[i].checked=false;}
|
||||
this.updateHeaderCount();},deleteLogGroups:function cl_deleteLogGroups(){var selector='input[type="checkbox"]:checked';var inputsSelected=this.callLogContainer.querySelectorAll(selector);var self=this;var msg={'id':'delete-n-log?','args':{n:inputsSelected.length}};var yesObject={title:'delete',isDanger:true,callback:function deleteLogGroup(){ConfirmDialog.hide();var logGroupsToDelete=[];for(var i=0,l=inputsSelected.length;i<l;i++){var logGroup=inputsSelected[i].parentNode.parentNode;var olContainer=logGroup.parentNode;olContainer.removeChild(logGroup);if(olContainer.children.length===0){var section=olContainer.parentNode;self.callLogContainer.removeChild(section);}
|
||||
var dataset=logGroup.dataset;var toDelete={date:parseInt(dataset.timestamp),number:dataset.phoneNumber===null?'':dataset.phoneNumber,type:dataset.type};if(dataset.status){toDelete.status=dataset.status;}
|
||||
logGroupsToDelete.push(toDelete);}
|
||||
CallLogDBManager.deleteGroupList(logGroupsToDelete,function(){self.hideEditMode();});}};var noObject={title:'cancel',callback:function onCancel(){ConfirmDialog.hide();}};ConfirmDialog.show(null,msg,noObject,yesObject);},_updateContact:function _updateContact(log,phoneNumber,contactId,updateDb){var self=this;Contacts.findByNumber(phoneNumber,function(contact,matchingTel){if(!contact||!matchingTel){self._removeContact(log,contactId,updateDb);return;}
|
||||
if(self._contactCache&&updateDb){CallLogDBManager.updateGroupContactInfo(contact,matchingTel,function(result){if(typeof result==='number'&&result>0){self.updateContactInfo(log,contact,matchingTel);}});}else{self.updateContactInfo(log,contact,matchingTel);}});},_removeContact:function _removeContact(log,contactId,updateDb){if(this._contactCache&&updateDb){var self=this;CallLogDBManager.removeGroupContactInfo(contactId,null,function(result){if(typeof result==='number'&&result>0){self.updateContactInfo(log);}});}else{this.updateContactInfo(log);}},updateListWithContactInfo:function cl_updateList(reason,contactId,target){var container=target||this.callLogContainer;if(!container){return;}
|
||||
var logs=[];switch(reason){case'remove':logs=container.querySelectorAll('li[data-contact-id="'+contactId+'"]');break;default:logs=container.querySelectorAll('.log-item');break;}
|
||||
for(var i=0,l=logs.length;i<l;i++){var log=logs[i];var logInfo=log.dataset;this._updateContact(log,logInfo.phoneNumber,contactId,i===0);}},updateContactInfo:function cl_updateContactInfo(element,contact,matchingTel){var primInfoCont=element.querySelector('.primary-info-main');var addInfo=element.getElementsByClassName('additional-info')[0];var typeAndCarrier=addInfo.querySelector('.type-carrier');if(!matchingTel){if(element.dataset.contactId){primInfoCont.textContent='';var bdi=document.createElement('bdi');bdi.textContent=element.dataset.phoneNumber;primInfoCont.appendChild(bdi);typeAndCarrier.textContent='';typeAndCarrier.setAttribute('data-l10n-id','unknown');delete element.dataset.contactId;}
|
||||
return;}
|
||||
var primaryInfo=Utils.getPhoneNumberPrimaryInfo(matchingTel,contact);if(primaryInfo){primInfoCont.textContent='';var bdiPrim=document.createElement('bdi');bdiPrim.textContent=primaryInfo;primInfoCont.appendChild(bdiPrim);}
|
||||
var phoneNumberAdditionalInfo=Utils.getPhoneNumberAdditionalInfo(matchingTel);navigator.mozL10n.setAttributes(typeAndCarrier,phoneNumberAdditionalInfo.id,phoneNumberAdditionalInfo.args);if(contact){element.dataset.contactId=contact.id;}},cleanNotifications:function cl_cleanNotifcations(){Notification.get().then(function onSuccess(notifications){for(var i=0;i<notifications.length;i++){if(!notifications[i].tag){notifications[i].close();}}},function onError(reason){console.debug('Call log Notification.get() promise error: '+reason);});},_getGroupFromLog:function cl_getGroupFromLog(log){if(!log){return;}
|
||||
var data=log.dataset;if(!data||!data.id){return;}
|
||||
var groupId=data.id.split('-');var group={date:groupId[0],number:groupId[1],type:groupId[2]};if(data.status){group.status=data.status;}
|
||||
return group;}};navigator.mozContacts.oncontactchange=function oncontactchange(event){var reason=event.reason;var options={filterBy:['id'],filterOp:'equals',filterValue:event.contactID};if(reason==='remove'){CallLog.updateListWithContactInfo('remove',event.contactID);return;}
|
||||
var request=navigator.mozContacts.find(options);request.onsuccess=function contactRetrieved(e){if(!e.target.result||e.target.result.length===0){console.warn('Call log: No Contact Found: ',event.contactID);return;}
|
||||
var contact=e.target.result[0];if(!fb.isFbContact(contact)){CallLog.updateListWithContactInfo(reason,event.contactID);return;}
|
||||
var fbReq=fb.getData(contact);fbReq.onsuccess=function fbContactSuccess(){CallLog.updateListWithContactInfo(reason,event.contactID);};fbReq.onerror=function fbContactError(){console.error('Error while querying FB: ',fbReq.error.name);CallLog.updateListWithContactInfo(reason,event.contactID);};};request.onerror=function errorHandler(e){console.error('Error retrieving contact by ID '+event.contactID);};};
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
;'use strict';var CallLogDBManager={_db:null,_dbName:'dialerRecents',_dbRecentsStore:'dialerRecents',_dbGroupsStore:'dialerGroups',_dbVersion:6,_maxNumberOfGroups:200,_numberOfGroupsToDelete:30,_asyncReturn:function _asyncReturn(callback,result){if(callback&&callback instanceof Function){callback(result);}},_ensureDB:function ensureDB(callback){if(this._db){callback(null,this._db);return;}
|
||||
LazyLoader.load(['/shared/js/dialer/utils.js','/shared/js/dialer/contacts.js'],(function(){try{var indexedDB=window.indexedDB||window.webkitIndexedDB||window.mozIndexedDB||window.msIndexedDB;if(!indexedDB){callback('NO_INDEXED_DB_AVAILABLE',null);return;}
|
||||
var self=this;var request=indexedDB.open(this._dbName,this._dbVersion);request.onsuccess=(function onsuccess(event){this._db=event.target.result;callback(null,this._db);}).bind(this);request.onerror=function onerror(event){callback(event.target.errorCode,null);};request.onblocked=function onblocked(){callback('DB_REQUEST_BLOCKED',null);};request.onupgradeneeded=function onupgradeneeded(event){var db=event.target.result;var txn=event.target.transaction;var currentVersion=event.oldVersion;function update(currentVersion){var next=update.bind(self,currentVersion+1);switch(currentVersion){case 0:self._createSchema(db,next);break;case 1:self._upgradeSchemaVersion2(db,txn,next);break;case 2:self._upgradeSchemaVersion3(next);break;case 3:self._upgradeSchemaVersion4(db,txn,next);break;case 4:self._upgradeSchemaVersion5(next);break;case 5:self._upgradeSchemaVersion6(db,txn,next);break;case 6:break;default:event.target.transaction.abort();break;}
|
||||
currentVersion++;}
|
||||
update(currentVersion);};}catch(ex){callback(ex.message,null);}}).bind(this));},_newTxn:function newTxn(txnType,objectStores,callback){if(!objectStores){objectStores=[this._dbGroupsStore];}
|
||||
if(!Array.isArray(objectStores)){objectStores=[objectStores];}
|
||||
this._ensureDB(function(error,db){if(error){callback(error);return;}
|
||||
var txn=db.transaction(objectStores,txnType);var stores;if(objectStores.length===1){stores=txn.objectStore(objectStores[0]);}else{stores=[];for(var i=0;i<objectStores.length;i++){stores.push(txn.objectStore(objectStores[i]));}}
|
||||
callback(null,txn,stores);});},close:function rbdm_close(){this._db.close();this._db=null;},_createSchema:function createSchema(db,next){var objStore=db.createObjectStore(this._dbRecentsStore,{keyPath:'date'});objStore.createIndex('number','number');next();},_upgradeSchemaVersion2:function upgradeSchemaVersion2(db,transaction,next){db.createObjectStore(this._dbGroupsStore,{keyPath:'id'});var recentsStore=transaction.objectStore(this._dbRecentsStore);recentsStore.createIndex('groupId','groupId');next();},_upgradeSchemaVersion3:function upgradeSchemaVersion3(next){next();},_upgradeSchemaVersion4:function upgradeSchemaVersion4(db,transaction,next){var groupsStore=transaction.objectStore(this._dbGroupsStore);groupsStore.createIndex('number','number');groupsStore.createIndex('contactId','contactId');groupsStore.createIndex('lastEntryDate','lastEntryDate');next();},_upgradeSchemaVersion5:function upgradeSchemaVersion5(next){next();},_upgradeSchemaVersion6:function upgradeSchemaVersion6(db,transaction,next){db.deleteObjectStore(this._dbRecentsStore);next();},_getDayDate:function getDayDate(timestamp){var time=new Date(+timestamp);time.setHours(0,0,0,0);return time.getTime();},_getGroupId:function getGroupId(recentCall){var groupId=[this._getDayDate(recentCall.date),(recentCall.number||''),recentCall.type];if(recentCall.status&&recentCall.type==='incoming'){groupId.push(recentCall.status);}
|
||||
return groupId;},_getGroupObject:function getGroupObject(group){if(!Array.isArray(group.id)||group.id.length<3){return null;}
|
||||
var contact;if(group.contactId){contact={id:group.contactId,primaryInfo:group.contactPrimaryInfo,matchingTel:{number:group.id[1],type:group.contactMatchingTelType,carrier:group.contactMatchingTelCarrier},photo:group.contactPhoto};}
|
||||
return{id:group.id.join('-'),date:group.id[0],number:group.id[1],serviceId:group.serviceId,type:group.id[2],status:group.id[3]||undefined,lastEntryDate:group.lastEntryDate,retryCount:group.retryCount,contact:contact,emergency:group.emergency,voicemail:!!(group.id[1]&&group.voicemail),calls:group.calls};},_keepDbPrettyAndFit:function _keepDbPrettyAndFit(txn,callback){var self=this;var store=txn.objectStore(this._dbGroupsStore);var req=store.count();req.onsuccess=function(){var groupsToDelete=req.result-self._maxNumberOfGroups;if(groupsToDelete>0){groupsToDelete+=self._numberOfGroupsToDelete;var cursorReq=store.index('lastEntryDate').openCursor();cursorReq.onsuccess=function(){var cursor=cursorReq.result;if(!cursor||!groupsToDelete){return;}
|
||||
groupsToDelete--;self.deleteGroup(null,cursor.value.id);cursor.continue();};}};txn.oncomplete=function(){if(callback&&callback instanceof Function){callback();}};},add:function add(recentCall,callback){if(typeof recentCall!=='object'){callback('INVALID_CALL');return;}
|
||||
var self=this;this._newTxn('readwrite',this._dbGroupsStore,function(error,txn,groupsStore){if(error){self._asyncReturn(callback,error);return;}
|
||||
var groupId=self._getGroupId(recentCall);groupsStore.get(groupId).onsuccess=function onsuccess(){var group=this.result;if(group){self._updateExistingGroup(group,recentCall,txn,callback);}else{self._createNewGroup(groupId,recentCall,callback);}};});},_updateExistingGroup:function(group,recentCall,txn,callback){var groupsStore=txn.objectStore(this._dbGroupsStore);var groupObject;var self=this;txn.oncomplete=function(){self._dispatchCallLogDbNewCall(groupObject);self._asyncReturn(callback,groupObject);};if(group.lastEntryDate<=recentCall.date){group.lastEntryDate=recentCall.date;group.serviceId=recentCall.serviceId;group.emergency=recentCall.emergency;group.voicemail=recentCall.voicemail;}
|
||||
group.calls=group.calls||[];group.calls.unshift({date:recentCall.date,duration:recentCall.duration});group.retryCount++;groupsStore.put(group).onsuccess=function onsuccess(){groupObject=self._getGroupObject(group);};},_createNewGroup:function(groupId,recentCall,callback){var self=this;var group={id:groupId,number:recentCall.number,serviceId:recentCall.serviceId,lastEntryDate:recentCall.date,retryCount:1,emergency:recentCall.emergency,voicemail:recentCall.voicemail,calls:[{date:recentCall.date,duration:recentCall.duration}]};Contacts.findByNumber(recentCall.number,function(contact,matchingTel){if(contact&&contact!==null){group.contactId=contact.id;var photo=ContactPhotoHelper.getThumbnail(contact);if(photo){group.contactPhoto=photo;}
|
||||
if(matchingTel){var primaryInfo=Utils.getPhoneNumberPrimaryInfo(matchingTel,contact);if(Array.isArray(primaryInfo)){primaryInfo=primaryInfo[0];}
|
||||
group.contactPrimaryInfo=String(primaryInfo);if(Array.isArray(matchingTel.type)&&matchingTel.type[0]){group.contactMatchingTelType=String(matchingTel.type[0]);}else{group.contactMatchingTelType=String(matchingTel.type);}
|
||||
if(matchingTel.carrier){group.contactMatchingTelCarrier=String(matchingTel.carrier);}}}
|
||||
self._newTxn('readwrite',[self._dbGroupsStore],function(error,txn,store){if(error){self._asyncReturn(callback,error);return;}
|
||||
store.get(groupId).onsuccess=function onsuccess(){if(this.result){return;}
|
||||
store.add(group).onsuccess=function onsuccess(){var groupObject=self._getGroupObject(group);self._dispatchCallLogDbNewCall(groupObject);self._keepDbPrettyAndFit(txn,function(){self._asyncReturn(callback,groupObject);});};};});});},_dispatchCallLogDbNewCall:function(group){var createOrUpdateEvt=new CustomEvent('CallLogDbNewCall',{detail:{group:group}});window.dispatchEvent(createOrUpdateEvt);},deleteGroup:function deleteGroup(group,groupId,callback){if(!groupId&&(!group||typeof group!=='object'||!group.date||!group.type)){callback('NOT_VALID_GROUP');return;}
|
||||
var self=this;this._newTxn('readwrite',this._dbGroupsStore,function(error,txn,groupsStore){if(error){self._asyncReturn(callback,error);return;}
|
||||
if(!groupId){groupId=self._getGroupId(group);}
|
||||
txn.oncomplete=function(){self._asyncReturn(callback);};groupsStore.delete(groupId);});},deleteGroupList:function deleteGroupList(groupList,callback){var self=this;if(groupList.length>0){var itemToDelete=groupList.pop();if(typeof itemToDelete!=='object'){self._asyncReturn(callback,'INVALID_GROUP_IN_LIST');return;}
|
||||
var ondeleted=function ondeleted(result){if(result){self._asyncReturn(callback,result);return;}
|
||||
self.deleteGroupList(groupList,callback);};self.deleteGroup(itemToDelete,null,ondeleted);}else{self._asyncReturn(callback);}},deleteAll:function deleteAll(callback){var self=this;this._newTxn('readwrite',this._dbGroupsStore,function(error,txn,groupsStore){if(error){self._asyncReturn(callback,error);return;}
|
||||
txn.oncomplete=function(){self._asyncReturn(callback);};groupsStore.clear();});},deleteDb:function deleteDb(callback){var indexedDB=window.indexedDB||window.webkitIndexedDB||window.mozIndexedDB||window.msIndexedDB;if(!indexedDB){callback('NO_INDEXEDDB_AVAILABLE');return;}
|
||||
if(this._db){this._db.close();}
|
||||
var self=this;var req=indexedDB.deleteDatabase(this._dbName);req.onsuccess=function onsuccess(){self._asyncReturn(callback);};req.onerror=function onerror(){self._asyncReturn(callback,req.error.name);};},_getList:function getList(storeName,callback,sortedBy,prev,getCursor,limit){var results=[];if(!callback||!(callback instanceof Function)){return;}
|
||||
var self=this;this._newTxn('readonly',[storeName],function(error,txn,store){if(error){callback(error);return;}
|
||||
if(!getCursor){txn.oncomplete=function(){callback(results);};}
|
||||
txn.onerror=function(event){callback(event.target.error);};var cursor=null;var direction=prev?'prev':'next';if(sortedBy&&sortedBy!==null){if(!store.indexNames.contains(sortedBy)&&sortedBy!='id'){callback('INVALID_SORTED_BY_KEY');txn.abort();return;}
|
||||
cursor=store.index(sortedBy).openCursor(null,direction);}else{cursor=store.openCursor(null,direction);}
|
||||
cursor.onsuccess=function onsuccess(event){var item=event.target.result;if(getCursor){if(!item){callback({value:null});}else if(storeName===self._dbGroupsStore){callback({value:self._getGroupObject(item.value),continue:function(){return item.continue();}});}else{callback(item);}
|
||||
return;}else if(item&&(typeof limit==='undefined'||limit>0)){if(storeName===self._dbGroupsStore){results.push(self._getGroupObject(item.value));}else{results.push(item.value);}
|
||||
if(limit){limit--;}
|
||||
item.continue();}};});},getGroupList:function getGroupList(callback,sortedBy,prev,getCursor,limit){if(sortedBy==='number'||sortedBy==='type'||sortedBy==='status'){sortedBy=null;}
|
||||
this._getList(this._dbGroupsStore,callback,sortedBy,prev,getCursor,limit);},getGroupAtPosition:function rdbm_getGroupAtPosition(position,sortedBy,prev,type,callback){if(!callback||!(callback instanceof Function)){return;}
|
||||
var self=this;this._newTxn('readonly',this._dbGroupsStore,function(error,txn,store){if(error){callback(error);return;}
|
||||
try{var request=null;var direction=prev?'prev':'next';if(sortedBy&&sortedBy!==null){request=store.index(sortedBy).openCursor(null,direction);}else{request=store.openCursor(null,direction);}
|
||||
var i=0;request.onsuccess=function(event){var cursor=event.target.result;if(!cursor){callback(null);return;}
|
||||
var recentGroup=self._getGroupObject(cursor.value);var matched=!type||recentGroup.type.indexOf(type)!=-1;if(matched){i++;}
|
||||
if(matched&&i==position){callback(recentGroup);}else{cursor.continue();}};request.onerror=function(event){callback(event.target.error.name);};}catch(e){callback(e);}});},getGroup:function(number,date,type,status){var self=this;return new Promise(function(resolve,reject){var recentCall={number:number,date:date,type:type,status:status};var groupId=self._getGroupId(recentCall);self._newTxn('readonly',self._dbGroupsStore,function(error,txn,groupsStore){var group=null;txn.oncomplete=function(){if(group){resolve(self._getGroupObject(group));}else{reject();}};groupsStore.get(groupId).onsuccess=function(){group=this.result;};});});},_updateCacheRevision:function _updateCacheRevision(callback){Contacts.getRevision(function(contactsRevision){if(contactsRevision){window.asyncStorage.setItem('contactCacheRevision',contactsRevision);}
|
||||
callback();});},updateGroupContactInfo:function updateGroupContactInfo(contact,matchingTel,callback){var self=this;this._newTxn('readwrite',[this._dbGroupsStore],function(error,txn,store){var result;if(error){self._asyncReturn(callback,error);return;}
|
||||
if(!contact){self._asyncReturn(callback,0);return;}
|
||||
txn.oncomplete=function(){self._updateCacheRevision(function(){self._asyncReturn(callback,result);});};var count=0;var req=store.index('number').openCursor(IDBKeyRange.only(matchingTel.value));req.onsuccess=function onsuccess(event){var cursor=event.target.result;if(cursor&&cursor.value){var group=cursor.value;group.contactId=contact.id;var photo=ContactPhotoHelper.getThumbnail(contact);if(photo){group.contactPhoto=photo;}
|
||||
if(matchingTel){var primaryInfo=Utils.getPhoneNumberPrimaryInfo(matchingTel,contact);if(Array.isArray(primaryInfo)&&primaryInfo[0]){primaryInfo=primaryInfo[0];}
|
||||
group.contactPrimaryInfo=String(primaryInfo);if(Array.isArray(matchingTel.type)&&matchingTel.type[0]){group.contactMatchingTelType=String(matchingTel.type[0]);}
|
||||
if(matchingTel.carrier){group.contactMatchingTelCarrier=String(matchingTel.carrier);}}
|
||||
cursor.update(group);self._dispatchCallLogDbNewCall(self._getGroupObject(group));count++;cursor.continue();}else{result=count;}};req.onerror=function onerror(event){result=event.target.error;};});},removeGroupContactInfo:function removeGroupContactInfo(contactId,group,callback){if(!contactId&&!group){this._asyncReturn(callback,0);return;}
|
||||
var self=this;this._newTxn('readwrite',[this._dbGroupsStore],function(error,txn,store){if(error){self._asyncReturn(callback,error);callback(error);return;}
|
||||
var count=0;txn.oncomplete=function(){self._updateCacheRevision(function(){self._asyncReturn(callback,count);});};txn.onerror=function(event){self._asyncReturn(callback,event.target.error);};var req;if(contactId){req=store.index('contactId').openCursor(contactId);}else if(group){var groupId=self._getGroupId(group);req=store.openCursor(groupId);}
|
||||
req.onsuccess=function onsuccess(event){var cursor=event.target.result;if(cursor){var group=cursor.value;if(group.contactId){delete group.contactId;}
|
||||
if(group.contactPrimaryInfo){delete group.contactPrimaryInfo;}
|
||||
if(group.contactMatchingTelType){delete group.contactMatchingTelType;}
|
||||
if(group.contactMatchingTelCarrier){delete group.contactMatchingTelCarrier;}
|
||||
if(group.contactPhoto){delete group.contactPhoto;}
|
||||
self._dispatchCallLogDbNewCall(self._getGroupObject(group));cursor.update(group);count++;cursor.continue();}};});},_gatherAllGroups:function _gatherAllGroups(){var self=this;return new Promise(function(resolve,reject){var groups=[];self._newTxn('readonly',[self._dbGroupsStore],function(error,txn,store){if(error){reject(error);return;}
|
||||
txn.oncomplete=function(){resolve(groups);};txn.onerror=function(event){reject(event.target.error);};var req=store.openCursor();req.onsuccess=function onsuccess(event){var cursor=event.target.result;if(!cursor){return;}
|
||||
groups.push(cursor.value);cursor.continue();};});});},_updateGroup:function _updateGroup(group){return new Promise(function(resolve,reject){Contacts.findByNumber(group.number,function update(contact,matchingTel){var needsUpdate=false;if(!contact&&!matchingTel){if(group.contactId){needsUpdate=true;delete group.contactId;}
|
||||
if(group.contactPhoto){needsUpdate=true;delete group.contactPhoto;}
|
||||
if(group.contactPrimaryInfo){needsUpdate=true;delete group.contactPrimaryInfo;}
|
||||
if(group.contactMatchingTelType){needsUpdate=true;delete group.contactMatchingTelType;}
|
||||
if(group.contactMatchingTelCarrier){needsUpdate=true;delete group.contactMatchingTelCarrier;}}else{group.contactId=contact.id;var photo=ContactPhotoHelper.getThumbnail(contact);if(photo&&group.contactPhoto!=photo){group.contactPhoto=photo;needsUpdate=true;}
|
||||
var primaryInfo=Utils.getPhoneNumberPrimaryInfo(matchingTel,contact);if(Array.isArray(primaryInfo)&&primaryInfo[0]){primaryInfo=primaryInfo[0];}
|
||||
if(group.contactPrimaryInfo!=String(primaryInfo)){group.contactPrimaryInfo=String(primaryInfo);needsUpdate=true;}
|
||||
if(Array.isArray(matchingTel.type)&&matchingTel.type[0]&&group.contactMatchingTelType!=String(matchingTel.type[0])){group.contactMatchingTelType=String(matchingTel.type[0]);needsUpdate=true;}
|
||||
if(matchingTel.carrier&&group.contactMatchingTelCarrier!=String(matchingTel.carrier)){group.contactMatchingTelCarrier=String(matchingTel.carrier);needsUpdate=true;}}
|
||||
resolve(needsUpdate?group:null);});});},invalidateContactsCache:function invalidateContactsCache(callback){var self=this;this._gatherAllGroups().then(function(groups){var promises=[];for(var i=0;i<groups.length;i++){promises.push(self._updateGroup(groups[i]));}
|
||||
return Promise.all(promises);}).then(function(updatedGroups){self._newTxn('readwrite',[self._dbGroupsStore],function(error,txn,store){if(error){self._asyncReturn(callback,error);return;}
|
||||
txn.oncomplete=function onContactsUpdated(){self._updateCacheRevision(function(){self._asyncReturn(callback);});};txn.onerror=function(event){self._asyncReturn(callback,event.target.error);};for(var i=0;i<updatedGroups.length;i++){if(updatedGroups[i]){store.put(updatedGroups[i]);}}});});}};
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
;'use strict';var NavbarManager={init:function nm_init(){Navigation.show('keypad');document.getElementById('views').addEventListener('click',function(e){var destination=e.target.dataset&&e.target.dataset.destination;if(!destination){return;}
|
||||
Navigation.show(destination);});},hide:function(){var views=document.getElementById('views');views.classList.add('hide-toolbar');},show:function(){var views=document.getElementById('views');views.classList.remove('hide-toolbar');},};var CallHandler=(function callHandler(){var COMMS_APP_ORIGIN=document.location.protocol+'//'+
|
||||
document.location.host;var FB_SYNC_ERROR_PARAM='isSyncError';var engineeringModeKey=null;function handleActivity(activity){if(activity.source.name!='dial'){return;}
|
||||
var number=activity.source.data.number;if(number){KeypadManager.updatePhoneNumber(number,'begin',false);if(Navigation.currentView!='keypad'){Navigation.showKeypad();}}else{if(Navigation.currentView!='contacts'){Navigation.showContacts();}}}
|
||||
function deserializeParameters(input){var rparams=/([^?=&]+)(?:=([^&]*))?/g;var parsed={};input.replace(rparams,function($0,$1,$2){parsed[$1]=decodeURIComponent($2);});return parsed;}
|
||||
function handleNotification(evt){if(!evt.clicked){return;}
|
||||
navigator.mozApps.getSelf().onsuccess=function gotSelf(selfEvt){var app=selfEvt.target.result;app.launch('dialer');var location=document.createElement('a');location.href=evt.imageURL;if(location.search.indexOf(FB_SYNC_ERROR_PARAM)!==-1){Navigation.showContacts();}else if(location.search.indexOf('ussdMessage')!==-1){var params=deserializeParameters(evt.imageURL);Notification.get({tag:evt.tag}).then(function(notifications){for(var i=0;i<notifications.length;i++){notifications[i].close();}});MmiManager.handleMMIReceived(evt.body,true,params.cardIndex);}else{Navigation.showCalllog();}};}
|
||||
function sendNotification(number,serviceId){LazyLoader.load('/shared/js/dialer/utils.js',function(){Contacts.findByNumber(number,function lookup(contact,matchingTel){var title;if(navigator.mozIccManager.iccIds.length>1){title={id:'missedCallMultiSims',args:{n:serviceId+1}};}else{title='missedCall';}
|
||||
var body;if(!number){body='from-withheld-number';}else if(contact){var primaryInfo=Utils.getPhoneNumberPrimaryInfo(matchingTel,contact);if(primaryInfo){if(primaryInfo!==matchingTel.value){body={id:'from-contact',args:{contact:primaryInfo.toString()}};}else{body={id:'from-number',args:{number:primaryInfo}};}}else{body='from-withheld-number';}}else{body={id:'from-number',args:{number:number}};}
|
||||
navigator.mozApps.getSelf().onsuccess=function getSelfCB(evt){var app=evt.target.result;var iconURL=NotificationHelper.getIconURI(app,'dialer');var clickCB=function(){app.launch('dialer');Navigation.showCalllog();};NotificationHelper.send(title,{bodyL10n:body,icon:iconURL}).then(function(notification){notification.addEventListener('click',clickCB);});};});});}
|
||||
function callEnded(data){var highPriorityWakeLock=navigator.requestWakeLock('high-priority');var number=data.number;var incoming=data.direction==='incoming';if(incoming&&!data.duration&&!data.hangUpLocal){sendNotification(number,data.serviceId);}
|
||||
Voicemail.check(number,data.serviceId).then(function(isVoicemailNumber){var entry={date:Date.now()-parseInt(data.duration),duration:data.duration,type:incoming?'incoming':'dialing',number:number,serviceId:data.serviceId,emergency:data.emergency||false,voicemail:isVoicemailNumber,status:(incoming&&data.duration>0)?'connected':null};CallLogDBManager.add(entry,function(logEntry){CallLog.appendGroup(logEntry);if(!data.secondNumber){highPriorityWakeLock.unlock();return;}
|
||||
_addSecondCdmaCall(data,isVoicemailNumber,highPriorityWakeLock);});});}
|
||||
function _addSecondCdmaCall(data,isVoicemailNumber,wakeLock){var entryCdmaSecond={date:Date.now()-parseInt(data.duration),duration:data.duration,type:'incoming',number:data.secondNumber,serviceId:data.serviceId,emergency:false,voicemail:isVoicemailNumber,status:'connected'};CallLogDBManager.add(entryCdmaSecond,function(logGroupCdmaSecondCall){CallLog.appendGroup(logGroupCdmaSecondCall);wakeLock.unlock();});}
|
||||
function handleMessage(evt){if(evt.origin!==COMMS_APP_ORIGIN){return;}
|
||||
var data=evt.data;if(!data.type){return;}
|
||||
if(data.type==='contactsiframe'){handleContactsIframeRequest(data.message);}else if(data.type==='hide-navbar'){NavbarManager.hide();}else if(data.type==='show-navbar'){NavbarManager.show();}}
|
||||
window.addEventListener('message',handleMessage);function handleContactsIframeRequest(message){switch(message){case'back':var contactsIframe=document.getElementById('iframe-contacts');contactsIframe.contentWindow.history.pushState(null,null,'/contacts/index.html');Navigation.showCalllog();break;}}
|
||||
function btCommandHandler(message){var command=message.command;var isAtd=command.startsWith('ATD');if(command!=='BLDN'&&!isAtd){return;}
|
||||
if(isAtd&&command[3]!=='>'){var phoneNumber=command.substring(3);LazyLoader.load(['/shared/js/sim_settings_helper.js'],function(){SimSettingsHelper.getCardIndexFrom('outgoingCall',function(defaultCardIndex){if(defaultCardIndex===SimSettingsHelper.ALWAYS_ASK_OPTION_VALUE){LazyLoader.load(['/shared/js/component_utils.js','/shared/elements/gaia_sim_picker/script.js'],function(){var simPicker=document.getElementById('sim-picker');simPicker.getOrPick(defaultCardIndex,phoneNumber,function(ci){CallHandler.call(phoneNumber,ci);});navigator.mozApps.getSelf().onsuccess=function(selfEvt){var app=selfEvt.target.result;app.launch('dialer');};});}else{CallHandler.call(phoneNumber,defaultCardIndex);}});});return;}
|
||||
var position=isAtd?parseInt(command.substring(4),10):1;CallLogDBManager.getGroupAtPosition(position,'lastEntryDate',true,'dialing',function(result){if(result&&(typeof result==='object')&&result.number){LazyLoader.load(['/shared/js/sim_settings_helper.js'],function(){SimSettingsHelper.getCardIndexFrom('outgoingCall',function(ci){if(ci===undefined||ci===null||ci==SimSettingsHelper.ALWAYS_ASK_OPTION_VALUE){ci=result.serviceId;}
|
||||
CallHandler.call(result.number,ci);});});}else{console.log('Could not get the group at: '+position+'. Error: '+result);}});}
|
||||
function call(number,cardIndex){if(engineeringModeKey&&number===engineeringModeKey){var activity=new MozActivity({name:'internal-system-engineering-mode'});activity.onerror=function(){console.log('Could not launch engineering mode');};return;}
|
||||
if(MmiManager.isImei(number)){MmiManager.showImei();KeypadManager.updatePhoneNumber('','begin',true);SuggestionBar.clear();return;}
|
||||
var connected,disconnected;connected=disconnected=function clearPhoneView(){KeypadManager.updatePhoneNumber('','begin',true);};var oncall=function(){SuggestionBar.hideOverlay();SuggestionBar.clear();};LazyLoader.load(['/dialer/js/telephony_helper.js'],function(){TelephonyHelper.call(number,cardIndex,oncall,connected,disconnected).catch(function(){KeypadManager.updatePhoneNumber(number,'begin',false);});});}
|
||||
function onUssdReceived(evt){var lock=null;var safetyId;function releaseWakeLock(){if(lock){lock.unlock();lock=null;clearTimeout(safetyId);}}
|
||||
if(document.hidden){lock=navigator.requestWakeLock('high-priority');safetyId=setTimeout(releaseWakeLock,30000);document.addEventListener('visibilitychange',releaseWakeLock);}
|
||||
if(!document.hidden||evt.session){MmiManager.handleMMIReceived(evt.message,evt.session,evt.serviceId);}else if(evt.message){MmiManager.sendNotification(evt.message,evt.serviceId).then(releaseWakeLock);}else{releaseWakeLock();}}
|
||||
function init(){LazyLoader.load(['/shared/js/mobile_operator.js','/dialer/js/mmi.js','/dialer/js/mmi_ui.js','/shared/style/progress_activity.css','/dialer/style/mmi.css'],function(){if(window.navigator.mozSetMessageHandler){window.navigator.mozSetMessageHandler('telephony-call-ended',callEnded);window.navigator.mozSetMessageHandler('activity',handleActivity);window.navigator.mozSetMessageHandler('notification',handleNotification);window.navigator.mozSetMessageHandler('bluetooth-dialer-command',btCommandHandler);window.navigator.mozSetMessageHandler('ussd-received',onUssdReceived);}});LazyLoader.load('/shared/js/settings_listener.js',function(){SettingsListener.observe('engineering-mode.key',null,function(value){engineeringModeKey=value||null;});});}
|
||||
return{init:init,call:call};})();window.onresize=function(e){if(window.innerHeight<440){NavbarManager.hide();}else{NavbarManager.show();}};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
;'use strict';function onLoadDialer(){window.performance.mark('navigationLoaded');window.performance.mark('visuallyLoaded');window.removeEventListener('load',onLoadDialer);if(navigator.mozAudioChannelManager){navigator.mozAudioChannelManager.volumeControlChannel='notification';}
|
||||
KeypadManager.init(false);window.performance.mark('contentInteractive');NavbarManager.init();window.performance.mark('navigationInteractive');setTimeout(function nextTick(){var lazyPanels=['confirmation-message','edit-mode','sim-picker'];var lazyPanelsElements=lazyPanels.map(function toElement(id){return document.getElementById(id);});LazyLoader.load(lazyPanelsElements);CallHandler.init();navigator.mozL10n.once(function loadLazyFilesSet(){LazyLoader.load(['/shared/js/fb/fb_request.js','/shared/js/fb/fb_data_reader.js','/shared/js/fb/fb_reader_utils.js','/shared/style/confirm.css','/shared/js/confirm.js','/shared/elements/config.js','/shared/elements/gaia-header/dist/gaia-header.js','/shared/style/edit_mode.css'],function fileSetLoaded(){window.performance.mark('fullyLoaded');});});});}
|
||||
window.addEventListener('load',onLoadDialer);
|
||||
475
assets/webapps/communications.gaiamobile.org/dialer/js/mmi.js
Normal file
|
|
@ -0,0 +1,475 @@
|
|||
/* globals LazyLoader, MmiUI, MobileOperator, NotificationHelper,
|
||||
Promise */
|
||||
|
||||
/* exported MmiManager */
|
||||
|
||||
'use strict';
|
||||
|
||||
// As defined in 3GPP TS 22.030 version 10.0.0 Release 10 standard
|
||||
// USSD code used to query call barring supplementary service status
|
||||
const CALL_BARRING_STATUS_MMI_CODE = '*#33#';
|
||||
// USSD code used to query call waiting supplementary service status
|
||||
const CALL_WAITING_STATUS_MMI_CODE = '*#43#';
|
||||
|
||||
var MmiManager = {
|
||||
|
||||
_: null,
|
||||
_conn: null,
|
||||
_ready: false,
|
||||
// In some cases, the RIL doesn't provide the expected order of events
|
||||
// while sending an MMI that triggers an interactive USSD request (specially
|
||||
// while roaming), which should be DOMRequest.onsuccess (or .onerror) +
|
||||
// ussdreceived. If the first event received is the ussdreceived one, we take
|
||||
// the DOMRequest.onsuccess received subsequenty as a closure of the USSD
|
||||
// session.
|
||||
_pendingRequest: null,
|
||||
_session: null,
|
||||
|
||||
init: function mm_init() {
|
||||
if (this._ready) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
this._ = navigator.mozL10n.get;
|
||||
|
||||
var self = this;
|
||||
var lazyFiles = ['/shared/js/icc_helper.js',
|
||||
'/shared/style/input_areas.css',
|
||||
'/shared/js/mobile_operator.js'];
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
LazyLoader.load(lazyFiles, function() {
|
||||
MmiUI.init();
|
||||
self._ready = true;
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle dialing an MMI code by starting the UI and following up on the
|
||||
* promise in the MMICall object returned by Telephony.dial().
|
||||
*
|
||||
* @param {Object} conn The MozMobileConnection on which the MMI code was
|
||||
* dialed on.
|
||||
* @param {String} message The dialed MMI code.
|
||||
* @param {Promise} promise The MMICall promise.
|
||||
* @returns {Promise} A promise that is resolved once the MMI message
|
||||
* response has been handled.
|
||||
*/
|
||||
handleDialing: function mm_handleDialing(conn, message, promise) {
|
||||
var self = this;
|
||||
|
||||
this._conn = conn;
|
||||
this._pendingRequest = promise;
|
||||
|
||||
return this.init().then(function() {
|
||||
self.openUI();
|
||||
|
||||
/* TODO we are creating this callback instead of just following up on
|
||||
* the promise because we need to pass the original mmi code sent. This
|
||||
* should be removed when bug 889737 and bug 1049651 are landed as it
|
||||
* should be possible to get it in the callback. */
|
||||
return promise.then(function(result) {
|
||||
if (result.success) {
|
||||
self.notifySuccess(result, message);
|
||||
} else {
|
||||
self.notifyError(result, message);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// Passing the sent MMI code because the message displayed to the user
|
||||
// could be different depending on the MMI code.
|
||||
notifySuccess: function mm_notifySuccess(mmiResult, sentMMI) {
|
||||
// Helper function to compose an informative message about a successful
|
||||
// request to query the call forwarding status.
|
||||
var processCf = (function processCf(result) {
|
||||
var voice, data, fax, sms, sync, async, packet, pad;
|
||||
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
if (!result[i].active) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var serviceClassMask = 1;
|
||||
serviceClassMask <= this._conn.ICC_SERVICE_CLASS_MAX;
|
||||
serviceClassMask <<= 1) {
|
||||
if ((serviceClassMask & result[i].serviceClass) !== 0) {
|
||||
switch (serviceClassMask) {
|
||||
case this._conn.ICC_SERVICE_CLASS_VOICE:
|
||||
voice = result[i].number;
|
||||
break;
|
||||
case this._conn.ICC_SERVICE_CLASS_DATA:
|
||||
data = result[i].number;
|
||||
break;
|
||||
case this._conn.ICC_SERVICE_CLASS_FAX:
|
||||
fax = result[i].number;
|
||||
break;
|
||||
case this._conn.ICC_SERVICE_CLASS_SMS:
|
||||
sms = result[i].number;
|
||||
break;
|
||||
case this._conn.ICC_SERVICE_CLASS_DATA_SYNC:
|
||||
sync = result[i].number;
|
||||
break;
|
||||
case this._conn.ICC_SERVICE_CLASS_DATA_ASYNC:
|
||||
async = result[i].number;
|
||||
break;
|
||||
case this._conn.ICC_SERVICE_CLASS_PACKET:
|
||||
packet = result[i].number;
|
||||
break;
|
||||
case this._conn.ICC_SERVICE_CLASS_PAD:
|
||||
pad = result[i].number;
|
||||
break;
|
||||
default:
|
||||
return this._('call-forwarding-error');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var inactive = this._('call-forwarding-inactive');
|
||||
var msg = [
|
||||
this._('call-forwarding-status'),
|
||||
this._('call-forwarding-voice', { voice: voice || inactive }),
|
||||
this._('call-forwarding-data', { data: data || inactive }),
|
||||
this._('call-forwarding-fax', { fax: fax || inactive }),
|
||||
this._('call-forwarding-sms', { sms: sms || inactive }),
|
||||
this._('call-forwarding-sync', { sync: sync || inactive }),
|
||||
this._('call-forwarding-async', { async: async || inactive }),
|
||||
this._('call-forwarding-packet', { packet: packet || inactive }),
|
||||
this._('call-forwarding-pad', { pad: pad || inactive })
|
||||
].join('\n');
|
||||
|
||||
return msg;
|
||||
}).bind(this);
|
||||
|
||||
var ci = this.cardIndexForConnection(this._conn);
|
||||
var message = null;
|
||||
var title = null;
|
||||
var error = null;
|
||||
|
||||
// We always expect an MMIResult object even for USSD requests.
|
||||
if (!mmiResult) {
|
||||
MmiUI.error(this._('GenericFailure'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (mmiResult.serviceCode) {
|
||||
title = this.prependSimNumber(this._(mmiResult.serviceCode), ci);
|
||||
}
|
||||
|
||||
var additionalInformation = mmiResult.additionalInformation;
|
||||
|
||||
switch (mmiResult.serviceCode) {
|
||||
case 'scCall':
|
||||
/* Call control, no need to show a result page as the command will
|
||||
* already have been executed (hang up a call, etc...). */
|
||||
MmiUI.cancel();
|
||||
return;
|
||||
case 'scUssd':
|
||||
// Bail out if there is nothing to show or if we got the .onsuccess
|
||||
// event after the .onussdevent.
|
||||
if (!mmiResult.statusMessage || this._pendingRequest === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
message = mmiResult.statusMessage;
|
||||
break;
|
||||
case 'scPin':
|
||||
case 'scPin2':
|
||||
case 'scPuk':
|
||||
case 'scPuk2':
|
||||
if (mmiResult.statusMessage) {
|
||||
message = this._(mmiResult.statusMessage);
|
||||
}
|
||||
break;
|
||||
case 'scCallForwarding':
|
||||
if (mmiResult.statusMessage) {
|
||||
message = this._(mmiResult.statusMessage);
|
||||
// Call forwarding requests via MMI codes might return an array of
|
||||
// nsIDOMMozMobileCFInfo objects. In that case we serialize that array
|
||||
// into a single string that can be shown on the screen.
|
||||
if (additionalInformation) {
|
||||
message = processCf(additionalInformation);
|
||||
}
|
||||
} else {
|
||||
error = this._('GenericFailure');
|
||||
}
|
||||
break;
|
||||
case 'scCallBarring':
|
||||
case 'scCallWaiting':
|
||||
message = this._(mmiResult.statusMessage);
|
||||
// If we are just querying the status of the service, we show a
|
||||
// different message, so the user knows she hasn't change anything
|
||||
if (sentMMI === CALL_BARRING_STATUS_MMI_CODE ||
|
||||
sentMMI === CALL_WAITING_STATUS_MMI_CODE) {
|
||||
if (mmiResult.statusMessage === 'smServiceEnabled') {
|
||||
message = this._('ServiceIsEnabled');
|
||||
} else if (mmiResult.statusMessage === 'smServiceDisabled') {
|
||||
message = this._('ServiceIsDisabled');
|
||||
} else if (mmiResult.statusMessage === 'smServiceEnabledFor') {
|
||||
message = this._('ServiceIsEnabledFor');
|
||||
}
|
||||
}
|
||||
// Call barring and call waiting requests via MMI codes might return an
|
||||
// array of strings indicating the service it is enabled for or just
|
||||
// the disabled status message.
|
||||
if (mmiResult.statusMessage === 'smServiceEnabledFor' &&
|
||||
additionalInformation &&
|
||||
Array.isArray(additionalInformation)) {
|
||||
for (var i = 0, l = additionalInformation.length; i < l; i++) {
|
||||
message += '\n' + this._(additionalInformation[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// This would allow carriers and others to implement custom MMI codes
|
||||
// with title and statusMessage only.
|
||||
if (mmiResult.statusMessage) {
|
||||
message = this._(mmiResult.statusMessage) || mmiResult.statusMessage;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
MmiUI.success(message, title);
|
||||
} else {
|
||||
MmiUI.error(error, title);
|
||||
}
|
||||
},
|
||||
|
||||
notifyError: function mm_notifyError(mmiError) {
|
||||
var title = null;
|
||||
var ci = this.cardIndexForConnection(this._conn);
|
||||
|
||||
if (mmiError.serviceCode) {
|
||||
title = this.prependSimNumber(this._(mmiError.serviceCode), ci);
|
||||
}
|
||||
|
||||
var error = mmiError.statusMessage ? this._(mmiError.statusMessage)
|
||||
: this._('GenericFailure');
|
||||
|
||||
switch (mmiError.serviceCode) {
|
||||
case 'scPin':
|
||||
case 'scPin2':
|
||||
case 'scPuk':
|
||||
case 'scPuk2':
|
||||
// If the error is related with an incorrect old PIN, we get the
|
||||
// number of remainings attempts.
|
||||
if (mmiError.additionalInformation &&
|
||||
(mmiError.statusMessage === 'emMmiErrorPasswordIncorrect' ||
|
||||
mmiError.statusMessage === 'emMmiErrorBadPin' ||
|
||||
mmiError.statusMessage === 'emMmiErrorBadPuk')) {
|
||||
error += '\n' + this._('emMmiErrorPinPukAttempts', {
|
||||
n: mmiError.additionalInformation
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
MmiUI.error(error, title);
|
||||
},
|
||||
|
||||
openUI: function mm_openUI() {
|
||||
this.init().then(function() {
|
||||
MmiUI.loading();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a notification/message string by prepending the SIM number if the
|
||||
* phone has more than one SIM card.
|
||||
*
|
||||
* @param text {String} The message text.
|
||||
* @param cardIndex {Integer} The SIM card slot index.
|
||||
* @return {String} Either the original string alone or with the SIM number
|
||||
* prepended to it.
|
||||
*/
|
||||
prependSimNumber: function mm_prependSimNumber(text, cardIndex) {
|
||||
if (window.navigator.mozIccManager &&
|
||||
window.navigator.mozIccManager.iccIds.length > 1) {
|
||||
var simName = this._('sim-number', { n: +cardIndex + 1 });
|
||||
|
||||
text = this._(
|
||||
'mmi-notification-title-with-sim',
|
||||
{ sim: simName, title: text }
|
||||
);
|
||||
}
|
||||
|
||||
return text;
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles an MMI/USSD message. Pops up the MMI UI and displays the message.
|
||||
*
|
||||
* @param {String} message An MMI/USSD message.
|
||||
* @param {Object} session The object representing the USSD session.
|
||||
* @param {Integer} cardIndex The index of the SIM card on which this message
|
||||
* was received.
|
||||
*/
|
||||
handleMMIReceived: function mm_handleMMIReceived(message, session, cardIndex)
|
||||
{
|
||||
var self = this;
|
||||
|
||||
return this.init().then(function() {
|
||||
self._pendingRequest = null;
|
||||
self._session = session;
|
||||
// Do not notify the UI if no message to show.
|
||||
if (!message && session) {
|
||||
return;
|
||||
}
|
||||
|
||||
var conn = navigator.mozMobileConnections[cardIndex || 0];
|
||||
var operator = MobileOperator.userFacingInfo(conn).operator;
|
||||
var title = self.prependSimNumber(operator || '', cardIndex);
|
||||
|
||||
MmiUI.received(session, message, title);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Sends a notification for the specified message, returns a promise that is
|
||||
* resolved once the operation is finished.
|
||||
*
|
||||
* @param {String} message An MMI/USSD message.
|
||||
* @param {Integer} cardIndex The index of the SIM card on which this message
|
||||
* was received.
|
||||
* @return {Promise} A promise that is resolved once the operation is
|
||||
* finished.
|
||||
*/
|
||||
sendNotification: function mm_sendNotification(message, cardIndex) {
|
||||
var self = this;
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
var request = window.navigator.mozApps.getSelf();
|
||||
request.onsuccess = function(evt) {
|
||||
var app = evt.target.result;
|
||||
|
||||
self.init().then(function() {
|
||||
LazyLoader.load('/shared/js/notification_helper.js', function() {
|
||||
var iconURL = NotificationHelper.getIconURI(app, 'dialer');
|
||||
var clickCB = function(evt) {
|
||||
self.handleMMIReceived(message, /* session */ null, cardIndex);
|
||||
};
|
||||
var conn = navigator.mozMobileConnections[cardIndex || 0];
|
||||
var operator = MobileOperator.userFacingInfo(conn).operator;
|
||||
var titleL10n = self.prependSimNumber(
|
||||
operator ? operator : '', cardIndex);
|
||||
/* XXX: Bug 1033254 - We put the |ussd-message=1| parameter in the
|
||||
* URL string to distinguish this notification from the others.
|
||||
* This should be thorought the application possibly by using the
|
||||
* tag field. */
|
||||
NotificationHelper.send(titleL10n, {
|
||||
body: message,
|
||||
icon: iconURL + '?ussdMessage=1&cardIndex=' + cardIndex,
|
||||
tag: Date.now()
|
||||
}).then(notification => {
|
||||
notification.addEventListener('click', clickCB);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
request.onerror = function(error) {
|
||||
reject(error);
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
reply: function mm_reply(message) {
|
||||
var self = this;
|
||||
|
||||
return this._session.send(message).then(function(request) {
|
||||
self._pendingRequest = request;
|
||||
});
|
||||
},
|
||||
|
||||
cancel: function mm_cancel() {
|
||||
this._pendingRequest = null;
|
||||
if (this._session) {
|
||||
this._session.cancel();
|
||||
this._session = null;
|
||||
}
|
||||
},
|
||||
|
||||
cardIndexForConnection: function mm_cardIndexForConnection(conn) {
|
||||
for (var i = 0; i < navigator.mozMobileConnections.length; i++) {
|
||||
if (conn === navigator.mozMobileConnections[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves the IMEI code for the specified SIM card slot.
|
||||
*
|
||||
* @param {Integer} cardIndex The index of the SIM card slot.
|
||||
* @returns {Promise} A promise that resolves to the IMEI code for the slot
|
||||
* upon successful completion or rejects upon failure.
|
||||
*/
|
||||
_getImeiForCard: function mm_getImeiForCard(cardIndex) {
|
||||
return navigator.mozTelephony.dial('*#06#', cardIndex).then(
|
||||
function(mmiCall) {
|
||||
return mmiCall.result.then(function(result) {
|
||||
/* We always expect the IMEI, so if we got a successful completion
|
||||
* without the IMEI value, we throw an error message. */
|
||||
if ((result === null) || (result.serviceCode !== 'scImei') ||
|
||||
(result.statusMessage === null)) {
|
||||
return Promise.reject(
|
||||
new Error('Could not retrieve the IMEI code for SIM' +
|
||||
cardIndex));
|
||||
}
|
||||
|
||||
return result.statusMessage;
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if the specified number is the MMI code used to request the
|
||||
* IMEI codes of the phone's SIM slots (*#06#).
|
||||
*
|
||||
* @param {String} number A phone number or MMI code.
|
||||
* @returns {Boolean} true if the passed number is the MMI IMEI request code
|
||||
* and false in all other cases.
|
||||
*/
|
||||
isImei: function mm_isImei(number) {
|
||||
return (number === '*#06#');
|
||||
},
|
||||
|
||||
/**
|
||||
* Sends the necessary MMI messages to retrieve IMEI codes for all SIM slots
|
||||
* and displays the resulting codes on the screen.
|
||||
*
|
||||
* @returns {Promise} A promise that is resolved when the operation has been
|
||||
* completed.
|
||||
*/
|
||||
showImei: function mm_showImei() {
|
||||
var self = this;
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
self.init().then(function() {
|
||||
var promises = [];
|
||||
|
||||
for (var i = 0; i < navigator.mozMobileConnections.length; i++) {
|
||||
promises.push(self._getImeiForCard(i));
|
||||
}
|
||||
|
||||
self.openUI();
|
||||
|
||||
Promise.all(promises).then(function(imeis) {
|
||||
MmiUI.success(imeis.join('\n'), self._('scImei'));
|
||||
resolve();
|
||||
}, function(reason) {
|
||||
MmiUI.error(self._('GenericFailure'));
|
||||
reject(reason);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
153
assets/webapps/communications.gaiamobile.org/dialer/js/mmi_ui.js
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
/* globals MmiManager */
|
||||
|
||||
/* exported MmiUI */
|
||||
|
||||
'use strict';
|
||||
|
||||
var MmiUI = {
|
||||
|
||||
_: null,
|
||||
|
||||
headerTitleNode: null,
|
||||
headerNode: null,
|
||||
cancelNode: null,
|
||||
sendNode: null,
|
||||
messageNode: null,
|
||||
responseTextNode: null,
|
||||
responseTextResetNode: null,
|
||||
mmiScreen: null,
|
||||
loadingOverlay: null,
|
||||
|
||||
init: function mui_init() {
|
||||
this._ = navigator.mozL10n.get;
|
||||
|
||||
this.headerTitleNode = document.getElementById('header-title');
|
||||
this.headerNode = document.getElementById('mmi-header');
|
||||
this.cancelNode = document.getElementById('cancel');
|
||||
this.sendNode = document.getElementById('send');
|
||||
this.messageNode = document.getElementById('message');
|
||||
this.responseTextNode = document.getElementById('response-text');
|
||||
this.responseTextResetNode = document.getElementById('response-text-reset');
|
||||
this.mmiScreen = document.getElementById('mmi-screen');
|
||||
this.loadingOverlay = document.getElementById('loading-overlay');
|
||||
|
||||
this.headerNode.addEventListener('action', this.closeWindow.bind(this));
|
||||
this.cancelNode.addEventListener('click', this.cancel.bind(this));
|
||||
this.sendNode.addEventListener('click', this.reply.bind(this));
|
||||
this.responseTextResetNode.addEventListener('click',
|
||||
this.resetResponse.bind(this));
|
||||
this.responseTextNode.addEventListener('input',
|
||||
this.responseUpdated.bind(this));
|
||||
},
|
||||
|
||||
showWindow: function mui_showWindow() {
|
||||
this.mmiScreen.hidden = false;
|
||||
},
|
||||
|
||||
closeWindow: function mui_closeWindow() {
|
||||
MmiManager.cancel();
|
||||
this.resetResponse();
|
||||
this.mmiScreen.hidden = true;
|
||||
},
|
||||
|
||||
cancel: function mui_cancel() {
|
||||
this.hideLoading();
|
||||
this.closeWindow();
|
||||
},
|
||||
|
||||
showMessage: function mui_showMessage(message, header) {
|
||||
this.showWindow();
|
||||
this.hideLoading();
|
||||
this.responseTextNode.removeAttribute('disabled');
|
||||
this.messageNode.textContent = message;
|
||||
if (header && header.length) {
|
||||
this.headerTitleNode.textContent = header;
|
||||
} else {
|
||||
this.headerTitleNode.textContent = '';
|
||||
}
|
||||
|
||||
// Make sure the app is displayed
|
||||
navigator.mozApps.getSelf().onsuccess = function getSelfCB(evt) {
|
||||
evt.target.result.launch('dialer');
|
||||
};
|
||||
},
|
||||
|
||||
showLoading: function mui_showLoading() {
|
||||
this.loadingOverlay.classList.remove('hide');
|
||||
this.loadingOverlay.classList.remove('fade-out');
|
||||
this.loadingOverlay.classList.add('fade-in');
|
||||
this.responseTextNode.setAttribute('disabled', 'disabled');
|
||||
this.sendNode.setAttribute('disabled', 'disabled');
|
||||
},
|
||||
|
||||
hideLoading: function mui_hideLoading() {
|
||||
var self = this;
|
||||
|
||||
this.loadingOverlay.classList.remove('fade-in');
|
||||
this.loadingOverlay.addEventListener('animationend',
|
||||
function mui_fadeOut(ev) {
|
||||
self.loadingOverlay.removeEventListener('animationend', mui_fadeOut);
|
||||
self.loadingOverlay.classList.add('hide');
|
||||
});
|
||||
this.loadingOverlay.classList.add('fade-out');
|
||||
},
|
||||
|
||||
showResponseForm: function mui_showForm() {
|
||||
this.mmiScreen.classList.add('responseForm');
|
||||
this.sendNode.classList.remove('hide');
|
||||
},
|
||||
|
||||
hideResponseForm: function mui_hideForm() {
|
||||
this.mmiScreen.classList.remove('responseForm');
|
||||
this.sendNode.classList.add('hide');
|
||||
},
|
||||
|
||||
resetResponse: function mui_resetResponse() {
|
||||
this.responseTextNode.value = '';
|
||||
this.sendNode.setAttribute('disabled', 'disabled');
|
||||
},
|
||||
|
||||
responseUpdated: function mui_responseUpdated() {
|
||||
if (this.responseTextNode.value.length <= 0) {
|
||||
this.sendNode.setAttribute('disabled', 'disabled');
|
||||
} else {
|
||||
this.sendNode.removeAttribute('disabled');
|
||||
}
|
||||
},
|
||||
|
||||
reply: function mui_reply() {
|
||||
this.showLoading();
|
||||
MmiManager.reply(this.responseTextNode.value);
|
||||
this.resetResponse();
|
||||
},
|
||||
|
||||
success: function mui_success(message, title) {
|
||||
message = message || this._('mmi-successfully-sent');
|
||||
|
||||
this.hideResponseForm();
|
||||
this.showMessage(message, title);
|
||||
},
|
||||
|
||||
error: function mui_error(error, title) {
|
||||
error = error || this._('mmi-error');
|
||||
|
||||
this.hideResponseForm();
|
||||
this.showMessage(error, title);
|
||||
},
|
||||
|
||||
received: function mui_received(session, message, title) {
|
||||
if (!session) {
|
||||
this.hideResponseForm();
|
||||
if (message === null) {
|
||||
message = this._('mmi-session-expired');
|
||||
}
|
||||
} else {
|
||||
this.showResponseForm();
|
||||
}
|
||||
this.showMessage(message, title);
|
||||
},
|
||||
|
||||
loading: function mui_loading() {
|
||||
this.showLoading();
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
;(function(exports){'use strict';var selectors={recents:'recents-panel',contacts:'iframe-contacts-container',keypad:'keypad-panel'};var currentDestination=null;function checkContactsTab(){var contactsIframe=document.getElementById('iframe-contacts');if(!contactsIframe){return;}
|
||||
var index=contactsIframe.src.indexOf('#add-parameters');if(index!=-1){contactsIframe.src=contactsIframe.src.substr(0,index);}}
|
||||
function update(destination){var recent=document.getElementById('option-recents');var contacts=document.getElementById('option-contacts');var keypad=document.getElementById('option-keypad');var tabs=[recent,contacts,keypad];recent.classList.remove('toolbar-option-selected');contacts.classList.remove('toolbar-option-selected');keypad.classList.remove('toolbar-option-selected');switch(destination){case'recents':checkContactsTab();recent.classList.add('toolbar-option-selected');AccessibilityHelper.setAriaSelected(recent,tabs);CallLog.init();break;case'contacts':var frame=document.getElementById('iframe-contacts');if(!frame){var view=document.getElementById('iframe-contacts-container');frame=document.createElement('iframe');frame.src='/contacts/index.html';frame.id='iframe-contacts';frame.setAttribute('frameBorder','no');frame.classList.add('grid-wrapper');view.appendChild(frame);}
|
||||
contacts.classList.add('toolbar-option-selected');AccessibilityHelper.setAriaSelected(contacts,tabs);var forceHashChange=new Date().getTime();frame.src='/contacts/index.html#home?forceHashChange='+
|
||||
forceHashChange;break;case'keypad':checkContactsTab();keypad.classList.add('toolbar-option-selected');AccessibilityHelper.setAriaSelected(keypad,tabs);break;}}
|
||||
exports.Navigation={get currentView(){return currentDestination;},show:function(destination){var selector=selectors[destination];if(!selector){throw new Error('Navigation: Invalid destination: '+destination);}
|
||||
var view=document.getElementById(selector);if(!view){throw new Error('Navigation: Panel does not exist: '+destination);}
|
||||
if(currentDestination&¤tDestination===destination){return;}
|
||||
view.style.visibility='visible';if(currentDestination){var currentSelector=selectors[currentDestination];document.getElementById(currentSelector).style.visibility='hidden';}
|
||||
currentDestination=destination;update(destination);},showKeypad:function(){this.show('keypad');},showContacts:function(){this.show('contacts');},showCalllog:function(){this.show('recents');}};}(window));
|
||||
|
|
@ -0,0 +1,409 @@
|
|||
/* globals CallHandler, Contacts, fb, KeypadManager, LazyLoader,
|
||||
SimplePhoneMatcher, SimSettingsHelper, Utils */
|
||||
|
||||
// Suggestion_bar.js will be loaded on init of KeypadManager through
|
||||
// lazy loader. So we call its init() directly at the end of file.
|
||||
|
||||
'use strict';
|
||||
|
||||
var SuggestionBar = {
|
||||
MIN_DIGIT_TO_SHOW: 3,
|
||||
SKIP_FOR_COUNTRYCODE: 2,
|
||||
MAX_ITEMS: 50,
|
||||
|
||||
_phoneNumber: null,
|
||||
_contactList: null,
|
||||
_loaded: false,
|
||||
|
||||
_pendingFbRequest: null,
|
||||
_hasMatchingFbContacts: false,
|
||||
_hasMatchingLocalContacts: false,
|
||||
|
||||
// Visual Elements
|
||||
bar: null,
|
||||
barSuggestionItem: null,
|
||||
countTag: null,
|
||||
list: null,
|
||||
overlay: null,
|
||||
overlayCancel: null,
|
||||
template: null,
|
||||
|
||||
init: function sb_init() {
|
||||
// When the DOM is absent (in the call screen) we don't need
|
||||
// to initialize the module.
|
||||
this.overlay = document.getElementById('contact-list-overlay');
|
||||
if (!this.overlay) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.bar = document.getElementById('suggestion-bar');
|
||||
this.barSuggestionItem = this.bar.querySelector('.js-suggestion-item');
|
||||
this.countTag = document.getElementById('suggestion-count');
|
||||
this.template = document.getElementById('contact-in-overlay-template');
|
||||
|
||||
this.overlay.addEventListener('click', this);
|
||||
this.bar.addEventListener('click', this);
|
||||
this.countTag.addEventListener('click', this.showOverlay.bind(this));
|
||||
KeypadManager.onValueChanged = this.update.bind(this);
|
||||
},
|
||||
|
||||
handleEvent: function sb_handleEvent(event) {
|
||||
var node = event.target;
|
||||
if (!node.classList.contains('js-suggestion-item')) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.stopPropagation();
|
||||
var telTag = node.querySelector('.js-tel');
|
||||
KeypadManager.updatePhoneNumber(telTag.textContent, 'begin', false);
|
||||
// In the multi-SIM case, we just autocomplete the phone number without
|
||||
// making the call. The call button is responsible for SIM selection
|
||||
// behavior.
|
||||
if (!navigator.mozIccManager ||
|
||||
navigator.mozIccManager.iccIds.length < 2) {
|
||||
LazyLoader.load('/shared/js/sim_settings_helper.js', function() {
|
||||
SimSettingsHelper.getCardIndexFrom('outgoingCall', function(ci) {
|
||||
CallHandler.call(KeypadManager.phoneNumber(), ci);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
this.hideOverlay();
|
||||
}
|
||||
},
|
||||
|
||||
update: function sb_update(number) {
|
||||
this._phoneNumber = number;
|
||||
|
||||
// when first letter of number is "+", we'll change minimum search criteria
|
||||
// from MIN_DIGIT_TO_SHOW to MIN_DIGIT_TO_SHOW + SKIP_FOR_COUNTRYCODE.
|
||||
var min = this.MIN_DIGIT_TO_SHOW +
|
||||
((number.charAt(0) === '+') ? this.SKIP_FOR_COUNTRYCODE : 0);
|
||||
|
||||
if (number.length < min) {
|
||||
this.clear(true);
|
||||
return;
|
||||
}
|
||||
if (this._loaded) {
|
||||
this._updateByContacts();
|
||||
return;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
LazyLoader.load(['/shared/js/async_storage.js',
|
||||
'/shared/js/dialer/contacts.js',
|
||||
'/shared/js/simple_phone_matcher.js',
|
||||
this.barSuggestionItem,
|
||||
this.template],
|
||||
function callback() {
|
||||
self._loaded = true;
|
||||
self._updateByContacts();
|
||||
});
|
||||
},
|
||||
|
||||
_renderBar: function sb_renderBar() {
|
||||
var self = this;
|
||||
|
||||
self.bar.classList.remove('hide');
|
||||
|
||||
// Create matching index table for reference
|
||||
self._allMatched = self._getAllMatched(self._contactList);
|
||||
var totalMatchNum = self._allMatched.totalMatchNum;
|
||||
|
||||
var contact = self._contactList[0];
|
||||
var firstMatch = self._allMatched.allMatches[0][0];
|
||||
|
||||
var shouldHideSuggestionBar = false;
|
||||
|
||||
// In a multi-SIM setup, tapping on a suggestion in the settings bar doesn't
|
||||
// place a call, it just fills in the phone number. In this case, we should
|
||||
// hide the suggestions bar to not confuse the user into thinking that
|
||||
// tapping it again will place the call.
|
||||
if (totalMatchNum === 1 &&
|
||||
contact.tel[firstMatch].value == self._phoneNumber &&
|
||||
navigator.mozIccManager &&
|
||||
navigator.mozIccManager.iccIds.length > 1) {
|
||||
shouldHideSuggestionBar = true;
|
||||
}
|
||||
|
||||
// Don't show any suggestions if we have too many. The user should narrow it
|
||||
// down further by entering more digits.
|
||||
if (totalMatchNum > self.MAX_ITEMS) {
|
||||
shouldHideSuggestionBar = true;
|
||||
}
|
||||
|
||||
if (shouldHideSuggestionBar) {
|
||||
self.clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
self.countTag.textContent = totalMatchNum;
|
||||
|
||||
var hasMoreThanOneMatch = (totalMatchNum > 1);
|
||||
self.countTag.hidden = !hasMoreThanOneMatch;
|
||||
self.countTag.classList.toggle('more', hasMoreThanOneMatch);
|
||||
|
||||
var node = self.barSuggestionItem;
|
||||
self._fillContacts(contact, firstMatch, node);
|
||||
self.bar.dataset.lastId = contact.id || contact.uid;
|
||||
|
||||
return totalMatchNum;
|
||||
},
|
||||
|
||||
_checkIfCleared: function sb_checkIfCleared() {
|
||||
var out = false;
|
||||
|
||||
if (!this._phoneNumber) {
|
||||
this.bar.dataset.lastId = '';
|
||||
this.clear(true);
|
||||
out = true;
|
||||
}
|
||||
return out;
|
||||
},
|
||||
|
||||
_searchCallback: function sb_searchCallback(contacts) {
|
||||
var self = this;
|
||||
|
||||
self._pendingFbRequest = null;
|
||||
|
||||
if (self._checkIfCleared()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var totalMatchNum = 0;
|
||||
|
||||
if (Array.isArray(contacts) && contacts.length > 0) {
|
||||
self._contactList = contacts;
|
||||
totalMatchNum = self._renderBar();
|
||||
self._hasMatchingLocalContacts = true;
|
||||
}
|
||||
else {
|
||||
// Avoid to clear the list if we have previous FB Contacts
|
||||
// This will avoid continous reflows while refreshing
|
||||
if (!self._hasMatchingFbContacts ||
|
||||
(self._hasMatchingFbContacts && self._hasMatchingLocalContacts)) {
|
||||
self.clear(false);
|
||||
}
|
||||
self._hasMatchingLocalContacts = false;
|
||||
self._contactList = null;
|
||||
}
|
||||
|
||||
if (totalMatchNum > self.MAX_ITEMS) {
|
||||
self._hasMatchingFbContacts = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var req = fb.contacts.search('phone', self._phoneNumber);
|
||||
self._pendingFbRequest = req;
|
||||
|
||||
req.onsuccess = function() {
|
||||
// Avoid to overlap FB requests
|
||||
if (self._pendingFbRequest === req) {
|
||||
self._pendingFbRequest = null;
|
||||
self._searchCallbackFb(req.result);
|
||||
}
|
||||
};
|
||||
req.onerror = function() {
|
||||
window.console.error('Error while searching FB Data: ', req.error.name);
|
||||
self._hasMatchingFbContacts = false;
|
||||
};
|
||||
},
|
||||
|
||||
_searchCallbackFb: function sb_searchCallbackFb(contacts) {
|
||||
if (this._checkIfCleared()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Array.isArray(contacts) || contacts.length === 0) {
|
||||
this._hasMatchingFbContacts = false;
|
||||
if (!this._hasMatchingLocalContacts) {
|
||||
this.clear(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this._hasMatchingFbContacts = true;
|
||||
this._contactList = (this._contactList || []).concat(contacts);
|
||||
this._renderBar();
|
||||
},
|
||||
|
||||
_updateByContacts: function sb_updateByContacts() {
|
||||
// A search is both launched on mozContacts and on Facebook DS
|
||||
Contacts.findListByNumber(this._phoneNumber, this.MAX_ITEMS + 1,
|
||||
this._searchCallback.bind(this));
|
||||
},
|
||||
|
||||
_fillContacts: function sb_fillContacts(contact, matchLocal, node) {
|
||||
|
||||
// if first letter of query is '+' and first letter of matchedTel isn't '+'
|
||||
// we use query without country code instead of original query for
|
||||
// markedNumber.
|
||||
var matchedTel = contact.tel[matchLocal];
|
||||
|
||||
var markedNumber = this._markMatched(matchedTel.value, this._phoneNumber);
|
||||
this._setItem(node, markedNumber, matchedTel.type,
|
||||
contact.name[0]);
|
||||
},
|
||||
|
||||
_createItem: function sb_createItem() {
|
||||
var itemElm = this.template.cloneNode(true);
|
||||
itemElm.removeAttribute('id');
|
||||
itemElm.hidden = false;
|
||||
itemElm.classList.add('ci--action-menu');
|
||||
this.list.insertBefore(itemElm, this.overlayCancel);
|
||||
return itemElm;
|
||||
},
|
||||
|
||||
_setItem: function sb_setItem(node, tel, type, name) {
|
||||
var typeTag = node.querySelector('.js-tel-type');
|
||||
var telTag = node.querySelector('.js-tel');
|
||||
var nameTag = node.querySelector('.js-name');
|
||||
|
||||
// Set the contact name
|
||||
nameTag.textContent = name ? name : null;
|
||||
|
||||
// Set the number with the highlighted match
|
||||
while (telTag.firstChild) {
|
||||
telTag.removeChild(telTag.firstChild);
|
||||
}
|
||||
|
||||
if (tel) {
|
||||
telTag.appendChild(tel);
|
||||
}
|
||||
|
||||
// Set the phone type
|
||||
if (type) {
|
||||
if (Utils.isPhoneType(type)) {
|
||||
navigator.mozL10n.setAttributes(typeTag, type);
|
||||
} else {
|
||||
// No localization found, use the type string as-is
|
||||
typeTag.removeAttribute('data-l10n-id');
|
||||
typeTag.textContent = type;
|
||||
}
|
||||
} else {
|
||||
typeTag.textContent = null;
|
||||
}
|
||||
},
|
||||
|
||||
clear: function sb_clear(isHardClear) {
|
||||
if (!this._loaded) {
|
||||
return;
|
||||
}
|
||||
this.countTag.textContent = '';
|
||||
this.countTag.classList.remove('more');
|
||||
// Clear contents
|
||||
var node = this.barSuggestionItem;
|
||||
this._setItem(node);
|
||||
this._contactList = null;
|
||||
this.bar.classList.add('hide');
|
||||
|
||||
if (isHardClear) {
|
||||
this._phoneNumber = null;
|
||||
delete this.bar.dataset.lastId;
|
||||
}
|
||||
},
|
||||
|
||||
_markMatched: function sb_markMatched(str, substr) {
|
||||
var fragment = document.createDocumentFragment();
|
||||
var sanitized = SimplePhoneMatcher.sanitizedNumber(str);
|
||||
var digitBeforeMatch = sanitized.indexOf(substr);
|
||||
if (digitBeforeMatch == -1) {
|
||||
fragment.appendChild(document.createTextNode(str));
|
||||
return fragment;
|
||||
}
|
||||
|
||||
// Highlight matched number. We need to count formatting character in.
|
||||
// we already have sanitized match position above. Then we search from
|
||||
// head of str, count only valid digits to find corresponding start and
|
||||
// end position in origin str.
|
||||
var start = NaN;
|
||||
var end = NaN;
|
||||
var validDigits = 0;
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
if (/^[\d\+*#]$/.test(str[i])) {
|
||||
validDigits++;
|
||||
}
|
||||
if ((validDigits > digitBeforeMatch) && isNaN(start)) {
|
||||
start = i;
|
||||
} else if (validDigits >= (digitBeforeMatch + substr.length) &&
|
||||
isNaN(end)) {
|
||||
end = i;
|
||||
}
|
||||
}
|
||||
var startStr = str.substr(0, start);
|
||||
var middleStr = str.substr(start, end - start + 1);
|
||||
var endStr = str.substr(end + 1);
|
||||
|
||||
var startNode = document.createTextNode(startStr);
|
||||
var middleNode = document.createElement('mark');
|
||||
middleNode.textContent = middleStr;
|
||||
middleNode.classList.add('ci__mark');
|
||||
var endNode = document.createTextNode(endStr);
|
||||
|
||||
fragment.appendChild(startNode);
|
||||
fragment.appendChild(middleNode);
|
||||
fragment.appendChild(endNode);
|
||||
|
||||
return fragment;
|
||||
},
|
||||
|
||||
_initOverlay: function() {
|
||||
if (this.list) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.list = document.getElementById('contact-list');
|
||||
this.overlayCancel = document.getElementById('contact-list-overlay-cancel');
|
||||
this.overlayCancel.addEventListener('click', this.hideOverlay.bind(this));
|
||||
},
|
||||
|
||||
_clearOverlay: function() {
|
||||
while (this.list.firstElementChild != this.overlayCancel) {
|
||||
this.list.firstElementChild.remove();
|
||||
}
|
||||
},
|
||||
|
||||
showOverlay: function sb_showOverlay() {
|
||||
var self = this;
|
||||
LazyLoader.load(this.overlay, function() {
|
||||
self._initOverlay();
|
||||
self._clearOverlay();
|
||||
var title = self.overlay.querySelector('header');
|
||||
navigator.mozL10n.setAttributes(
|
||||
title,
|
||||
'suggestionMatches',
|
||||
{
|
||||
n: +self.countTag.textContent,
|
||||
matchNumber: self._phoneNumber
|
||||
}
|
||||
);
|
||||
for (var i = 0; i < self._contactList.length; i++) {
|
||||
for (var j = 0; j < self._allMatched.allMatches[i].length; j++) {
|
||||
var node = self._createItem();
|
||||
self._fillContacts(self._contactList[i],
|
||||
self._allMatched.allMatches[i][j], node);
|
||||
}
|
||||
}
|
||||
self.overlay.setAttribute('aria-hidden', false);
|
||||
self.overlay.classList.add('display');
|
||||
});
|
||||
},
|
||||
|
||||
_getAllMatched: function sb_getAllMatched(contacts) {
|
||||
var variants = SimplePhoneMatcher.generateVariants(this._phoneNumber);
|
||||
|
||||
var contactTels = contacts.map(function getTels(contact) {
|
||||
return contact.tel.map(function getNumber(tel) {
|
||||
return tel.value;
|
||||
});
|
||||
});
|
||||
|
||||
return SimplePhoneMatcher.bestMatch(variants, contactTels);
|
||||
},
|
||||
|
||||
hideOverlay: function sb_hideOverlay() {
|
||||
this.overlay.setAttribute('aria-hidden', true);
|
||||
this.overlay.classList.remove('display');
|
||||
}
|
||||
};
|
||||
|
||||
SuggestionBar.init();
|
||||
|
|
@ -0,0 +1,225 @@
|
|||
'use strict';
|
||||
|
||||
/* global LazyLoader, ConfirmDialog, MmiManager, TelephonyCall,
|
||||
TelephonyMessages */
|
||||
/* exported TelephonyHelper */
|
||||
|
||||
var TelephonyHelper = (function() {
|
||||
// DTMF control digit separator length (ms) as defined in GSM ETSI GSM 02.07
|
||||
const DTMF_SEPARATOR_PAUSE_DURATION = 3000;
|
||||
|
||||
var confirmLoaded = false;
|
||||
|
||||
var loadTelephonyMessages = function(callback) {
|
||||
LazyLoader.load(['/shared/js/dialer/telephony_messages.js'], callback);
|
||||
};
|
||||
|
||||
var call = function t_call(number, cardIndex, oncall, onconnected,
|
||||
ondisconnected) {
|
||||
var sanitizedNumber = number.replace(/(\s|-|\.|\(|\))/g, '');
|
||||
if (!isValid(sanitizedNumber)) {
|
||||
loadTelephonyMessages(function() {
|
||||
TelephonyMessages.displayMessage('BadNumber');
|
||||
});
|
||||
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
var conn = navigator.mozMobileConnections &&
|
||||
navigator.mozMobileConnections[cardIndex];
|
||||
|
||||
if (!conn || !conn.voice) {
|
||||
// No voice connection, the call won't make it
|
||||
loadTelephonyMessages(function() {
|
||||
TelephonyMessages.displayMessage('NoNetwork');
|
||||
});
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
return startDial(
|
||||
cardIndex, conn, sanitizedNumber, oncall, onconnected, ondisconnected
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
function getNumberAsDtmfToneGroups(number) {
|
||||
return number.split(',');
|
||||
}
|
||||
|
||||
function playDtmfToneGroups(dtmfToneGroups, cardIndex) {
|
||||
var length;
|
||||
|
||||
// Remove the dialed number from the beginning of the array.
|
||||
dtmfToneGroups = dtmfToneGroups.slice(1);
|
||||
length = dtmfToneGroups.length;
|
||||
|
||||
// Remove the latest entries from dtmfToneGroups corresponding to ','
|
||||
// characters not to play those pauses.
|
||||
var lastCommaIndex = length - 1;
|
||||
while (dtmfToneGroups[lastCommaIndex] === '') {
|
||||
lastCommaIndex--;
|
||||
}
|
||||
dtmfToneGroups = dtmfToneGroups.slice(0, ++lastCommaIndex);
|
||||
length = dtmfToneGroups.length;
|
||||
|
||||
var promise = Promise.resolve(),
|
||||
counter = 0,
|
||||
pauses;
|
||||
// Traverse the dtmfToneGroups array.
|
||||
while (counter < length) {
|
||||
// Reset the number of pauses before each group of tones.
|
||||
pauses = 1;
|
||||
while (dtmfToneGroups[counter] === '') {
|
||||
// Add a new pause for each '' in the dtmfToneGroups array.
|
||||
pauses++;
|
||||
counter++;
|
||||
}
|
||||
// Send a new group of tones as well as the pauses to play before it.
|
||||
promise = promise.then(playDtmfToneGroup.bind(null,
|
||||
dtmfToneGroups[counter++], pauses, cardIndex));
|
||||
}
|
||||
return promise;
|
||||
}
|
||||
|
||||
function playDtmfToneGroup(toneGroup, pauses, cardIndex) {
|
||||
return navigator.mozTelephony.sendTones(
|
||||
toneGroup,
|
||||
DTMF_SEPARATOR_PAUSE_DURATION * pauses,
|
||||
null /* tone duration */,
|
||||
cardIndex
|
||||
);
|
||||
}
|
||||
|
||||
function startDial(cardIndex, conn, sanitizedNumber, oncall, onconnected,
|
||||
ondisconnected) {
|
||||
var telephony = navigator.mozTelephony;
|
||||
if (!telephony) {
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
var emergencyOnly = conn.voice.emergencyCallsOnly;
|
||||
var hasCard = (conn.iccId !== null);
|
||||
var callPromise;
|
||||
var baseNumber = getNumberAsDtmfToneGroups(sanitizedNumber)[0];
|
||||
|
||||
if (emergencyOnly) {
|
||||
loadConfirm(function() {
|
||||
ConfirmDialog.show(
|
||||
'connectingEllipsis',
|
||||
'',
|
||||
{
|
||||
title: 'emergencyDialogBtnOk',
|
||||
callback: function() {
|
||||
ConfirmDialog.hide();
|
||||
}
|
||||
}
|
||||
);
|
||||
document.addEventListener('visibilitychange', function hideDialog() {
|
||||
document.removeEventListener('visibilitychange', hideDialog);
|
||||
|
||||
/* In tests this event can happen after the ConfirmDialog mock has
|
||||
* been removed so check that it's still there. */
|
||||
ConfirmDialog && ConfirmDialog.hide();
|
||||
});
|
||||
});
|
||||
|
||||
// If the mobileConnection has a sim card we let gecko take the
|
||||
// default service, otherwise we force the first slot.
|
||||
cardIndex = hasCard ? undefined : 0;
|
||||
callPromise = telephony.dialEmergency(baseNumber);
|
||||
} else {
|
||||
callPromise = telephony.dial(baseNumber, cardIndex);
|
||||
}
|
||||
|
||||
callPromise.then(function(obj) {
|
||||
if (obj instanceof TelephonyCall) {
|
||||
installHandlers(obj, sanitizedNumber, emergencyOnly, cardIndex,
|
||||
oncall, onconnected, ondisconnected);
|
||||
} else {
|
||||
/* This is an MMICall object, manually invoke the handlers to provide
|
||||
* feedback to the user, the rest of the UX will be dealt with by the
|
||||
* MMI manager. */
|
||||
oncall();
|
||||
onconnected();
|
||||
MmiManager.handleDialing(conn, sanitizedNumber, obj.result);
|
||||
}
|
||||
}, function(errorName) {
|
||||
loadTelephonyMessages(function() {
|
||||
var messageType = emergencyOnly ? TelephonyMessages.NO_NETWORK :
|
||||
TelephonyMessages.REGULAR_CALL;
|
||||
TelephonyMessages.handleError(
|
||||
errorName, sanitizedNumber, messageType);
|
||||
});
|
||||
});
|
||||
|
||||
return callPromise;
|
||||
}
|
||||
|
||||
function installHandlers(call, number, emergencyOnly, cardIndex,
|
||||
oncall, onconnected, ondisconnected) {
|
||||
if (oncall) {
|
||||
oncall();
|
||||
}
|
||||
var dtmfToneGroups = getNumberAsDtmfToneGroups(number);
|
||||
if (dtmfToneGroups.length > 1) {
|
||||
call.addEventListener('connected', function dtmfToneGroupPlayer() {
|
||||
call.removeEventListener('connected', dtmfToneGroupPlayer);
|
||||
playDtmfToneGroups(dtmfToneGroups, cardIndex);
|
||||
});
|
||||
}
|
||||
call.addEventListener('connected', onconnected);
|
||||
|
||||
call.addEventListener('disconnected', function handleDisconnect(evt) {
|
||||
loadTelephonyMessages(function() {
|
||||
TelephonyMessages.handleDisconnect(
|
||||
evt.call.disconnectedReason, number, emergencyOnly
|
||||
);
|
||||
});
|
||||
ondisconnected && ondisconnected();
|
||||
});
|
||||
}
|
||||
|
||||
var isValid = function t_isValid(sanitizedNumber) {
|
||||
var validExp = /^(?!,)([0-9#+*,]){1,50}$/;
|
||||
return validExp.test(sanitizedNumber);
|
||||
};
|
||||
|
||||
var loadConfirm = function t_loadConfirm(cb) {
|
||||
if (confirmLoaded) {
|
||||
cb();
|
||||
return;
|
||||
}
|
||||
|
||||
var confMsg = document.getElementById('confirmation-message');
|
||||
|
||||
LazyLoader.load(['/shared/js/confirm.js', confMsg], function() {
|
||||
confirmLoaded = true;
|
||||
cb();
|
||||
});
|
||||
};
|
||||
|
||||
var getInUseSim = function t_getInUseSim() {
|
||||
var telephony = navigator.mozTelephony;
|
||||
if (telephony) {
|
||||
var isInCall = !!telephony.calls.length;
|
||||
var isInConference = !!telephony.conferenceGroup &&
|
||||
!!telephony.conferenceGroup.calls.length;
|
||||
|
||||
if (isInCall || isInConference) {
|
||||
return isInCall ?
|
||||
navigator.mozTelephony.calls[0].serviceId :
|
||||
navigator.mozTelephony.conferenceGroup.calls[0].serviceId;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
window.TelephonyHelper = TelephonyHelper;
|
||||
|
||||
return {
|
||||
call: call,
|
||||
getInUseSim: getInUseSim
|
||||
};
|
||||
|
||||
})();
|
||||
|
|
@ -0,0 +1,332 @@
|
|||
/**
|
||||
* FIXME/bug 1060293: This is entirely copied and pasted from
|
||||
* shared/style/buttons.css because the selectors in there are overly broad and
|
||||
* had to be made more specific. We should remove this file and use that one
|
||||
* instead.
|
||||
*/
|
||||
/* ----------------------------------
|
||||
* Buttons
|
||||
* ---------------------------------- */
|
||||
|
||||
.activity::-moz-focus-inner {
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.activity {
|
||||
font-family: sans-serif;
|
||||
font-style: italic;
|
||||
width: 100%;
|
||||
height: 4rem;
|
||||
margin: 0 0 1rem;
|
||||
padding: 0 1.2rem;
|
||||
box-sizing: border-box;
|
||||
/*display: inline-block;*/
|
||||
vertical-align: middle;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
background: #d8d8d8;
|
||||
border: none;
|
||||
border-radius: 2rem;
|
||||
font-weight: normal;
|
||||
font-size: 1.6rem;
|
||||
line-height: 4rem;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* Recommend */
|
||||
.activity.recommend {
|
||||
background-color: #00caf2;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Danger */
|
||||
.danger.activity {
|
||||
background-color: #e51e1e;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Pressed */
|
||||
.activity:active {
|
||||
background-color: #b2f2ff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Icons */
|
||||
.activity[data-icon] {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.activity[data-icon]:before {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
margin-top: -1.5rem;
|
||||
offset-inline-end: 1.5rem;
|
||||
line-height: 3rem;
|
||||
}
|
||||
|
||||
.activity[data-icon]:active:before {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Pressed with dark skin */
|
||||
.skin-dark .activity:active {
|
||||
background-color: #00aacc;
|
||||
}
|
||||
|
||||
/* Disabled */
|
||||
.activity[aria-disabled="true"] {
|
||||
background-color: rgba(0,0,0,0.05);
|
||||
color: #c7c7c7;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.activity[aria-disabled="true"].recommend {
|
||||
background-color: #97cbd5;
|
||||
color: rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
.activity[aria-disabled="true"].danger {
|
||||
background-color: #eb7474;
|
||||
color: rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
/* Disabled with dark background */
|
||||
.skin-dark .activity[aria-disabled="true"] {
|
||||
background-color: #565656;
|
||||
color: rgba(255,255,255,0.4);
|
||||
}
|
||||
|
||||
.skin-dark .activity[aria-disabled="true"].recommend {
|
||||
background-color: #006579;
|
||||
}
|
||||
|
||||
.skin-dark .activity[aria-disabled="true"].danger {
|
||||
background-color: #730f0f;
|
||||
}
|
||||
|
||||
.activity[aria-disabled="true"]::-moz-selection {
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
/* ----------------------------------
|
||||
* Buttons inside lists
|
||||
* ---------------------------------- */
|
||||
|
||||
li .activity {
|
||||
position: relative;
|
||||
text-align: start;
|
||||
border: 0.1rem solid #c7c7c7;
|
||||
background: rgba(0,0,0,0.05);
|
||||
margin: 0 0 1rem;
|
||||
overflow: hidden;
|
||||
border-radius: 0;
|
||||
/*display: flex;*/
|
||||
height: auto;
|
||||
min-height: 4rem;
|
||||
text-overflow: initial;
|
||||
white-space: normal;
|
||||
line-height: 2rem;
|
||||
padding: 1rem 1.2rem;
|
||||
}
|
||||
|
||||
/* Press */
|
||||
li .activity:active:after {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* Disabled */
|
||||
li .activity[aria-disabled="true"] {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* Icons */
|
||||
li .activity.icon {
|
||||
padding-inline-end: 4rem;
|
||||
}
|
||||
|
||||
li .activity.icon:before {
|
||||
content: "";
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
offset-inline-end: 0.5rem;
|
||||
margin-top: -1.5rem;
|
||||
background: transparent no-repeat center center / 100% auto;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
li .activity.icon-view:active {
|
||||
background-color: #b2f2ff;
|
||||
}
|
||||
|
||||
li .activity.icon-view:before {
|
||||
background-size: 3rem;
|
||||
offset-inline-end: 0;
|
||||
}
|
||||
|
||||
li .activity[data-icon]:before {
|
||||
offset-inline-end: 1rem;
|
||||
}
|
||||
|
||||
li .activity[data-icon="expand"]:before {
|
||||
color: #00aac5;
|
||||
top: unset;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
li .activity[data-icon="expand"][aria-disabled="true"]:before {
|
||||
color: #A9A9A9;
|
||||
}
|
||||
|
||||
li .activity[data-icon="forward"]:before {
|
||||
color: #686f72;
|
||||
}
|
||||
|
||||
/* Getting more space for text, as icon is shorter */
|
||||
li .activity.icon-dialog {
|
||||
padding-inline-end: 3rem;
|
||||
}
|
||||
|
||||
li .activity.icon-dialog:before {
|
||||
width: 0;
|
||||
height: 0;
|
||||
top: auto;
|
||||
offset-inline-end: 0.8rem;
|
||||
bottom: 0.5rem;
|
||||
border-top: 0.7rem solid transparent;
|
||||
border-bottom: 0.7rem solid transparent;
|
||||
border-inline-start: 0.7rem solid #00aac5;
|
||||
transform: rotate(45deg);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
li .activity[aria-disabled="true"].icon-dialog:before {
|
||||
border-inline-start: 0.7rem solid #a9a9a9;
|
||||
}
|
||||
|
||||
/* ----------------------------------
|
||||
* Theme: Dark
|
||||
* ---------------------------------- */
|
||||
|
||||
.skin-dark li .activity {
|
||||
background-color: #454545;
|
||||
border: none;
|
||||
color: #fff;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.skin-dark li .activity:active {
|
||||
background-color: #00aacc;
|
||||
}
|
||||
|
||||
.skin-dark li .activity.icon-view:active {
|
||||
background-color: #00aacc;
|
||||
}
|
||||
|
||||
.skin-dark li .activity.icon-dialog:active:before {
|
||||
border-inline-start: 0.7rem solid #b2f2ff;
|
||||
}
|
||||
|
||||
.skin-dark li .activity[aria-disabled="true"] {
|
||||
background-color: #454545;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* Inputs inside of .button */
|
||||
body[role="application"] .activity input {
|
||||
border: 0;
|
||||
background: none;
|
||||
}
|
||||
|
||||
/* select */
|
||||
select {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
font-family: sans-serif;
|
||||
font-style: italic;
|
||||
font-size: 1.6rem;
|
||||
color: #333;
|
||||
margin: 0 0 1rem;
|
||||
padding: 0;
|
||||
padding-inline-start: 1.1rem;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
height: 4rem;
|
||||
border: 0.1rem solid #c7c7c7;
|
||||
background: rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
.skin-dark select {
|
||||
background-color: rgba(87, 87, 87, 0.8);
|
||||
border: none;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* remove dotted outline */
|
||||
select:-moz-focusring {
|
||||
color: transparent;
|
||||
text-shadow: 0 0 0 #333;
|
||||
}
|
||||
|
||||
.skin-dark select:-moz-focusring {
|
||||
text-shadow: 0 0 0 #fff;
|
||||
}
|
||||
|
||||
/* Hides dropdown arrow until bug #649849 is fixed */
|
||||
.activity.icon select,
|
||||
.activity[data-icon] select {
|
||||
position: absolute;
|
||||
top: -0.6rem;
|
||||
offset-inline-start: 0;
|
||||
width: calc(100% + 3rem);
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
padding-inline-end: 5rem;
|
||||
text-indent: 0;
|
||||
font-weight: 400;
|
||||
font-size: 1.7rem;
|
||||
/*
|
||||
The select element uses the text color to determine the color of the outline.
|
||||
We put a text shadow with needed offset and no blur, so that replaces the text.
|
||||
*/
|
||||
color: rgba(0,0,0,0);
|
||||
border: none;
|
||||
background: none;
|
||||
}
|
||||
html[dir="ltr"] .activity.icon select,
|
||||
html[dir="ltr"] .activity[data-icon] select {
|
||||
text-shadow: 1rem 0.5rem 0 #333;
|
||||
}
|
||||
html[dir="rtl"] .activity.icon select,
|
||||
html[dir="rtl"] .activity[data-icon] select {
|
||||
text-shadow: -1rem 0.5rem 0 #333;
|
||||
}
|
||||
|
||||
.activity.icon select option,
|
||||
.activity[data-icon] select option {
|
||||
color: #000;
|
||||
border: 0;
|
||||
padding: 0.6rem 1.3rem;
|
||||
text-shadow: 0 0 0 rgba(0,0,0,0);
|
||||
}
|
||||
|
||||
.activity.icon-dialog {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
html[dir="ltr"] .skin-dark .activity.icon select,
|
||||
html[dir="ltr"] .skin-dark .activity[data-icon] select {
|
||||
text-shadow: 1rem 0.5rem 0 #fff;
|
||||
}
|
||||
html[dir="rtl"] .skin-dark .activity.icon select,
|
||||
html[dir="rtl"] .skin-dark .activity[data-icon] select {
|
||||
text-shadow: -1rem 0.5rem 0 #fff;
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
#call-info-view {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
background: white;
|
||||
width: 100vw;
|
||||
height: calc(100vh - 4.5rem);
|
||||
color: #333;
|
||||
}
|
||||
|
||||
#call-info-view p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.ci__wrapper {
|
||||
padding: 1.4rem 1.5rem 0;
|
||||
}
|
||||
|
||||
.ci__calls-wrapper {
|
||||
padding: 0 0.9rem 1.4rem;
|
||||
padding-inline-start: 1.5rem;
|
||||
margin-bottom: 1.6rem;
|
||||
border-bottom: 1px solid #e7e7e7;
|
||||
}
|
||||
|
||||
.ci__group-info {
|
||||
display: flex;
|
||||
font-size: 1.6rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.ci__grow {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.call-duration {
|
||||
display: flex;
|
||||
margin-top: 1rem;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
.cd__duration {
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
.ci__direction-icon {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.icon-outgoing {
|
||||
background-image: url(images/call_info/callinfo_ic_outgoing.png);
|
||||
}
|
||||
|
||||
.icon-incoming {
|
||||
background-image: url(images/call_info/callinfo_ic_incoming.png);
|
||||
}
|
||||
|
||||
.icon-missed {
|
||||
background-image: url(images/call_info/callinfo_ic_missed.png);
|
||||
}
|
||||
|
||||
/**
|
||||
* As <gaia-header> does not support <h1 dir="auto"> children, a <bdi> element
|
||||
* must be nested and specific ellipsis rules must be applied.
|
||||
*
|
||||
* Horizontal padding must be applied in order to:
|
||||
* - not overlap the [action="back"] button
|
||||
* - keep the title centered
|
||||
* (the magic 50px value corresponds to the size of the "back" button).
|
||||
*/
|
||||
#call-info-title {
|
||||
display: block;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
padding-left: 50px;
|
||||
padding-right: 50px;
|
||||
}
|
||||
|
|
@ -0,0 +1,298 @@
|
|||
/* Overriding BB styles for headers */
|
||||
section[role="region"] > header:first-child .icon {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
/* Overriding BB styles for edit mode */
|
||||
form[role="dialog"][data-type="edit"] gaia-header {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
#call-log-container[data-type="list"] section {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
#sticky {
|
||||
position: absolute;
|
||||
|
||||
/* The sticky element is positioned at the beginning of the list. */
|
||||
top: 0;
|
||||
|
||||
/* The width is not 100% so the scrollbar is visible. */
|
||||
width: calc(100% - 1.5rem);
|
||||
|
||||
/* The height needs to be kept in sync with the header height. */
|
||||
height: 3.1rem;
|
||||
|
||||
/* Those style will affect the bagroundImage: -moz-element. */
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
html[dir="ltr"] #sticky { background-position: left 1.5rem top 0; }
|
||||
html[dir="rtl"] #sticky { background-position: right 1.5rem top 0; }
|
||||
|
||||
#call-log-container[data-type="list"] header {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
/* Override Building Block styles for lists */
|
||||
#call-log-container[data-type="list"] {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#call-log-container[data-type="list"] header {
|
||||
margin: 0 1.5rem;
|
||||
}
|
||||
|
||||
#call-log-container[data-type="list"] ol {
|
||||
padding: 0 1.5rem;
|
||||
|
||||
/* Bug 967880 - [Call Log] Background doesn't scroll with the logs causing
|
||||
* expensive over-invalidation.
|
||||
*/
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
#call-log-container[data-type="list"] li {
|
||||
height: 6rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* For preventig active status with withheld number */
|
||||
#call-log-container[data-type="list"] li[data-phone-number=""]:after,
|
||||
#call-log-container[data-type="list"] li[data-phone-number=""]:active:after {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#call-log-container[data-type="list"] li a p {
|
||||
line-height: 2.4rem;
|
||||
}
|
||||
|
||||
#call-log-container[data-type="list"] li a p:nth-last-of-type(3) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
button[disabled],
|
||||
input[type="text"][disabled],
|
||||
a.bb-button[disabled],
|
||||
a.bb-button[disabled] * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
input[type="text"][disabled],
|
||||
a.bb-button[disabled] {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
li, ol, ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font-size: 100%;
|
||||
font: inherit;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
ol, ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.view-body {
|
||||
color: black;
|
||||
height: calc(100% - 9.1rem);
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.view-body-inner {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.view-body-inner ol {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.icon-container {
|
||||
height: 100%;
|
||||
width: 5rem;
|
||||
}
|
||||
html[dir="ltr"] .icon-container { float: left; }
|
||||
html[dir="rtl"] .icon-container { float: right; }
|
||||
|
||||
.icon-incoming,
|
||||
.icon-outgoing,
|
||||
.icon-missed {
|
||||
background-size: 3rem;
|
||||
}
|
||||
|
||||
/* .first-sim and .second-sim classes should only affect the style
|
||||
* if the .dual-sim class is set on the container */
|
||||
|
||||
[data-type="list"] aside.icon.icon-incoming {
|
||||
background-image: url('images/CallLog_30x30_incoming.png');
|
||||
}
|
||||
[data-type="list"].dual-sim aside.icon.icon-incoming.first-sim {
|
||||
background-image: url('images/CallLog_30x30_incoming-first-sim.png');
|
||||
}
|
||||
[data-type="list"].dual-sim aside.icon.icon-incoming.second-sim {
|
||||
background-image: url('images/CallLog_30x30_incoming-second-sim.png');
|
||||
}
|
||||
|
||||
[data-type="list"] aside.icon.icon-outgoing {
|
||||
background-image: url('images/CallLog_30x30_outgoing.png');
|
||||
}
|
||||
[data-type="list"].dual-sim aside.icon.icon-outgoing.first-sim {
|
||||
background-image: url('images/CallLog_30x30_outgoing-first-sim.png');
|
||||
}
|
||||
[data-type="list"].dual-sim aside.icon.icon-outgoing.second-sim {
|
||||
background-image: url('images/CallLog_30x30_outgoing-second-sim.png');
|
||||
}
|
||||
|
||||
[data-type="list"] aside.icon.icon-missed {
|
||||
background-image: url('images/CallLog_30x30_missed.png');
|
||||
}
|
||||
[data-type="list"].dual-sim aside.icon.icon-missed.first-sim {
|
||||
background-image: url('images/CallLog_30x30_missed-first-sim.png');
|
||||
}
|
||||
[data-type="list"].dual-sim aside.icon.icon-missed.second-sim {
|
||||
background-image: url('images/CallLog_30x30_missed-second-sim.png');
|
||||
}
|
||||
|
||||
.log-item * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.log-item .primary-info {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* Decrease padding defined by BB styles to compensate increased line-height */
|
||||
.log-item .primary-info:first-of-type {
|
||||
padding-top: 0.8rem;
|
||||
}
|
||||
|
||||
.log-item a > p {
|
||||
width: calc(100% - 4rem);
|
||||
}
|
||||
|
||||
.log-item.missed-call .primary-info {
|
||||
color: #bc1515;
|
||||
}
|
||||
|
||||
.log-item .primary-info-main {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.log-item .primary-info-main bdi {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.log-item .retry-count {
|
||||
margin-inline-start: 0.5rem;
|
||||
}
|
||||
|
||||
.log-item .additional-info {
|
||||
display: inline-flex;
|
||||
justify-content: space-between;
|
||||
margin-top: -0.4rem;
|
||||
}
|
||||
|
||||
.log-item .type-carrier {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.log-item .call-time {
|
||||
margin-inline-start: 0.5rem;
|
||||
}
|
||||
|
||||
.log-item .pack-checkbox {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
/* Edit mode state */
|
||||
.recents-edit form[role="dialog"][data-type="edit"] header,
|
||||
.recents-edit form[role="dialog"][data-type="edit"] > menu {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
html[dir="ltr"] .recents-edit .pack-checkbox.call-log-selection {
|
||||
transform: translateX(4rem);
|
||||
}
|
||||
html[dir="rtl"] .recents-edit .pack-checkbox.call-log-selection {
|
||||
transform: translateX(-4rem);
|
||||
}
|
||||
|
||||
.recents-edit .log-item a {
|
||||
visibility: hidden;
|
||||
}
|
||||
html[dir="ltr"] .recents-edit .log-item a { transform: translateX(3rem); }
|
||||
html[dir="rtl"] .recents-edit .log-item a { transform: translateX(-3rem); }
|
||||
|
||||
.recents-edit .log-item a > aside,
|
||||
.recents-edit .log-item a > p {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.recents-edit .log-item a > p {
|
||||
width: calc(100% - 6.5rem);
|
||||
}
|
||||
|
||||
.recents-edit .log-item .pack-checkbox {
|
||||
pointer-events: auto;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/*
|
||||
No result container
|
||||
*/
|
||||
|
||||
#no-result-container {
|
||||
background: url('images/ComLog_200x200_clock.png') fixed no-repeat center / 20rem;
|
||||
height: 100%;
|
||||
margin: 0 1.5rem;
|
||||
}
|
||||
|
||||
#no-result-message {
|
||||
position: relative;
|
||||
top: 11.5rem;
|
||||
border-top: .1rem solid rgba(96,96,96,.5);
|
||||
padding: 1rem 1.5rem;
|
||||
}
|
||||
|
||||
#no-result-message > p {
|
||||
text-align: start;
|
||||
line-height: 3rem;
|
||||
font-size: 2.2rem;
|
||||
font-weight: 300;
|
||||
color: #606060;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.recents-edit #edit-mode {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.recents-edit .recents-filter-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.recents-edit .view-body {
|
||||
height: calc(100% - 7.6rem);
|
||||
}
|
||||
|
||||
.filter .log-item:not(.missed-call) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.filter .groupFiltered {
|
||||
display: none;
|
||||
}
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 2 KiB |
|
After Width: | Height: | Size: 508 B |
|
After Width: | Height: | Size: 528 B |
|
After Width: | Height: | Size: 459 B |
|
After Width: | Height: | Size: 498 B |
|
After Width: | Height: | Size: 503 B |
|
After Width: | Height: | Size: 451 B |
|
After Width: | Height: | Size: 504 B |
|
After Width: | Height: | Size: 521 B |
|
After Width: | Height: | Size: 452 B |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 264 B |
|
After Width: | Height: | Size: 316 B |
|
After Width: | Height: | Size: 271 B |
|
After Width: | Height: | Size: 393 B |
|
After Width: | Height: | Size: 380 B |
|
After Width: | Height: | Size: 512 B |
|
After Width: | Height: | Size: 138 B |
|
|
@ -0,0 +1,49 @@
|
|||
#mmi-screen {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: white;
|
||||
color: black;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#mmi-screen[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#mmi-container {
|
||||
flex: 1;
|
||||
padding: 0 3rem;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#message {
|
||||
font-size: 2rem;
|
||||
padding: 2rem 0;
|
||||
white-space: pre-line;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
#response {
|
||||
display: none;
|
||||
padding: 1.5rem 1.5rem 0.5rem;
|
||||
border-top: 0.1rem solid #E7E7E7;
|
||||
}
|
||||
|
||||
.responseForm #response {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#response-text[disabled] {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/*
|
||||
Loading screen
|
||||
*/
|
||||
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
.suggestion-bar {
|
||||
display: flex;
|
||||
margin-top: -4.5rem;
|
||||
height: 4.5rem;
|
||||
font-size: 1.7rem;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
color: #033B37;
|
||||
}
|
||||
|
||||
.suggestion-count {
|
||||
width: 5.5rem;
|
||||
box-sizing: border-box;
|
||||
border-inline-start: 1px solid rgba(255,255,255,0.2);
|
||||
padding-inline-end: 2rem;
|
||||
padding-inline-start: 1rem;
|
||||
line-height: 4.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.suggestion-count.more {
|
||||
background-image: url(/dialer/style/images/suggestion/actionicon_dialer_more.png);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 3rem;
|
||||
}
|
||||
html[dir="ltr"] .suggestion-count.more { background-position: right 0 bottom 0.8rem; }
|
||||
html[dir="rtl"] .suggestion-count.more { background-position: left 0 bottom 0.8rem; }
|
||||
|
||||
.suggestion-bar .contact-item:active,
|
||||
.suggestion-bar .suggestion-count:active {
|
||||
background-color: #94eee9;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/* Structure for toolbar*/
|
||||
|
||||
.icon-recents {
|
||||
background-image: url("images/recents.png");
|
||||
}
|
||||
|
||||
.icon-contacts {
|
||||
background-image: url("images/contacts.png");
|
||||
}
|
||||
|
||||
.icon-keypad {
|
||||
background-image: url("images/dialpad.png");
|
||||
}
|
||||
|
||||
/* Making lazy loading look nice */
|
||||
#contacts-view .bb-tabpanel,
|
||||
#recents-view.hidden .bb-tabpanel {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
#contacts-view .bb-tabpanel:before,
|
||||
#recents-view.hidden .bb-tabpanel:before {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 5rem;
|
||||
|
||||
background-color: var(--header-background);
|
||||
content: "";
|
||||
}
|
||||
|
||||
#iframe-contacts-container {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#iframe-contacts {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#recents-view.hidden .bb-tabpanel section {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.no-opacity {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
|
||||
/* For showing/hiding navbar */
|
||||
#views:before {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
#views.hide-toolbar:before {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
#views > li > .icon {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#views.hide-toolbar > li {
|
||||
background: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#views.hide-toolbar > li:before,
|
||||
#views.hide-toolbar > li > .icon {
|
||||
transform: translateY(100%);
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#views.hide-toolbar #iframe-contacts-container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#views .bb-tabpanel {
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
#contacts-view .bb-tabpanel {
|
||||
height: calc(100% - 4.5rem);
|
||||
z-index: 1;
|
||||
}
|
||||