Increment channel post views
Add missing comment translations
This commit is contained in:
parent
4d9793efb7
commit
552611ce6c
@ -71,6 +71,8 @@ import whichChild from "../../helpers/dom/whichChild";
|
||||
import { cancelAnimationByKey } from "../../helpers/animation";
|
||||
import assumeType from "../../helpers/assumeType";
|
||||
import { EmoticonsDropdown } from "../emoticonsDropdown";
|
||||
import debounce from "../../helpers/schedulers/debounce";
|
||||
import { formatNumber } from "../../helpers/number";
|
||||
|
||||
const USE_MEDIA_TAILS = false;
|
||||
const IGNORE_ACTIONS: Set<Message.messageService['action']['_']> = new Set([
|
||||
@ -162,6 +164,10 @@ export default class ChatBubbles {
|
||||
private resolveLadderAnimation: () => Promise<any>;
|
||||
private emptyPlaceholderMid: number;
|
||||
|
||||
private viewsObserver: IntersectionObserver;
|
||||
private viewsMids: Set<number> = new Set();
|
||||
private sendViewCountersDebounced: () => Promise<void>;
|
||||
|
||||
constructor(private chat: Chat,
|
||||
private appMessagesManager: AppMessagesManager,
|
||||
private appStickersManager: AppStickersManager,
|
||||
@ -580,6 +586,27 @@ export default class ChatBubbles {
|
||||
}
|
||||
});
|
||||
|
||||
this.listenerSetter.add(rootScope)('message_views', (e) => {
|
||||
if(this.peerId !== e.peerId) return;
|
||||
|
||||
fastRaf(() => {
|
||||
const bubble = this.bubbles[e.mid];
|
||||
if(!bubble) return;
|
||||
|
||||
const postViewsElements = Array.from(bubble.querySelectorAll('.post-views')) as HTMLElement[];
|
||||
if(postViewsElements.length) {
|
||||
const str = formatNumber(e.views, 1);
|
||||
let different = false;
|
||||
postViewsElements.forEach(postViews => {
|
||||
if(different || postViews.innerHTML !== str) {
|
||||
different = true;
|
||||
postViews.innerHTML = str;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.unreadedObserver = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if(entry.isIntersecting) {
|
||||
@ -590,6 +617,23 @@ export default class ChatBubbles {
|
||||
});
|
||||
});
|
||||
|
||||
this.viewsObserver = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if(entry.isIntersecting) {
|
||||
this.viewsMids.add(+(entry.target as HTMLElement).dataset.mid);
|
||||
this.viewsObserver.unobserve(entry.target);
|
||||
this.sendViewCountersDebounced();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.sendViewCountersDebounced = debounce(() => {
|
||||
const mids = [...this.viewsMids];
|
||||
this.viewsMids.clear();
|
||||
|
||||
this.appMessagesManager.incrementMessageViews(this.peerId, mids);
|
||||
}, 1000, false, true);
|
||||
|
||||
if('ResizeObserver' in window) {
|
||||
let wasHeight = this.scrollable.container.offsetHeight;
|
||||
let resizing = false;
|
||||
@ -1291,6 +1335,10 @@ export default class ChatBubbles {
|
||||
this.unreadedObserver.unobserve(bubble);
|
||||
this.unreaded.delete(bubble);
|
||||
}
|
||||
if(this.viewsObserver) {
|
||||
this.viewsObserver.unobserve(bubble);
|
||||
this.viewsMids.delete(mid);
|
||||
}
|
||||
//this.unreaded.findAndSplice(mid => mid === id);
|
||||
bubble.remove();
|
||||
//bubble.remove();
|
||||
@ -1515,10 +1563,12 @@ export default class ChatBubbles {
|
||||
|
||||
this.lazyLoadQueue.clear();
|
||||
this.unreadedObserver && this.unreadedObserver.disconnect();
|
||||
this.viewsObserver && this.viewsObserver.disconnect();
|
||||
this.stickyIntersector && this.stickyIntersector.disconnect();
|
||||
|
||||
delete this.lazyLoadQueue;
|
||||
this.unreadedObserver && delete this.unreadedObserver;
|
||||
this.viewsObserver && delete this.viewsObserver;
|
||||
this.stickyIntersector && delete this.stickyIntersector;
|
||||
}
|
||||
|
||||
@ -1569,6 +1619,11 @@ export default class ChatBubbles {
|
||||
this.unreadedSeen.clear();
|
||||
this.readPromise = undefined;
|
||||
}
|
||||
|
||||
if(this.viewsObserver) {
|
||||
this.viewsObserver.disconnect();
|
||||
this.viewsMids.clear();
|
||||
}
|
||||
|
||||
this.loadedTopTimes = this.loadedBottomTimes = 0;
|
||||
|
||||
@ -2012,7 +2067,11 @@ export default class ChatBubbles {
|
||||
}
|
||||
}
|
||||
|
||||
this.bubbleGroups.addBubble(bubble, message, reverse);
|
||||
if(message._ === 'message') {
|
||||
this.bubbleGroups.addBubble(bubble, message, reverse);
|
||||
} else {
|
||||
bubble.classList.add('is-group-first', 'is-group-last');
|
||||
}
|
||||
}
|
||||
|
||||
public getMiddleware() {
|
||||
@ -2227,6 +2286,10 @@ export default class ChatBubbles {
|
||||
bubbleContainer.prepend(messageDiv);
|
||||
//bubble.prepend(timeSpan, messageDiv); // that's bad
|
||||
|
||||
if(message.views && !message.pFlags.is_outgoing && this.viewsObserver) {
|
||||
this.viewsObserver.observe(bubble);
|
||||
}
|
||||
|
||||
if(message.reply_markup && message.reply_markup._ === 'replyInlineMarkup' && message.reply_markup.rows && message.reply_markup.rows.length) {
|
||||
const rows = (message.reply_markup as ReplyMarkup.replyKeyboardMarkup).rows;
|
||||
|
||||
@ -2421,9 +2484,9 @@ export default class ChatBubbles {
|
||||
case 'messageMediaWebPage': {
|
||||
processingWebPage = true;
|
||||
|
||||
let webpage: WebPage.webPage | WebPage.webPageEmpty = messageMedia.webpage;
|
||||
let webpage: WebPage = messageMedia.webpage;
|
||||
////////this.log('messageMediaWebPage', webpage);
|
||||
if(webpage._ === 'webPageEmpty') {
|
||||
if(webpage._ !== 'webPage') {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2445,10 +2508,8 @@ export default class ChatBubbles {
|
||||
previewResizer.append(preview);
|
||||
}
|
||||
|
||||
let doc: any = null;
|
||||
if(webpage.document) {
|
||||
doc = webpage.document;
|
||||
|
||||
const doc = webpage.document as MyDocument;
|
||||
if(doc) {
|
||||
if(doc.type === 'gif' || doc.type === 'video') {
|
||||
//if(doc.size <= 20e6) {
|
||||
bubble.classList.add('video');
|
||||
|
@ -27,7 +27,7 @@ export namespace MessageRender {
|
||||
const postAuthor = message.post_author || message.fwd_from?.post_author;
|
||||
|
||||
bubble.classList.add('channel-post');
|
||||
time = formatNumber(message.views, 1) + ' <i class="tgico-channelviews time-icon"></i> ' + (postAuthor ? RichTextProcessor.wrapEmojiText(postAuthor) + ', ' : '') + time;
|
||||
time = '<span class="post-views">' + formatNumber(message.views, 1) + '</span> <i class="tgico-channelviews time-icon"></i> ' + (postAuthor ? RichTextProcessor.wrapEmojiText(postAuthor) + ', ' : '') + time;
|
||||
|
||||
if(!message.fwd_from?.saved_from_msg_id && chat.type !== 'pinned') {
|
||||
const forward = document.createElement('div');
|
||||
|
@ -12,6 +12,8 @@ import appPeersManager from "../../lib/appManagers/appPeersManager";
|
||||
import rootScope from "../../lib/rootScope";
|
||||
import { ripple } from "../ripple";
|
||||
import AvatarElement from "../avatar";
|
||||
import { i18n } from "../../lib/langPack";
|
||||
import replaceContent from "../../helpers/dom/replaceContent";
|
||||
|
||||
const TAG_NAME = 'replies-element';
|
||||
|
||||
@ -103,15 +105,15 @@ export default class RepliesElement extends HTMLElement {
|
||||
this.append(leftPart);
|
||||
}
|
||||
|
||||
let text: string;
|
||||
let text: HTMLElement;
|
||||
if(replies) {
|
||||
if(replies.replies) {
|
||||
text = replies.replies + ' ' + (replies.replies > 1 ? 'Comments' : 'Comment');
|
||||
text = i18n('Comments', [replies.replies]);
|
||||
} else {
|
||||
text = 'Leave a Comment';
|
||||
text = i18n('LeaveAComment');
|
||||
}
|
||||
} else {
|
||||
text = 'View in chat';
|
||||
text = i18n('ViewInChat');
|
||||
}
|
||||
|
||||
if(replies) {
|
||||
@ -141,7 +143,7 @@ export default class RepliesElement extends HTMLElement {
|
||||
this.append(textSpan, iconSpan, rippleContainer);
|
||||
}
|
||||
|
||||
textSpan.innerHTML = text;
|
||||
replaceContent(textSpan, text);
|
||||
} else {
|
||||
this.classList.add('bubble-beside-button');
|
||||
this.innerHTML = `<span class="tgico-commentssticker"></span><span class="replies-beside-text">${replies?.replies ? formatNumber(replies.replies, 0) : ''}</span>`;
|
||||
|
@ -183,6 +183,7 @@ const lang = {
|
||||
"ChannelMegaJoined": "You joined this group",
|
||||
"Channel.DescriptionPlaceholder": "Description (optional)",
|
||||
"DescriptionPlaceholder": "Description",
|
||||
"DiscussionStarted": "Discussion started",
|
||||
"Draft": "Draft",
|
||||
"FilterAlwaysShow": "Include Chats",
|
||||
"FilterNeverShow": "Exclude Chats",
|
||||
@ -211,6 +212,10 @@ const lang = {
|
||||
"one_value": "%1$d channel",
|
||||
"other_value": "%1$d channels"
|
||||
},
|
||||
"Comments": {
|
||||
"one_value": "%1$d Comment",
|
||||
"other_value": "%1$d Comments"
|
||||
},
|
||||
"Groups": {
|
||||
"one_value": "%1$d group",
|
||||
"other_value": "%1$d groups"
|
||||
@ -544,6 +549,8 @@ const lang = {
|
||||
"Send": "Send",
|
||||
"ChannelJoin": "JOIN",
|
||||
"Yesterday": "yesterday",
|
||||
"LeaveAComment": "Leave a comment",
|
||||
"ViewInChat": "View in chat",
|
||||
|
||||
// * macos
|
||||
"AccountSettings.Filters": "Chat Folders",
|
||||
|
7
src/layer.d.ts
vendored
7
src/layer.d.ts
vendored
@ -996,7 +996,7 @@ export namespace MessageMedia {
|
||||
/**
|
||||
* @link https://core.telegram.org/type/MessageAction
|
||||
*/
|
||||
export type MessageAction = MessageAction.messageActionEmpty | MessageAction.messageActionChatCreate | MessageAction.messageActionChatEditTitle | MessageAction.messageActionChatEditPhoto | MessageAction.messageActionChatDeletePhoto | MessageAction.messageActionChatAddUser | MessageAction.messageActionChatDeleteUser | MessageAction.messageActionChatJoinedByLink | MessageAction.messageActionChannelCreate | MessageAction.messageActionChatMigrateTo | MessageAction.messageActionChannelMigrateFrom | MessageAction.messageActionPinMessage | MessageAction.messageActionHistoryClear | MessageAction.messageActionGameScore | MessageAction.messageActionPaymentSentMe | MessageAction.messageActionPaymentSent | MessageAction.messageActionPhoneCall | MessageAction.messageActionScreenshotTaken | MessageAction.messageActionCustomAction | MessageAction.messageActionBotAllowed | MessageAction.messageActionSecureValuesSentMe | MessageAction.messageActionSecureValuesSent | MessageAction.messageActionContactSignUp | MessageAction.messageActionGeoProximityReached | MessageAction.messageActionGroupCall | MessageAction.messageActionInviteToGroupCall | MessageAction.messageActionSetMessagesTTL | MessageAction.messageActionGroupCallScheduled | MessageAction.messageActionChatLeave | MessageAction.messageActionChannelDeletePhoto | MessageAction.messageActionChannelEditTitle | MessageAction.messageActionChannelEditPhoto | MessageAction.messageActionChannelEditVideo | MessageAction.messageActionChatEditVideo | MessageAction.messageActionChatAddUsers | MessageAction.messageActionChatJoined | MessageAction.messageActionChatReturn | MessageAction.messageActionChatJoinedYou | MessageAction.messageActionChatReturnYou;
|
||||
export type MessageAction = MessageAction.messageActionEmpty | MessageAction.messageActionChatCreate | MessageAction.messageActionChatEditTitle | MessageAction.messageActionChatEditPhoto | MessageAction.messageActionChatDeletePhoto | MessageAction.messageActionChatAddUser | MessageAction.messageActionChatDeleteUser | MessageAction.messageActionChatJoinedByLink | MessageAction.messageActionChannelCreate | MessageAction.messageActionChatMigrateTo | MessageAction.messageActionChannelMigrateFrom | MessageAction.messageActionPinMessage | MessageAction.messageActionHistoryClear | MessageAction.messageActionGameScore | MessageAction.messageActionPaymentSentMe | MessageAction.messageActionPaymentSent | MessageAction.messageActionPhoneCall | MessageAction.messageActionScreenshotTaken | MessageAction.messageActionCustomAction | MessageAction.messageActionBotAllowed | MessageAction.messageActionSecureValuesSentMe | MessageAction.messageActionSecureValuesSent | MessageAction.messageActionContactSignUp | MessageAction.messageActionGeoProximityReached | MessageAction.messageActionGroupCall | MessageAction.messageActionInviteToGroupCall | MessageAction.messageActionSetMessagesTTL | MessageAction.messageActionGroupCallScheduled | MessageAction.messageActionDiscussionStarted | MessageAction.messageActionChatLeave | MessageAction.messageActionChannelDeletePhoto | MessageAction.messageActionChannelEditTitle | MessageAction.messageActionChannelEditPhoto | MessageAction.messageActionChannelEditVideo | MessageAction.messageActionChatEditVideo | MessageAction.messageActionChatAddUsers | MessageAction.messageActionChatJoined | MessageAction.messageActionChatReturn | MessageAction.messageActionChatJoinedYou | MessageAction.messageActionChatReturnYou;
|
||||
|
||||
export namespace MessageAction {
|
||||
export type messageActionEmpty = {
|
||||
@ -1156,6 +1156,10 @@ export namespace MessageAction {
|
||||
schedule_date: number
|
||||
};
|
||||
|
||||
export type messageActionDiscussionStarted = {
|
||||
_: 'messageActionDiscussionStarted'
|
||||
};
|
||||
|
||||
export type messageActionChatLeave = {
|
||||
_: 'messageActionChatLeave',
|
||||
user_id?: number
|
||||
@ -9822,6 +9826,7 @@ export interface ConstructorDeclMap {
|
||||
'messageEntityHighlight': MessageEntity.messageEntityHighlight,
|
||||
'messageEntityLinebreak': MessageEntity.messageEntityLinebreak,
|
||||
'messageEntityCaret': MessageEntity.messageEntityCaret,
|
||||
'messageActionDiscussionStarted': MessageAction.messageActionDiscussionStarted,
|
||||
'messageActionChatLeave': MessageAction.messageActionChatLeave,
|
||||
'messageActionChannelDeletePhoto': MessageAction.messageActionChannelDeletePhoto,
|
||||
'messageActionChannelEditTitle': MessageAction.messageActionChannelEditTitle,
|
||||
|
@ -120,9 +120,6 @@ type PendingAfterMsg = Partial<InvokeApiOptions & {
|
||||
}>;
|
||||
|
||||
export class AppMessagesManager {
|
||||
private static MESSAGE_ID_INCREMENT = 0x10000;
|
||||
private static MESSAGE_ID_OFFSET = 0xFFFFFFFF;
|
||||
|
||||
private messagesStorageByPeerId: {[peerId: string]: MessagesStorage};
|
||||
public groupedMessagesStorage: {[groupId: string]: MessagesStorage}; // will be used for albums
|
||||
private scheduledMessagesStorage: {[peerId: string]: MessagesStorage};
|
||||
@ -3463,8 +3460,7 @@ export class AppMessagesManager {
|
||||
from_id: {_: 'peerUser', user_id: 0}/* message.from_id */,
|
||||
peer_id: message.peer_id,
|
||||
action: {
|
||||
_: 'messageActionCustomAction',
|
||||
message: 'Discussion started'
|
||||
_: 'messageActionDiscussionStarted'
|
||||
},
|
||||
reply_to: this.generateReplyHeader(message.id)
|
||||
};
|
||||
@ -4280,12 +4276,12 @@ export class AppMessagesManager {
|
||||
|
||||
private onUpdateChannelMessageViews = (update: Update.updateChannelMessageViews) => {
|
||||
const views = update.views;
|
||||
//const mid = update.id;
|
||||
const peerId = -update.channel_id;
|
||||
const mid = appMessagesIdsManager.generateMessageId(update.id);
|
||||
const message = this.getMessageByPeer(-update.channel_id, mid);
|
||||
const message: Message.message = this.getMessageByPeer(peerId, mid);
|
||||
if(!message.deleted && message.views && message.views < views) {
|
||||
message.views = views;
|
||||
rootScope.dispatchEvent('message_views', {mid, views});
|
||||
rootScope.dispatchEvent('message_views', {peerId, mid, views});
|
||||
}
|
||||
};
|
||||
|
||||
@ -4627,6 +4623,36 @@ export class AppMessagesManager {
|
||||
});
|
||||
}
|
||||
|
||||
public incrementMessageViews(peerId: number, mids: number[]) {
|
||||
if(!mids.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
return apiManager.invokeApiSingle('messages.getMessagesViews', {
|
||||
peer: appPeersManager.getInputPeerById(peerId),
|
||||
id: mids.map(mid => appMessagesIdsManager.getServerMessageId(mid)),
|
||||
increment: true
|
||||
}).then(views => {
|
||||
const updates: Update[] = new Array(mids.length);
|
||||
const channelId = -peerId;
|
||||
for(let i = 0, length = mids.length; i < length; ++i) {
|
||||
updates[i] = {
|
||||
_: 'updateChannelMessageViews',
|
||||
channel_id: channelId,
|
||||
id: mids[i],
|
||||
views: views.views[i].views
|
||||
};
|
||||
}
|
||||
|
||||
apiUpdatesManager.processUpdateMessage({
|
||||
_: 'updates',
|
||||
updates,
|
||||
chats: views.chats,
|
||||
users: views.users
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private notifyAboutMessage(message: MyMessage, options: Partial<{
|
||||
fwdCount: number,
|
||||
peerTypeNotifySettings: PeerNotifySettings
|
||||
|
@ -41,6 +41,7 @@ export const langPack: {[actionType: string]: LangPackKey} = {
|
||||
"messageActionChannelEditVideo": "Chat.Service.Channel.UpdatedVideo",
|
||||
"messageActionChannelDeletePhoto": "Chat.Service.Channel.RemovedPhoto",
|
||||
"messageActionHistoryClear": "HistoryCleared",
|
||||
"messageActionDiscussionStarted": "DiscussionStarted",
|
||||
|
||||
"messageActionChannelMigrateFrom": "ActionMigrateFromGroup",
|
||||
|
||||
|
@ -57,7 +57,7 @@ export type BroadcastEvents = {
|
||||
//'history_request': void,
|
||||
|
||||
'message_edit': {storage: MessagesStorage, peerId: number, mid: number},
|
||||
'message_views': {mid: number, views: number},
|
||||
'message_views': {peerId: number, mid: number, views: number},
|
||||
'message_sent': {storage: MessagesStorage, tempId: number, tempMessage: any, mid: number},
|
||||
'messages_pending': void,
|
||||
'messages_read': void,
|
||||
|
@ -56,7 +56,8 @@
|
||||
{"name": "clear_history", "type": "boolean"},
|
||||
{"name": "pending", "type": "boolean"},
|
||||
{"name": "error", "type": "any"},
|
||||
{"name": "send", "type": "() => Promise<any>"}
|
||||
{"name": "send", "type": "() => Promise<any>"},
|
||||
{"name": "totalEntities", "type": "MessageEntity[]"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageService",
|
||||
@ -152,6 +153,10 @@
|
||||
"params": [
|
||||
{"name": "initials", "type": "string"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageActionDiscussionStarted",
|
||||
"params": [],
|
||||
"type": "MessageAction"
|
||||
}, {
|
||||
"predicate": "messageActionChatLeave",
|
||||
"params": [
|
||||
|
Loading…
Reference in New Issue
Block a user