Browse Source

fix reply unknown messages & reply sticker background & minor css fixes

master
Eduard Kuzmenko 5 years ago
parent
commit
b2ddf3dd0a
  1. 4
      src/components/wrappers.ts
  2. 7
      src/lib/appManagers/appDialogsManager.ts
  3. 199
      src/lib/appManagers/appImManager.ts
  4. 4
      src/lib/appManagers/appMessagesIDsManager.ts
  5. 39
      src/lib/appManagers/appMessagesManager.ts
  6. 2
      src/lib/utils.js
  7. 88
      src/scss/partials/_chat.scss
  8. 4
      src/scss/style.scss
  9. 2
      tsconfig.json

4
src/components/wrappers.ts

@ -54,7 +54,7 @@ export function wrapVideo(this: any, doc: MTDocument, container: HTMLDivElement, @@ -54,7 +54,7 @@ export function wrapVideo(this: any, doc: MTDocument, container: HTMLDivElement,
//container.classList.add('video');
let img = container.firstElementChild as HTMLImageElement || new Image();
img.setAttribute('message-id', '' + message.id);
img.setAttribute('message-id', '' + message.mid);
if(!container.contains(img)) {
container.append(img);
@ -93,7 +93,7 @@ export function wrapVideo(this: any, doc: MTDocument, container: HTMLDivElement, @@ -93,7 +93,7 @@ export function wrapVideo(this: any, doc: MTDocument, container: HTMLDivElement,
video.volume = 0;
} */
video.setAttribute('message-id', '' + message.id);
video.setAttribute('message-id', '' + message.mid);
let source = document.createElement('source');
//source.src = doc.url;

7
src/lib/appManagers/appDialogsManager.ts

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
import apiManager from "../mtproto/apiManager";
import apiFileManager from '../mtproto/apiFileManager';
import { $rootScope, findUpTag, isElementInViewport } from "../utils";
import { $rootScope, findUpTag, isElementInViewport, langPack } from "../utils";
import appImManager from "./appImManager";
import appPeersManager from './appPeersManager';
import appMessagesManager from "./appMessagesManager";
@ -315,6 +315,11 @@ export class AppDialogsManager { @@ -315,6 +315,11 @@ export class AppDialogsManager {
}
}
if(lastMessage.action) {
// @ts-ignore
lastMessageText = langPack[lastMessage.action._];
}
dom.lastMessageSpan.innerHTML = lastMessageText +
(lastMessage.message ? RichTextProcessor.wrapRichText(lastMessage.message.replace(/\n/g, ' '), {noLinebreakers: true}) : '');

199
src/lib/appManagers/appImManager.ts

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
import apiManager from '../mtproto/apiManager';
import { $rootScope, isElementInViewport, numberWithCommas, findUpClassName, formatNumber, placeCaretAtEnd, calcImageInBox, findUpTag, getRichValue, getRichValueWithCaret, getSelectedText } from "../utils";
import { $rootScope, isElementInViewport, numberWithCommas, findUpClassName, formatNumber, placeCaretAtEnd, calcImageInBox, findUpTag, getRichValue, getRichValueWithCaret, getSelectedText, langPack } from "../utils";
import appUsersManager from "./appUsersManager";
import appMessagesManager from "./appMessagesManager";
import appPeersManager from "./appPeersManager";
@ -259,6 +259,7 @@ class ChatInput { @@ -259,6 +259,7 @@ class ChatInput {
this.attachMediaPopUp.mediaContainer.innerHTML = '';
this.attachMediaPopUp.mediaContainer.style.width = '';
this.attachMediaPopUp.mediaContainer.style.height = '';
this.attachMediaPopUp.mediaContainer.classList.remove('is-document');
switch(willAttach) {
case 'media': {
@ -295,6 +296,7 @@ class ChatInput { @@ -295,6 +296,7 @@ class ChatInput {
this.attachMediaPopUp.titleEl.innerText = 'Send File';
this.attachMediaPopUp.mediaContainer.append(docDiv);
this.attachMediaPopUp.mediaContainer.classList.add('is-document');
this.attachMediaPopUp.container.classList.add('active');
break;
}
@ -465,6 +467,7 @@ export class AppImManager { @@ -465,6 +467,7 @@ export class AppImManager {
public dateMessages: {[timestamp: number]: { div: HTMLDivElement, firstTimestamp: number }} = {};
public unreaded: number[] = [];
public unreadOut: number[] = [];
public needUpdate: {replyMid: number, mid: number}[] = []; // if need wrapSingleMessage
public offline = false;
public updateStatusInterval = 0;
@ -628,19 +631,37 @@ export class AppImManager { @@ -628,19 +631,37 @@ export class AppImManager {
if(!bubble) return;
let message = appMessagesManager.getMessage(mid);
this.renderMessage(message, false, false, bubble);
this.renderMessage(message, false, false, bubble, false);
});
$rootScope.$on('messages_downloaded', (e: CustomEvent) => {
let mid = e.detail;
let mids: number[] = e.detail;
mids.forEach(mid => {
if(this.pinnedMsgID == mid) {
let message = appMessagesManager.getMessage(mid);
this.log('setting pinned message', message);
this.pinnedMessageContainer.dataset.mid = '' + mid;
this.pinnedMessageContainer.style.display = '';
this.pinnedMessageContent.innerHTML = RichTextProcessor.wrapEmojiText(message.message);
}
if(this.pinnedMsgID == mid) {
let message = appMessagesManager.getMessage(mid);
this.log('setting pinned message', message);
this.pinnedMessageContainer.setAttribute('data-mid', mid);
this.pinnedMessageContainer.style.display = '';
this.pinnedMessageContent.innerHTML = RichTextProcessor.wrapEmojiText(message.message);
}
let idx = this.needUpdate.findIndex(v => v.replyMid == mid);
if(idx !== -1) {
let {mid, replyMid} = this.needUpdate.splice(idx, 1)[0];
let bubble = this.bubbles[mid];
if(!bubble) return;
let message = appMessagesManager.getMessage(mid);
let repliedMessage = appMessagesManager.getMessage(replyMid);
if(repliedMessage.deleted) { // чтобы не пыталось бесконечно загрузить удалённое сообщение
delete message.reply_to_mid; // WARNING!
}
this.renderMessage(message, false, false, bubble, false);
}
});
});
$rootScope.$on('apiUpdate', (e: CustomEvent) => {
@ -1285,6 +1306,7 @@ export class AppImManager { @@ -1285,6 +1306,7 @@ export class AppImManager {
this.unreadOut = [];
this.loadMediaQueue = [];
this.loadingMedia = 0;
this.needUpdate.length = 0;
lottieLoader.checkAnimations(false, 'chat', true);
@ -1344,7 +1366,7 @@ export class AppImManager { @@ -1344,7 +1366,7 @@ export class AppImManager {
this.log('setPeer peerID:', this.peerID, dialog, lastMsgID);
appDialogsManager.loadDialogPhoto(this.avatarEl, this.peerID);
appDialogsManager.loadDialogPhoto(appSidebarRight.profileElements.avatar, this.peerID);
if(appDialogsManager.lastActiveListElement) {
if(!samePeer && appDialogsManager.lastActiveListElement) {
appDialogsManager.lastActiveListElement.classList.remove('active');
}
@ -1483,7 +1505,7 @@ export class AppImManager { @@ -1483,7 +1505,7 @@ export class AppImManager {
});
}
public renderMessage(message: any, reverse = false, multipleRender?: boolean, bubble: HTMLDivElement = null) {
public renderMessage(message: any, reverse = false, multipleRender?: boolean, bubble: HTMLDivElement = null, updatePosition = true) {
this.log('message to render:', message);
if(message.deleted) return;
@ -1844,6 +1866,16 @@ export class AppImManager { @@ -1844,6 +1866,16 @@ export class AppImManager {
this.log('message to render reply', originalMessage, originalPeerTitle, bubble, message);
// need to download separately
if(originalMessage._ == 'messageEmpty') {
this.log('message to render reply empty, need download');
if(appMessagesManager.wrapSingleMessage(message.reply_to_mid).loading) {
this.needUpdate.push({replyMid: message.reply_to_mid, mid: message.mid});
}
originalPeerTitle = 'Loading...';
}
let originalText = '';
if(originalMessage.message) {
originalText = RichTextProcessor.wrapRichText(originalMessage.message, {
@ -1871,6 +1903,8 @@ export class AppImManager { @@ -1871,6 +1903,8 @@ export class AppImManager {
if(originalMessage.mid) {
bubble.setAttribute('data-original-mid', originalMessage.mid);
} else {
bubble.setAttribute('data-original-mid', message.reply_to_mid);
}
bubble.append(box);
@ -1928,86 +1962,107 @@ export class AppImManager { @@ -1928,86 +1962,107 @@ export class AppImManager {
}
}
let type = our ? 'out' : 'in';
if(message._ == 'messageService') {
bubble.className = 'service';
let containerDiv = reverse ? this.firstContainerDiv : this.lastContainerDiv;
if(!containerDiv || !containerDiv.classList.contains(type)) {
/* if(containerDiv) {
if(reverse) this.chatInner.prepend(containerDiv);
else this.chatInner.append(containerDiv);
} */
let action = message.action;
containerDiv = document.createElement('div');
containerDiv.classList.add(type);
let title = appPeersManager.getPeerTitle(message.fromID);
let name = document.createElement('div');
name.classList.add('name');
name.dataset.peerID = message.fromID;
name.innerHTML = title;
if(!this.firstContainerDiv) this.firstContainerDiv = containerDiv;
// @ts-ignore
let str = name.outerHTML + ' ' + langPack[action._];
bubble.innerHTML = `<div class="service-msg">${str}</div>`;
}
if(reverse) this.firstContainerDiv = containerDiv;
else this.lastContainerDiv = containerDiv;
if(!multipleRender) {
this.scrollPosition.prepareFor(reverse ? 'up' : 'down'); // лагает из-за этого
}
if(reverse) {
if(!multipleRender) {
this.scrollPosition.prepareFor('up'); // лагает из-за этого
}
if(updatePosition) {
let type = our ? 'out' : 'in';
let containerDiv = reverse ? this.firstContainerDiv : this.lastContainerDiv;
if(!containerDiv || !containerDiv.classList.contains(type)) {
/* if(containerDiv) {
if(reverse) this.chatInner.prepend(containerDiv);
else this.chatInner.append(containerDiv);
} */
containerDiv.prepend(bubble);
this.chatInner.prepend(containerDiv);
} else {
if(!multipleRender) {
this.scrollPosition.prepareFor('down'); // лагает из-за этого
containerDiv = document.createElement('div');
containerDiv.classList.add(type);
if(!this.firstContainerDiv) this.firstContainerDiv = containerDiv;
if(reverse) this.firstContainerDiv = containerDiv;
else this.lastContainerDiv = containerDiv;
}
containerDiv.append(bubble);
this.chatInner.append(containerDiv);
}
if(reverse) {
/* if(!multipleRender) {
this.scrollPosition.prepareFor('up'); // лагает из-за этого
} */
/* if(bubble.classList.contains('webpage')) {
this.log('night running', bubble, bubble.scrollHeight);
} */
containerDiv.prepend(bubble);
this.chatInner.prepend(containerDiv);
} else {
/* if(!multipleRender) {
this.scrollPosition.prepareFor('down'); // лагает из-за этого
} */
//return //this.scrollPosition.restore();
containerDiv.append(bubble);
this.chatInner.append(containerDiv);
}
let justDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
let dateTimestamp = justDate.getTime();
if(!(dateTimestamp in this.dateMessages)) {
let str = '';
let justDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
let dateTimestamp = justDate.getTime();
if(!(dateTimestamp in this.dateMessages)) {
let str = '';
let today = new Date();
today.setHours(0);
today.setMinutes(0);
today.setSeconds(0);
let today = new Date();
today.setHours(0);
today.setMinutes(0);
today.setSeconds(0);
if(today < date) {
str = 'Today';
} else {
const months = ['January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December'];
str = justDate.getFullYear() == new Date().getFullYear() ?
months[justDate.getMonth()] + ' ' + justDate.getDate() :
justDate.toISOString().split('T')[0].split('-').reverse().join('.');
}
if(today < date) {
str = 'Today';
} else {
const months = ['January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December'];
str = justDate.getFullYear() == new Date().getFullYear() ?
months[justDate.getMonth()] + ' ' + justDate.getDate() :
justDate.toISOString().split('T')[0].split('-').reverse().join('.');
}
let div = document.createElement('div');
div.classList.add('service');
div.innerHTML = `<div class="service-msg">${str}</div>`;
this.log('need to render date message', dateTimestamp, str);
let div = document.createElement('div');
div.classList.add('service');
div.innerHTML = `<div class="service-msg">${str}</div>`;
this.log('need to render date message', dateTimestamp, str);
this.dateMessages[dateTimestamp] = {
div,
firstTimestamp: date.getTime()
};
this.dateMessages[dateTimestamp] = {
div,
firstTimestamp: date.getTime()
};
//this.chatInner.insertBefore(div, containerDiv);
containerDiv.insertBefore(div, bubble);
} else {
let dateMessage = this.dateMessages[dateTimestamp];
if(dateMessage.firstTimestamp > date.getTime()) {
//this.chatInner.insertBefore(dateMessage.div, containerDiv);
containerDiv.insertBefore(dateMessage.div, bubble);
//this.chatInner.insertBefore(div, containerDiv);
containerDiv.insertBefore(div, bubble);
} else {
let dateMessage = this.dateMessages[dateTimestamp];
if(dateMessage.firstTimestamp > date.getTime()) {
//this.chatInner.insertBefore(dateMessage.div, containerDiv);
containerDiv.insertBefore(dateMessage.div, bubble);
}
}
}
/* if(bubble.classList.contains('webpage')) {
this.log('night running', bubble, bubble.scrollHeight);
} */
//return //this.scrollPosition.restore();
if(!multipleRender) {
this.scrollPosition.restore(); // лагает из-за этого
}

4
src/lib/appManagers/appMessagesIDsManager.ts

@ -37,8 +37,8 @@ export class AppMessagesIDsManager { @@ -37,8 +37,8 @@ export class AppMessagesIDsManager {
}
public splitMessageIDsByChannels (mids: any[]) {
var msgIDsByChannels: any = {};
var midsByChannels: any = {};
var msgIDsByChannels: {[channelID: number]: number[]} = {};
var midsByChannels: {[channelID: number]: number[]} = {};
var i;
var mid, msgChannel;
var channelID;

39
src/lib/appManagers/appMessagesManager.ts

@ -3206,7 +3206,7 @@ export class AppMessagesManager { @@ -3206,7 +3206,7 @@ export class AppMessagesManager {
});
}
public wrapForDialog(msgID: number, dialog?: any) {
/* public wrapForDialog(msgID: number, dialog?: any) {
var useCache = msgID && dialog !== undefined;
var unreadCount = dialog && dialog.unread_count;
@ -3255,7 +3255,7 @@ export class AppMessagesManager { @@ -3255,7 +3255,7 @@ export class AppMessagesManager {
}
return message;
}
} */
public fetchSingleMessages() {
if(this.fetchSingleMessagesPromise) {
@ -3263,20 +3263,21 @@ export class AppMessagesManager { @@ -3263,20 +3263,21 @@ export class AppMessagesManager {
}
var mids = this.needSingleMessages.slice();
this.needSingleMessages = [];
this.needSingleMessages.length = 0;
var splitted = appMessagesIDsManager.splitMessageIDsByChannels(mids);
let promises: Promise<void>[] = [];
Object.keys(splitted.msgIDs).forEach((channelID: number | string) => {
let msgIDs = splitted.msgIDs[channelID].map((mid: number) => {
channelID = +channelID;
let msgIDs = splitted.msgIDs[channelID].map((msgID: number) => {
return {
_: 'inputMessageID',
id: mid
id: msgID
};
});
var promise;
channelID = +channelID;
if(channelID > 0) {
promise = apiManager.invokeApi('channels.getMessages', {
channel: appChatsManager.getChannelInput(channelID),
@ -3293,43 +3294,39 @@ export class AppMessagesManager { @@ -3293,43 +3294,39 @@ export class AppMessagesManager {
appChatsManager.saveApiChats(getMessagesResult.chats);
this.saveMessages(getMessagesResult.messages);
$rootScope.$broadcast('messages_downloaded', splitted.mids[channelID])
$rootScope.$broadcast('messages_downloaded', splitted.mids[+channelID]);
}));
});
return this.fetchSingleMessagesPromise = Promise.all(promises).then(() => {
this.fetchSingleMessagesTimeout = 0;
this.fetchSingleMessagesPromise = null;
if(this.needSingleMessages.length) this.fetchSingleMessages();
}).catch(() => {
this.fetchSingleMessagesTimeout = 0;
this.fetchSingleMessagesPromise = null;
if(this.needSingleMessages.length) this.fetchSingleMessages();
});
}
/* public wrapSingleMessage(msgID: number) {
public wrapSingleMessage(msgID: number) {
if(this.messagesStorage[msgID]) {
return this.wrapForDialog(msgID);
//let ret = this.wrapForDialog(msgID); // hm
$rootScope.$broadcast('messages_downloaded', [msgID]);
//return ret;
return {mid: msgID, loading: false};
}
if(this.needSingleMessages.indexOf(msgID) == -1) {
this.needSingleMessages.push(msgID);
if(this.fetchSingleMessagesTimeout == 0) {
this.fetchSingleMessagesTimeout = window.setTimeout(this.fetchSingleMessages.bind(this), 100);
this.fetchSingleMessagesTimeout = window.setTimeout(this.fetchSingleMessages.bind(this), 25);
}
}
return {mid: msgID, loading: true};
} */
public wrapSingleMessage(msgID: number) {
if(this.messagesStorage[msgID]) {
$rootScope.$broadcast('messages_downloaded', msgID);
return;
return {mid: msgID, loading: true};
}
if(this.needSingleMessages.indexOf(msgID) == -1) {
this.needSingleMessages.push(msgID);
this.fetchSingleMessages();
}
return {mid: msgID, loading: false};
}
}

2
src/lib/utils.js

@ -324,11 +324,11 @@ export const langPack = { @@ -324,11 +324,11 @@ export const langPack = {
"messageActionChatLeave": "left group",
"messageActionChatDeleteUser": "removed user",
"messageActionChatJoinedByLink": "joined the group",
"messageActionPinMessage": "pinned message",
"messageActionChannelCreate": "Channel created",
"messageActionChannelEditTitle": "Channel renamed",
"messageActionChannelEditPhoto": "Channel photo updated",
"messageActionChannelDeletePhoto": "Channel photo removed",
"messageActionPinMessage": "pinned message",
"messageActionPhoneCall.in_ok": "Incoming Call",
"messageActionPhoneCall.out_ok": "Outgoing Call",

88
src/scss/partials/_chat.scss

@ -178,9 +178,8 @@ @@ -178,9 +178,8 @@
}
.service {
justify-content: center;
align-self: center;
margin: 1rem 0;
align-self: center;
.service-msg {
color: #fff;
@ -190,6 +189,14 @@ @@ -190,6 +189,14 @@
font-size: 15px;
border-radius: 12px;
user-select: none;
display: flex;
align-items: center;
justify-content: center;
.name {
cursor: pointer;
margin-right: 5px;
}
}
}
@ -488,6 +495,20 @@ @@ -488,6 +495,20 @@
}
}
&.is-reply {
&.emoji-big, &.sticker {
.box {
padding: 10px;
border-radius: 12px;
border: 1px solid #ccc;
max-width: 300px;
white-space: nowrap;
position: absolute;
top: 0;
}
}
}
.message {
font-size: 16px;
//padding: 0 .6rem .2675rem .6rem;
@ -542,7 +563,7 @@ @@ -542,7 +563,7 @@
position: absolute;
bottom: 0;
right: 0;
font-size: .75rem;
font-size: 12px;
display: flex;
align-items: center;
line-height: 1;
@ -572,6 +593,20 @@ @@ -572,6 +593,20 @@
width: 90px;
}
.message.message-empty .time {
padding: 0;
display: flex;
align-items: center;
width: auto;
.inner {
margin-bottom: 0;
position: relative;
padding: 0 2.5px;
bottom: 0;
}
}
.user-avatar {
position: absolute;
left: -3rem;
@ -659,6 +694,15 @@ @@ -659,6 +694,15 @@
background-color: $light;
}
.bubble.is-reply {
&.emoji-big, &.sticker {
.box {
left: calc(100% + 10px);
background-color: #fff;
}
}
}
.quote {
border-left: 2px $darkblue solid;
@ -673,11 +717,11 @@ @@ -673,11 +717,11 @@
}
.time {
color: rgba($darkgrey, 0.6);
width: 2rem;
color: #a3adb6;
width: 36px;
.inner {
padding: 0 .35rem;
padding: 0 7px 0 5px;
margin-bottom: 4px;
}
}
@ -705,8 +749,8 @@ @@ -705,8 +749,8 @@
}
&.forwarded .attachment,
&.is-reply .attachment,
&:not(.hide-name):not(.sticker) .attachment {
&.is-reply .attachment/* ,
&:not(.hide-name):not(.sticker) .attachment */ {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
@ -724,6 +768,16 @@ @@ -724,6 +768,16 @@
background-color: rgba($green, 0.12);
}
.bubble.is-reply {
&.emoji-big, &.sticker {
.box {
background-color: #eeffde;
right: calc(100% + 10px);
border-color: rgba($green, .12);
}
}
}
.quote {
border-left: 2px $darkgreen solid;
@ -734,20 +788,20 @@ @@ -734,20 +788,20 @@
.time {
color: $darkgreen;
width: 48px;
width: 50px;
display: inline-block;
.inner {
padding: 0 .25rem;
padding: 0 4px 0 4px;
bottom: 1px;
}
}
.bubble {
.time .tgico:after {
font-size: 1.1rem;
font-size: 19px;
vertical-align: middle;
margin-left: .1rem;
margin-left: 1px;
}
}
@ -902,6 +956,12 @@ @@ -902,6 +956,12 @@
transform: scaleX(-1);
}
#attach-file {
&.menu-open {
color: $blue;
}
}
> div {
display: flex;
justify-content: space-between;
@ -950,7 +1010,7 @@ @@ -950,7 +1010,7 @@
color: $placeholder-color;
font-size: 1.5rem;
line-height: 1.5rem;
transition: .2s color;
flex: 0 0 auto;
&.active {
@ -1307,8 +1367,6 @@ @@ -1307,8 +1367,6 @@
.popup {
&.popup-delete-message {
.popup-header {
margin-bottom: 1rem;
}

4
src/scss/style.scss

@ -1385,6 +1385,10 @@ div.scrollable::-webkit-scrollbar-thumb { @@ -1385,6 +1385,10 @@ div.scrollable::-webkit-scrollbar-thumb {
margin: 0 auto;
/* align-items: center; */
&.is-document {
margin-left: 0;
}
.document {
max-width: 100%;
overflow: hidden;

2
tsconfig.json

@ -65,8 +65,8 @@ @@ -65,8 +65,8 @@
"node_modules",
"public",
"coverage",
"./src/lib/StackBlur.js",
"./src/lib/*.js",
"src/lib/StackBlur.js",
"./src/*.js",
"*.js",
]

Loading…
Cancel
Save