Merge branch 'audio-player-446'
This commit is contained in:
commit
bf00606f8d
186
app/css/app.css
186
app/css/app.css
@ -425,7 +425,7 @@ input[type="number"] {
|
||||
.modal-close-button i {
|
||||
display: inline-block;
|
||||
background: url(../img/icons/IconsetW.png) -15px -320px no-repeat;
|
||||
background-size: 42px 891px;
|
||||
background-size: 42px 971px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin: 21px;
|
||||
@ -877,7 +877,7 @@ input.tg_range::-moz-range-thumb {
|
||||
font-size: 12px;
|
||||
line-height: normal;
|
||||
background: #F2F2F2 url(../img/icons/IconsetW.png) -6px -205px no-repeat;
|
||||
background-size: 42px 891px;
|
||||
background-size: 42px 971px;
|
||||
border: 1px solid #F2F2F2;
|
||||
border-radius: 3px;
|
||||
padding: 6px 20px 6px 30px;
|
||||
@ -905,7 +905,7 @@ input.tg_range::-moz-range-thumb {
|
||||
height: 13px;
|
||||
vertical-align: text-top;
|
||||
background: url(../img/icons/IconsetW.png) -15px -192px no-repeat;
|
||||
background-size: 42px 891px;
|
||||
background-size: 42px 971px;
|
||||
opacity: 0.6;
|
||||
}
|
||||
.is_1x .im_dialogs_search_clear {
|
||||
@ -1111,7 +1111,7 @@ a.im_dialog_selected .im_dialog_date {
|
||||
margin-left: 6px;
|
||||
|
||||
background: url(../img/icons/IconsetW.png) -17px -444px no-repeat;
|
||||
background-size: 42px 891px;
|
||||
background-size: 42px 971px;
|
||||
}
|
||||
.is_1x .icon-caret {
|
||||
background-image: url(../img/icons/IconsetW_1x.png);
|
||||
@ -1194,57 +1194,7 @@ a.im_dialog_selected .im_dialog_date {
|
||||
.non_osx .im_message_fwd_author {
|
||||
font-size: 12px;
|
||||
}
|
||||
.im_grouped_short .im_message_from_photo,
|
||||
.im_grouped_short .im_message_author,
|
||||
.im_grouped .im_message_from_photo,
|
||||
.im_grouped .im_message_author,
|
||||
.im_grouped_fwd .im_message_author,
|
||||
.im_grouped_fwd .im_message_from_photo,
|
||||
.im_grouped_fwd_short .im_message_author,
|
||||
.im_grouped_fwd_short .im_message_from_photo {
|
||||
display: none;
|
||||
}
|
||||
.im_grouped_short .im_message_body,
|
||||
.im_grouped .im_message_body,
|
||||
.im_grouped_fwd .im_message_body,
|
||||
.im_grouped_fwd_short .im_message_body {
|
||||
margin-left: 46px;
|
||||
}
|
||||
.im_grouped_short .im_content_message_select_area,
|
||||
.im_grouped .im_content_message_select_area {
|
||||
height: 34px;
|
||||
}
|
||||
.im_history_appending .im_content_message_select_area {
|
||||
height: 52px;
|
||||
}
|
||||
.im_grouped_short .icon-select-tick,
|
||||
.im_grouped_fwd_short .icon-select-tick {
|
||||
margin-top: 5px;
|
||||
}
|
||||
.im_grouped_short .icon-message-status,
|
||||
.im_grouped_fwd_short .icon-message-status {
|
||||
margin-top: 5px;
|
||||
}
|
||||
.im_grouped_fwd .im_message_fwd_from,
|
||||
.im_grouped_fwd_short .im_message_fwd_from {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.im_grouped_short .im_message_fwd .im_message_date,
|
||||
.im_grouped .im_message_fwd .im_message_date,
|
||||
.im_grouped_fwd .im_message_fwd .im_message_date,
|
||||
.im_grouped_fwd_short .im_message_fwd .im_message_date {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.im_grouped_fwd .im_message_fwd,
|
||||
.im_grouped_fwd_short .im_message_fwd {
|
||||
margin-top: 8px;
|
||||
}
|
||||
.im_grouped_fwd .im_message_fwd,
|
||||
.im_grouped_fwd_short .im_message_fwd {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.im_message_from_photo,
|
||||
.im_message_contact_photo,
|
||||
@ -1323,7 +1273,7 @@ div.im_message_video_thumb {
|
||||
height: 42px;
|
||||
|
||||
background: url(../img/icons/IconsetW.png) 0 -590px no-repeat;
|
||||
background-size: 42px 891px;
|
||||
background-size: 42px 971px;
|
||||
z-index: 1;
|
||||
}
|
||||
.is_1x .icon-videoplay {
|
||||
@ -1350,7 +1300,7 @@ div.im_message_video_thumb {
|
||||
height: 19px;
|
||||
|
||||
background: url(../img/icons/IconsetW.png) -14px -389px no-repeat;
|
||||
background-size: 42px 891px;
|
||||
background-size: 42px 971px;
|
||||
}
|
||||
.is_1x .icon-geo-point {
|
||||
background-image: url(../img/icons/IconsetW_1x.png);
|
||||
@ -1392,13 +1342,15 @@ div.im_message_video_thumb {
|
||||
}
|
||||
|
||||
.im_message_document,
|
||||
.im_message_audio,
|
||||
.im_message_upload_file {
|
||||
margin-top: 3px;
|
||||
border-radius: 3px;
|
||||
display: inline-block;
|
||||
width: 340px;
|
||||
}
|
||||
.im_message_audio {
|
||||
margin-top: 3px;
|
||||
}
|
||||
.icon-document,
|
||||
.icon-photo,
|
||||
.icon-video {
|
||||
@ -1409,7 +1361,7 @@ div.im_message_video_thumb {
|
||||
vertical-align: text-top;
|
||||
|
||||
background: #F2F2F2 url(../img/icons/IconsetW.png) -2px -229px no-repeat;
|
||||
background-size: 42px 891px;
|
||||
background-size: 42px 971px;
|
||||
border-radius: 3px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
@ -1478,44 +1430,39 @@ img.im_message_document_thumb {
|
||||
color: #999;
|
||||
padding-left: 2px;
|
||||
}
|
||||
.im_message_document_actions a {
|
||||
.im_message_document_actions a,
|
||||
.audio_player_actions a {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.icon-audio {
|
||||
display: block;
|
||||
float: left;
|
||||
.audio_player_button {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
vertical-align: text-top;
|
||||
|
||||
background: #F2F2F2 url(../img/icons/IconsetW.png) -2px -277px no-repeat;
|
||||
background-size: 42px 891px;
|
||||
border-radius: 3px;
|
||||
margin-right: 10px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
.is_1x .icon-audio {
|
||||
.audio_player_btn_icon {
|
||||
display: block;
|
||||
width: 13px;
|
||||
height: 18px;
|
||||
background: url(../img/icons/IconsetW.png) -15px -898px no-repeat;
|
||||
background-size: 42px 971px;
|
||||
}
|
||||
.is_1x .audio_player_btn_icon {
|
||||
background-image: url(../img/icons/IconsetW_1x.png);
|
||||
}
|
||||
.im_message_selected .icon-audio,
|
||||
.im_history_selectable .im_message_outer_wrap:hover .icon-audio {
|
||||
background-color: #dae6f0;
|
||||
background-position: -2px -697px;
|
||||
.audio_player_btn_icon_pause {
|
||||
background-position: -15px -924px;
|
||||
}
|
||||
|
||||
|
||||
.im_message_audio_info {
|
||||
float: left;
|
||||
width: 292px;
|
||||
.audio_player_btn_icon_cancel {
|
||||
background-position: -15px -948px;
|
||||
}
|
||||
.im_message_audio_name_wrap {
|
||||
.audio_player_title_wrap {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
width: 290px;
|
||||
padding: 0 0 1px;
|
||||
}
|
||||
.im_message_audio_name {
|
||||
.audio_player_title {
|
||||
color: #222;
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
@ -1525,25 +1472,33 @@ img.im_message_document_thumb {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.im_message_audio_duration,
|
||||
.im_message_audio_size {
|
||||
.audio_player_title:hover {
|
||||
color: #222;
|
||||
}
|
||||
.audio_player_meta {
|
||||
overflow: hidden;
|
||||
vertical-align: text-top;
|
||||
display: inline-block;
|
||||
}
|
||||
.audio_player_size,
|
||||
.audio_player_duration {
|
||||
color: #999;
|
||||
padding-left: 2px;
|
||||
}
|
||||
.im_message_audio_info audio {
|
||||
width: 100%;
|
||||
height: 38px;
|
||||
line-height: 38px;
|
||||
}
|
||||
|
||||
.im_message_upload_progress_wrap,
|
||||
.im_message_download_progress_wrap {
|
||||
margin-top: 5px;
|
||||
width: 290px;
|
||||
}
|
||||
.audio_player_progress_wrap {
|
||||
margin-top: 5px;
|
||||
max-width: 290px;
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.im_message_document_thumbed .im_message_document_name_wrap,
|
||||
.im_message_document_thumbed .im_message_audio_name_wrap,
|
||||
.im_message_document_thumbed .im_message_upload_progress_wrap,
|
||||
.im_message_document_thumbed .im_message_download_progress_wrap {
|
||||
width: 230px;
|
||||
@ -1566,7 +1521,8 @@ img.im_message_document_thumb {
|
||||
}
|
||||
|
||||
.tg_up_progress,
|
||||
.tg_down_progress {
|
||||
.tg_down_progress,
|
||||
.tg_play_progress {
|
||||
height: 5px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
@ -1577,7 +1533,8 @@ img.im_message_document_thumb {
|
||||
box-shadow: none;
|
||||
}
|
||||
.tg_up_progress .progress-bar,
|
||||
.tg_down_progress .progress-bar {
|
||||
.tg_down_progress .progress-bar,
|
||||
.tg_play_progress .progress-bar {
|
||||
height: 5px;
|
||||
line-height: 5px;
|
||||
background: #6B9ABD;
|
||||
@ -1586,6 +1543,18 @@ img.im_message_document_thumb {
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
.tg_play_progress {
|
||||
background: #e4e9ed;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.tg_play_progress .progress-bar {
|
||||
background: #628fb2;
|
||||
border-radius: 2px;
|
||||
/*-webkit-transition: width 1s linear;
|
||||
transition: width 1s linear;*/
|
||||
-webkit-transition: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1626,24 +1595,11 @@ div.im_message_body {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
}
|
||||
.im_message_fwd_from {
|
||||
margin-top: 5px;
|
||||
}
|
||||
.im_grouped .im_message_fwd_from {
|
||||
margin-top: 0;
|
||||
}
|
||||
.im_message_fwd {
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
a.im_message_fwd_photo {
|
||||
position: absolute;
|
||||
margin-top: 1px;
|
||||
}
|
||||
.im_message_fwd_author {
|
||||
margin-right: 5px;
|
||||
}
|
||||
.im_message_fwd_date {
|
||||
padding: 0;
|
||||
}
|
||||
@ -1758,7 +1714,7 @@ textarea.im_message_field {
|
||||
height: 23px;
|
||||
vertical-align: text-top;
|
||||
background: url(../img/icons/IconsetW.png) -12px -68px no-repeat;
|
||||
background-size: 42px 891px;
|
||||
background-size: 42px 971px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
.is_1x .icon-paperclip {
|
||||
@ -1786,7 +1742,7 @@ textarea.im_message_field {
|
||||
height: 23px;
|
||||
vertical-align: text-top;
|
||||
background: url(../img/icons/IconsetW.png) -10px -4px no-repeat;
|
||||
background-size: 42px 891px;
|
||||
background-size: 42px 971px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
.is_1x .icon-emoji {
|
||||
@ -1835,7 +1791,7 @@ textarea.im_message_field {
|
||||
height: 21px;
|
||||
vertical-align: text-top;
|
||||
background: url(../img/icons/IconsetW.png) -9px -132px no-repeat;
|
||||
background-size: 42px 891px;
|
||||
background-size: 42px 971px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
.is_1x .icon-camera {
|
||||
@ -2174,7 +2130,7 @@ a:hover .icon-twitter {
|
||||
font-size: 12px;
|
||||
line-height: normal;
|
||||
background: url(../img/icons/IconsetW.png) -6px -205px no-repeat;
|
||||
background-size: 42px 891px;
|
||||
background-size: 42px 971px;
|
||||
border: 1px solid #d9dbde;
|
||||
border-radius: 3px;
|
||||
padding: 6px 15px 6px 30px;
|
||||
@ -2193,7 +2149,7 @@ a:hover .icon-twitter {
|
||||
height: 13px;
|
||||
vertical-align: text-top;
|
||||
background: url(../img/icons/IconsetW.png) -15px -192px no-repeat;
|
||||
background-size: 42px 891px;
|
||||
background-size: 42px 971px;
|
||||
opacity: 0.6;
|
||||
}
|
||||
.is_1x .contacts_modal_search_clear {
|
||||
@ -2309,7 +2265,7 @@ img.chat_modal_participant_photo {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
background: url(../img/icons/IconsetW.png) -9px -516px no-repeat;
|
||||
background-size: 42px 891px;
|
||||
background-size: 42px 971px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
.is_1x .icon-contact-tick {
|
||||
@ -2378,8 +2334,8 @@ img.chat_modal_participant_photo {
|
||||
|
||||
.im_message_focus .im_message_date,
|
||||
.im_message_focus .im_message_document_size,
|
||||
.im_message_focus .im_message_audio_duration,
|
||||
.im_message_focus .im_message_audio_size,
|
||||
.im_message_focus .audio_player_duration,
|
||||
.im_message_focus .audio_player_size,
|
||||
.im_message_focus .im_message_fwd_date {
|
||||
color: #68839c;
|
||||
}
|
||||
@ -2390,7 +2346,7 @@ img.chat_modal_participant_photo {
|
||||
height: 26px;
|
||||
margin: 13px 0 0 40px;
|
||||
background: url(../img/icons/IconsetW.png) -9px -516px no-repeat;
|
||||
background-size: 42px 891px;
|
||||
background-size: 42px 971px;
|
||||
}
|
||||
.is_1x .icon-select-tick {
|
||||
background-image: url(../img/icons/IconsetW_1x.png);
|
||||
@ -2509,7 +2465,7 @@ ce671b orange
|
||||
font-size: 12px;
|
||||
line-height: normal;
|
||||
background: #F2F2F2 url(../img/icons/IconsetW.png) -6px -205px no-repeat;
|
||||
background-size: 42px 891px;
|
||||
background-size: 42px 971px;
|
||||
border: 1px solid #F2F2F2;
|
||||
border-radius: 3px;
|
||||
padding: 6px 20px 6px 30px;
|
||||
@ -2532,7 +2488,7 @@ ce671b orange
|
||||
height: 13px;
|
||||
vertical-align: text-top;
|
||||
background: url(../img/icons/IconsetW.png) -15px -192px no-repeat;
|
||||
background-size: 42px 891px;
|
||||
background-size: 42px 971px;
|
||||
opacity: 0.6;
|
||||
}
|
||||
.is_1x .countries_modal_search_clear {
|
||||
|
@ -462,6 +462,9 @@ a.footer_lang_link.active:active {
|
||||
}
|
||||
|
||||
|
||||
.im_message_fwd_author {
|
||||
margin-right: 5px;
|
||||
}
|
||||
.im_message_fwd .im_message_fwd_author_wrap,
|
||||
.im_message_fwd .im_message_text,
|
||||
.im_message_fwd .im_message_media {
|
||||
@ -788,6 +791,70 @@ div.im_panel_own_photo {
|
||||
}
|
||||
}
|
||||
|
||||
/* Groupings */
|
||||
.im_message_fwd_from {
|
||||
margin-top: 5px;
|
||||
}
|
||||
.im_grouped .im_message_fwd_from {
|
||||
margin-top: 0;
|
||||
}
|
||||
.im_message_fwd {
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.im_grouped_short .im_message_from_photo,
|
||||
.im_grouped_short .im_message_author,
|
||||
.im_grouped .im_message_from_photo,
|
||||
.im_grouped .im_message_author,
|
||||
.im_grouped_fwd .im_message_author,
|
||||
.im_grouped_fwd .im_message_from_photo,
|
||||
.im_grouped_fwd_short .im_message_author,
|
||||
.im_grouped_fwd_short .im_message_from_photo {
|
||||
display: none;
|
||||
}
|
||||
.im_grouped_short .im_message_body,
|
||||
.im_grouped .im_message_body,
|
||||
.im_grouped_fwd .im_message_body,
|
||||
.im_grouped_fwd_short .im_message_body {
|
||||
margin-left: 46px;
|
||||
}
|
||||
.im_grouped_short .im_content_message_select_area,
|
||||
.im_grouped .im_content_message_select_area {
|
||||
height: 34px;
|
||||
}
|
||||
.im_history_appending .im_content_message_select_area {
|
||||
height: 52px;
|
||||
}
|
||||
.im_grouped_short .icon-select-tick,
|
||||
.im_grouped_fwd_short .icon-select-tick {
|
||||
margin-top: 5px;
|
||||
}
|
||||
.im_grouped_short .icon-message-status,
|
||||
.im_grouped_fwd_short .icon-message-status {
|
||||
margin-top: 5px;
|
||||
}
|
||||
.im_grouped_fwd .im_message_fwd_from,
|
||||
.im_grouped_fwd_short .im_message_fwd_from {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.im_grouped_short .im_message_fwd .im_message_date,
|
||||
.im_grouped .im_message_fwd .im_message_date,
|
||||
.im_grouped_fwd .im_message_fwd .im_message_date,
|
||||
.im_grouped_fwd_short .im_message_fwd .im_message_date {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.im_grouped_fwd .im_message_fwd,
|
||||
.im_grouped_fwd_short .im_message_fwd {
|
||||
margin-top: 8px;
|
||||
}
|
||||
.im_grouped_fwd .im_message_fwd,
|
||||
.im_grouped_fwd_short .im_message_fwd {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
|
||||
.tooltip-inner {
|
||||
background: rgba(0,0,0, 0.8);
|
||||
}
|
||||
|
@ -39,8 +39,6 @@ html {
|
||||
}
|
||||
|
||||
.tg_page_head .navbar-inverse .navbar-toggle:hover,
|
||||
/*.tg_page_head .navbar-inverse .navbar-toggle:active,*/
|
||||
.tg_page_head .navbar-inverse .navbar-toggle:focus,
|
||||
.tg_page_head .navbar-inverse .open .navbar-toggle {
|
||||
background-color: rgba(0,0,0,0.1);
|
||||
}
|
||||
@ -331,14 +329,12 @@ html {
|
||||
}
|
||||
|
||||
|
||||
.im_message_body,
|
||||
.im_message_document {
|
||||
.im_message_body {
|
||||
padding: 7px 10px;
|
||||
border-radius: 3px;
|
||||
background: #f1f1f1;
|
||||
}
|
||||
.im_message_out .im_message_body,
|
||||
.im_message_out .im_message_document {
|
||||
.im_message_out .im_message_body {
|
||||
background: #e4ecf2;
|
||||
}
|
||||
.im_message_body_media,
|
||||
@ -348,7 +344,8 @@ html {
|
||||
background: none;
|
||||
}
|
||||
.im_message_selected .im_message_body,
|
||||
.im_message_selected .im_message_document {
|
||||
.im_message_selected .im_message_document,
|
||||
.im_message_selected .im_message_audio {
|
||||
background: #497495;
|
||||
color: #FFF;
|
||||
}
|
||||
@ -357,68 +354,44 @@ html {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.im_message_fwd .im_message_body,
|
||||
.im_message_fwd .im_message_document {
|
||||
padding: 7px 8px;
|
||||
}
|
||||
.im_grouped_fwd_start .im_message_body,
|
||||
.im_grouped_fwd_short .im_message_body,
|
||||
.im_grouped_fwd .im_message_body,
|
||||
.im_grouped .im_message_fwd .im_message_body,
|
||||
.im_grouped_fwd_start .im_message_document,
|
||||
.im_grouped_fwd_short .im_message_document,
|
||||
.im_grouped_fwd .im_message_document,
|
||||
.im_grouped .im_message_fwd .im_message_document {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.im_grouped_fwd_start .im_message_fwd .im_message_body,
|
||||
.im_grouped_fwd_start .im_message_fwd .im_message_document {
|
||||
border-radius: 3px 3px 0 0;
|
||||
}
|
||||
.im_grouped_fwd_end .im_message_fwd .im_message_body,
|
||||
.im_grouped_fwd_end .im_message_fwd .im_message_document {
|
||||
border-radius: 0 0 3px 3px;
|
||||
}
|
||||
|
||||
.im_message_fwd .im_message_text {
|
||||
min-height: 21px;
|
||||
}
|
||||
.im_grouped_fwd .im_message_text,
|
||||
.im_grouped_fwd_short .im_message_text {
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.im_service_message {
|
||||
font-size: 13px;
|
||||
}
|
||||
.im_message_document {
|
||||
.audio_player_button {
|
||||
margin-right: 8px;
|
||||
}
|
||||
.im_message_body_media .im_message_document,
|
||||
.im_message_body_media .im_message_audio {
|
||||
padding: 5px;
|
||||
width: auto;
|
||||
max-width: 250px;
|
||||
border-radius: 3px;
|
||||
background: #f1f1f1;
|
||||
margin-top: 0;
|
||||
}
|
||||
.im_message_audio,
|
||||
.im_message_body_media a.im_message_photo_thumb,
|
||||
.im_message_body_media .im_message_video {
|
||||
margin-top: 0;
|
||||
}
|
||||
.im_message_out .im_message_body_media .im_message_document,
|
||||
.im_message_out .im_message_body_media .im_message_audio {
|
||||
background: #e4ecf2;
|
||||
}
|
||||
.im_message_document {
|
||||
width: auto;
|
||||
max-width: 250px;
|
||||
}
|
||||
.im_message_document {
|
||||
position: relative;
|
||||
}
|
||||
.im_message_audio > a,
|
||||
.im_message_document .icon-document,
|
||||
.im_message_audio .icon-audio,
|
||||
.im_message_document_thumb_wrap {
|
||||
position: absolute;
|
||||
}
|
||||
.im_message_out .im_message_audio .icon-audio,
|
||||
.im_message_out .im_message_document .icon-document {
|
||||
background-color: #e4ecf2;
|
||||
}
|
||||
.im_message_document_thumb_wrap {
|
||||
background-color: transparent;
|
||||
}
|
||||
.im_message_audio_done i {
|
||||
display: none;
|
||||
}
|
||||
.im_message_audio_info,
|
||||
.im_message_document_info {
|
||||
float: none;
|
||||
margin-left: 43px;
|
||||
@ -428,25 +401,6 @@ html {
|
||||
.im_message_document_thumbed .im_message_document_info {
|
||||
margin-left: 110px;
|
||||
}
|
||||
.im_message_audio_name,
|
||||
.im_message_audio_duration {
|
||||
display: inline;
|
||||
vertical-align: baseline;
|
||||
line-height: 38px;
|
||||
}
|
||||
.im_message_audio_progress .im_message_audio_name,
|
||||
.im_message_audio_progress .im_message_audio_duration {
|
||||
line-height: 18px;
|
||||
}
|
||||
.im_message_audio_done .im_message_audio_info {
|
||||
margin-left: 0;
|
||||
width: auto;
|
||||
float: none;
|
||||
}
|
||||
.im_message_audio_player_wrap {
|
||||
height: 38px;
|
||||
line-height: 38px;
|
||||
}
|
||||
.im_message_document_size {
|
||||
display: block;
|
||||
padding-left: 0;
|
||||
@ -454,13 +408,11 @@ html {
|
||||
.im_message_document_thumbed .im_message_document_info {
|
||||
min-height: 100px;
|
||||
}
|
||||
.im_message_document_info .cancelable_progress_wrap,
|
||||
.im_message_audio_info .cancelable_progress_wrap {
|
||||
.im_message_document_info .cancelable_progress_wrap {
|
||||
margin-top: 4px;
|
||||
}
|
||||
.im_message_document_thumbed .im_message_document_name_wrap,
|
||||
.im_message_document_name_wrap,
|
||||
.im_message_audio_name_wrap {
|
||||
.im_message_document_name_wrap {
|
||||
width: auto;
|
||||
}
|
||||
.im_message_document_progress .im_message_document_size {
|
||||
@ -504,10 +456,7 @@ img.im_message_video_thumb,
|
||||
.im_message_document_thumb_wrap {
|
||||
position: absolute;
|
||||
}
|
||||
.im_grouped_short .im_message_body,
|
||||
.im_grouped .im_message_body,
|
||||
.im_grouped_fwd .im_message_body,
|
||||
.im_grouped_fwd_short .im_message_body {
|
||||
.im_grouped .im_message_body {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
@ -551,42 +500,19 @@ img.im_message_video_thumb,
|
||||
padding-left: 0;
|
||||
padding-right: 42px;
|
||||
}
|
||||
.im_message_fwd.im_content_message_wrap {
|
||||
float: none;
|
||||
}
|
||||
.im_history_messages_group .im_message_in.im_content_message_wrap,
|
||||
.im_history_messages_group .im_grouped_short .im_message_in.im_content_message_wrap,
|
||||
.im_history_messages_group .im_grouped .im_message_in.im_content_message_wrap,
|
||||
.im_history_messages_group .im_grouped_fwd .im_message_in.im_content_message_wrap,
|
||||
.im_history_messages_group .im_grouped_fwd_short .im_message_in.im_content_message_wrap {
|
||||
.im_history_messages_group .im_grouped .im_message_in.im_content_message_wrap {
|
||||
padding-left: 45px;
|
||||
}
|
||||
.im_grouped_short .im_message_out.im_message_fwd,
|
||||
.im_grouped .im_message_out.im_message_fwd,
|
||||
.im_grouped_fwd .im_message_out.im_message_fwd,
|
||||
.im_grouped_fwd_short .im_message_out.im_message_fwd {
|
||||
padding-left: 80px;
|
||||
}
|
||||
.im_grouped_short .im_content_message_wrap,
|
||||
.im_grouped .im_content_message_wrap {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.im_grouped_fwd_start .im_message_fwd.im_content_message_wrap,
|
||||
.im_grouped_short .im_message_fwd.im_content_message_wrap,
|
||||
.im_grouped .im_message_fwd.im_content_message_wrap,
|
||||
.im_grouped_fwd .im_message_fwd.im_content_message_wrap,
|
||||
.im_grouped_fwd_short .im_message_fwd.im_content_message_wrap {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
.im_message_fwd_header {
|
||||
font-size: 12px;
|
||||
}
|
||||
.im_grouped_fwd_start .im_message_fwd.im_content_message_wrap {
|
||||
margin-top: 8px;
|
||||
}
|
||||
.im_grouped_fwd_end .im_message_fwd.im_content_message_wrap {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.im_message_meta {
|
||||
float: none;
|
||||
position: absolute;
|
||||
@ -602,18 +528,6 @@ img.im_message_video_thumb,
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.im_grouped_fwd .im_message_meta,
|
||||
.im_grouped_fwd_short .im_message_meta,
|
||||
.im_grouped_fwd_start .im_message_meta {
|
||||
display: none;
|
||||
}
|
||||
.im_grouped_fwd_end .im_message_meta {
|
||||
display: block;
|
||||
}
|
||||
.im_grouped_fwd_end .im_message_fwd .im_message_date {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.im_message_out .im_message_fwd_date {
|
||||
color: #93a2ae;
|
||||
}
|
||||
@ -624,27 +538,21 @@ img.im_message_video_thumb,
|
||||
background-color: #dae6f0;
|
||||
background-position: -2px -542px;
|
||||
}
|
||||
.im_message_out .icon-audio,
|
||||
.im_history_selectable .im_message_outer_wrap:hover .icon-audio {
|
||||
background-color: #dae6f0;
|
||||
background-position: -2px -697px;
|
||||
}
|
||||
|
||||
.im_message_out .im_message_document_size,
|
||||
.im_message_out .im_message_audio_duration,
|
||||
.im_message_out .im_message_audio_size,
|
||||
.im_message_out .audio_player_duration,
|
||||
.im_message_out .audio_player_size,
|
||||
.im_message_out .im_message_fwd_date,
|
||||
.im_message_selected .im_message_document_size,
|
||||
.im_message_selected .im_message_audio_duration,
|
||||
.im_message_selected .im_message_audio_size,
|
||||
.im_message_selected .audio_player_duration,
|
||||
.im_message_selected .audio_player_size,
|
||||
.im_message_selected .im_message_fwd_date,
|
||||
.im_message_focus .im_message_document_size,
|
||||
.im_message_focus .im_message_audio_duration,
|
||||
.im_message_focus .im_message_audio_size,
|
||||
.im_message_focus .audio_player_duration,
|
||||
.im_message_focus .audio_player_size,
|
||||
.im_message_focus .im_message_fwd_date,
|
||||
.im_history_selectable .im_message_outer_wrap:hover .im_message_document_size,
|
||||
.im_history_selectable .im_message_outer_wrap:hover .im_message_audio_duration,
|
||||
.im_history_selectable .im_message_outer_wrap:hover .im_message_audio_size,
|
||||
.im_history_selectable .im_message_outer_wrap:hover .audio_player_duration,
|
||||
.im_history_selectable .im_message_outer_wrap:hover .audio_player_size,
|
||||
.im_history_selectable .im_message_outer_wrap:hover .im_message_fwd_date {
|
||||
color: #68839c;
|
||||
}
|
||||
@ -853,15 +761,15 @@ a.im_dialog_selected .im_dialog_message_text {
|
||||
}
|
||||
.im_message_selected .im_message_body a,
|
||||
.im_message_selected .im_message_fwd_title,
|
||||
.im_message_selected .im_message_audio_name,
|
||||
.im_message_selected .im_message_fwd_date,
|
||||
.im_message_selected .im_message_document_name,
|
||||
.im_message_selected .im_message_document_size,
|
||||
.im_message_selected .im_message_audio_duration,
|
||||
.im_message_selected .im_message_audio_size,
|
||||
.im_message_selected .im_message_fwd_date,
|
||||
.im_message_selected .audio_player_title,
|
||||
.im_message_selected .audio_player_duration,
|
||||
.im_message_selected .audio_player_size,
|
||||
.im_history_selectable .im_message_selected:hover .im_message_document_size,
|
||||
.im_history_selectable .im_message_selected:hover .im_message_audio_duration,
|
||||
.im_history_selectable .im_message_selected:hover .im_message_audio_size,
|
||||
.im_history_selectable .im_message_selected:hover .audio_player_duration,
|
||||
.im_history_selectable .im_message_selected:hover .audio_player_size,
|
||||
.im_history_selectable .im_message_selected:hover .im_message_fwd_date {
|
||||
color: #FFF;
|
||||
}
|
||||
@ -870,13 +778,6 @@ a.im_dialog_selected .im_dialog_message_text {
|
||||
a.im_message_fwd_author {
|
||||
color: #323232;
|
||||
}
|
||||
.im_message_fwd .im_message_fwd_author_wrap,
|
||||
.im_message_fwd .im_message_text,
|
||||
.im_message_fwd .im_message_media {
|
||||
margin-left: 50px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.im_dialogs_scrollable_wrap a.im_dialog:hover,
|
||||
.im_dialogs_scrollable_wrap a.im_dialog_selected,
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 25 KiB |
Binary file not shown.
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Binary file not shown.
Before Width: | Height: | Size: 158 KiB |
@ -50,6 +50,7 @@
|
||||
<script type="text/javascript" src="vendor/angular/angular-sanitize.js"></script>
|
||||
<script type="text/javascript" src="vendor/angular/angular-touch.js"></script>
|
||||
<script type="text/javascript" src="vendor/ui-bootstrap/ui-bootstrap-custom-tpls-0.10.0.js"></script>
|
||||
<script type="text/javascript" src="vendor/angular-media-player/angular-media-player.js"></script>
|
||||
|
||||
<script type="text/javascript" src="vendor/jsbn/jsbn_combined.js"></script>
|
||||
<script type="text/javascript" src="vendor/cryptoJS/crypto.js"></script>
|
||||
|
@ -13,6 +13,7 @@ angular.module('myApp', [
|
||||
'ngSanitize',
|
||||
'ngTouch',
|
||||
'ui.bootstrap',
|
||||
'mediaPlayer',
|
||||
'izhukov.utils',
|
||||
'izhukov.mtproto',
|
||||
'izhukov.mtproto.wrapper',
|
||||
|
@ -1482,27 +1482,6 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
}
|
||||
})
|
||||
|
||||
.directive('myAudioAutoplay', function() {
|
||||
|
||||
return {
|
||||
link: link,
|
||||
scope: {
|
||||
audio: '='
|
||||
}
|
||||
};
|
||||
|
||||
function link ($scope, element, attrs) {
|
||||
$scope.$watch('audio.autoplay', function (autoplay) {
|
||||
if (autoplay) {
|
||||
element.autoplay = true;
|
||||
element[0].play();
|
||||
} else {
|
||||
element.autoplay = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
.directive('myFocused', function(){
|
||||
return {
|
||||
link: function($scope, element, attrs) {
|
||||
@ -1842,3 +1821,69 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
.directive('myAudioPlayer', function ($sce, $timeout, $q, FileManager, MtpApiFileManager) {
|
||||
|
||||
return {
|
||||
link: link,
|
||||
scope: {
|
||||
audio: '='
|
||||
},
|
||||
templateUrl: templateUrl('audio_player')
|
||||
};
|
||||
|
||||
function downloadAudio (audio) {
|
||||
var inputFileLocation = {
|
||||
_: audio._ == 'document' ? 'inputDocumentFileLocation' : 'inputAudioFileLocation',
|
||||
id: audio.id,
|
||||
access_hash: audio.access_hash
|
||||
};
|
||||
|
||||
audio.progress = {enabled: true, percent: 1, total: audio.size};
|
||||
|
||||
var downloadPromise = MtpApiFileManager.downloadFile(audio.dc_id, inputFileLocation, audio.size, {mime: 'audio/ogg'});
|
||||
|
||||
audio.progress.cancel = downloadPromise.cancel;
|
||||
|
||||
return downloadPromise.then(function (url) {
|
||||
delete audio.progress;
|
||||
audio.rawUrl = url;
|
||||
audio.url = $sce.trustAsResourceUrl(url);
|
||||
}, function (e) {
|
||||
console.log('audio download failed', e);
|
||||
audio.progress.enabled = false;
|
||||
}, function (progress) {
|
||||
console.log('audio dl progress', progress);
|
||||
audio.progress.done = progress.done;
|
||||
audio.progress.percent = Math.max(1, Math.floor(100 * progress.done / progress.total));
|
||||
});
|
||||
}
|
||||
|
||||
function link($scope, element, attrs) {
|
||||
$scope.mediaPlayer = {};
|
||||
|
||||
$scope.download = function () {
|
||||
($scope.audio.rawUrl ? $q.when() : downloadAudio($scope.audio)).then(
|
||||
function () {
|
||||
FileManager.download($scope.audio.rawUrl, $scope.audio.mime_type || 'audio/ogg', $scope.audio.file_name || 'audio.ogg');
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
$scope.togglePlay = function () {
|
||||
if ($scope.audio.url) {
|
||||
$scope.mediaPlayer.player.playPause();
|
||||
}
|
||||
else if ($scope.audio.progress && $scope.audio.progress.enabled) {
|
||||
$scope.audio.progress.cancel();
|
||||
}
|
||||
else {
|
||||
downloadAudio($scope.audio).then(function () {
|
||||
onContentLoaded(function () {
|
||||
$scope.mediaPlayer.player.play();
|
||||
})
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
})
|
||||
|
@ -104,6 +104,7 @@ angular.module('myApp.filters', ['myApp.i18n'])
|
||||
|
||||
.filter('duration', [function() {
|
||||
return function (duration) {
|
||||
duration = parseInt(duration);
|
||||
var secs = duration % 60,
|
||||
mins = Math.floor((duration - secs) / 60.0);
|
||||
|
||||
|
@ -304,6 +304,7 @@
|
||||
"login_controller_unknown_country": "Unknown",
|
||||
|
||||
"message_forwarded_message": "Forwarded message",
|
||||
"message_forwarded_message_mobile": "Forwarded from {from}, {date}",
|
||||
|
||||
"message_attach_audio_message": "Voice message",
|
||||
"message_attach_audio_play": "Play",
|
||||
|
@ -1809,6 +1809,9 @@ angular.module('myApp.services', ['myApp.i18n'])
|
||||
{noLinks: true, noLinebreaks: true}
|
||||
);
|
||||
break;
|
||||
|
||||
case 'messageMediaEmpty':
|
||||
delete message.media;
|
||||
}
|
||||
}
|
||||
else if (message.action) {
|
||||
@ -1839,7 +1842,8 @@ angular.module('myApp.services', ['myApp.i18n'])
|
||||
len = history.length,
|
||||
end = len,
|
||||
i, curDay, prevDay, curMessage, prevMessage, curGrouped, prevGrouped,
|
||||
wasUpdated = false;
|
||||
wasUpdated = false,
|
||||
groupFwd = !Config.Mobile;
|
||||
|
||||
if (limit > 0) {
|
||||
end = Math.min(limit, len);
|
||||
@ -1874,12 +1878,12 @@ angular.module('myApp.services', ['myApp.i18n'])
|
||||
curMessage.date < prevMessage.date + 900) {
|
||||
|
||||
var singleLine = curMessage.message && curMessage.message.length < 70 && curMessage.message.indexOf("\n") == -1;
|
||||
if (curMessage.fwd_from_id && curMessage.fwd_from_id == prevMessage.fwd_from_id) {
|
||||
if (groupFwd && curMessage.fwd_from_id && curMessage.fwd_from_id == prevMessage.fwd_from_id) {
|
||||
curMessage.grouped = singleLine ? 'im_grouped_fwd_short' : 'im_grouped_fwd';
|
||||
} else {
|
||||
curMessage.grouped = !curMessage.fwd_from_id && singleLine ? 'im_grouped_short' : 'im_grouped';
|
||||
}
|
||||
if (curMessage.fwd_from_id) {
|
||||
if (groupFwd && curMessage.fwd_from_id) {
|
||||
if (!prevMessage.grouped) {
|
||||
prevMessage.grouped = 'im_grouped_fwd_start';
|
||||
}
|
||||
@ -1890,7 +1894,7 @@ angular.module('myApp.services', ['myApp.i18n'])
|
||||
} else if (prevMessage || !i) {
|
||||
delete curMessage.grouped;
|
||||
|
||||
if (prevMessage && prevMessage.grouped && prevMessage.fwd_from_id) {
|
||||
if (groupFwd && prevMessage && prevMessage.grouped && prevMessage.fwd_from_id) {
|
||||
prevMessage.grouped += ' im_grouped_fwd_end';
|
||||
}
|
||||
}
|
||||
@ -2328,8 +2332,8 @@ angular.module('myApp.services', ['myApp.i18n'])
|
||||
|
||||
function wrapForHistory (photoID) {
|
||||
var photo = angular.copy(photos[photoID]) || {_: 'photoEmpty'},
|
||||
width = Math.min(windowW - 80, 260),
|
||||
height = Math.min(windowH - 100, 260),
|
||||
width = Math.min(windowW - 80, Config.Mobile ? 210 : 260),
|
||||
height = Math.min(windowH - 100, Config.Mobile ? 210 : 260),
|
||||
thumbPhotoSize = choosePhotoSize(photo, width, height),
|
||||
thumb = {
|
||||
placeholder: 'img/placeholders/PhotoThumbConversation.gif',
|
||||
@ -2506,8 +2510,8 @@ angular.module('myApp.services', ['myApp.i18n'])
|
||||
}
|
||||
|
||||
var video = angular.copy(videos[videoID]),
|
||||
width = Math.min(windowW - 80, windowW <= 479 ? 260 : 200),
|
||||
height = Math.min(windowH - 100, windowW <= 479 ? 260 : 200),
|
||||
width = Math.min(windowW - 80, Config.Mobile ? 210 : 200),
|
||||
height = Math.min(windowH - 100, Config.Mobile ? 210 : 200),
|
||||
thumbPhotoSize = video.thumb,
|
||||
thumb = {
|
||||
placeholder: 'img/placeholders/VideoThumbConversation.gif',
|
||||
@ -2677,6 +2681,7 @@ angular.module('myApp.services', ['myApp.i18n'])
|
||||
|
||||
var doc = angular.copy(docs[docID]),
|
||||
isGif = doc.mime_type == 'image/gif',
|
||||
isAudio = doc.mime_type.substr(0, 6) == 'audio/',
|
||||
width = isGif ? Math.min(windowW - 80, 260) : 100,
|
||||
height = isGif ? Math.min(windowH - 100, 260) : 100,
|
||||
thumbPhotoSize = doc.thumb,
|
||||
@ -2711,6 +2716,9 @@ angular.module('myApp.services', ['myApp.i18n'])
|
||||
if (doc.withPreview && isGif) {
|
||||
doc.isSpecial = 'gif';
|
||||
}
|
||||
else if (isAudio) {
|
||||
doc.isSpecial = 'audio';
|
||||
}
|
||||
|
||||
return docsForHistory[docID] = doc;
|
||||
}
|
||||
@ -2836,6 +2844,8 @@ angular.module('myApp.services', ['myApp.i18n'])
|
||||
}, updateDownloadProgress);
|
||||
|
||||
historyAudio.progress.cancel = downloadPromise.cancel;
|
||||
|
||||
return downloadPromise;
|
||||
}
|
||||
|
||||
$rootScope.openAudio = openAudio;
|
||||
|
31
app/partials/desktop/audio_player.html
Normal file
31
app/partials/desktop/audio_player.html
Normal file
@ -0,0 +1,31 @@
|
||||
<div class="audio_player_wrap clearfix">
|
||||
<button class="btn btn-primary pull-left audio_player_button" ng-click="togglePlay()">
|
||||
<i class="icon audio_player_btn_icon" ng-class="{audio_player_btn_icon_pause: mediaPlayer.player.playing, audio_player_btn_icon_cancel: audio.progress.enabled}"></i>
|
||||
</button>
|
||||
<div class="audio_player_title_wrap clearfix">
|
||||
<a ng-click="download()" class="audio_player_title" ng-switch="::audio.file_name.length > 0">
|
||||
<span ng-switch-when="true" ng-bind="::audio.file_name"></span>
|
||||
<span ng-switch-default my-i18n="message_attach_audio_message"></span>
|
||||
</a>
|
||||
<div class="audio_player_meta" ng-switch="audio.progress.enabled ? 'progress' : (!mediaPlayer.player.duration && !audio.duration ? 'size' : '')">
|
||||
<span ng-switch-when="progress" class="audio_player_size" ng-bind="audio.progress | formatSizeProgress"></span>
|
||||
<span ng-switch-when="size" class="audio_player_size" ng-bind="audio.size | formatSize"></span>
|
||||
<span ng-switch-default class="audio_player_duration" ng-bind="(mediaPlayer.player.playing || mediaPlayer.player.currentTime > 0) ? mediaPlayer.player.currentTime : (mediaPlayer.player.duration || audio.duration) | duration"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="audio_player_actions" ng-if="!audio.progress.enabled && !audio.url">
|
||||
<a ng-click="togglePlay()" my-i18n="message_attach_audio_play"></a>
|
||||
<a ng-if="audio._ == 'document'" ng-click="download()" my-i18n="message_attach_document_download"></a>
|
||||
</div>
|
||||
<div class="audio_player_progress_wrap" ng-if="audio.progress.enabled || audio.url" ng-switch="audio.progress.enabled">
|
||||
<div ng-switch-when="true" class="progress tg_down_progress">
|
||||
<div class="progress-bar progress-bar-success" ng-style="{width: audio.progress.percent + '%'}"></div>
|
||||
</div>
|
||||
<div ng-switch-default class="progress tg_play_progress">
|
||||
<div class="progress-bar progress-bar-success" ng-style="{width: mediaPlayer.player.currentTime / (mediaPlayer.player.duration || audio.duration) * 100 + '%'}"></div>
|
||||
</div>
|
||||
</div>
|
||||
<audio ng-if="audio.url" media-player="mediaPlayer.player">
|
||||
<source ng-src="{{::audio.url}}" type="audio/ogg" />
|
||||
</audio>
|
||||
</div>
|
@ -37,18 +37,18 @@
|
||||
<span class="im_message_date" ng-bind="::historyMessage.date | time"></span>
|
||||
</div>
|
||||
|
||||
<div class="im_message_body" ng-class="::{im_message_body_media: historyMessage._ == 'message' && historyMessage.media && historyMessage.media._ != 'messageMediaEmpty'}">
|
||||
<div class="im_message_body" ng-class="::{im_message_body_media: historyMessage._ == 'message' && historyMessage.media ? true : false}">
|
||||
|
||||
<a class="im_message_author" my-user-link="historyMessage.from_id" short="!historyMessage.to_id.chat_id" color="historyMessage.to_id.chat_id > 0"></a>
|
||||
|
||||
<div ng-if="::historyMessage._ == 'messageForwarded' || false" class="im_message_fwd_from">
|
||||
<a class="im_message_fwd_photo pull-left" my-user-photolink="historyMessage.fwd_from_id" img-class="im_message_fwd_photo"></a>
|
||||
<div class="im_message_fwd_author_wrap">
|
||||
<a class="im_message_fwd_author" my-user-link="historyMessage.fwd_from_id" short="true"></a><span class="im_message_fwd_date" ng-bind="historyMessage.fwd_date | dateOrTime"></span>
|
||||
<a class="im_message_fwd_author" my-user-link="historyMessage.fwd_from_id" short="true"></a><span class="im_message_fwd_date" ng-bind="::historyMessage.fwd_date | dateOrTime"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="::historyMessage.media && historyMessage.media._ != 'messageMediaEmpty' || false" class="im_message_media" ng-switch="historyMessage.media._">
|
||||
<div ng-if="::historyMessage.media ? true : false" class="im_message_media" ng-switch="historyMessage.media._">
|
||||
|
||||
<div ng-switch-when="messageMediaPhoto" my-message-photo></div>
|
||||
<div ng-switch-when="messageMediaVideo" my-message-video></div>
|
||||
|
@ -1,31 +1,3 @@
|
||||
<div class="im_message_document im_message_audio" ng-class="{im_message_audio_done: historyMessage.media.audio.url, im_message_audio_progress: historyMessage.media.audio.progress.enabled}">
|
||||
<a href="" ng-click="openAudio(historyMessage.media.audio.id)" ng-if="!historyMessage.media.audio.progress.enabled && !historyMessage.media.audio.url">
|
||||
<i class="icon icon-audio"></i>
|
||||
</a>
|
||||
<i class="icon icon-audio" ng-if="historyMessage.media.audio.progress.enabled || historyMessage.media.audio.url"></i>
|
||||
|
||||
<div class="im_message_audio_info">
|
||||
<div class="im_message_audio_name_wrap" ng-if="!historyMessage.media.audio.url">
|
||||
<span class="im_message_audio_name" my-i18n="message_attach_audio_message"></span>
|
||||
<span class="im_message_audio_duration" ng-if="!historyMessage.media.audio.progress.enabled" ng-bind="::historyMessage.media.audio.duration | duration"></span>
|
||||
<span class="im_message_audio_size" ng-if="historyMessage.media.audio.progress.enabled" ng-bind="historyMessage.media.audio.progress | formatSizeProgress"></span>
|
||||
</div>
|
||||
<div class="im_message_audio_actions" ng-if="!historyMessage.media.audio.progress.enabled && !historyMessage.media.audio.url">
|
||||
<a href="" ng-click="openAudio(historyMessage.media.audio.id)" my-i18n="message_attach_audio_play"></a>
|
||||
</div>
|
||||
<div class="clearfix cancelable_progress_wrap" ng-if="historyMessage.media.audio.progress.enabled">
|
||||
<a class="im_message_media_progress_cancel pull-right" ng-click="historyMessage.media.audio.progress.cancel()" my-i18n="modal_cancel"></a>
|
||||
<div class="im_message_download_progress_wrap">
|
||||
<div class="progress tg_down_progress">
|
||||
<div class="progress-bar progress-bar-success" ng-style="{width: historyMessage.media.audio.progress.percent + '%'}"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="im_message_audio_player_wrap" ng-if="historyMessage.media.audio.url">
|
||||
<audio my-audio-autoplay audio="historyMessage.media.audio" controls="controls">
|
||||
<source ng-src="{{::historyMessage.media.audio.url}}" type="audio/ogg" />
|
||||
<embed ng-src="{{::historyMessage.media.audio.url}}" hidden="true" autostart="true" loop="false" />
|
||||
</audio>
|
||||
</div>
|
||||
</div>
|
||||
<div class="im_message_audio">
|
||||
<div my-audio-player audio="historyMessage.media.audio"></div>
|
||||
</div>
|
||||
|
@ -2,6 +2,10 @@
|
||||
|
||||
<div ng-switch-when="gif" my-load-gif document="historyMessage.media.document"></div>
|
||||
|
||||
<div ng-switch-when="audio" class="im_message_audio">
|
||||
<div my-audio-player audio="historyMessage.media.document"></div>
|
||||
</div>
|
||||
|
||||
<div ng-switch-default class="im_message_document" ng-class="{im_message_document_thumbed: !!historyMessage.media.document.thumb, im_message_document_progress: historyMessage.media.document.progress.enabled}">
|
||||
|
||||
<a href="" ng-click="downloadDoc(historyMessage.media.document.id, historyMessage.media.document.withPreview)" ng-class="{im_message_document_link_disabled: historyMessage.media.document.progress.enabled}">
|
||||
|
1
app/partials/mobile/audio_player.html
Symbolic link
1
app/partials/mobile/audio_player.html
Symbolic link
@ -0,0 +1 @@
|
||||
../desktop/audio_player.html
|
@ -19,7 +19,7 @@
|
||||
|
||||
</div>
|
||||
|
||||
<div ng-if="::historyMessage._ != 'messageService'" class="im_content_message_wrap" ng-class="::[historyMessage.out ? 'im_message_out' : 'im_message_in', historyMessage._ == 'messageForwarded' ? 'im_message_fwd' : '']">
|
||||
<div ng-if="::historyMessage._ != 'messageService'" class="im_content_message_wrap" ng-class="::[historyMessage.out ? 'im_message_out' : 'im_message_in']">
|
||||
<i ng-if="::historyMessage.unread || historyMessage.pending || false" class="icon-message-status" ng-class="{'icon-message-status-unread': historyMessage.unread, 'icon-message-status-pending': historyMessage.pending}" ng-show="!historyMessage.error"></i>
|
||||
|
||||
<a class="im_message_from_photo pull-left" my-user-photolink="historyMessage.from_id" img-class="im_message_from_photo"></a>
|
||||
@ -29,19 +29,16 @@
|
||||
<span class="im_message_date" ng-bind="::historyMessage.date | time"></span>
|
||||
</div>
|
||||
|
||||
<div class="im_message_body" ng-class="::{im_message_body_media: historyMessage._ == 'message' && historyMessage.media && historyMessage.media._ != 'messageMediaEmpty'}">
|
||||
<div class="im_message_body" ng-class="::{im_message_body_media: !!historyMessage.media}">
|
||||
|
||||
<a class="im_message_author" my-user-link="historyMessage.from_id" short="!historyMessage.to_id.chat_id" color="historyMessage.to_id.chat_id > 0"></a>
|
||||
|
||||
<div ng-if="::historyMessage._ == 'messageForwarded' || false" class="im_message_fwd_from">
|
||||
<div class="im_message_fwd_title" ng-if="::historyMessage.grouped == 'im_grouped_fwd_start'">Forwarded message</div>
|
||||
<a class="im_message_fwd_photo pull-left" my-user-photolink="historyMessage.fwd_from_id" img-class="im_message_fwd_photo"></a>
|
||||
<div class="im_message_fwd_author_wrap">
|
||||
<a class="im_message_fwd_author" my-user-link="historyMessage.fwd_from_id" short="true"></a><span class="im_message_fwd_date" ng-bind="historyMessage.fwd_date | dateOrTime"></span>
|
||||
</div>
|
||||
<div ng-if="::historyMessage._ == 'messageForwarded' && !historyMessage.media" class="im_message_fwd_header" my-i18n="message_forwarded_message_mobile">
|
||||
<a my-i18n-param="from" class="im_message_fwd_author" my-user-link="historyMessage.fwd_from_id"></a>
|
||||
<span my-i18n-param="date" class="im_message_fwd_date" ng-bind="::historyMessage.fwd_date | dateOrTime"></span>
|
||||
</div>
|
||||
|
||||
<div ng-if="::historyMessage.media && historyMessage.media._ != 'messageMediaEmpty' || false" class="im_message_media" ng-switch="historyMessage.media._">
|
||||
<div ng-if="::historyMessage.media || false" class="im_message_media" ng-switch="historyMessage.media._">
|
||||
|
||||
<div ng-switch-when="messageMediaPhoto" my-message-photo></div>
|
||||
<div ng-switch-when="messageMediaVideo" my-message-video></div>
|
||||
|
@ -1,30 +1,3 @@
|
||||
<div class="im_message_document im_message_audio" ng-class="{im_message_audio_done: historyMessage.media.audio.url, im_message_audio_progress: historyMessage.media.audio.progress.enabled}">
|
||||
<a href="" ng-click="openAudio(historyMessage.media.audio.id)" ng-if="!historyMessage.media.audio.progress.enabled && !historyMessage.media.audio.url">
|
||||
<i class="icon icon-audio"></i>
|
||||
</a>
|
||||
<i class="icon icon-audio" ng-if="historyMessage.media.audio.progress.enabled || historyMessage.media.audio.url"></i>
|
||||
|
||||
<div class="im_message_audio_info">
|
||||
<div class="im_message_audio_name_wrap" ng-if="!historyMessage.media.audio.url">
|
||||
<span class="im_message_audio_name">
|
||||
Voice message
|
||||
</span>
|
||||
<span class="im_message_audio_duration" ng-if="!historyMessage.media.audio.progress.enabled" ng-bind="::historyMessage.media.audio.duration | duration"></span>
|
||||
<span class="im_message_audio_size" ng-if="historyMessage.media.audio.progress.enabled" ng-bind="historyMessage.media.audio.progress | formatSizeProgress"></span>
|
||||
</div>
|
||||
<div class="clearfix cancelable_progress_wrap" ng-if="historyMessage.media.audio.progress.enabled">
|
||||
<a class="im_message_media_progress_cancel pull-right" ng-click="historyMessage.media.audio.progress.cancel()">Cancel</a>
|
||||
<div class="im_message_download_progress_wrap">
|
||||
<div class="progress tg_down_progress">
|
||||
<div class="progress-bar progress-bar-success" ng-style="{width: historyMessage.media.audio.progress.percent + '%'}"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="im_message_audio_player_wrap" ng-if="historyMessage.media.audio.url">
|
||||
<audio my-audio-autoplay audio="historyMessage.media.audio" controls="controls">
|
||||
<source ng-src="{{::historyMessage.media.audio.url}}" type="audio/ogg" />
|
||||
<embed ng-src="{{::historyMessage.media.audio.url}}" hidden="true" autostart="true" loop="false" />
|
||||
</audio>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="im_message_audio">
|
||||
<div my-audio-player audio="historyMessage.media.audio"></div>
|
||||
</div>
|
||||
|
@ -2,6 +2,10 @@
|
||||
|
||||
<div ng-switch-when="gif" my-load-gif document="historyMessage.media.document"></div>
|
||||
|
||||
<div ng-switch-when="audio" class="im_message_audio">
|
||||
<div my-audio-player audio="historyMessage.media.document"></div>
|
||||
</div>
|
||||
|
||||
<div ng-switch-default class="im_message_document" ng-class="{im_message_document_thumbed: !!historyMessage.media.document.thumb, im_message_document_progress: historyMessage.media.document.progress.enabled}">
|
||||
|
||||
<a href="" ng-click="downloadDoc(historyMessage.media.document.id, historyMessage.media.document.withPreview)" ng-class="{im_message_document_link_disabled: historyMessage.media.document.progress.enabled}">
|
||||
|
510
app/vendor/angular-media-player/angular-media-player.js
vendored
Normal file
510
app/vendor/angular-media-player/angular-media-player.js
vendored
Normal file
@ -0,0 +1,510 @@
|
||||
/**
|
||||
* MDN references for hackers:
|
||||
* ===========================
|
||||
* Media events on <audio> and <video> tags:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Media_events
|
||||
* Properties and Methods:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
|
||||
* Internet Exploder version:
|
||||
* http://msdn.microsoft.com/en-us/library/ff975061(v=vs.85).aspx
|
||||
*
|
||||
* Understanding TimeRanges objects:
|
||||
* http://html5doctor.com/html5-audio-the-state-of-play/
|
||||
*/
|
||||
angular.module('mediaPlayer', ['mediaPlayer.helpers'])
|
||||
.constant('mp.playerDefaults', {
|
||||
// general properties
|
||||
currentTrack: 0,
|
||||
ended: undefined,
|
||||
network: undefined,
|
||||
playing: false,
|
||||
seeking: false,
|
||||
tracks: 0,
|
||||
volume: 1,
|
||||
|
||||
// formatted properties
|
||||
formatDuration: '00:00',
|
||||
formatTime: '00:00',
|
||||
loadPercent: 0
|
||||
})
|
||||
|
||||
.directive('mediaPlayer', ['$rootScope', '$interpolate', '$timeout', 'mp.throttle', 'mp.playerDefaults',
|
||||
function ($rootScope, $interpolate, $timeout, throttle, playerDefaults) {
|
||||
|
||||
var playerMethods = {
|
||||
/**
|
||||
* @usage load([mediaElement], [autoplay]);
|
||||
*
|
||||
* @param {mediaElement Obj} mediaElement a single mediaElement, may contain multiple <source>(s)
|
||||
* @param {boolean} autoplay: flag to autostart loaded element
|
||||
*/
|
||||
load: function (mediaElement, autoplay) {
|
||||
// method overloading
|
||||
if (typeof mediaElement === 'boolean') {
|
||||
autoplay = mediaElement;
|
||||
mediaElement = null;
|
||||
} else if (typeof mediaElement === 'object') {
|
||||
this.$clearSourceList();
|
||||
this.$addSourceList(mediaElement);
|
||||
}
|
||||
this.$domEl.load();
|
||||
this.ended = undefined;
|
||||
if (autoplay) {
|
||||
this.$element.one('canplay', this.play.bind(this));
|
||||
}
|
||||
},
|
||||
/**
|
||||
* resets the player (clear the <source>s) and reloads the playlist
|
||||
*
|
||||
* @usage reset([autoplay]);
|
||||
* @param {boolean} autoplay: flag to autoplay once resetted
|
||||
*/
|
||||
reset: function (autoplay) {
|
||||
angular.extend(this, playerDefaults);
|
||||
this.$clearSourceList();
|
||||
this.load(this.$playlist, autoplay);
|
||||
},
|
||||
/**
|
||||
* @usage play([index], [selectivePlay])
|
||||
* @param {integer} index: playlist index (0...n), to start playing from
|
||||
* @param {boolean} selectivePlay: only correct value is `true`, in which case will only play the specified,
|
||||
* or current, track. The default is to continue playing the next one.
|
||||
*/
|
||||
play: function (index, selectivePlay) {
|
||||
// method overloading
|
||||
if (typeof index === 'boolean') {
|
||||
selectivePlay = index;
|
||||
index = undefined;
|
||||
}
|
||||
if (selectivePlay) {
|
||||
this.$selective = true;
|
||||
}
|
||||
|
||||
if (this.$playlist.length > index) {
|
||||
this.currentTrack = index + 1;
|
||||
return this.load(this.$playlist[index], true);
|
||||
}
|
||||
// readyState = HAVE_NOTHING (0) means there's nothing into the <audio>/<video> tag
|
||||
if (!this.currentTrack && this.$domEl.readyState) { this.currentTrack++; }
|
||||
|
||||
// In case the stream is completed, reboot it with a load()
|
||||
if (this.ended) {
|
||||
this.load(true);
|
||||
} else {
|
||||
this.$domEl.play();
|
||||
}
|
||||
},
|
||||
playPause: function (index, selectivePlay) {
|
||||
// method overloading
|
||||
if (typeof index === 'boolean') {
|
||||
selectivePlay = index;
|
||||
index = undefined;
|
||||
}
|
||||
if (selectivePlay) {
|
||||
this.$selective = true;
|
||||
}
|
||||
|
||||
if (typeof index === 'number' && index + 1 !== this.currentTrack) {
|
||||
this.play(index);
|
||||
} else if (this.playing) {
|
||||
this.pause();
|
||||
} else {
|
||||
this.play();
|
||||
}
|
||||
},
|
||||
pause: function () {
|
||||
this.$domEl.pause();
|
||||
},
|
||||
stop: function () {
|
||||
this.reset();
|
||||
},
|
||||
toggleMute: function () {
|
||||
this.muted = this.$domEl.muted = !this.$domEl.muted;
|
||||
},
|
||||
next: function (autoplay) {
|
||||
var self = this;
|
||||
if (self.currentTrack && self.currentTrack < self.tracks) {
|
||||
var wasPlaying = autoplay || self.playing;
|
||||
self.pause();
|
||||
$timeout(function () {
|
||||
self.$clearSourceList();
|
||||
self.$addSourceList(self.$playlist[self.currentTrack]);
|
||||
self.load(wasPlaying); // setup autoplay here.
|
||||
self.currentTrack++;
|
||||
});
|
||||
}
|
||||
},
|
||||
prev: function (autoplay) {
|
||||
var self = this;
|
||||
if (self.currentTrack && self.currentTrack - 1) {
|
||||
var wasPlaying = autoplay || self.playing;
|
||||
self.pause();
|
||||
$timeout(function () {
|
||||
self.$clearSourceList();
|
||||
self.$addSourceList(self.$playlist[self.currentTrack - 2]);
|
||||
self.load(wasPlaying); // setup autoplay here.
|
||||
self.currentTrack--;
|
||||
});
|
||||
}
|
||||
},
|
||||
setPlaybackRate: function (value) {
|
||||
this.$domEl.playbackRate = value;
|
||||
},
|
||||
setVolume: function (value) {
|
||||
this.$domEl.volume = value;
|
||||
},
|
||||
seek: function (value) {
|
||||
var doubleval = 0, valuesArr;
|
||||
if (typeof value === 'string') {
|
||||
valuesArr = value.split(':');
|
||||
doubleval += parseInt(valuesArr.pop(), 10);
|
||||
if (valuesArr.length) { doubleval += parseInt(valuesArr.pop(), 10) * 60; }
|
||||
if (valuesArr.length) { doubleval += parseInt(valuesArr.pop(), 10) * 3600; }
|
||||
if (!isNaN(doubleval)) {
|
||||
return this.$domEl.currentTime = doubleval;
|
||||
}
|
||||
} else {
|
||||
return this.$domEl.currentTime = value;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* binds a specific event directly to the element
|
||||
* @param {string} type event name
|
||||
* @param {function} fn callback
|
||||
* @return {function} unbind function, call it in order to remove the listener
|
||||
*/
|
||||
on: function (type, fn) {
|
||||
return this.$element.on(type, fn);
|
||||
},
|
||||
off: function (type, fn) {
|
||||
return this.$element.off(type, fn);
|
||||
},
|
||||
one: function (type, fn) {
|
||||
return this.$element.one(type, fn);
|
||||
},
|
||||
$addSourceList: function (sourceList) {
|
||||
var self = this;
|
||||
if (angular.isArray(sourceList)) {
|
||||
angular.forEach(sourceList, function (singleElement, index) {
|
||||
var sourceElem = document.createElement('SOURCE');
|
||||
['src', 'type', 'media'].forEach(function (key) { // use only a subset of the properties
|
||||
if (singleElement[key] !== undefined) { // firefox is picky if you set undefined attributes
|
||||
sourceElem.setAttribute(key, singleElement[key]);
|
||||
}
|
||||
});
|
||||
self.$element.append(sourceElem);
|
||||
});
|
||||
} else if (angular.isObject(sourceList)) {
|
||||
var sourceElem = document.createElement('SOURCE');
|
||||
['src', 'type', 'media'].forEach(function (key) {
|
||||
if (sourceList[key] !== undefined) {
|
||||
sourceElem.setAttribute(key, sourceList[key]);
|
||||
}
|
||||
});
|
||||
self.$element.append(sourceElem);
|
||||
}
|
||||
},
|
||||
$clearSourceList: function () {
|
||||
this.$element.contents().remove();
|
||||
},
|
||||
$formatTime: function (seconds) {
|
||||
if (seconds === Infinity) {
|
||||
return '∞'; // If the data is streaming
|
||||
}
|
||||
var hours = parseInt(seconds / 3600, 10) % 24,
|
||||
minutes = parseInt(seconds / 60, 10) % 60,
|
||||
secs = parseInt(seconds % 60, 10),
|
||||
result,
|
||||
fragment = (minutes < 10 ? '0' + minutes : minutes) + ':' + (secs < 10 ? '0' + secs : secs);
|
||||
if (hours > 0) {
|
||||
result = (hours < 10 ? '0' + hours : hours) + ':' + fragment;
|
||||
} else {
|
||||
result = fragment;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
$attachPlaylist: function (pl) {
|
||||
if (pl === undefined || pl === null) {
|
||||
this.playlist = [];
|
||||
} else {
|
||||
this.$playlist = pl;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Binding function that gives life to AngularJS scope
|
||||
* @param {Scope} au Player Scope
|
||||
* @param {HTMLMediaElement} HTML5 element
|
||||
* @param {jQlite} element <audio>/<video> element
|
||||
* @return {function}
|
||||
*
|
||||
* Returns an unbinding function
|
||||
*/
|
||||
var bindListeners = function (au, al, element) {
|
||||
var listeners = {
|
||||
playing: function () {
|
||||
au.$apply(function (scope) {
|
||||
scope.playing = true;
|
||||
scope.ended = false;
|
||||
});
|
||||
},
|
||||
pause: function () {
|
||||
au.$apply(function (scope) {
|
||||
scope.playing = false;
|
||||
});
|
||||
},
|
||||
ended: function () {
|
||||
if (!au.$selective && au.currentTrack < au.tracks) {
|
||||
au.next(true);
|
||||
} else {
|
||||
au.$apply(function (scope) {
|
||||
scope.ended = true;
|
||||
scope.playing = false; // IE9 does not throw 'pause' when file ends
|
||||
});
|
||||
}
|
||||
},
|
||||
timeupdate: throttle(1000, false, function () {
|
||||
au.$apply(function (scope) {
|
||||
scope.currentTime = al.currentTime;
|
||||
scope.formatTime = scope.$formatTime(scope.currentTime);
|
||||
});
|
||||
}),
|
||||
loadedmetadata: function () {
|
||||
au.$apply(function (scope) {
|
||||
if (!scope.currentTrack) { scope.currentTrack++; } // This is triggered *ONLY* the first time a <source> gets loaded.
|
||||
scope.duration = al.duration;
|
||||
scope.formatDuration = scope.$formatTime(scope.duration);
|
||||
if (al.buffered.length) {
|
||||
scope.loadPercent = Math.round((al.buffered.end(al.buffered.length - 1) / scope.duration) * 100);
|
||||
}
|
||||
});
|
||||
},
|
||||
progress: function () {
|
||||
if (au.$domEl.buffered.length) {
|
||||
au.$apply(function (scope) {
|
||||
scope.loadPercent = Math.round((al.buffered.end(al.buffered.length - 1) / scope.duration) * 100);
|
||||
scope.network = 'progress';
|
||||
});
|
||||
}
|
||||
},
|
||||
volumechange: function () { // Sent when volume changes (both when the volume is set and when the muted attribute is changed).
|
||||
au.$apply(function (scope) {
|
||||
// scope.volume = Math.floor(al.volume * 100);
|
||||
scope.volume = al.volume;
|
||||
scope.muted = al.muted;
|
||||
});
|
||||
},
|
||||
seeked: function () {
|
||||
au.$apply(function (scope) {
|
||||
scope.seeking = false;
|
||||
});
|
||||
},
|
||||
seeking: function () {
|
||||
au.$apply(function (scope) {
|
||||
scope.seeking = true;
|
||||
});
|
||||
},
|
||||
ratechange: function () {
|
||||
au.$apply(function (scope) {
|
||||
// scope.playbackRate = Math.floor(al.playbackRate * 100);
|
||||
scope.playbackRate = al.playbackRate;
|
||||
});
|
||||
},
|
||||
stalled: function () {
|
||||
au.$apply(function (scope) {
|
||||
scope.network = 'stalled';
|
||||
});
|
||||
},
|
||||
suspend: function () {
|
||||
au.$apply(function (scope) {
|
||||
scope.network = 'suspend';
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
angular.forEach(listeners, function (f, listener) {
|
||||
element.on(listener, f);
|
||||
});
|
||||
};
|
||||
|
||||
var MediaPlayer = function (element) {
|
||||
var mediaScope = angular.extend($rootScope.$new(true), {
|
||||
$element: element,
|
||||
$domEl: element[0],
|
||||
$playlist: undefined,
|
||||
|
||||
// bind TimeRanges structures to actual MediaElement
|
||||
buffered: element[0].buffered,
|
||||
played: element[0].played,
|
||||
seekable: element[0].seekable,
|
||||
}, playerDefaults, playerMethods);
|
||||
bindListeners(mediaScope, element[0], element);
|
||||
return mediaScope;
|
||||
};
|
||||
|
||||
// creates a watch function bound to the specific player
|
||||
// optimizable: closures eats ram
|
||||
function playlistWatch(player) {
|
||||
return function (playlistNew, playlistOld, watchScope) {
|
||||
var currentTrack,
|
||||
newTrackNum = null;
|
||||
|
||||
// on every playlist change, it refreshes the reference, safer/shorter approach
|
||||
// than using multiple ifs and refresh only if it changed; there's no benefit in that
|
||||
player.$attachPlaylist(playlistNew);
|
||||
if (playlistNew === undefined && playlistOld !== undefined) {
|
||||
return player.pause();
|
||||
}
|
||||
|
||||
/**
|
||||
* Playlist update logic:
|
||||
* If the player has started ->
|
||||
* Check if the playing track is in the new Playlist [EXAMPLE BELOW]
|
||||
* If it is ->
|
||||
* Assign to it the new tracknumber
|
||||
* Else ->
|
||||
* If the new Playlist has some song ->
|
||||
* Pause the player, and get the new Playlist
|
||||
* Else ->
|
||||
* Reset the player, and await for orders
|
||||
*
|
||||
* Else (if the player hasn't started yet)
|
||||
* Just replace the <src> tags
|
||||
*
|
||||
* Example
|
||||
* playlist: [a,b,c], playing: c, trackNum: 2
|
||||
* ----delay 5 sec-----
|
||||
* playlist: [f,a,b,c], playing: c, trackNum: 3
|
||||
*
|
||||
*/
|
||||
if (player.currentTrack) {
|
||||
currentTrack = playlistOld ? playlistOld[player.currentTrack - 1] : -1;
|
||||
for (var i = 0; i < playlistNew.length; i++) {
|
||||
if (angular.equals(playlistNew[i], currentTrack)) { newTrackNum = i; break; }
|
||||
}
|
||||
if (newTrackNum !== null) { // currentTrack it's still in the new playlist, update trackNumber
|
||||
player.currentTrack = newTrackNum + 1;
|
||||
player.tracks = playlistNew.length;
|
||||
} else { // currentTrack has been removed.
|
||||
player.pause();
|
||||
if (playlistNew.length) { // if the new playlist has some elements, replace actual.
|
||||
$timeout(function () { // need $timeout because the mediaTag needs a little time to launch the 'pause' event
|
||||
player.$clearSourceList();
|
||||
player.$addSourceList(playlistNew[0]);
|
||||
player.load();
|
||||
player.tracks = playlistNew.length;
|
||||
});
|
||||
} else { // the new playlist has no elements, clear actual
|
||||
player.reset();
|
||||
}
|
||||
}
|
||||
} else if (playlistNew.length) { // new playlist has elements, load them
|
||||
player.$clearSourceList();
|
||||
player.$addSourceList(playlistNew[0]);
|
||||
player.load();
|
||||
player.tracks = playlistNew.length;
|
||||
} else { // new playlist has no elements, clear actual
|
||||
player.reset();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* The directive uses the Scope in which gets declared,
|
||||
* so it can read/write it with ease.
|
||||
* The only isolated Scope here gets created for the MediaPlayer.
|
||||
*/
|
||||
scope: false,
|
||||
link: function (scope, element, attrs, ctrl) {
|
||||
var playlistName = attrs.playlist,
|
||||
mediaName = attrs.mediaPlayer || attrs.playerControl;
|
||||
|
||||
var player = new MediaPlayer(element), playlist = scope[playlistName];
|
||||
// create data-structures in the father Scope
|
||||
if (playlistName === undefined) {
|
||||
playlist = []; // local playlist gets defined as new
|
||||
} else if (scope[playlistName] === undefined) {
|
||||
playlist = scope[playlistName] = []; // define playlist on father scope
|
||||
} else {
|
||||
playlist = scope[playlistName];
|
||||
}
|
||||
if (mediaName !== undefined) {
|
||||
scope.$eval(mediaName + ' = player', {player: player});
|
||||
}
|
||||
|
||||
if (element[0].tagName !== 'AUDIO' && element[0].tagName !== 'VIDEO') {
|
||||
return new Error('player directive works only when attached to an <audio>/<video> type tag');
|
||||
}
|
||||
var mediaElement = [],
|
||||
sourceElements = element.find('source');
|
||||
|
||||
// create a single playlist element from <source> tag(s).
|
||||
// if the <source> tag is one, use object notation...
|
||||
if (sourceElements.length === 1) {
|
||||
playlist.unshift({ src: sourceElements[0].src, type: sourceElements[0].type, media: sourceElements[0].media });
|
||||
} else if (sourceElements.length > 1) { // otherwise use array notation
|
||||
angular.forEach(sourceElements, function (sourceElement) {
|
||||
mediaElement.push({ src: sourceElement.src, type: sourceElement.type, media: sourceElement.media });
|
||||
});
|
||||
// put mediaElement as first element in the playlist
|
||||
playlist.unshift(mediaElement);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the user wants to keep track of the playlist changes
|
||||
* has to use data-playlist="variableName" in the <audio>/<video> tag
|
||||
*
|
||||
* Otherwise: it will be created an empty playlist and attached to the player.
|
||||
*/
|
||||
if (playlistName === undefined) {
|
||||
player.$attachPlaylist(playlist); // empty playlist case
|
||||
} else if (playlist.length) {
|
||||
playlistWatch(player)(playlist, undefined, scope); // playlist already populated gets bootstrapped
|
||||
scope.$watch(playlistName, playlistWatch(player), true); // then watch gets applied
|
||||
} else {
|
||||
scope.$watch(playlistName, playlistWatch(player), true); // playlist empty, only watch
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}]
|
||||
);
|
||||
|
||||
angular.module('mediaPlayer.helpers', [])
|
||||
.factory('mp.throttle', ['$timeout', function ($timeout) {
|
||||
return function (delay, no_trailing, callback, debounce_mode) {
|
||||
var timeout_id,
|
||||
last_exec = 0;
|
||||
|
||||
if (typeof no_trailing !== 'boolean') {
|
||||
debounce_mode = callback;
|
||||
callback = no_trailing;
|
||||
no_trailing = undefined;
|
||||
}
|
||||
|
||||
var wrapper = function () {
|
||||
var that = this,
|
||||
elapsed = +new Date() - last_exec,
|
||||
args = arguments,
|
||||
exec = function () {
|
||||
last_exec = +new Date();
|
||||
callback.apply(that, args);
|
||||
},
|
||||
clear = function () {
|
||||
timeout_id = undefined;
|
||||
};
|
||||
|
||||
if (debounce_mode && !timeout_id) { exec(); }
|
||||
if (timeout_id) { $timeout.cancel(timeout_id); }
|
||||
if (debounce_mode === undefined && elapsed > delay) {
|
||||
exec();
|
||||
} else if (no_trailing !== true) {
|
||||
timeout_id = $timeout(debounce_mode ? clear : exec, debounce_mode === undefined ? delay - elapsed : delay);
|
||||
}
|
||||
};
|
||||
|
||||
return wrapper;
|
||||
};
|
||||
}]);
|
@ -1,6 +1,6 @@
|
||||
CACHE MANIFEST
|
||||
|
||||
# 33
|
||||
# 34
|
||||
|
||||
NETWORK:
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user