diff --git a/src/components/wrappers.ts b/src/components/wrappers.ts
index 87358c0e..492dfecc 100644
--- a/src/components/wrappers.ts
+++ b/src/components/wrappers.ts
@@ -10,6 +10,7 @@ import LazyLoadQueue from './lazyLoadQueue';
import apiFileManager, { CancellablePromise } from '../lib/mtproto/apiFileManager';
import appWebpManager from '../lib/appManagers/appWebpManager';
import {wrapPlayer} from '../lib/ckin';
+import { RichTextProcessor } from '../lib/richtextprocessor';
export type MTDocument = {
_: 'document',
@@ -159,7 +160,7 @@ export function wrapDocument(doc: MTDocument, withTime = false): HTMLDivElement
if(doc.type == 'voice') {
return wrapAudio(doc, withTime);
}
-
+
let docDiv = document.createElement('div');
docDiv.classList.add('document');
@@ -210,27 +211,27 @@ export function wrapDocument(doc: MTDocument, withTime = false): HTMLDivElement
appDocsManager.saveDocFile(doc.id).then(res => {
promise = res.promise;
-
+
preloader.attach(downloadDiv, true, promise);
-
+
promise.then(() => {
downloadDiv.classList.remove('downloading');
downloadDiv.remove();
});
})
-
+
downloadDiv.classList.add('downloading');
} else {
downloadDiv.classList.remove('downloading');
promise = null;
}
});
-
+
/* apiFileManager.getDownloadedFile(Object.assign({}, doc, {_: 'inputDocumentFileLocation'})).then(() => {
downloadDiv.classList.remove('downloading');
downloadDiv.remove();
}, () => {
-
+
}); */
return docDiv;
@@ -241,51 +242,51 @@ let lastAudioToggle: HTMLDivElement = null;
export function wrapAudio(doc: MTDocument, withTime = false): HTMLDivElement {
let div = document.createElement('div');
div.classList.add('audio');
-
+
let duration = doc.duration;
-
+
// @ts-ignore
let durationStr = String(duration | 0).toHHMMSS(true);
-
+
div.innerHTML = `
${durationStr}
`;
-
+
console.log('wrapping audio', doc, doc.attributes[0].waveform);
-
+
let timeDiv = div.lastElementChild as HTMLDivElement;
let downloadDiv = div.querySelector('.audio-download') as HTMLDivElement;
let preloader: ProgressivePreloader;
let promise: CancellablePromise;
-
+
let svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.classList.add('audio-waveform');
svg.setAttributeNS(null, 'width', '250');
svg.setAttributeNS(null, 'height', '23');
svg.setAttributeNS(null, 'viewBox', '0 0 250 23');
-
+
div.insertBefore(svg, div.lastElementChild);
let wave = doc.attributes[0].waveform as Uint8Array;
-
+
let index = 0;
for(let uint8 of wave) {
let percents = uint8 / 255;
-
+
let height = 23 * percents;
if(/* !height || */height < 2) {
height = 2;
}
-
+
svg.insertAdjacentHTML('beforeend', `
-
+
`);
++index;
}
-
+
let onClick = () => {
if(!promise) {
if(downloadDiv.classList.contains('downloading')) {
@@ -298,47 +299,47 @@ export function wrapAudio(doc: MTDocument, withTime = false): HTMLDivElement {
let promise = appDocsManager.downloadDoc(doc.id);
preloader.attach(downloadDiv, true, promise);
-
+
promise.then(blob => {
downloadDiv.classList.remove('downloading');
downloadDiv.remove();
-
+
let audio = document.createElement('audio');
let source = document.createElement('source');
source.src = URL.createObjectURL(blob);
source.type = doc.mime_type;
-
+
div.removeEventListener('click', onClick);
let toggle = div.querySelector('.audio-toggle') as HTMLDivElement;
-
+
let interval = 0;
-
+
toggle.addEventListener('click', () => {
if(audio.paused) {
if(lastAudioToggle && lastAudioToggle.classList.contains('tgico-largepause')) {
lastAudioToggle.click();
}
-
+
audio.currentTime = 0;
audio.play();
-
+
lastAudioToggle = toggle;
-
+
toggle.classList.remove('tgico-largeplay');
toggle.classList.add('tgico-largepause');
-
+
(Array.from(svg.children) as HTMLElement[]).forEach(node => node.classList.remove('active'));
-
+
let lastIndex = 0;
interval = setInterval(() => {
if(lastIndex >= svg.childElementCount) {
clearInterval(interval);
return;
}
-
+
// @ts-ignore
timeDiv.innerText = String(audio.currentTime | 0).toHHMMSS(true);
-
+
//svg.children[lastIndex].setAttributeNS(null, 'fill', '#000');
svg.children[lastIndex].classList.add('active');
++lastIndex;
@@ -348,23 +349,23 @@ export function wrapAudio(doc: MTDocument, withTime = false): HTMLDivElement {
audio.pause();
toggle.classList.add('tgico-largeplay');
toggle.classList.remove('tgico-largepause');
-
+
clearInterval(interval);
}
});
-
+
audio.addEventListener('ended', () => {
toggle.classList.add('tgico-largeplay');
toggle.classList.remove('tgico-largepause');
clearInterval(interval);
-
+
// @ts-ignore
timeDiv.innerText = String(audio.currentTime | 0).toHHMMSS(true);
});
-
+
audio.append(source);
});
-
+
downloadDiv.classList.add('downloading');
} else {
downloadDiv.classList.remove('downloading');
@@ -373,7 +374,7 @@ export function wrapAudio(doc: MTDocument, withTime = false): HTMLDivElement {
};
div.addEventListener('click', onClick);
-
+
div.click();
return div;
@@ -397,9 +398,9 @@ export function wrapPhoto(this: AppImManager, photo: any, message: any, containe
let load = () => {
let promise = appPhotosManager.preloadPhoto(photo.id, size);
-
+
preloader.attach(container, true, promise);
-
+
return promise.then((blob) => {
if(this.peerID != peerID) {
this.log.warn('peer changed');
@@ -527,3 +528,63 @@ export function wrapSticker(doc: MTDocument, div: HTMLDivElement, middleware?: (
return lazyLoadQueue ? (lazyLoadQueue.push({div, load}), Promise.resolve()) : load();
}
+
+export function wrapReply(title: string, subtitle: string, media?: any) {
+ let div = document.createElement('div');
+ div.classList.add('reply');
+
+ let replyBorder = document.createElement('div');
+ replyBorder.classList.add('reply-border');
+
+ let replyContent = document.createElement('div');
+ replyContent.classList.add('reply-content');
+
+ let replyTitle = document.createElement('div');
+ replyTitle.classList.add('reply-title');
+
+ let replySubtitle = document.createElement('div');
+ replySubtitle.classList.add('reply-subtitle');
+
+ replyTitle.innerHTML = title ? RichTextProcessor.wrapEmojiText(title) : '';
+
+ if(media) {
+ if(media.photo) {
+ replySubtitle.innerHTML = 'Photo';
+ } else if(media.document && media.document.type) {
+ replySubtitle.innerHTML = media.document.type;
+ } else if(media.webpage) {
+ replySubtitle.innerHTML = RichTextProcessor.wrapPlainText(media.webpage.url);
+ } else {
+ replySubtitle.innerHTML = media._;
+ }
+
+ if(media.photo || (media.document && ['video'].indexOf(media.document.type) !== -1)) {
+ let replyMedia = document.createElement('div');
+ replyMedia.classList.add('reply-media');
+
+ let photo = media.photo || media.document;
+
+ let sizes = photo.sizes || photo.thumbs;
+ if(sizes && sizes[0].bytes) {
+ appPhotosManager.setAttachmentPreview(sizes[0].bytes, replyMedia, false, true);
+ }
+
+ appPhotosManager.preloadPhoto(photo, appPhotosManager.choosePhotoSize(photo, 32, 32))
+ .then((blob) => {
+ replyMedia.style.backgroundImage = 'url(' + URL.createObjectURL(blob) + ')';
+ });
+
+ replyContent.append(replyMedia);
+ div.classList.add('is-reply-media');
+ }
+ } else {
+ replySubtitle.innerHTML = subtitle ? RichTextProcessor.wrapEmojiText(subtitle) : '';
+ }
+
+ replyContent.append(replyTitle, replySubtitle);
+ div.append(replyBorder, replyContent);
+
+ console.log('wrapReply', title, subtitle, media);
+
+ return div;
+}
diff --git a/src/lib/appManagers/appImManager.ts b/src/lib/appManagers/appImManager.ts
index 22cf00de..469666d5 100644
--- a/src/lib/appManagers/appImManager.ts
+++ b/src/lib/appManagers/appImManager.ts
@@ -20,7 +20,7 @@ import appMessagesIDsManager from "./appMessagesIDsManager";
import apiUpdatesManager from './apiUpdatesManager';
import initEmoticonsDropdown, { EMOTICONSSTICKERGROUP } from '../../components/emoticonsDropdown';
import LazyLoadQueue from '../../components/lazyLoadQueue';
-import { wrapDocument, wrapPhoto, wrapVideo, wrapSticker } from '../../components/wrappers';
+import { wrapDocument, wrapPhoto, wrapVideo, wrapSticker, wrapReply } from '../../components/wrappers';
import ProgressivePreloader from '../../components/preloader';
import { openBtnMenu } from '../../components/misc';
import appWebPagesManager from './appWebPagesManager';
@@ -490,11 +490,15 @@ class ChatInput {
this.btnSend.classList.add('tgico-microphone2');
};
- public setTopInfo(title: string, subtitle: string, input?: string) {
+ public setTopInfo(title: string, subtitle: string, input?: string, media?: any) {
//appImManager.scrollPosition.prepareFor('down');
- this.replyElements.titleEl.innerHTML = title ? RichTextProcessor.wrapEmojiText(title) : '';
- this.replyElements.subtitleEl.innerHTML = subtitle ? RichTextProcessor.wrapEmojiText(subtitle) : '';
+ if(this.replyElements.container.lastElementChild.tagName == 'DIV') {
+ this.replyElements.container.lastElementChild.remove();
+ this.replyElements.container.append(wrapReply(title, subtitle, media));
+ }
+ //this.replyElements.titleEl.innerHTML = title ? RichTextProcessor.wrapEmojiText(title) : '';
+ //this.replyElements.subtitleEl.innerHTML = subtitle ? RichTextProcessor.wrapEmojiText(subtitle) : '';
this.replyElements.container.classList.add('active');
if(input !== undefined) {
@@ -796,7 +800,7 @@ export class AppImManager {
let isReplyClick = false;
try {
- isReplyClick = !!findUpClassName(e.target, 'box');
+ isReplyClick = !!findUpClassName(e.target, 'reply');
} catch(err) {}
if(isReplyClick && bubble.classList.contains('is-reply')/* || bubble.classList.contains('forwarded') */) {
@@ -1000,14 +1004,14 @@ export class AppImManager {
this.contextMenu.querySelector('.menu-reply').addEventListener('click', () => {
let message = appMessagesManager.getMessage(this.contextMenuMsgID);
- this.chatInputC.setTopInfo(appPeersManager.getPeerTitle(message.fromID, true), message.message);
+ this.chatInputC.setTopInfo(appPeersManager.getPeerTitle(message.fromID, true), message.message, undefined, message.media);
this.chatInputC.replyToMsgID = this.contextMenuMsgID;
this.chatInputC.editMsgID = 0;
});
this.contextMenuEdit.addEventListener('click', () => {
let message = appMessagesManager.getMessage(this.contextMenuMsgID);
- this.chatInputC.setTopInfo('Editing', message.message, message.message);
+ this.chatInputC.setTopInfo('Editing', message.message, message.message, message.media);
this.chatInputC.replyToMsgID = 0;
this.chatInputC.editMsgID = this.contextMenuMsgID;
});
@@ -1563,7 +1567,7 @@ export class AppImManager {
if(this.peerID == peerID) {
this.setPeerPromise = null;
}
-
+
this.log.error('setPeer promises error:', err);
return false;
});
@@ -1992,20 +1996,8 @@ export class AppImManager {
}
} else {
if(message.reply_to_mid) {
- let box = document.createElement('div');
- box.classList.add('box');
-
- let quote = document.createElement('div');
- quote.classList.add('quote');
-
- let nameEl = document.createElement('a');
- nameEl.classList.add('name');
-
- let textDiv = document.createElement('div');
- textDiv.classList.add('text');
-
let originalMessage = appMessagesManager.getMessage(message.reply_to_mid);
- let originalPeerTitle = appPeersManager.getPeerTitle(originalMessage.fromID) || '';
+ let originalPeerTitle = appPeersManager.getPeerTitle(originalMessage.fromID, true) || '';
this.log('message to render reply', originalMessage, originalPeerTitle, bubble, message);
@@ -2018,54 +2010,16 @@ export class AppImManager {
originalPeerTitle = 'Loading...';
}
- let originalText = '';
- if(originalMessage.message) {
- originalText = RichTextProcessor.wrapRichText(originalMessage.message, {
- entities: originalMessage.totalEntities,
- noLinebreaks: true
- });
- }
-
- if(originalMessage.media) {
- switch(originalMessage.media._) {
- case 'messageMediaPhoto':
- if(!originalText) originalText = 'Photo';
- break;
-
- default:
- if(!originalText) originalText = originalMessage.media._;
- break;
- }
- }
-
- nameEl.innerHTML = originalPeerTitle;
- textDiv.innerHTML = originalText;
-
- quote.append(nameEl, textDiv);
- box.append(quote);
-
if(originalMessage.mid) {
bubble.setAttribute('data-original-mid', originalMessage.mid);
} else {
bubble.setAttribute('data-original-mid', message.reply_to_mid);
}
- bubble.append(box);
+ bubble.append(wrapReply(originalPeerTitle, originalMessage.message || '', originalMessage.media));
bubble.classList.add('is-reply');
}
- /* if(message.media) {
- switch(message.media._) {
- case 'messageMediaWebPage': {
- let nameDiv = document.createElement('div');
- nameDiv.classList.add('name');
- nameDiv.innerText = title;
- bubble.append(nameDiv);
- break;
- }
- }
- } */
-
if(!bubble.classList.contains('sticker') && (peerID < 0 && peerID != message.fromID)) {
let nameDiv = document.createElement('div');
nameDiv.classList.add('name');
diff --git a/src/scss/partials/_chat.scss b/src/scss/partials/_chat.scss
index 349dacc5..d7b6dea3 100644
--- a/src/scss/partials/_chat.scss
+++ b/src/scss/partials/_chat.scss
@@ -250,6 +250,14 @@
opacity: 1;
}
}
+
+ .reply {
+ width: auto;
+
+ .reply-content {
+ height: auto;
+ }
+ }
&.photo, &.video {
width: min-content;
@@ -426,7 +434,7 @@
}
}
- .box {
+ .box, .reply {
font-size: .95rem;
// margin: .25rem;
margin: 4px 4px 4px 6px;
@@ -498,43 +506,45 @@
max-width: 100%;
overflow: hidden;
width: 100%;
+ }
- .text {
- line-height: 1.2;
- }
-
+ .text, .reply-subtitle {
+ line-height: 1.2;
}
- .name {
+ .name, .reply-title {
font-weight: 500;
display: inline!important;
}
-
- &:not(.web) {
- margin-bottom: 0;
- margin-top: 0;
- cursor: pointer;
- }
+ }
+
+ .reply {
+ margin-bottom: 6px;
+ margin-top: 0;
+ cursor: pointer;
}
&.is-reply {
&.emoji-big, &.sticker {
- .box {
+ .reply {
padding: 10px;
border-radius: 12px;
border: 1px solid #ccc;
max-width: 300px;
+ height: 54px;
+ max-height: 54px;
white-space: nowrap;
position: absolute;
top: 0;
+ margin-bottom: 0;
- .quote {
+ .reply-content {
margin-top: 0;
}
}
}
- .quote .text {
+ .reply-content {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
@@ -688,12 +698,12 @@
}
}
- &.hide-name .message:not(.message-empty) {
+ &.hide-name:not(.is-reply) .message:not(.message-empty) {
//padding-top: .2675rem;
padding-top: 6px;
}
- &.hide-name:not(.sticker):not(.emoji-big) .box:not(.web) .quote {
+ &.hide-name:not(.sticker):not(.emoji-big) .reply {
margin-top: 6px;
}
@@ -726,13 +736,13 @@
color: $darkblue;
}
- .quote:hover {
+ .quote:hover, .reply:hover {
background-color: $light;
}
.bubble.is-reply {
&.emoji-big, &.sticker {
- .box {
+ .box, .reply {
left: calc(100% + 10px);
background-color: #fff;
}
@@ -741,17 +751,16 @@
.quote {
border-left: 2px $darkblue solid;
- //margin-top: 6px; //MOJET VREMENNO
-
- .name {
- color: $darkblue;
- }
* {
overflow: hidden;
text-overflow: ellipsis;
}
}
+
+ .quote .name, .reply-title {
+ color: $darkblue;
+ }
.time {
color: #a3adb6;
@@ -798,13 +807,13 @@
.out {
align-items: flex-end;
- .quote:hover {
+ .quote:hover, .reply:hover {
background-color: rgba($green, 0.12);
}
.bubble.is-reply {
&.emoji-big, &.sticker {
- .box {
+ .box, .reply {
background-color: #eeffde;
right: calc(100% + 10px);
border-color: rgba($green, .12);
@@ -814,10 +823,14 @@
.quote {
border-left: 2px $darkgreen solid;
-
- .name {
- color: $darkgreen;
- }
+ }
+
+ .reply-border {
+ background-color: $darkgreen;
+ }
+
+ .quote .name, .reply-title {
+ color: $darkgreen;
}
.time {
@@ -920,7 +933,7 @@
}
&-toggle, &-download {
- background-color: #68AB5A;
+ background-color: #4FAE4E;
}
}
}
@@ -1089,7 +1102,14 @@
width: 187px;
margin-right: 1rem;
max-height: 35px;
+ position: relative;
/* padding: .25rem; */
+
+ &.is-reply-media {
+ .pinned-message-content, .reply-content {
+ padding-left: 40px;
+ }
+ }
&:hover {
background-color: rgba(112, 117, 121, 0.08);
@@ -1108,6 +1128,10 @@
flex-shrink: 1;
overflow: hidden;
pointer-events: none;
+ position: relative;
+ height: 32px;
+ display: flex;
+ flex-direction: column;
}
&-title {
@@ -1127,6 +1151,19 @@
color: #111;
}
+ &-media {
+ height: 32px;
+ width: 32px;
+ border-radius: 8px;
+ overflow: hidden;
+ position: absolute;
+ left: 0;
+ top: 0;
+ background-repeat: no-repeat;
+ background-size: cover;
+ background-position: center center;
+ }
+
img.emoji {
height: 16px;
width: 16px;
diff --git a/src/scss/style.scss b/src/scss/style.scss
index 919d79ed..e85e72c5 100644
--- a/src/scss/style.scss
+++ b/src/scss/style.scss
@@ -479,14 +479,14 @@ input {
.audio {
position: relative;
padding-left: 67px;
- min-height: 54px;
+ min-height: 58px;
max-width: 286px;
overflow: visible!important;
&-toggle, &-download {
border-radius: 50%;
background-color: $blue;
- font-size: 2.5rem;
+ font-size: 2.2rem;
align-items: center;
}
@@ -512,7 +512,7 @@ input {
&-time {
font-size: 14px;
color: $color-gray;
- margin-top: 4px;
+ margin-top: 3px;
margin-left: -1px;
}
}
@@ -1317,10 +1317,12 @@ div.scrollable::-webkit-scrollbar-thumb {
&.scrollable-x {
overflow-x: auto;
+ scrollbar-width: none;
}
&.scrollable-y {
overflow-y: auto;
+ scrollbar-width: none;
}
&.scrollable-x ~ .scrollbar-thumb {