Added possibility to jump by pin service message
This commit is contained in:
parent
180d151ac9
commit
2ee82d7597
@ -1466,7 +1466,7 @@ export default class ChatBubbles {
|
||||
this.deleteEmptyDateGroups();
|
||||
}
|
||||
|
||||
public renderNewMessagesByIds(mids: number[], scrolledDown = this.scrolledDown) {
|
||||
public renderNewMessagesByIds(mids: number[], scrolledDown?: boolean) {
|
||||
if(!this.scrollable.loadedAll.bottom) { // seems search active or sliced
|
||||
//this.log('renderNewMessagesByIds: seems search is active, skipping render:', mids);
|
||||
return;
|
||||
@ -1487,19 +1487,29 @@ export default class ChatBubbles {
|
||||
} */
|
||||
|
||||
if(!scrolledDown) {
|
||||
if(this.scrollingToBubble && this.scrollingToBubble === this.getLastBubble()) {
|
||||
scrolledDown = true;
|
||||
}
|
||||
scrolledDown = this.scrolledDown && (!this.scrollingToBubble || this.scrollingToBubble === this.getLastBubble());
|
||||
}
|
||||
|
||||
const middleware = this.getMiddleware();
|
||||
let isPaddingNeeded = false;
|
||||
let setPaddingTo: HTMLElement;
|
||||
if(!this.isTopPaddingSet) {
|
||||
const {scrollHeight} = this.scrollable;
|
||||
const clientHeight = this.scrollable.container.clientHeight;
|
||||
const {clientHeight, scrollHeight} = this.scrollable.container;
|
||||
isPaddingNeeded = clientHeight === scrollHeight;
|
||||
/* const firstEl = this.chatInner.firstElementChild as HTMLElement;
|
||||
if(this.chatInner.firstElementChild) {
|
||||
const visibleRect = getVisibleRect(firstEl, this.scrollable.container);
|
||||
isPaddingNeeded = !visibleRect.overflow.top && (visibleRect.rect.top - firstEl.offsetTop) !== this.scrollable.container.getBoundingClientRect().top;
|
||||
} else {
|
||||
isPaddingNeeded = true;
|
||||
} */
|
||||
|
||||
if(isPaddingNeeded) {
|
||||
this.chatInner.style.paddingTop = clientHeight + 'px';
|
||||
/* const add = clientHeight - scrollHeight;
|
||||
this.chatInner.style.paddingTop = add + 'px';
|
||||
this.scrollable.scrollTop += add; */
|
||||
setPaddingTo = this.chatInner;
|
||||
setPaddingTo.style.paddingTop = clientHeight + 'px';
|
||||
this.scrollable.scrollTop = scrollHeight;
|
||||
this.isTopPaddingSet = true;
|
||||
}
|
||||
@ -1522,7 +1532,7 @@ export default class ChatBubbles {
|
||||
if(isPaddingNeeded) {
|
||||
promise.then(() => { // it will be called only once even if was set multiple times (that won't happen)
|
||||
if(middleware() && isPaddingNeeded) {
|
||||
this.chatInner.style.paddingTop = '';
|
||||
setPaddingTo.style.paddingTop = '';
|
||||
this.isTopPaddingSet = false;
|
||||
}
|
||||
});
|
||||
@ -3029,6 +3039,15 @@ export default class ChatBubbles {
|
||||
} else {
|
||||
title = new PeerTitle({peerId: message.viaBotId || message.fwdFromId || message.fromId}).element;
|
||||
}
|
||||
|
||||
if(message.reply_to_mid && message.reply_to_mid !== this.chat.threadId) {
|
||||
MessageRender.setReply({
|
||||
chat: this.chat,
|
||||
bubble,
|
||||
bubbleContainer,
|
||||
message
|
||||
});
|
||||
}
|
||||
|
||||
//this.log(title);
|
||||
|
||||
@ -3094,15 +3113,6 @@ export default class ChatBubbles {
|
||||
}
|
||||
}
|
||||
|
||||
if(message.reply_to_mid && message.reply_to_mid !== this.chat.threadId) {
|
||||
MessageRender.setReply({
|
||||
chat: this.chat,
|
||||
bubble,
|
||||
bubbleContainer,
|
||||
message
|
||||
});
|
||||
}
|
||||
|
||||
const needAvatar = this.chat.isAnyGroup() && !isOut;
|
||||
if(needAvatar) {
|
||||
let avatarElem = new AvatarElement();
|
||||
|
6
src/layer.d.ts
vendored
6
src/layer.d.ts
vendored
@ -869,7 +869,8 @@ export namespace Message {
|
||||
pending?: boolean,
|
||||
error?: any,
|
||||
send?: () => Promise<any>,
|
||||
totalEntities?: MessageEntity[]
|
||||
totalEntities?: MessageEntity[],
|
||||
reply_to_mid?: number
|
||||
};
|
||||
|
||||
export type messageService = {
|
||||
@ -902,7 +903,8 @@ export namespace Message {
|
||||
pending?: boolean,
|
||||
error?: any,
|
||||
send?: () => Promise<any>,
|
||||
random_id?: string
|
||||
random_id?: string,
|
||||
reply_to_mid?: number
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -2345,6 +2345,7 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
if(message._ === 'messageEmpty') {
|
||||
message.deleted = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2977,17 +2978,37 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
case 'messageActionPinMessage': {
|
||||
const pinnedMessage = this.getMessageByPeer(message.peerId, message.reply_to_mid);
|
||||
const peerId = message.peerId;
|
||||
const pinnedMessage = this.getMessageByPeer(peerId, message.reply_to_mid);
|
||||
|
||||
args = [
|
||||
getNameDivHTML(message.fromId, plain),
|
||||
];
|
||||
|
||||
if(pinnedMessage.deleted || true) {
|
||||
if(pinnedMessage.deleted/* || true */) {
|
||||
langPackKey = 'ActionPinnedNoText';
|
||||
|
||||
if(message.reply_to_mid) { // refresh original message
|
||||
this.fetchMessageReplyTo(message).then(originalMessage => {
|
||||
if(!originalMessage.deleted && !message.deleted) {
|
||||
rootScope.dispatchEvent('message_edit', {
|
||||
storage: this.getMessagesStorage(peerId),
|
||||
peerId: peerId,
|
||||
mid: message.mid
|
||||
});
|
||||
|
||||
if(this.isMessageIsTopMessage(message)) {
|
||||
rootScope.dispatchEvent('dialogs_multiupdate', {
|
||||
[peerId]: this.getDialogOnly(peerId)
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const a = document.createElement('a');
|
||||
const a = document.createElement('i');
|
||||
a.dataset.savedFrom = pinnedMessage.peerId + '_' + pinnedMessage.mid;
|
||||
a.dir = 'auto';
|
||||
a.append(this.wrapMessageForReply(pinnedMessage, undefined, undefined, plain as any));
|
||||
args.push(a);
|
||||
}
|
||||
@ -4836,12 +4857,16 @@ export class AppMessagesManager {
|
||||
};
|
||||
|
||||
public setDialogToStateIfMessageIsTop(message: MyMessage) {
|
||||
const dialog = this.getDialogOnly(message.peerId);
|
||||
if(dialog && dialog.top_message === message.mid) {
|
||||
this.dialogsStorage.setDialogToState(dialog);
|
||||
if(this.isMessageIsTopMessage(message)) {
|
||||
this.dialogsStorage.setDialogToState(this.getDialogOnly(message.peerId));
|
||||
}
|
||||
}
|
||||
|
||||
public isMessageIsTopMessage(message: MyMessage) {
|
||||
const dialog = this.getDialogOnly(message.peerId);
|
||||
return dialog && dialog.top_message === message.mid;
|
||||
}
|
||||
|
||||
private updateMessageRepliesIfNeeded(threadMessage: MyMessage) {
|
||||
try { // * на всякий случай, скорее всего это не понадобится
|
||||
const threadKey = this.getThreadKey(threadMessage);
|
||||
@ -5562,6 +5587,18 @@ export class AppMessagesManager {
|
||||
}
|
||||
}
|
||||
|
||||
public fetchMessageReplyTo(message: MyMessage): Promise<Message> {
|
||||
if(!message.reply_to_mid) return Promise.resolve(this.generateEmptyMessage(0));
|
||||
const replyToPeerId = message.reply_to.reply_to_peer_id ? appPeersManager.getPeerId(message.reply_to.reply_to_peer_id) : message.peerId;
|
||||
return this.wrapSingleMessage(replyToPeerId, message.reply_to_mid).then(originalMessage => {
|
||||
if(originalMessage.deleted) { // ! чтобы не пыталось бесконечно загрузить удалённое сообщение
|
||||
delete message.reply_to_mid; // ! WARNING!
|
||||
}
|
||||
|
||||
return originalMessage;
|
||||
});
|
||||
}
|
||||
|
||||
public setTyping(peerId: PeerId, action: SendMessageAction): Promise<boolean> {
|
||||
let typing = this.typings[peerId];
|
||||
if(!rootScope.myId ||
|
||||
|
@ -77,7 +77,8 @@
|
||||
{"name": "pending", "type": "boolean"},
|
||||
{"name": "error", "type": "any"},
|
||||
{"name": "send", "type": "() => Promise<any>"},
|
||||
{"name": "totalEntities", "type": "MessageEntity[]"}
|
||||
{"name": "totalEntities", "type": "MessageEntity[]"},
|
||||
{"name": "reply_to_mid", "type": "number"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageService",
|
||||
@ -94,7 +95,8 @@
|
||||
{"name": "pending", "type": "boolean"},
|
||||
{"name": "error", "type": "any"},
|
||||
{"name": "send", "type": "() => Promise<any>"},
|
||||
{"name": "random_id", "type": "string"}
|
||||
{"name": "random_id", "type": "string"},
|
||||
{"name": "reply_to_mid", "type": "number"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageEmpty",
|
||||
|
@ -1018,8 +1018,6 @@ $chat-helper-size: 36px;
|
||||
.bubbles {
|
||||
--translateY: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-height: 100%;
|
||||
flex: 1 1 auto;
|
||||
position: relative;
|
||||
|
||||
@ -1145,9 +1143,7 @@ $chat-helper-size: 36px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 1;
|
||||
margin: 0 auto;
|
||||
box-sizing: border-box;
|
||||
min-height: 100%;
|
||||
justify-content: flex-end;
|
||||
padding: 0 $chat-padding;
|
||||
|
@ -792,9 +792,12 @@ $bubble-beside-button-width: 38px;
|
||||
order: -1;
|
||||
margin-top: .5rem;
|
||||
justify-content: center;
|
||||
flex: 1 1 auto;
|
||||
align-items: center;
|
||||
max-width: 100%;
|
||||
|
||||
@include animation-level(0) {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.bubble-content-wrapper {
|
||||
max-width: 100%;
|
||||
@ -1040,7 +1043,8 @@ $bubble-beside-button-width: 38px;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.just-media):not(.is-message-empty) .reply {
|
||||
// &:not(.just-media):not(.is-message-empty) .reply {
|
||||
.message + .reply {
|
||||
// margin-bottom: .125rem; // ! JS2 mockup
|
||||
margin-bottom: 0; // ! same margin as between name and message
|
||||
}
|
||||
@ -1293,7 +1297,8 @@ $bubble-beside-button-width: 38px;
|
||||
left: -75vw;
|
||||
}
|
||||
|
||||
&.is-highlighted, &.is-selected {
|
||||
&.is-highlighted,
|
||||
&.is-selected {
|
||||
.document-wrapper {
|
||||
&:before {
|
||||
content: " ";
|
||||
@ -1314,7 +1319,8 @@ $bubble-beside-button-width: 38px;
|
||||
}
|
||||
|
||||
body:not(.animation-level-0) & {
|
||||
.document-selection, .document-wrapper:before {
|
||||
.document-selection,
|
||||
.document-wrapper:before {
|
||||
animation: bubbleSelected 2s linear;
|
||||
}
|
||||
}
|
||||
@ -1326,12 +1332,14 @@ $bubble-beside-button-width: 38px;
|
||||
}
|
||||
|
||||
body:not(.animation-level-0) & {
|
||||
.document-selection, .document-wrapper:before {
|
||||
.document-selection,
|
||||
.document-wrapper:before {
|
||||
animation: fade-in-opacity .2s linear forwards;
|
||||
}
|
||||
|
||||
&.backwards {
|
||||
.document-selection, .document-wrapper:before {
|
||||
.document-selection,
|
||||
.document-wrapper:before {
|
||||
animation: fade-in-backwards-opacity .2s linear forwards;
|
||||
}
|
||||
}
|
||||
@ -1417,8 +1425,9 @@ $bubble-beside-button-width: 38px;
|
||||
padding: .25rem .5rem;
|
||||
|
||||
> .name {
|
||||
// padding: .0625rem 0 .375rem;
|
||||
padding: 0 0 .25rem 0;
|
||||
margin-top: -.25rem;
|
||||
margin-top: -.1875rem;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1649,7 +1658,7 @@ $bubble-beside-button-width: 38px;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
order: 1;
|
||||
// order: 1;
|
||||
//width: max-content;
|
||||
//white-space: nowrap;
|
||||
}
|
||||
@ -1933,6 +1942,11 @@ $bubble-beside-button-width: 38px;
|
||||
.bubble-content {
|
||||
background-color: transparent;
|
||||
border-radius: .875rem;
|
||||
|
||||
&-wrapper {
|
||||
max-width: 100%;
|
||||
padding: 0 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.service-msg {
|
||||
@ -1960,7 +1974,8 @@ $bubble-beside-button-width: 38px;
|
||||
}
|
||||
|
||||
a,
|
||||
.peer-title {
|
||||
.peer-title,
|
||||
[data-saved-from] {
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
@ -2019,7 +2034,8 @@ $bubble-beside-button-width: 38px;
|
||||
}
|
||||
|
||||
&.just-media {
|
||||
.reply, .name {
|
||||
.reply,
|
||||
.name {
|
||||
left: calc(100% + 10px);
|
||||
|
||||
@include respond-to(handhelds) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user