Browse Source

merged with master

gh-pages
Igor Zhukov 11 years ago
parent
commit
aa743aebb6
  1. 577
      css/app.css
  2. BIN
      img/Logo_1x.png
  3. BIN
      img/Logo_2x.png
  4. BIN
      img/TLogo2_1x.png
  5. BIN
      img/TLogo2_2x.png
  6. BIN
      img/TLogo_1x.png
  7. BIN
      img/Tlogo_2x.png
  8. BIN
      img/bg_full.png
  9. BIN
      img/icons/IconsetW.png
  10. BIN
      img/icons/IconsetW_1x.png
  11. 2
      js/app.js
  12. 4
      js/background.js
  13. 123
      js/controllers.js
  14. 21
      js/directives.js
  15. 4
      js/filters.js
  16. 4
      js/lib/aes_worker.js
  17. 2
      js/lib/config.js
  18. 2
      js/lib/mtproto.js
  19. 4
      js/lib/pq_worker.js
  20. 1
      js/lib/schema.tl.txt
  21. 4
      js/lib/sha1_worker.js
  22. 53
      js/services.js
  23. 2
      js/util.js
  24. 2
      manifest.json
  25. 2
      manifest.webapp
  26. 4
      partials/head.html
  27. 94
      partials/im.html
  28. 381
      partials/message.html
  29. 2
      partials/settings_modal.html
  30. 2
      partials/welcome.html

577
css/app.css

@ -3,11 +3,6 @@
html {
background: #dee4e9 url(../img/bg_tile.png?1) 0 0 repeat;
/*background-size: 300px 468px;*/
/*background: #dee4e9 url(../img/bg_full.png) 0 0 no-repeat;*/
/*background-size: cover;*/
/*background-size: contain;*/
/*background-size: 248px 382px;*/
}
body {
color: #000;
@ -114,6 +109,13 @@ fieldset[disabled] .btn-tg.active {
border-color: #999;
}
.tg_page_head .navbar {
min-height: 44px;
}
.tg_page_head .navbar-toggle {
margin-top: 5px;
margin-bottom: 5px;
}
.tg_page_head .container {
display: block;
width: auto;
@ -133,27 +135,54 @@ fieldset[disabled] .btn-tg.active {
padding: 9px 15px;
opacity: 0.9;
margin-left: 0;
margin-right: 20px;
-webkit-transition: opacity swing .9s;
}
@media (max-width: 480px) {
.tg_page_head .navbar > .container .navbar-brand {
padding-left: 9px;
}
display: block;
line-height: 0;
height: auto;
}
@media (min-width: 480px) {
.tg_page_head .navbar-quick-nav {
display: none;
}
.tg_head_logo {
background: url(../img/Tlogo_2x.png) 0 0 no-repeat;
background-size: 26px 26px;
display: inline-block;
width: 26px;
height: 26px;
vertical-align: text-top;
}
.is_1x .tg_head_logo {
background-image: url(../img/TLogo_1x.png);
}
.tg_head_logo_text {
background: url(../img/TLogo2_2x.png) 0 0 no-repeat;
background-size: 97px 15px;
display: inline-block;
width: 97px;
height: 15px;
vertical-align: text-top;
margin-top: 7px;
margin-left: 10px;
}
.is_1x .tg_head_logo_text {
background-image: url(../img/TLogo2_1x.png);
}
.tg_head_logo {
background: url(../img/Logo_2x.png) 0 0 no-repeat;
background-size: 110px 31px;
.icon-back {
display: inline-block;
width: 110px;
height: 31px;
width: 10px;
height: 18px;
vertical-align: text-top;
background: url(../img/icons/IconsetW.png?1) -15px -419px no-repeat;
background-size: 42px 460px;
}
.is_1x .icon-back {
background-image: url(../img/icons/IconsetW_1x.png?2);
}
.tg_page_head .navbar > .container .navbar-brand:hover {
@ -161,6 +190,8 @@ fieldset[disabled] .btn-tg.active {
}
.tg_page_head .navbar-inverse .navbar-nav > li > a {
padding-top: 12px;
padding-bottom: 12px;
color: #b9cfe3;
font-size: 13px;
}
@ -434,7 +465,7 @@ fieldset[disabled] .btn-tg.active {
font-size: 12px;
line-height: normal;
background: #F2F2F2 url(../img/icons/IconsetW.png?1) -6px -205px no-repeat;
background-size: 42px 430px;
background-size: 42px 460px;
border: 1px solid #F2F2F2;
border-radius: 3px;
padding: 6px 20px 6px 30px;
@ -458,7 +489,7 @@ fieldset[disabled] .btn-tg.active {
height: 13px;
vertical-align: text-top;
background: url(../img/icons/IconsetW.png?1) -15px -192px no-repeat;
background-size: 42px 430px;
background-size: 42px 460px;
opacity: 0.6;
}
.is_1x .im_dialogs_search_clear {
@ -612,16 +643,13 @@ a.im_dialog:hover .im_dialog_date {
/* IM history */
.im_history_col {
padding: 0 8px 0 15px;
}
.im_history_col .nano > .pane {
background : rgba(3,36,64,0.08);
/*background: #E9EBED;*/
width : 9px;
top: 10px;
/*margin-top: 10px;*/
/*bottom: */
right: 8px;
-webkit-transition : .2s;
-moz-transition : .2s;
-o-transition : .2s;
@ -632,7 +660,6 @@ a.im_dialog:hover .im_dialog_date {
}
.im_history_col .nano > .pane > .slider {
background : rgba(3,46,79,0.22);
/*background: #B3BFC7;*/
margin: 0;
-moz-border-radius : 2px;
-webkit-border-radius : 2px;
@ -640,12 +667,12 @@ a.im_dialog:hover .im_dialog_date {
}
.im_history_panel_wrap {
margin: 0 23px 0 15px;
cursor: pointer;
position: relative;
-webkit-box-shadow: 0px 2px 0px rgba(0, 0, 0, 0.12);
-moz-box-shadow: 0px 2px 0px rgba(0, 0, 0, 0.12);
box-shadow: 0px 2px 0px rgba(0, 0, 0, 0.12);
margin-right: 15px;
position: relative;
z-index: 2;
@ -656,21 +683,69 @@ a.im_dialog:hover .im_dialog_date {
.im_history_panel_title h4 {
margin-bottom: 7px;
font-size: 17px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.im_history_panel_title h4 small {
color: #999;
font-size: 13px;
margin-left: 5px;
}
.im_history_panel_info_link {
color: #3a6d99;
.im_history_panel_info_link,
.im_history_panel_edit_link,
.im_history_panel_return_link,
.im_history_panel_media_dropdown .dropdown-toggle {
font-size: 13px;
font-weight: normal;
padding-top: 5px;
padding-top: 4px;
line-height: 1;
}
.im_history_panel_info_link:hover {
text-decoration: underline;
.im_history_panel_media_dropdown {
padding-top: 1px;
}
.im_history_panel_edit_link,
.im_history_panel_return_link,
.im_history_panel_media_dropdown {
font-size: 13px;
margin-right: 20px;
}
.im_history_panel_return_count {
margin-left: 5px;
}
.im_history_panel_media_dropdown .dropdown-menu > li > a {
font-size: 13px;
}
.icon-caret {
width: 8px;
height: 4px;
display: inline-block;
vertical-align: text-top;
margin-top: 7px;
margin-left: 6px;
background: url(../img/icons/IconsetW.png?1) -17px -444px no-repeat;
background-size: 42px 460px;
}
.is_1x .icon-caret {
background-image: url(../img/icons/IconsetW_1x.png?2);
}
.im_history_panel_media_dropdown .dropdown-menu {
border-radius: 2px;
right: auto;
left: -15px;
margin-top: 13px;
padding: 0;
-webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.175);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.175);
}
.dropdown-menu > li > a {
padding: 3px 14px;
}
@ -692,9 +767,10 @@ a.im_dialog:hover .im_dialog_date {
width: 100%;
}
.im_history {
padding: 20px 0 0 3px;
max-width: 500px;
margin: 0 auto;
/*padding: 20px 0 0 3px;*/
padding: 20px 0 0 0;
/*max-width: 500px;*/
/*margin: 0 auto;*/
position: relative;
}
@ -710,10 +786,9 @@ a.im_dialog:hover .im_dialog_date {
.im_history_typing {
font-size: 11px;
color: #999;
max-width: 495px;
max-width: 526px;
margin: 0 auto;
padding: 0 40px 0 47px;
padding: 0 77px 0 77px;
}
/*.im_history_typing {
@ -843,7 +918,7 @@ div.im_message_video_thumb {
height: 19px;
background: url(../img/icons/IconsetW.png?1) -14px -389px no-repeat;
background-size: 42px 430px;
background-size: 42px 460px;
}
.is_1x .icon-geo-point {
background-image: url(../img/icons/IconsetW_1x.png?2);
@ -871,7 +946,7 @@ div.im_message_video_thumb {
vertical-align: text-top;
background: #F2F2F2 url(../img/icons/IconsetW.png?1) -2px -229px no-repeat;
background-size: 42px 430px;
background-size: 42px 460px;
border-radius: 3px;
margin-right: 10px;
}
@ -916,7 +991,7 @@ div.im_message_video_thumb {
vertical-align: text-top;
background: #F2F2F2 url(../img/icons/IconsetW.png?1) -2px -277px no-repeat;
background-size: 42px 430px;
background-size: 42px 460px;
border-radius: 3px;
margin-right: 10px;
}
@ -1007,7 +1082,7 @@ div.im_message_video_thumb {
.im_content_message_wrap {
margin: 10px 0 5px;
margin: 10px 0px 5px 16px;
}
.icon-message-status {
background: #43A4DB;
@ -1094,7 +1169,7 @@ span.emoji {
.im_send_panel_wrap {
max-width: 526px;
margin: 0 auto;
padding: 10px 12px 22px 0;
padding: 10px 15px 22px 15px;
}
.im_send_form_wrap {
position: relative;
@ -1152,7 +1227,7 @@ textarea.im_message_field {
height: 23px;
vertical-align: text-top;
background: url(../img/icons/IconsetW.png?1) -12px -68px no-repeat;
background-size: 42px 430px;
background-size: 42px 460px;
opacity: 0.8;
}
.is_1x .icon-paperclip {
@ -1173,7 +1248,6 @@ textarea.im_message_field {
width: 23px;
height: 23px;
margin-top: 4px;
margin-left: 15px;
}
.icon-emoji {
display: inline-block;
@ -1181,7 +1255,7 @@ textarea.im_message_field {
height: 23px;
vertical-align: text-top;
background: url(../img/icons/IconsetW.png?1) -10px -4px no-repeat;
background-size: 42px 430px;
background-size: 42px 460px;
opacity: 0.8;
}
.is_1x .icon-emoji {
@ -1221,15 +1295,17 @@ textarea.im_message_field {
width: 24px;
height: 22px;
margin-top: 5px;
margin-left: 20px;
}
.icon-camera {
display: inline-block;
width: 25px;
height: 21px;
vertical-align: text-top;
background: url(../img/icons/IconsetW.png?1) -9px -132px no-repeat;
background-size: 42px 430px;
background-size: 42px 460px;
opacity: 0.8;
}
.is_1x .icon-camera {
@ -1307,9 +1383,10 @@ img.img_fullsize {
}
.user_modal_window .modal-dialog {
padding-top: 150px;
max-width: 506px;
}
.user_modal_wrap .modal-body {
padding: 23px 25px 30px;
}
@ -1510,7 +1587,7 @@ img.img_fullsize {
.emoji-menu-tail {
background: url(../img/icons/IconsetW.png?1) -14px -268px no-repeat;
background-size: 42px 430px;
background-size: 42px 460px;
width: 14px;
height: 7px;
margin: 0 83px;
@ -1571,141 +1648,7 @@ img.img_fullsize {
@media (max-width: 480px) {
.login_form_wrap {
border-radius: 0;
max-width: auto;
box-shadow: none;
-webkit-box-shadow: none;
margin: 30px auto 20px;
}
.im_panel_own_photo,
.im_panel_peer_photo {
display: none;
}
.im_send_form {
left: 0;
right: 0;
max-width: none;
}
}
@media (max-height: 480px) {
.navbar {
min-height: 40px;
}
.tg_page_head .navbar > .container .navbar-brand {
padding: 4.5px 15px;
display: block;
/*overflow: hidden;
width: 49px;
height: 36px;*/
}
.navbar-nav > li > a,
.tg_page_head .navbar-quick-nav a {
padding-top: 10px;
padding-bottom: 10px;
}
.navbar-toggle {
margin-top: 2px;
margin-bottom: 2px;
}
.im_page_footer {
display: none;
}
.im_send_panel_wrap {
padding-bottom: 12px;
}
.emoji-wysiwyg-editor {
min-height: 34px;
max-height: 150px;
}
}
@media (max-width: 640px) {
.im_dialog_peer {
white-space: normal;
height: 2.84em;
}
.im_dialog_message {
display: none;
}
}
@media (max-width: 900px) {
/*.icon-message-status {
margin-left: 0;
margin-top: 18px;
right: -1px;
}*/
.icon-message-status {
z-index: 10;
margin-left: -5px;
border-radius: 0;
height: 34px;
border: 0;
width: 2px;
margin-top: 1px;
border: 0;
}
/*.icon-message-status {
z-index: 10;
margin-left: -15px;
}*/
}
@media (max-width: 480px) {
.im_dialogs_col_wrap,
.im_page_peer_not_selected .im_history_col_wrap {
display: none;
}
.im_page_peer_not_selected .im_dialogs_col_wrap {
display: block;
border-right: 0;
}
.im_page_peer_not_selected .im_dialogs_col {
margin-right: 0;
}
.im_page_peer_not_selected .im_dialogs_col_wrap .pane {
width: 12px;
right: 0px;
}
.im_page_peer_not_selected .im_dialogs_col_wrap .pane > .slider {
border-radius: 3px;
margin: 0 3px;
}
.im_dialogs_scrollable_wrap {
padding: 0 12px 0 12px;
}
.im_dialogs_col_wrap,
.im_history_col_wrap {
float: none;
width: auto;
max-width: auto;
min-width: auto;
}
.im_page_peer_not_selected .im_dialog_peer {
white-space: nowrap;
height: auto;
}
.im_page_peer_not_selected .im_dialog_message {
display: block;
}
.im_emoji_btn {
display: none;
}
}
.settings_modal_window .modal-dialog {
@ -1777,7 +1720,7 @@ img.img_fullsize {
font-size: 12px;
line-height: normal;
background: #F2F2F2 url(../img/icons/IconsetW.png?1) -6px -205px no-repeat;
background-size: 42px 430px;
background-size: 42px 460px;
border: 1px solid #F2F2F2;
border-radius: 3px;
padding: 6px 20px 6px 30px;
@ -1801,7 +1744,7 @@ img.img_fullsize {
height: 13px;
vertical-align: text-top;
background: url(../img/icons/IconsetW.png?1) -15px -192px no-repeat;
background-size: 42px 430px;
background-size: 42px 460px;
opacity: 0.6;
}
.is_1x .contacts_modal_search_clear {
@ -1835,4 +1778,268 @@ img.img_fullsize {
height: 40px;
margin-right: 10px;
overflow: hidden;
}
/* Messages edit panel */
.im_edit_panel_wrap {
border-top: 1px solid #EEE;
padding: 5px 5px;
}
.im_panel_to_top .im_edit_panel_wrap {
background: #FFF;
position: absolute;
/*width: 652px;*/
width: 100%;
}
.im_edit_delete_link,
.im_edit_cancel_link {
display: block;
padding: 8px 17px;
}
.im_edit_cancel_link {
float: left;
}
.im_edit_delete_link {
float: right;
}
.im_edit_delete_link:hover,
.im_edit_cancel_link:hover {
background: #f2f6fa;
text-decoration: none;
}
.im_edit_delete_link {
line-height: 0;
}
.im_edit_panel_title {
text-align: center;
margin: 0;
font-size: 14px;
line-height: 34px;
}
.icon-delete {
display: inline-block;
width: 12px;
height: 15px;
background: url(../img/icons/IconsetW.png?1) -15px -319px no-repeat;
background-size: 42px 460px;
}
.is_1x .icon-delete {
background-image: url(../img/icons/IconsetW_1x.png?2);
}
.im_message_date:hover {
cursor: pointer;
text-decoration: underline;
}
.im_message_selected {
background: #f2f6fa;
}
.im_history_selectable .im_message_outer_wrap {
cursor: pointer;
}
.im_history_selectable .im_message_outer_wrap:hover {
background: #f2f6fa;
}
.im_message_selected .im_message_date,
.im_history_selectable .im_message_outer_wrap:hover .im_message_date {
color: #91a6ba;
}
.im_history_selectable .im_message_date:hover {
text-decoration: none;
}
.im_message_wrap {
max-width: 526px;
padding: 0 15px;
margin: 0 auto;
position: relative;
}
.icon-select-tick {
display: none;
position: absolute;
width: 17px;
height: 15px;
margin: 10px 0 0 -75px;
background: url(../img/icons/IconsetW.png?1) -13px -344px no-repeat;
background-size: 42px 460px;
}
.is_1x .icon-select-tick {
background-image: url(../img/icons/IconsetW_1x.png?2);
}
.im_history_selectable .icon-select-tick {
display: inline-block;
}
.im_message_selected .icon-select-tick,
.im_history_selectable .im_message_outer_wrap:hover .icon-select-tick {
background-position: -13px -367px;
opacity: 0.6;
}
.im_message_selected .icon-select-tick {
opacity: 1 !important;
}
@media (min-width: 480px) {
.tg_page_head .navbar-quick-nav {
display: none;
}
}
@media (max-width: 480px) {
.tg_page_head .navbar > .container .navbar-brand {
padding-left: 9px;
}
.im_history_panel_info_link {
display: none;
}
.im_history_panel_edit_link {
margin-right: 0;
}
}
@media (min-height: 768px) {
.user_modal_window .modal-dialog {
padding-top: 150px;
}
}
@media (max-width: 480px) {
.login_form_wrap {
border-radius: 0;
max-width: auto;
box-shadow: none;
-webkit-box-shadow: none;
margin: 30px auto 20px;
}
.im_panel_own_photo,
.im_panel_peer_photo {
display: none;
}
.im_history_panel_wrap {
margin: 0 15px;
}
.im_send_panel_wrap {
padding: 10px 15px;
}
.icon-select-tick {
margin: 10px 0 0 -24px
}
.im_content_message_wrap {
margin-left: 0;
}
.im_history_typing {
padding: 0 15px 0 60px;
}
.im_send_form {
left: 0;
right: 0;
max-width: none;
}
}
@media (max-height: 480px) {
.im_page_footer {
display: none;
}
.im_send_panel_wrap {
padding-bottom: 12px;
}
.emoji-wysiwyg-editor {
min-height: 34px;
max-height: 150px;
}
}
@media (max-width: 640px) {
.im_dialog_peer {
white-space: normal;
height: 2.84em;
}
.im_dialog_message {
display: none;
}
}
@media (max-width: 900px) {
/*.icon-message-status {
margin-left: 0;
margin-top: 18px;
right: -1px;
}*/
.icon-message-status {
z-index: 10;
margin-left: -5px;
border-radius: 0;
height: 34px;
border: 0;
width: 2px;
margin-top: 1px;
border: 0;
}
/*.icon-message-status {
z-index: 10;
margin-left: -15px;
}*/
}
@media (max-width: 480px) {
.im_dialogs_col_wrap,
.im_page_peer_not_selected .im_history_col_wrap {
display: none;
}
.im_page_peer_not_selected .im_dialogs_col_wrap {
display: block;
border-right: 0;
}
.im_page_peer_not_selected .im_dialogs_col {
margin-right: 0;
}
.im_page_peer_not_selected .im_dialogs_col_wrap .pane {
width: 12px;
right: 0px;
}
.im_page_peer_not_selected .im_dialogs_col_wrap .pane > .slider {
border-radius: 3px;
margin: 0 3px;
}
.im_dialogs_scrollable_wrap {
padding: 0 12px 0 12px;
}
.im_dialogs_col_wrap,
.im_history_col_wrap {
float: none;
width: auto;
max-width: auto;
min-width: auto;
}
.im_page_peer_not_selected .im_dialog_peer {
white-space: nowrap;
height: auto;
}
.im_page_peer_not_selected .im_dialog_message {
display: block;
}
.im_emoji_btn {
display: none;
}
}

BIN
img/Logo_1x.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

BIN
img/Logo_2x.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

BIN
img/TLogo2_1x.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
img/TLogo2_2x.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
img/TLogo_1x.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
img/Tlogo_2x.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
img/bg_full.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 574 KiB

BIN
img/icons/IconsetW.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

BIN
img/icons/IconsetW_1x.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

2
js/app.js

@ -1,5 +1,5 @@
/*!
* Webogram v0.1 - messaging web application for MTProto
* Webogram v0.0.17 - messaging web application for MTProto
* https://github.com/zhukov/webogram
* Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>
* https://github.com/zhukov/webogram/blob/master/LICENSE

4
js/background.js

@ -1,5 +1,5 @@
/*!
* Webogram v0.1 - messaging web application for MTProto
* Webogram v0.0.17 - messaging web application for MTProto
* https://github.com/zhukov/webogram
* Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>
* https://github.com/zhukov/webogram/blob/master/LICENSE
@ -15,4 +15,4 @@ chrome.app.runtime.onLaunched.addListener(function(launchData) {
minHeight: 400,
frame: 'chrome'
});
});
});

123
js/controllers.js

@ -1,5 +1,5 @@
/*!
* Webogram v0.1 - messaging web application for MTProto
* Webogram v0.0.17 - messaging web application for MTProto
* https://github.com/zhukov/webogram
* Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>
* https://github.com/zhukov/webogram/blob/master/LICENSE
@ -209,7 +209,7 @@ angular.module('myApp.controllers', [])
$scope.$on('dialog_unread', function (e, dialog) {
angular.forEach($scope.dialogs, function(curDialog) {
if (curDialog.peerID == dialog.peerID) {
curDialog.unreadCount = dialog.unread_count;
curDialog.unreadCount = dialog.count;
}
});
});
@ -308,15 +308,32 @@ angular.module('myApp.controllers', [])
StatusManager.start();
$scope.history = [];
$scope.mediaType = false;
$scope.selectedMsgs = {};
$scope.selectedCount = 0;
$scope.selectActions = false;
$scope.missedCount = 0;
$scope.typing = {};
$scope.state = {};
$scope.toggleMessage = toggleMessage;
$scope.selectedDelete = selectedDelete;
$scope.selectedCancel = selectedCancel;
$scope.toggleEdit = toggleEdit;
$scope.toggleMedia = toggleMedia;
$scope.showPeerInfo = showPeerInfo;
var peerID,
offset = 0,
hasMore = false,
maxID = 0,
startLimit = 20,
limit = 50,
inputMediaFilters = {
photos: 'inputMessagesFilterPhotoVideo',
video: 'inputMessagesFilterVideo',
documents: 'inputMessagesFilterDocument',
},
jump = 0;
function applyDialogSelect (newPeer) {
@ -326,10 +343,11 @@ angular.module('myApp.controllers', [])
$scope.curDialog.peerID = peerID;
$scope.curDialog.inputPeer = AppPeersManager.getInputPeer(newPeer);
$scope.mediaType = false;
if (peerID) {
updateHistoryPeer(true);
loadHistory(peerID);
loadHistory();
} else {
showEmptyHistory();
}
@ -367,7 +385,15 @@ angular.module('myApp.controllers', [])
return;
}
// console.trace('load history');
AppMessagesManager.getHistory($scope.curDialog.inputPeer, maxID, limit).then(function (historyResult) {
var inputMediaFilter = $scope.mediaType && {_: inputMediaFilters[$scope.mediaType]},
getMessagesPromise = inputMediaFilter
? AppMessagesManager.getSearch($scope.curDialog.inputPeer, '', inputMediaFilter, maxID, startLimit)
: AppMessagesManager.getHistory($scope.curDialog.inputPeer, maxID, startLimit);
getMessagesPromise.then(function (historyResult) {
console.log('got', maxID, historyResult);
offset += limit;
hasMore = offset < historyResult.count;
maxID = historyResult.history[historyResult.history.length - 1];
@ -387,9 +413,13 @@ angular.module('myApp.controllers', [])
offset = 0;
maxID = 0;
var curJump = ++jump;
var curJump = ++jump,
inputMediaFilter = $scope.mediaType && {_: inputMediaFilters[$scope.mediaType]},
getMessagesPromise = inputMediaFilter
? AppMessagesManager.getSearch($scope.curDialog.inputPeer, '', inputMediaFilter, maxID, startLimit)
: AppMessagesManager.getHistory($scope.curDialog.inputPeer, maxID, startLimit);
AppMessagesManager.getHistory($scope.curDialog.inputPeer, maxID, startLimit).then(function (historyResult) {
getMessagesPromise.then(function (historyResult) {
if (curJump != jump) return;
offset += startLimit;
@ -420,6 +450,70 @@ angular.module('myApp.controllers', [])
$scope.$broadcast('ui_history_change');
}
function toggleMessage (messageID, target) {
if (!$scope.selectActions && !$(target).hasClass('im_message_date') && !$(target).hasClass('im_message_meta')) {
return false;
}
if ($scope.selectedMsgs[messageID]) {
delete $scope.selectedMsgs[messageID];
$scope.selectedCount--;
if (!$scope.selectedCount) {
$scope.selectActions = false;
$scope.$broadcast('ui_panel_update');
}
} else {
$scope.selectedMsgs[messageID] = true;
$scope.selectedCount++;
if (!$scope.selectActions) {
$scope.selectActions = true;
$scope.$broadcast('ui_panel_update');
}
}
}
function selectedCancel () {
$scope.selectedMsgs = {};
$scope.selectedCount = 0;
$scope.selectActions = false;
$scope.$broadcast('ui_panel_update');
}
function selectedDelete () {
if ($scope.selectedCount > 0) {
var selectedMessageIDs = [];
angular.forEach($scope.selectedMsgs, function (t, messageID) {
selectedMessageIDs.push(messageID);
});
AppMessagesManager.deleteMessages(selectedMessageIDs).then(function () {
selectedCancel();
});
}
}
function toggleEdit () {
if ($scope.selectActions) {
selectedCancel();
} else {
$scope.selectActions = true;
$scope.$broadcast('ui_panel_update');
}
}
function toggleMedia (mediaType) {
if (mediaType) {
$scope.missedCount = 0;
}
$scope.mediaType = mediaType || false;
loadHistory();
}
function showPeerInfo () {
if ($scope.curDialog.peerID > 0) {
$rootScope.openUser($scope.curDialog.peerID)
} else if ($scope.curDialog.peerID < 0) {
$rootScope.openChat(-$scope.curDialog.peerID)
}
}
var typingTimeouts = {};
@ -428,6 +522,10 @@ angular.module('myApp.controllers', [])
$scope.$on('history_append', function (e, addedMessage) {
if (addedMessage.peerID == $scope.curDialog.peerID) {
if ($scope.mediaType) {
$scope.missedCount++;
return;
}
// console.log('append', addedMessage);
// console.trace();
$scope.history.push(AppMessagesManager.wrapForHistory(addedMessage.messageID));
@ -444,6 +542,19 @@ angular.module('myApp.controllers', [])
}
});
$scope.$on('history_delete', function (e, historyUpdate) {
if (historyUpdate.peerID == $scope.curDialog.peerID) {
var newHistory = [];
for (var i = 0; i < $scope.history.length; i++) {
if (!historyUpdate.msgs[$scope.history[i].id]) {
newHistory.push($scope.history[i]);
}
};
$scope.history = newHistory;
}
})
$scope.$on('dialog_flush', function (e, dialog) {
if (dialog.peerID == $scope.curDialog.peerID) {
$scope.history = [];

21
js/directives.js

@ -1,5 +1,5 @@
/*!
* Webogram v0.1 - messaging web application for MTProto
* Webogram v0.0.17 - messaging web application for MTProto
* https://github.com/zhukov/webogram
* Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>
* https://github.com/zhukov/webogram/blob/master/LICENSE
@ -203,6 +203,25 @@ angular.module('myApp.directives', ['myApp.filters'])
});
});
scope.$on('ui_panel_update', function () {
var h = $(historyWrap).height();
$(panelWrap).addClass('im_panel_to_top');
onContentLoaded(function () {
$(panelWrap).removeClass('im_panel_to_top');
updateSizes(true);
var newH = $(historyWrap).height();
if (atBottom) {
scrollableWrap.scrollTop = scrollableWrap.scrollHeight;
updateScroller();
} else {
scrollableWrap.scrollTop -= newH - h;
updateScroller();
}
});
});
scope.$on('ui_editor_resize', updateSizes);
var atBottom = true;

4
js/filters.js

@ -1,5 +1,5 @@
/*!
* Webogram v0.1 - messaging web application for MTProto
* Webogram v0.0.17 - messaging web application for MTProto
* https://github.com/zhukov/webogram
* Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>
* https://github.com/zhukov/webogram/blob/master/LICENSE
@ -155,4 +155,4 @@ angular.module('myApp.filters', [])
}
return $filter('dateOrTime')(timestamp);
}
}])
}])

4
js/lib/aes_worker.js

@ -1,5 +1,5 @@
/*!
* Webogram v0.1 - messaging web application for MTProto
* Webogram v0.0.17 - messaging web application for MTProto
* https://github.com/zhukov/webogram
* Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>
* https://github.com/zhukov/webogram/blob/master/LICENSE
@ -23,4 +23,4 @@ onmessage = function (e) {
result = aesDecrypt(e.data.encryptedBytes, e.data.keyBytes, e.data.ivBytes);
}
postMessage({taskID: taskID, result: result});
}
}

2
js/lib/config.js

File diff suppressed because one or more lines are too long

2
js/lib/mtproto.js

@ -1,5 +1,5 @@
/*!
* Webogram v0.1 - messaging web application for MTProto
* Webogram v0.0.17 - messaging web application for MTProto
* https://github.com/zhukov/webogram
* Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>
* https://github.com/zhukov/webogram/blob/master/LICENSE

4
js/lib/pq_worker.js

@ -1,5 +1,5 @@
/*!
* Webogram v0.1 - messaging web application for MTProto
* Webogram v0.0.17 - messaging web application for MTProto
* https://github.com/zhukov/webogram
* Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>
* https://github.com/zhukov/webogram/blob/master/LICENSE
@ -13,4 +13,4 @@ importScripts(
onmessage = function (e) {
postMessage(pqPrimeFactorization(e.data));
}
}

1
js/lib/schema.tl.txt

@ -222,6 +222,7 @@ inputMessagesFilterEmpty#57e2f66c = MessagesFilter;
inputMessagesFilterPhotos#9609a51c = MessagesFilter;
inputMessagesFilterVideo#9fc00e65 = MessagesFilter;
inputMessagesFilterPhotoVideo#56e9f0e4 = MessagesFilter;
inputMessagesFilterDocument#9eddf188 = MessagesFilter;
updateNewMessage#13abdb3 message:Message pts:int = Update;
updateMessageID#4e90bfd6 id:int random_id:long = Update;

4
js/lib/sha1_worker.js

@ -1,5 +1,5 @@
/*!
* Webogram v0.1 - messaging web application for MTProto
* Webogram v0.0.17 - messaging web application for MTProto
* https://github.com/zhukov/webogram
* Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>
* https://github.com/zhukov/webogram/blob/master/LICENSE
@ -15,4 +15,4 @@ onmessage = function (e) {
var taskID = e.data.taskID;
postMessage({taskID: taskID, result: sha1Hash(e.data.bytes)});
}
}

53
js/services.js

@ -1,5 +1,5 @@
/*!
* Webogram v0.1 - messaging web application for MTProto
* Webogram v0.0.17 - messaging web application for MTProto
* https://github.com/zhukov/webogram
* Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>
* https://github.com/zhukov/webogram/blob/master/LICENSE
@ -746,6 +746,52 @@ angular.module('myApp.services', [])
return deferred.promise;
}
function getSearch (inputPeer, query, inputFilter, maxID, limit) {
return MtpApiManager.invokeApi('messages.search', {
peer: inputPeer,
q: query || '',
filter: inputFilter || {_: 'inputMessagesFilterEmpty'},
min_date: 0,
max_date: 0,
limit: limit,
max_id: maxID || 0
}).then(function (searchResult) {
AppUsersManager.saveApiUsers(searchResult.users);
AppChatsManager.saveApiChats(searchResult.chats);
saveMessages(searchResult.messages);
var foundCount = searchResult._ == 'messages.messagesSlice'
? searchResult.count
: searchResult.messages.length;
var foundMsgs = [];
angular.forEach(searchResult.messages, function (message) {
foundMsgs.push(message.id);
});
return {
count: foundCount,
history: foundMsgs
};
});
}
function deleteMessages (messageIDs) {
return MtpApiManager.invokeApi('messages.deleteMessages', {
id: messageIDs
}).then(function (deletedMessageIDs) {
ApiUpdatesManager.saveUpdate({
_: 'updateDeleteMessages',
messages: deletedMessageIDs
});
return deletedMessageIDs;
});
}
function processAffectedHistory (inputPeer, affectedHistory, method) {
if (!ApiUpdatesManager.saveSeq(affectedHistory.seq)) {
return false;
@ -1419,7 +1465,7 @@ angular.module('myApp.services', [])
message = messagesStorage[messageID];
if (message) {
peerID = getMessagePeer(message);
history = historiesUpdated[peer] || (historiesUpdated[peer] = {count: 0, unread: 0, msgs: {}});
history = historiesUpdated[peerID] || (historiesUpdated[peerID] = {count: 0, unread: 0, msgs: {}});
if (!message.out && message.unread) {
history.unread++;
@ -1460,6 +1506,7 @@ angular.module('myApp.services', [])
}
}
historyStorage.history = newHistory;
$rootScope.$broadcast('history_delete', {peerID: peerID, msgs: updatedData.msgs});
}
});
break;
@ -1469,8 +1516,10 @@ angular.module('myApp.services', [])
return {
getDialogs: getDialogs,
getHistory: getHistory,
getSearch: getSearch,
readHistory: readHistory,
flushHistory: flushHistory,
deleteMessages: deleteMessages,
saveMessages: saveMessages,
sendText: sendText,
sendFile: sendFile,

2
js/util.js

@ -1,5 +1,5 @@
/*!
* Webogram v0.1 - messaging web application for MTProto
* Webogram v0.0.17 - messaging web application for MTProto
* https://github.com/zhukov/webogram
* Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>
* https://github.com/zhukov/webogram/blob/master/LICENSE

2
manifest.json

@ -1,6 +1,6 @@
{
"name": "Telegram UNOFFICIAL",
"version": "0.0.16",
"version": "0.0.17",
"short_name": "Webogram",
"manifest_version": 2,
"app": {

2
manifest.webapp

@ -1,7 +1,7 @@
{
"name": "Webogram",
"description": "Webogram – UNOFFICIAL Telegram Web App.\nMore info & source code here: https://github.com/zhukov/webogram",
"version": "0.0.16",
"version": "0.0.17",
"launch_path": "/index.html",
"developer": {
"name": "Igor Zhukov",

4
partials/head.html

@ -8,11 +8,11 @@
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#/im"><img src="img/Logo_2x.png" class="tg_head_logo" alt="Telegram logo" width="110" height="31" /></a>
<a class="navbar-brand" href="{{isLoggedIn ? '#/im' : '#/'}}"><span class="tg_head_logo"></span><span class="tg_head_logo_text"></span></a>
<ul class="nav navbar-nav navbar-quick-nav" ng-show="curDialog.peer">
<li>
<a href="#/im">
<span class="glyphicon glyphicon-chevron-left"></span> Back
<i class="icon icon-back"></i> Back
</a>
</li>
</ul>

94
partials/im.html

@ -31,30 +31,62 @@
<div class="im_history_panel clearfix" ng-controller="AppImPanelController">
<div class="im_history_panel_title">
<div ng-if="historyPeer.id < 0" ng-click="openChat(-historyPeer.id)">
<span class="im_history_panel_info_link pull-right">Info</span>
<h4>
<span ng-bind-html="historyPeer.data.rTitle"></span>
<small class="im_chat_users">
<ng-pluralize count="historyPeer.data.participants_count"
when="{'0': 'No members', 'one': '1 member', 'other': '{} members'}">
</ng-pluralize>
</small>
</h4>
</div>
<div ng-if="historyPeer.id > 0" ng-click="openUser(historyPeer.id)">
<span class="im_history_panel_info_link pull-right">Info</span>
<h4>
<span ng-bind-html="historyPeer.data.rFullName"></span>
<small class="im_peer_online">{{historyPeer.data | userStatus}}</small>
</h4>
<a class="im_history_panel_info_link pull-right" ng-click="showPeerInfo()">Info</a>
<a class="im_history_panel_edit_link pull-right" ng-click="toggleEdit()">Edit</a>
<div class="dropdown im_history_panel_media_dropdown pull-right">
<a class="dropdown-toggle">Media<i class="icon icon-caret"></i></a>
<ul class="dropdown-menu">
<li>
<a ng-click="toggleMedia('photos')">Photos</a>
</li>
<li>
<a ng-click="toggleMedia('video')">Video</a>
</li>
<li>
<a ng-click="toggleMedia('documents')">Documents</a>
</li>
</ul>
</div>
<a ng-if="mediaType !== false" class="im_history_panel_return_link pull-right" ng-click="toggleMedia()">
Show all messages
<strong class="im_history_panel_return_count" ng-show="missedCount > 0">+{{missedCount}}</strong>
</a>
<h4 ng-if="mediaType !== false" ng-switch="mediaType">
<span ng-switch-when="photos"> Photos &amp; Videos </span>
<span ng-switch-when="documents"> Documents </span>
</h4>
<h4 ng-if="mediaType === false &amp;&amp; historyPeer.id < 0" ng-click="showPeerInfo()">
<span ng-bind-html="historyPeer.data.rTitle"></span>
<small class="im_chat_users">
<ng-pluralize count="historyPeer.data.participants_count"
when="{'0': 'No members', 'one': '1 member', 'other': '{} members'}">
</ng-pluralize>
</small>
</h4>
<h4 ng-if="mediaType === false &amp;&amp; historyPeer.id > 0" ng-click="showPeerInfo()">
<span ng-bind-html="historyPeer.data.rFullName"></span>
<small class="im_peer_online">{{historyPeer.data | userStatus}}</small>
</h4>
</div>
</div>
<div class="im_edit_panel_wrap clearfix" ng-show="selectActions">
<a class="im_edit_delete_link" ng-click="selectedDelete()"><i class="icon icon-delete"></i></a>
<a class="im_edit_cancel_link" ng-click="selectedCancel()">Cancel</a>
<h4 class="im_edit_panel_title">
<ng-pluralize count="selectedCount"
when="{'0': 'Select messages', 'one': '1 message', 'other': '{} messages'}">
</ng-pluralize>
</h4>
</div>
</div>
<div class="im_history_wrap nano">
@ -63,12 +95,12 @@
<div class="im_history_scrollable">
<div class="im_history">
<div class="im_history" ng-class="{im_history_selectable: selectActions}">
<div class="im_history_message_wrap" my-message ng-repeat="historyMessage in history"></div>
</div>
<div class="im_history_typing_wrap">
<div class="im_history_typing" ng-animate="{enter:'animate-show', leave:'animate-hide'}" ng-if="typing.user">
<div class="im_history_typing" ng-show="typing.user">
<strong class="im_history_typing_author" ng-bind-html="typing.user.rFullName"></strong> is typing<span my-typing-dots></span>
</div>
</div>
@ -84,20 +116,13 @@
<div class="im_send_form_wrap1">
<div class="im_send_form_wrap clearfix" ng-controller="AppImSendController">
<div class="pull-right im_panel_peer_photo" ng-click="openUser(historyPeer.id)" ng-if="historyPeer.id > 0">
<img
class="im_panel_peer_photo"
my-load-thumb
thumb="historyPeer.photo"
/>
<i class="icon im_panel_peer_online" ng-show="historyPeer.data.status._ == 'userStatusOnline'"></i>
</div>
<div class="pull-right im_panel_peer_photo" ng-click="openChat(-historyPeer.id)" ng-if="historyPeer.id < 0">
<div class="pull-right im_panel_peer_photo" ng-click="showPeerInfo()">
<img
class="im_panel_peer_photo"
my-load-thumb
thumb="historyPeer.photo"
/>
<i class="icon im_panel_peer_online" ng-show="historyPeer.id > 0 &amp;&amp; historyPeer.data.status._ == 'userStatusOnline'"></i>
</div>
<div class="pull-left im_panel_own_photo">
<img
@ -110,8 +135,9 @@
<div class="im_send_dropbox_wrap"> Drop photos here to send </div>
<textarea ng-model="draftMessage.text" placeholder="Write a message..." class="form-control im_message_field"></textarea>
<div class="im_emoji_btn pull-right">
<i class="icon icon-emoji"></i>
<div class="im_media_attach pull-right">
<input type="file" class="im_media_attach_input" size="28" multiple="true" accept="image/x-png, image/png, image/gif, image/jpeg, video/*, audio/mpeg, audio/mp3" />
<i class="icon icon-camera"></i>
</div>
<div class="im_attach pull-right">
@ -119,9 +145,9 @@
<i class="icon icon-paperclip"></i>
</div>
<div class="im_media_attach pull-right">
<input type="file" class="im_media_attach_input" size="28" multiple="true" accept="image/x-png, image/png, image/gif, image/jpeg, video/*, audio/mpeg, audio/mp3" />
<i class="icon icon-camera"></i>
<div class="im_emoji_btn pull-right">
<i class="icon icon-emoji"></i>
</div>
<button type="submit" class="btn btn-tg im_submit">Send</button>

381
partials/message.html

@ -1,233 +1,240 @@
<div class="im_message_wrap clearfix" ng-class="{im_message_out: historyMessage.out}">
<div class="im_message_outer_wrap" ng-class="{im_message_selected: selectedMsgs[historyMessage.id]}" ng-click="toggleMessage(historyMessage.id, $event.target)">
<div class="im_service_message_wrap" ng-if="historyMessage._ == 'messageService'">
<div class="im_service_message">
<a ng-click="openUser(historyMessage.from_id)" class="im_message_author" ng-bind-html="historyMessage.fromUser.rFirstName"></a>
<div class="im_message_wrap clearfix">
<span class="im_message_service" ng-switch="historyMessage.action['_']">
<span ng-switch-when="messageActionChatCreate">
created the group &laquo;<strong>{{historyMessage.action.title}}</strong>&raquo;
</span>
<span ng-switch-when="messageActionChatEditTitle">
changed group name to &laquo;<strong>{{historyMessage.action.title}}</strong>&raquo;
</span>
<span ng-switch-when="messageActionChatEditPhoto">
changed group photo
</span>
<span ng-switch-when="messageActionChatDeletePhoto">
removed group photo
</span>
<span ng-switch-when="messageActionChatAddUser">
<span ng-if="historyMessage.from_id != historyMessage.action.user_id">
invited <a ng-click="openUser(historyMessage.action.user_id)" ng-bind-html="historyMessage.action.user.rFullName"></a>
<div class="im_service_message_wrap" ng-if="historyMessage._ == 'messageService'">
<div class="im_service_message">
<a ng-click="openUser(historyMessage.from_id)" class="im_message_author" ng-bind-html="historyMessage.fromUser.rFirstName"></a>
<span class="im_message_service" ng-switch="historyMessage.action['_']">
<span ng-switch-when="messageActionChatCreate">
created the group &laquo;<strong>{{historyMessage.action.title}}</strong>&raquo;
</span>
<span ng-if="historyMessage.from_id == historyMessage.action.user_id">
returned to group
<span ng-switch-when="messageActionChatEditTitle">
changed group name to &laquo;<strong>{{historyMessage.action.title}}</strong>&raquo;
</span>
</span>
<span ng-switch-when="messageActionChatDeleteUser">
<span ng-if="historyMessage.from_id != historyMessage.action.user_id">
kicked <a ng-click="openUser(historyMessage.action.user_id)" ng-bind-html="historyMessage.action.user.rFullName"></a>
<span ng-switch-when="messageActionChatEditPhoto">
changed group photo
</span>
<span ng-if="historyMessage.from_id == historyMessage.action.user_id">
left group
<span ng-switch-when="messageActionChatDeletePhoto">
removed group photo
</span>
<span ng-switch-when="messageActionChatAddUser">
<span ng-if="historyMessage.from_id != historyMessage.action.user_id">
invited <a ng-click="openUser(historyMessage.action.user_id)" ng-bind-html="historyMessage.action.user.rFullName"></a>
</span>
<span ng-if="historyMessage.from_id == historyMessage.action.user_id">
returned to group
</span>
</span>
<span ng-switch-when="messageActionChatDeleteUser">
<span ng-if="historyMessage.from_id != historyMessage.action.user_id">
kicked <a ng-click="openUser(historyMessage.action.user_id)" ng-bind-html="historyMessage.action.user.rFullName"></a>
</span>
<span ng-if="historyMessage.from_id == historyMessage.action.user_id">
left group
</span>
</span>
</span>
<span ng-switch-default>
unsupported action {{historyMessage.action}}
<span ng-switch-default>
unsupported action {{historyMessage.action}}
</span>
</span>
</span>
</div>
<a ng-if="historyMessage.action._ == 'messageActionChatEditPhoto'" class="im_service_message_photo_thumb" href="" ng-click="openPhoto(historyMessage.action.photo.id)">
<img
class="im_service_message_photo_thumb"
my-load-thumb
thumb="historyMessage.action.photo.thumb"
width="{{historyMessage.action.photo.thumb.width}}"
height="{{historyMessage.action.photo.thumb.height}}"
/>
</a>
</div>
</div>
<a ng-if="historyMessage.action._ == 'messageActionChatEditPhoto'" class="im_service_message_photo_thumb" href="" ng-click="openPhoto(historyMessage.action.photo.id)">
<img
class="im_service_message_photo_thumb"
my-load-thumb
thumb="historyMessage.action.photo.thumb"
width="{{historyMessage.action.photo.thumb.width}}"
height="{{historyMessage.action.photo.thumb.height}}"
/>
</a>
<div class="im_content_message_wrap" ng-if="historyMessage._ != 'messageService'">
<a ng-click="historyMessage.send()" ng-if="historyMessage.error">
<i class="icon-message-status icon-message-status-error" tooltip="Try again"></i>
</a>
<i class="icon-message-status" ng-class="{'icon-message-status-unread': historyMessage.unread, 'icon-message-status-pending': historyMessage.pending}" ng-if="!historyMessage.error"></i>
<a ng-click="openUser(historyMessage.from_id)" class="im_message_from_photo pull-left">
<img
class="im_message_from_photo"
my-load-thumb
thumb="historyMessage.fromPhoto"
/>
</a>
<div class="im_message_meta pull-right text-right">
<i ng-if="historyMessage.out" class="icon icon-message-status-tick" ng-class="{'message-status-delivered-tick': true, 'message-status-unread-tick': historyMessage.unread}"></i>
<span class="im_message_date">{{historyMessage.date | dateOrTime}}</span>
</div>
<div class="im_message_body">
<div class="im_content_message_wrap" ng-if="historyMessage._ != 'messageService'">
<i class="icon icon-select-tick"></i>
<a ng-click="historyMessage.send()" ng-if="historyMessage.error">
<i class="icon-message-status icon-message-status-error" tooltip="Try again"></i>
</a>
<i class="icon-message-status" ng-class="{'icon-message-status-unread': historyMessage.unread, 'icon-message-status-pending': historyMessage.pending}" ng-if="!historyMessage.error"></i>
<a ng-click="openUser(historyMessage.from_id)" class="im_message_from_photo pull-left">
<img
class="im_message_from_photo"
my-load-thumb
thumb="historyMessage.fromPhoto"
/>
</a>
<div class="im_message_meta pull-right text-right">
<span class="im_message_date">{{historyMessage.date | dateOrTime}}</span>
</div>
<a class="im_message_author" ng-click="openUser(historyMessage.from_id)" ng-bind-html="historyMessage.fromUser.rFirstName"></a>
<div class="im_message_body">
<a class="im_message_author" ng-click="openUser(historyMessage.from_id)" ng-bind-html="historyMessage.fromUser.rFirstName"></a>
<div class="im_message_fwd_header" ng-if="historyMessage._ == 'messageForwarded'">
Forwarded message from <a class="im_message_fwd_author" ng-click="openUser(historyMessage.fwd_from_id)" ng-bind-html="historyMessage.fwdUser.rFirstName"></a>, <span class="im_message_fwd_date">{{historyMessage.fwd_date | dateOrTime}}</span>
</div>
<div class="im_message_media" ng-if="historyMessage.media &amp;&amp; historyMessage.media._ != 'messageMediaEmpty'" ng-switch="historyMessage.media._">
<a ng-switch-when="messageMediaPhoto" class="im_message_photo_thumb" href="" ng-click="openPhoto(historyMessage.media.photo.id)" style="width: {{historyMessage.media.photo.thumb.width}}px;">
<img
class="im_message_photo_thumb"
my-load-thumb
thumb="historyMessage.media.photo.thumb"
width="{{historyMessage.media.photo.thumb.width}}"
height="{{historyMessage.media.photo.thumb.height}}"
/>
</a>
<a ng-switch-when="messageMediaVideo" class="im_message_video_thumb" href="" ng-click="openVideo(historyMessage.media.video.id)" style="width: {{historyMessage.media.video.thumb.width}}px;">
<img
class="im_message_video_thumb"
my-load-thumb
thumb="historyMessage.media.video.thumb"
width="{{historyMessage.media.video.thumb.width}}"
height="{{historyMessage.media.video.thumb.height}}"
/>
<div class="im_message_video_duration_wrap" style="width: {{historyMessage.media.video.thumb.width}}px;">
<span class="im_message_video_duration pull-right">{{historyMessage.media.video.duration | duration}}</span>
<span class="glyphicon glyphicon-facetime-video"></span>
</div>
</a>
<div class="im_message_fwd_header" ng-if="historyMessage._ == 'messageForwarded'">
Forwarded message from <a class="im_message_fwd_author" ng-click="openUser(historyMessage.fwd_from_id)" ng-bind-html="historyMessage.fwdUser.rFirstName"></a>, <span class="im_message_fwd_date">{{historyMessage.fwd_date | dateOrTime}}</span>
</div>
<div ng-switch-when="messageMediaDocument" class="im_message_document">
<a href="" ng-click="openDoc(historyMessage.media.document.id)" ng-if="!historyMessage.media.document.progress.enabled">
<i class="icon icon-document"></i>
<div class="im_message_media" ng-if="historyMessage.media &amp;&amp; historyMessage.media._ != 'messageMediaEmpty'" ng-switch="historyMessage.media._">
<a ng-switch-when="messageMediaPhoto" class="im_message_photo_thumb" href="" ng-click="openPhoto(historyMessage.media.photo.id)" style="width: {{historyMessage.media.photo.thumb.width}}px;">
<img
class="im_message_photo_thumb"
my-load-thumb
thumb="historyMessage.media.photo.thumb"
width="{{historyMessage.media.photo.thumb.width}}"
height="{{historyMessage.media.photo.thumb.height}}"
/>
</a>
<i class="icon icon-document" ng-if="historyMessage.media.document.progress.enabled"></i>
<div class="im_message_document_info">
<div class="im_message_document_name_wrap">
<span class="im_message_document_name">
{{historyMessage.media.document.file_name}}
</span>
<span class="im_message_document_size" ng-if="!historyMessage.media.document.progress.enabled">
{{historyMessage.media.document.size | formatSize}}
</span>
<span class="im_message_document_size" ng-if="historyMessage.media.document.progress.enabled">
{{historyMessage.media.document.progress | formatSizeProgress}}
</span>
</div>
<div class="im_message_document_actions" ng-if="!historyMessage.media.document.progress.enabled">
<a href="" ng-click="openDoc(historyMessage.media.document.id)">Download</a>
<a ng-switch-when="messageMediaVideo" class="im_message_video_thumb" href="" ng-click="openVideo(historyMessage.media.video.id)" style="width: {{historyMessage.media.video.thumb.width}}px;">
<img
class="im_message_video_thumb"
my-load-thumb
thumb="historyMessage.media.video.thumb"
width="{{historyMessage.media.video.thumb.width}}"
height="{{historyMessage.media.video.thumb.height}}"
/>
<div class="im_message_video_duration_wrap" style="width: {{historyMessage.media.video.thumb.width}}px;">
<span class="im_message_video_duration pull-right">{{historyMessage.media.video.duration | duration}}</span>
<span class="glyphicon glyphicon-facetime-video"></span>
</div>
<div class="im_message_download_progress_wrap" ng-if="historyMessage.media.document.progress.enabled">
<div class="progress tg_down_progress">
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="{{historyMessage.media.document.progress.percent}}" aria-valuemin="0" aria-valuemax="100" style="width: {{historyMessage.media.document.progress.percent}}%">
<span class="sr-only">
{{historyMessage.media.document.progress.percent}}% Complete (success)
</span>
</a>
<div ng-switch-when="messageMediaDocument" class="im_message_document">
<a href="" ng-click="openDoc(historyMessage.media.document.id)" ng-if="!historyMessage.media.document.progress.enabled">
<i class="icon icon-document"></i>
</a>
<i class="icon icon-document" ng-if="historyMessage.media.document.progress.enabled"></i>
<div class="im_message_document_info">
<div class="im_message_document_name_wrap">
<span class="im_message_document_name">
{{historyMessage.media.document.file_name}}
</span>
<span class="im_message_document_size" ng-if="!historyMessage.media.document.progress.enabled">
{{historyMessage.media.document.size | formatSize}}
</span>
<span class="im_message_document_size" ng-if="historyMessage.media.document.progress.enabled">
{{historyMessage.media.document.progress | formatSizeProgress}}
</span>
</div>
<div class="im_message_document_actions" ng-if="!historyMessage.media.document.progress.enabled">
<a href="" ng-click="openDoc(historyMessage.media.document.id)">Download</a>
</div>
<div class="im_message_download_progress_wrap" ng-if="historyMessage.media.document.progress.enabled">
<div class="progress tg_down_progress">
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="{{historyMessage.media.document.progress.percent}}" aria-valuemin="0" aria-valuemax="100" style="width: {{historyMessage.media.document.progress.percent}}%">
<span class="sr-only">
{{historyMessage.media.document.progress.percent}}% Complete (success)
</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div ng-switch-when="messageMediaAudio" class="im_message_document">
<a href="" ng-click="openAudio(historyMessage.media.audio.id)" ng-if="!historyMessage.media.audio.progress.enabled &amp;&amp; !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">
{{historyMessage.media.audio.duration | duration}}
</span>
<span class="im_message_audio_size" ng-if="historyMessage.media.audio.progress.enabled">
{{historyMessage.media.audio.progress | formatSizeProgress}}
</span>
</div>
<div class="im_message_audio_actions" ng-if="!historyMessage.media.audio.progress.enabled &amp;&amp; !historyMessage.media.audio.url">
<a href="" ng-click="openAudio(historyMessage.media.audio.id)">Play</a>
</div>
<div class="im_message_download_progress_wrap" ng-if="historyMessage.media.audio.progress.enabled">
<div class="progress tg_down_progress">
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="{{historyMessage.media.audio.progress.percent}}" aria-valuemin="0" aria-valuemax="100" style="width: {{historyMessage.media.audio.progress.percent}}%">
<span class="sr-only">
{{historyMessage.media.audio.progress.percent}}% Complete (success)
</span>
<div ng-switch-when="messageMediaAudio" class="im_message_document">
<a href="" ng-click="openAudio(historyMessage.media.audio.id)" ng-if="!historyMessage.media.audio.progress.enabled &amp;&amp; !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">
{{historyMessage.media.audio.duration | duration}}
</span>
<span class="im_message_audio_size" ng-if="historyMessage.media.audio.progress.enabled">
{{historyMessage.media.audio.progress | formatSizeProgress}}
</span>
</div>
<div class="im_message_audio_actions" ng-if="!historyMessage.media.audio.progress.enabled &amp;&amp; !historyMessage.media.audio.url">
<a href="" ng-click="openAudio(historyMessage.media.audio.id)">Play</a>
</div>
<div class="im_message_download_progress_wrap" ng-if="historyMessage.media.audio.progress.enabled">
<div class="progress tg_down_progress">
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="{{historyMessage.media.audio.progress.percent}}" aria-valuemin="0" aria-valuemax="100" style="width: {{historyMessage.media.audio.progress.percent}}%">
<span class="sr-only">
{{historyMessage.media.audio.progress.percent}}% Complete (success)
</span>
</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/mpeg" />
<embed hidden="true" autostart="true" loop="false" src="{{historyMessage.media.audio.url}}" />
</audio>
<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/mpeg" />
<embed hidden="true" autostart="true" loop="false" src="{{historyMessage.media.audio.url}}" />
</audio>
</div>
</div>
</div>
</div>
<a ng-switch-when="messageMediaGeo" my-map-point point="historyMessage.media.geo" class="im_message_geopoint">
<i class="icon icon-geo-point"></i>
</a>
<div ng-switch-when="messageMediaContact">
<a ng-click="openUser(historyMessage.media.user.id)" class="im_message_contact_photo pull-left" ng-if="historyMessage.media.user">
<img
class="im_message_contact_photo"
my-load-thumb
thumb="historyMessage.media.userPhoto"
/>
<a ng-switch-when="messageMediaGeo" my-map-point point="historyMessage.media.geo" class="im_message_geopoint">
<i class="icon icon-geo-point"></i>
</a>
<div class="im_message_contact_name"><span class="glyphicon glyphicon-user"></span>
{{historyMessage.media.first_name}} {{historyMessage.media.last_name}}
</div>
<div class="im_message_contact_phone">
{{historyMessage.media.phone_number}}
</div>
</div>
<div ng-switch-when="messageMediaPending" class="im_message_upload_file im_message_upload_{{historyMessage.media.type}}">
<i class="icon icon-{{historyMessage.media.type}}"></i>
<div class="im_message_document_info">
<div class="im_message_document_name_wrap">
<span class="im_message_document_name">
{{historyMessage.media.file_name}}
</span>
<span class="im_message_document_size" ng-if="historyMessage.media.progress">
{{historyMessage.media.progress | formatSizeProgress}}
</span>
<div ng-switch-when="messageMediaContact">
<a ng-click="openUser(historyMessage.media.user.id)" class="im_message_contact_photo pull-left" ng-if="historyMessage.media.user">
<img
class="im_message_contact_photo"
my-load-thumb
thumb="historyMessage.media.userPhoto"
/>
</a>
<div class="im_message_contact_name"><span class="glyphicon glyphicon-user"></span>
{{historyMessage.media.first_name}} {{historyMessage.media.last_name}}
</div>
<div class="im_message_download_progress_wrap">
<div class="progress tg_down_progress">
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="{{historyMessage.media.progress.percent}}" aria-valuemin="0" aria-valuemax="100" style="width: {{historyMessage.media.progress.percent}}%">
<span class="sr-only">
{{historyMessage.media.progress.percent}}% Complete (success)
</span>
<div class="im_message_contact_phone">
{{historyMessage.media.phone_number}}
</div>
</div>
<div ng-switch-when="messageMediaPending" class="im_message_upload_file im_message_upload_{{historyMessage.media.type}}">
<i class="icon icon-{{historyMessage.media.type}}"></i>
<div class="im_message_document_info">
<div class="im_message_document_name_wrap">
<span class="im_message_document_name">
{{historyMessage.media.file_name}}
</span>
<span class="im_message_document_size" ng-if="historyMessage.media.progress">
{{historyMessage.media.progress | formatSizeProgress}}
</span>
</div>
<div class="im_message_download_progress_wrap">
<div class="progress tg_down_progress">
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="{{historyMessage.media.progress.percent}}" aria-valuemin="0" aria-valuemax="100" style="width: {{historyMessage.media.progress.percent}}%">
<span class="sr-only">
{{historyMessage.media.progress.percent}}% Complete (success)
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="im_message_text" ng-if="historyMessage.message.length" ng-bind-html="historyMessage.richMessage"></div>
</div>
<div class="im_message_text" ng-if="historyMessage.message.length" ng-bind-html="historyMessage.richMessage"></div>
</div>
</div>
</div>

2
partials/settings_modal.html

@ -61,7 +61,7 @@
<p>
<strong>Version: </strong>
<span class="settings_version">alpha 0.0.16</span>
<span class="settings_version">alpha 0.0.17</span>
</p>
<hr/>

2
partials/welcome.html

@ -8,7 +8,7 @@
<div class="welcome_box_wrap">
<div class="welcome_text">
<p>Welcome to an unofficial web-client of mobile <strong>Telegram</strong> messenger.</p>
<p>Is in alpha, which means it is still not 200% secure and functional.</p>
<p>It is an alpha, which means it is still not 200% secure and functional.</p>
<p>Visit <a target="_blank" href="https://telegram.org/">telegram.org</a> to learn more.</p>
</div>
<a href="#/login" class="btn btn-tg btn-block">Start Messaging</a>

Loading…
Cancel
Save