Browse Source

Refactor message's rReply

Actions in chatlist
master
Eduard Kuzmenko 3 years ago
parent
commit
445e6d8ece
  1. 6
      src/components/appMediaViewer.ts
  2. 7
      src/components/appMediaViewerNew.ts
  3. 5
      src/components/chat/bubbles.ts
  4. 20
      src/components/chat/input.ts
  5. 11
      src/components/chat/replyContainer.ts
  6. 3
      src/components/sidebarRight/tabs/stickers.ts
  7. 2
      src/config/app.ts
  8. 12
      src/helpers/array.ts
  9. 7
      src/helpers/dom.ts
  10. 5
      src/lang.ts
  11. 67
      src/layer.d.ts
  12. 33
      src/lib/appManagers/appDialogsManager.ts
  13. 2
      src/lib/appManagers/appDraftsManager.ts
  14. 268
      src/lib/appManagers/appMessagesManager.ts
  15. 10
      src/lib/appManagers/appStateManager.ts
  16. 3
      src/lib/appManagers/appStickersManager.ts
  17. 10
      src/lib/langPack.ts
  18. 3
      src/lib/mtproto/networker.ts
  19. 8
      src/lib/polyfill.ts
  20. 6
      src/lib/rootScope.ts
  21. 5
      src/lib/storages/filters.ts
  22. 64
      src/scripts/in/schema_additional_params.json
  23. 7
      src/scss/partials/_chatlist.scss

6
src/components/appMediaViewer.ts

@ -29,6 +29,8 @@ import { months, ONE_DAY } from "../helpers/date"; @@ -29,6 +29,8 @@ import { months, ONE_DAY } from "../helpers/date";
import { SearchSuperContext } from "./appSearchSuper.";
import DEBUG from "../config/debug";
import appNavigationController from "./appNavigationController";
import { Message } from "../layer";
import { forEachReverse } from "../helpers/array";
// TODO: масштабирование картинок (не SVG) при ресайзе, и правильный возврат на исходную позицию
// TODO: картинки "обрезаются" если возвращаются или появляются с места, где есть их перекрытие (топбар, поле ввода)
@ -1338,8 +1340,8 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet @@ -1338,8 +1340,8 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet
//}
}
const method = older ? value.history.forEach : value.history.forEachReverse;
method.call(value.history, message => {
const method: any = older ? value.history.forEach.bind(value.history) : forEachReverse.bind(null, value.history);
method((message: Message.message) => {
const {mid, peerId} = message;
const media = this.getMediaFromMessage(message);

7
src/components/appMediaViewerNew.ts

@ -27,7 +27,8 @@ import appSidebarRight, { AppSidebarRight } from "./sidebarRight"; @@ -27,7 +27,8 @@ import appSidebarRight, { AppSidebarRight } from "./sidebarRight";
import SwipeHandler from "./swipeHandler";
import { months, ONE_DAY } from "../helpers/date";
import { SearchSuperContext } from "./appSearchSuper.";
import { PhotoSize } from "../layer";
import { Message, PhotoSize } from "../layer";
import { forEachReverse } from "../helpers/array";
// TODO: масштабирование картинок (не SVG) при ресайзе, и правильный возврат на исходную позицию
// TODO: картинки "обрезаются" если возвращаются или появляются с места, где есть их перекрытие (топбар, поле ввода)
@ -1241,8 +1242,8 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet @@ -1241,8 +1242,8 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet
//}
}
const method = older ? value.history.forEach : value.history.forEachReverse;
method.call(value.history, message => {
const method: any = older ? value.history.forEach.bind(value.history) : forEachReverse.bind(null, value.history);
method((message: Message.message) => {
const {mid, peerId} = message;
const media = this.getMediaFromMessage(message);

5
src/components/chat/bubbles.ts

@ -48,6 +48,7 @@ import DEBUG from "../../config/debug"; @@ -48,6 +48,7 @@ import DEBUG from "../../config/debug";
import { SliceEnd } from "../../helpers/slicedArray";
import serverTimeManager from "../../lib/mtproto/serverTimeManager";
import PeerTitle from "../peerTitle";
import { forEachReverse } from "../../helpers/array";
const USE_MEDIA_TAILS = false;
const IGNORE_ACTIONS: Message.messageService['action']['_'][] = [/* 'messageActionHistoryClear' */];
@ -341,7 +342,7 @@ export default class ChatBubbles { @@ -341,7 +342,7 @@ export default class ChatBubbles {
promise.then(() => {
}); */
this.needUpdate.forEachReverse((obj, idx) => {
forEachReverse(this.needUpdate, (obj, idx) => {
if(obj.replyMid === mid && obj.replyToPeerId === peerId) {
const {mid, replyMid} = this.needUpdate.splice(idx, 1)[0];
@ -888,7 +889,7 @@ export default class ChatBubbles { @@ -888,7 +889,7 @@ export default class ChatBubbles {
public onGoDownClick() {
if(this.replyFollowHistory.length) {
this.replyFollowHistory.forEachReverse((mid, idx) => {
forEachReverse(this.replyFollowHistory, (mid, idx) => {
const bubble = this.bubbles[mid];
let bad = true;
if(bubble) {

20
src/components/chat/input.ts

@ -1386,10 +1386,11 @@ export default class ChatInput { @@ -1386,10 +1386,11 @@ export default class ChatInput {
let input = RichTextProcessor.wrapDraftText(message.message, {entities: message.totalEntities});
const f = () => {
// ! костыль
const replyText = this.appMessagesManager.getRichReplyText(message, undefined, [message.mid]);
const replyFragment = this.appMessagesManager.wrapMessageForReply(message, undefined, [message.mid]);
this.setTopInfo('edit', f, 'Editing', undefined, input, message);
const subtitleEl = this.replyElements.container.querySelector('.reply-subtitle');
subtitleEl.innerHTML = replyText;
subtitleEl.textContent = '';
subtitleEl.append(replyFragment);
this.editMsgId = mid;
input = undefined;
@ -1419,13 +1420,22 @@ export default class ChatInput { @@ -1419,13 +1420,22 @@ export default class ChatInput {
const title = peerTitles.length < 3 ? peerTitles.join(' and ') : peerTitles[0] + ' and ' + (peerTitles.length - 1) + ' others';
const firstMessage = this.appMessagesManager.getMessageByPeer(fromPeerId, mids[0]);
const replyText = this.appMessagesManager.getRichReplyText(firstMessage, undefined, mids);
if(replyText.includes('Album') || mids.length === 1) {
let usingFullAlbum = true;
if(firstMessage.grouped_id) {
const albumMids = this.appMessagesManager.getMidsByMessage(firstMessage);
if(albumMids.length !== mids.length || albumMids.find(mid => !mids.includes(mid))) {
usingFullAlbum = false;
}
}
const replyFragment = this.appMessagesManager.wrapMessageForReply(firstMessage, undefined, mids);
if(usingFullAlbum || mids.length === 1) {
this.setTopInfo('forward', f, title);
// ! костыль
const subtitleEl = this.replyElements.container.querySelector('.reply-subtitle');
subtitleEl.innerHTML = replyText;
subtitleEl.textContent = '';
subtitleEl.append(replyFragment);
} else {
this.setTopInfo('forward', f, title, mids.length + ' ' + (mids.length > 1 ? 'forwarded messages' : 'forwarded message'));
}

11
src/components/chat/replyContainer.ts

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
import { limitSymbols } from "../../helpers/string";
import appImManager, { CHAT_ANIMATION_GROUP } from "../../lib/appManagers/appImManager";
import appMessagesManager from "../../lib/appManagers/appMessagesManager";
import appPhotosManager from "../../lib/appManagers/appPhotosManager";
import { RichTextProcessor } from "../../lib/richtextprocessor";
import DivAndCaption from "../divAndCaption";
@ -22,12 +23,11 @@ export function wrapReplyDivAndCaption(options: { @@ -22,12 +23,11 @@ export function wrapReplyDivAndCaption(options: {
titleEl.innerHTML = title;
}
subtitle = limitSymbols(subtitle, 140);
const media = message && message.media;
let setMedia = false;
if(media && mediaEl) {
subtitle = message.rReply;
subtitleEl.textContent = '';
subtitleEl.append(appMessagesManager.wrapMessageForReply(message));
//console.log('wrap reply', media);
@ -81,10 +81,11 @@ export function wrapReplyDivAndCaption(options: { @@ -81,10 +81,11 @@ export function wrapReplyDivAndCaption(options: {
}
}
} else {
subtitle = limitSymbols(subtitle, 140);
subtitle = subtitle ? RichTextProcessor.wrapEmojiText(subtitle) : '';
subtitleEl.innerHTML = subtitle;
}
subtitleEl.innerHTML = subtitle;
return setMedia;
}

3
src/components/sidebarRight/tabs/stickers.ts

@ -10,6 +10,7 @@ import { RichTextProcessor } from "../../../lib/richtextprocessor"; @@ -10,6 +10,7 @@ import { RichTextProcessor } from "../../../lib/richtextprocessor";
import { wrapSticker } from "../../wrappers";
import appSidebarRight from "..";
import { StickerSet, StickerSetCovered } from "../../../layer";
import { forEachReverse } from "../../../helpers/array";
export default class AppStickersTab extends SliderSuperTab {
private inputSearch: InputSearch;
@ -202,7 +203,7 @@ export default class AppStickersTab extends SliderSuperTab { @@ -202,7 +203,7 @@ export default class AppStickersTab extends SliderSuperTab {
coveredSets = coveredSets.slice();
const children = Array.from(this.setsDiv.children) as HTMLElement[];
children.forEachReverse(el => {
forEachReverse(children, el => {
const id = el.dataset.stickerSet;
const index = coveredSets.findIndex(covered => covered.set.id === id);

2
src/config/app.ts

@ -2,7 +2,7 @@ const App = { @@ -2,7 +2,7 @@ const App = {
id: 1025907,
hash: '452b0359b988148995f22ff0f4229750',
version: '0.4.0',
langPackVersion: '0.0.1',
langPackVersion: '0.0.2',
domains: [] as string[],
baseDcId: 2
};

12
src/helpers/array.ts

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
import { copy } from "./object";
/* import { copy } from "./object";
export function listMergeSorted(list1: any[] = [], list2: any[] = []) {
const result = copy(list1);
@ -11,7 +11,7 @@ export function listMergeSorted(list1: any[] = [], list2: any[] = []) { @@ -11,7 +11,7 @@ export function listMergeSorted(list1: any[] = [], list2: any[] = []) {
}
return result;
}
} */
export const accumulate = (arr: number[], initialValue: number) => arr.reduce((acc, value) => acc + value, initialValue);
@ -23,4 +23,10 @@ export function findAndSpliceAll<T>(array: Array<T>, verify: (value: T, index: n @@ -23,4 +23,10 @@ export function findAndSpliceAll<T>(array: Array<T>, verify: (value: T, index: n
}
return out;
}
}
export function forEachReverse<T>(array: Array<T>, callback: (value: T, index?: number, array?: Array<T>) => void) {
for(let length = array.length, i = length - 1; i >= 0; --i) {
callback(array[i], i, array);
}
};

7
src/helpers/dom.ts

@ -798,3 +798,10 @@ export function toggleDisability(elements: HTMLElement[], disable: boolean) { @@ -798,3 +798,10 @@ export function toggleDisability(elements: HTMLElement[], disable: boolean) {
export function canFocus(isFirstInput: boolean) {
return !isMobileSafari || !isFirstInput;
}
export function htmlToDocumentFragment(html: string) {
var template = document.createElement('template');
html = html.trim(); // Never return a text node of whitespace as the result
template.innerHTML = html;
return template.content;
}

5
src/lang.ts

@ -49,13 +49,15 @@ const lang = { @@ -49,13 +49,15 @@ const lang = {
"ActionChangedVideo": "un1 changed the group video",
"ActionAddUser": "un1 added un2",
"ActionAddUserSelf": "un1 returned to the group",
"ActionAddUserSelfMega": "un1 joined the group",
"ActionAddUserSelfYou": "You returned to the group",
"ActionAddUserSelfMega": "un1 joined the group",
"ActionLeftUser": "un1 left the group",
"ActionKickUser": "un1 removed un2",
"ActionInviteUser": "un1 joined the group via invite link",
"ActionPinnedNoText": "un1 pinned a message",
"ActionMigrateFromGroup": "This group was upgraded to a supergroup",
//"ChannelJoined": "You joined this channel",
"ChannelMegaJoined": "You joined this group",
"FilterAlwaysShow": "Include Chats",
"FilterNeverShow": "Exclude Chats",
"FilterInclude": "Included Chats",
@ -155,6 +157,7 @@ const lang = { @@ -155,6 +157,7 @@ const lang = {
"Chat.Service.Channel.UpdatedTitle": "Channel renamed to \"%@\"",
"Chat.Service.Channel.UpdatedPhoto": "Channel photo updated",
"Chat.Service.Channel.RemovedPhoto": "Channel photo removed",
"Chat.Service.Channel.UpdatedVideo": "Channel video updated",
"Chat.Service.BotPermissionAllowed": "You allowed this bot to message you when you logged in on %@",
"ChatList.Service.Call.incoming": "Incoming Call (%@)",
"ChatList.Service.Call.outgoing": "Outgoing Call (%@)",

67
src/layer.d.ts vendored

@ -967,7 +967,7 @@ export namespace MessageMedia { @@ -967,7 +967,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;
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.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 = {
@ -1102,6 +1102,60 @@ export namespace MessageAction { @@ -1102,6 +1102,60 @@ export namespace MessageAction {
to_id: Peer,
distance: number
};
export type messageActionChatLeave = {
_: 'messageActionChatLeave',
user_id?: number
};
export type messageActionChannelDeletePhoto = {
_: 'messageActionChannelDeletePhoto'
};
export type messageActionChannelEditTitle = {
_: 'messageActionChannelEditTitle',
title?: string
};
export type messageActionChannelEditPhoto = {
_: 'messageActionChannelEditPhoto',
photo?: Photo
};
export type messageActionChannelEditVideo = {
_: 'messageActionChannelEditVideo',
photo?: Photo
};
export type messageActionChatEditVideo = {
_: 'messageActionChatEditVideo',
photo?: Photo
};
export type messageActionChatAddUsers = {
_: 'messageActionChatAddUsers',
users?: Array<number>
};
export type messageActionChatJoined = {
_: 'messageActionChatJoined',
users?: Array<number>
};
export type messageActionChatReturn = {
_: 'messageActionChatReturn',
users?: Array<number>
};
export type messageActionChatJoinedYou = {
_: 'messageActionChatJoinedYou',
users?: Array<number>
};
export type messageActionChatReturnYou = {
_: 'messageActionChatReturnYou',
users?: Array<number>
};
}
/**
@ -9018,6 +9072,17 @@ export interface ConstructorDeclMap { @@ -9018,6 +9072,17 @@ export interface ConstructorDeclMap {
'messageEntityEmoji': MessageEntity.messageEntityEmoji,
'messageEntityHighlight': MessageEntity.messageEntityHighlight,
'messageEntityLinebreak': MessageEntity.messageEntityLinebreak,
'messageActionChatLeave': MessageAction.messageActionChatLeave,
'messageActionChannelDeletePhoto': MessageAction.messageActionChannelDeletePhoto,
'messageActionChannelEditTitle': MessageAction.messageActionChannelEditTitle,
'messageActionChannelEditPhoto': MessageAction.messageActionChannelEditPhoto,
'messageActionChannelEditVideo': MessageAction.messageActionChannelEditVideo,
'messageActionChatEditVideo': MessageAction.messageActionChatEditVideo,
'messageActionChatAddUsers': MessageAction.messageActionChatAddUsers,
'messageActionChatJoined': MessageAction.messageActionChatJoined,
'messageActionChatReturn': MessageAction.messageActionChatReturn,
'messageActionChatJoinedYou': MessageAction.messageActionChatJoinedYou,
'messageActionChatReturnYou': MessageAction.messageActionChatReturnYou,
}
export type InvokeAfterMsg = {

33
src/lib/appManagers/appDialogsManager.ts

@ -1056,38 +1056,13 @@ export class AppDialogsManager { @@ -1056,38 +1056,13 @@ export class AppDialogsManager {
/* if(!dom.lastMessageSpan.classList.contains('user-typing')) */ {
dom.lastMessageSpan.textContent = '';
if(highlightWord && lastMessage.message) {
let lastMessageText = appMessagesManager.getRichReplyText(lastMessage, '');
let messageText = lastMessage.message;
let entities = RichTextProcessor.parseEntities(messageText.replace(/\n/g, ' '));
let regExp = new RegExp(escapeRegExp(highlightWord), 'gi');
let match: any;
if(!entities) entities = [];
let found = false;
while((match = regExp.exec(messageText)) !== null) {
entities.push({_: 'messageEntityHighlight', length: highlightWord.length, offset: match.index});
found = true;
}
if(found) {
entities.sort((a, b) => a.offset - b.offset);
}
let messageWrapped = RichTextProcessor.wrapRichText(messageText, {
noLinebreaks: true,
entities: entities,
noTextFormat: true
});
dom.lastMessageSpan.innerHTML = lastMessageText + messageWrapped;
dom.lastMessageSpan.append(appMessagesManager.wrapMessageForReply(lastMessage, undefined, undefined, false, highlightWord));
} else if(draftMessage) {
dom.lastMessageSpan.innerHTML = draftMessage.rReply;
dom.lastMessageSpan.append(appMessagesManager.wrapMessageForReply(draftMessage));
} else if(!lastMessage.deleted) {
dom.lastMessageSpan.innerHTML = lastMessage.rReply;
} else {
dom.lastMessageSpan.innerHTML = '';
dom.lastMessageSpan.append(appMessagesManager.wrapMessageForReply(lastMessage));
}
/* if(lastMessage.from_id === auth.id) { // You: */

2
src/lib/appManagers/appDraftsManager.ts

@ -163,7 +163,7 @@ export class AppDraftsManager { @@ -163,7 +163,7 @@ export class AppDraftsManager {
const totalEntities = RichTextProcessor.mergeEntities(apiEntities, myEntities); // ! only in this order, otherwise bold and emoji formatting won't work
draft.rMessage = RichTextProcessor.wrapDraftText(draft.message, {entities: totalEntities});
draft.rReply = appMessagesManager.getRichReplyText(draft);
//draft.rReply = appMessagesManager.getRichReplyText(draft);
if(draft.reply_to_msg_id) {
draft.reply_to_msg_id = appMessagesManager.generateMessageId(draft.reply_to_msg_id);
}

268
src/lib/appManagers/appMessagesManager.ts

@ -5,10 +5,10 @@ import { tsNow } from "../../helpers/date"; @@ -5,10 +5,10 @@ import { tsNow } from "../../helpers/date";
import { createPosterForVideo } from "../../helpers/files";
import { copy, defineNotNumerableProperties, getObjectKeysAndSort } from "../../helpers/object";
import { randomLong } from "../../helpers/random";
import { splitStringByLength, limitSymbols } from "../../helpers/string";
import { splitStringByLength, limitSymbols, escapeRegExp } from "../../helpers/string";
import { Chat, ChatFull, Dialog as MTDialog, DialogPeer, DocumentAttribute, InputMedia, InputMessage, InputPeerNotifySettings, InputSingleMedia, Message, MessageAction, MessageEntity, MessageFwdHeader, MessageReplies, MessageReplyHeader, MessagesDialogs, MessagesFilter, MessagesMessages, MessagesPeerDialogs, MethodDeclMap, NotifyPeer, PeerNotifySettings, PhotoSize, SendMessageAction, Update } from "../../layer";
import { InvokeApiOptions } from "../../types";
import I18n, { langPack, LangPackKey, _i18n } from "../langPack";
import I18n, { join, langPack, LangPackKey, _i18n } from "../langPack";
import { logger, LogLevels } from "../logger";
import type { ApiFileManager } from '../mtproto/apiFileManager';
//import apiManager from '../mtproto/apiManager';
@ -39,6 +39,8 @@ import DEBUG, { MOUNT_CLASS_TO } from "../../config/debug"; @@ -39,6 +39,8 @@ import DEBUG, { MOUNT_CLASS_TO } from "../../config/debug";
import SlicedArray, { Slice, SliceEnd } from "../../helpers/slicedArray";
import appNotificationsManager, { NotifyOptions } from "./appNotificationsManager";
import PeerTitle from "../../components/peerTitle";
import { forEachReverse } from "../../helpers/array";
import { htmlToDocumentFragment } from "../../helpers/dom";
//console.trace('include');
// TODO: если удалить сообщение в непрогруженном диалоге, то при обновлении, из-за стейта, последнего сообщения в чатлисте не будет
@ -92,6 +94,8 @@ export type MessagesStorage = { @@ -92,6 +94,8 @@ export type MessagesStorage = {
[mid: string]: any
};
export type MyMessageActionType = Message.messageService['action']['_'];
export class AppMessagesManager {
public static MESSAGE_ID_INCREMENT = 0x10000;
public static MESSAGE_ID_OFFSET = 0xFFFFFFFF;
@ -292,7 +296,7 @@ export class AppMessagesManager { @@ -292,7 +296,7 @@ export class AppMessagesManager {
}
if(state.dialogs) {
state.dialogs.forEachReverse(dialog => {
forEachReverse(state.dialogs, dialog => {
dialog.top_message = this.getServerMessageId(dialog.top_message); // * fix outgoing message to avoid copying dialog
this.saveConversation(dialog);
@ -1755,7 +1759,7 @@ export class AppMessagesManager { @@ -1755,7 +1759,7 @@ export class AppMessagesManager {
let maxSeenIdIncremented = offsetDate ? true : false;
let hasPrepend = false;
const noIdsDialogs: {[peerId: number]: Dialog} = {};
(dialogsResult.dialogs as Dialog[]).forEachReverse(dialog => {
forEachReverse((dialogsResult.dialogs as Dialog[]), dialog => {
//const d = Object.assign({}, dialog);
// ! нужно передавать folderId, так как по папке !== 0 нет свойства folder_id
this.saveConversation(dialog, dialog.folder_id ?? folderId);
@ -2221,7 +2225,7 @@ export class AppMessagesManager { @@ -2221,7 +2225,7 @@ export class AppMessagesManager {
isScheduled: true,
isOutgoing: true
}> = {}) {
let groups: Set<string>;
//let groups: Set<string>;
messages.forEach((message) => {
if(message.pFlags === undefined) {
message.pFlags = {};
@ -2384,8 +2388,12 @@ export class AppMessagesManager { @@ -2384,8 +2388,12 @@ export class AppMessagesManager {
//case 'messageActionChannelEditPhoto':
case 'messageActionChatEditPhoto':
message.action.photo = appPhotosManager.savePhoto(message.action.photo, mediaContext);
if(isBroadcast) { // ! messageActionChannelEditPhoto не существует в принципе, это используется для перевода.
message.action._ = 'messageActionChannelEditPhoto';
if(message.action.photo.video_sizes) {
message.action._ = isBroadcast ? 'messageActionChannelEditVideo' : 'messageActionChatEditVideo';
} else {
if(isBroadcast) { // ! messageActionChannelEditPhoto не существует в принципе, это используется для перевода.
message.action._ = 'messageActionChannelEditPhoto';
}
}
break;
@ -2405,10 +2413,11 @@ export class AppMessagesManager { @@ -2405,10 +2413,11 @@ export class AppMessagesManager {
if(message.action.users.length === 1) {
message.action.user_id = message.action.users[0];
if(message.fromId === message.action.user_id) {
let suffix = message.fromId === appUsersManager.getSelf().id ? 'You' : '';
if(isChannel) {
message.action._ = 'messageActionChatJoined';
message.action._ = 'messageActionChatJoined' + suffix;
} else {
message.action._ = 'messageActionChatReturn';
message.action._ = 'messageActionChatReturn' + suffix;
}
}
} else if(message.action.users.length > 1) {
@ -2460,7 +2469,7 @@ export class AppMessagesManager { @@ -2460,7 +2469,7 @@ export class AppMessagesManager {
}
}
if(message.grouped_id) {
/* if(message.grouped_id) {
if(!groups) {
groups = new Set();
}
@ -2468,7 +2477,7 @@ export class AppMessagesManager { @@ -2468,7 +2477,7 @@ export class AppMessagesManager {
groups.add(message.grouped_id);
} else {
message.rReply = this.getRichReplyText(message);
}
} */
if(message.message && message.message.length && !message.totalEntities) {
const myEntities = RichTextProcessor.parseEntities(message.message);
@ -2479,7 +2488,7 @@ export class AppMessagesManager { @@ -2479,7 +2488,7 @@ export class AppMessagesManager {
storage[mid] = message;
});
if(groups) {
/* if(groups) {
for(const groupId of groups) {
const mids = this.groupedMessagesStorage[groupId];
for(const mid in mids) {
@ -2487,11 +2496,28 @@ export class AppMessagesManager { @@ -2487,11 +2496,28 @@ export class AppMessagesManager {
message.rReply = this.getRichReplyText(message);
}
}
}
} */
}
public getRichReplyText(message: any, text: string = message.message, usingMids?: number[], plain = false) {
let messageText = '';
public wrapMessageForReply(message: any, text: string, usingMids: number[], plain: true, highlightWord?: string): string;
public wrapMessageForReply(message: any, text?: string, usingMids?: number[], plain?: false, highlightWord?: string): DocumentFragment;
public wrapMessageForReply(message: any, text: string = message.message, usingMids?: number[], plain?: boolean, highlightWord?: string): DocumentFragment | string {
const parts: (HTMLElement | string)[] = [];
const addPart = (part: string | HTMLElement, text?: string) => {
if(text) {
part += ', ';
}
if(plain) {
parts.push(part);
} else {
const el = document.createElement('i');
if(typeof(part) === 'string') el.innerHTML = part;
else el.append(part);
parts.push(el);
}
};
if(message.media) {
let usingFullAlbum = true;
@ -2512,7 +2538,7 @@ export class AppMessagesManager { @@ -2512,7 +2538,7 @@ export class AppMessagesManager {
if(usingFullAlbum) {
text = this.getAlbumText(message.grouped_id).message;
messageText += '<i>Album' + (text ? ', ' : '') + '</i>';
addPart('Album', text);
}
} else {
usingFullAlbum = false;
@ -2522,36 +2548,36 @@ export class AppMessagesManager { @@ -2522,36 +2548,36 @@ export class AppMessagesManager {
const media = message.media;
switch(media._) {
case 'messageMediaPhoto':
messageText += '<i>Photo' + (message.message ? ', ' : '') + '</i>';
addPart('Photo', message.message);
break;
case 'messageMediaDice':
messageText += plain ? media.emoticon : RichTextProcessor.wrapEmojiText(media.emoticon);
addPart(plain ? media.emoticon : RichTextProcessor.wrapEmojiText(media.emoticon));
break;
case 'messageMediaGeo':
messageText += '<i>Geolocation</i>';
addPart('Geolocation');
break;
case 'messageMediaPoll':
messageText += '<i>' + (plain ? '📊' + ' ' + media.poll.question || 'poll' : media.poll.rReply) + '</i>';
addPart(plain ? '📊' + ' ' + (media.poll.question || 'poll') : media.poll.rReply);
break;
case 'messageMediaContact':
messageText += '<i>Contact</i>';
addPart('Contact');
break;
case 'messageMediaDocument':
let document = media.document;
if(document.type === 'video') {
messageText = '<i>Video' + (message.message ? ', ' : '') + '</i>';
addPart('Video', message.message);
} else if(document.type === 'voice') {
messageText = '<i>Voice message' + (message.message ? ', ' : '') + '</i>';
addPart('Voice message', message.message);
} else if(document.type === 'gif') {
messageText = '<i>GIF' + (message.message ? ', ' : '') + '</i>';
addPart('GIF', message.message);
} else if(document.type === 'round') {
messageText = '<i>Video message' + (message.message ? ', ' : '') + '</i>';
addPart('Video message', message.message);
} else if(document.type === 'sticker') {
messageText = (document.stickerEmoji || '') + '<i>Sticker</i>';
addPart(((plain ? document.stickerEmojiRaw : document.stickerEmoji) || '') + 'Sticker');
text = '';
} else {
messageText = '<i>' + document.file_name + (message.message ? ', ' : '') + '</i>';
addPart(document.file_name, message.message);
}
break;
@ -2565,30 +2591,53 @@ export class AppMessagesManager { @@ -2565,30 +2591,53 @@ export class AppMessagesManager {
}
if(message.action) {
const str = this.wrapMessageActionText(message, plain);
messageText = str ? '<i>' + str + '</i>' : '';
const actionWrapped = this.wrapMessageActionTextNew(message, plain);
if(actionWrapped) {
addPart(actionWrapped);
}
}
let messageWrapped = '';
if(text) {
text = limitSymbols(text, 100);
const entities = RichTextProcessor.parseEntities(text.replace(/\n/g, ' '));
if(plain) {
parts.push(text);
} else {
let entities = RichTextProcessor.parseEntities(text.replace(/\n/g, ' '));
if(highlightWord) {
if(!entities) entities = [];
let found = false;
let match: any;
let regExp = new RegExp(escapeRegExp(highlightWord), 'gi');
while((match = regExp.exec(text)) !== null) {
entities.push({_: 'messageEntityHighlight', length: highlightWord.length, offset: match.index});
found = true;
}
if(found) {
entities.sort((a, b) => a.offset - b.offset);
}
}
messageWrapped = plain ? text : RichTextProcessor.wrapRichText(text, {
noLinebreaks: true,
entities,
noLinks: true,
noTextFormat: true
});
const messageWrapped = RichTextProcessor.wrapRichText(text, {
noLinebreaks: true,
entities,
noLinks: true,
noTextFormat: true
});
parts.push(htmlToDocumentFragment(messageWrapped) as any);
}
}
if(plain) {
messageText = messageText.replace(/<i>/g, '').replace(/<\/i>/g, '');
return parts.join('');
} else {
const fragment = document.createDocumentFragment();
fragment.append(...parts);
return fragment;
}
return messageText + messageWrapped;
}
public getSenderToPeerText(message: MyMessage) {
@ -2606,84 +2655,9 @@ export class AppMessagesManager { @@ -2606,84 +2655,9 @@ export class AppMessagesManager {
return senderTitle;
}
public wrapMessageActionText(message: any, plain?: boolean) {
const action = message.action as MessageAction;
let str = '';
if((action as MessageAction.messageActionCustomAction).message) {
str = RichTextProcessor.wrapRichText((action as MessageAction.messageActionCustomAction).message, {noLinebreaks: true});
} else {
let _ = action._;
let suffix = '';
let l = '';
const getNameDivHTML = (peerId: number) => {
const title = appPeersManager.getPeerTitle(peerId);
return title ? (plain ? title + ' ' : `<div class="name inline" data-peer-id="${peerId}">${title}</div> `) : '';
};
switch(action._) {
case "messageActionPhoneCall": {
_ += '.' + (action as any).type;
const duration = action.duration;
if(duration) {
const d: string[] = [];
d.push(duration % 60 + ' s');
if(duration >= 60) d.push((duration / 60 | 0) + ' min');
//if(duration >= 3600) d.push((duration / 3600 | 0) + ' h');
suffix = ' (' + d.reverse().join(' ') + ')';
}
return langPack[_] + suffix;
}
case 'messageActionChatDeleteUser':
// @ts-ignore
case 'messageActionChatAddUsers':
case 'messageActionChatAddUser': {
const users: number[] = (action as MessageAction.messageActionChatAddUser).users || [(action as MessageAction.messageActionChatDeleteUser).user_id];
l = langPack[_].replace('{}', users.map((userId: number) => getNameDivHTML(userId).trim()).join(', '));
break;
}
case 'messageActionBotAllowed': {
const anchorHTML = RichTextProcessor.wrapRichText(action.domain, {
entities: [{
_: 'messageEntityUrl',
length: action.domain.length,
offset: 0
}]
});
l = langPack[_].replace('{}', anchorHTML);
break;
}
default:
str = langPack[_] || `[${action._}]`;
break;
}
if(!l) {
l = langPack[_];
if(l === undefined) {
l = '[' + _ + ']';
}
}
str = !l || l[0].toUpperCase() === l[0] ? l : getNameDivHTML(message.fromId) + l + (suffix ? ' ' : '');
}
//this.log('message action:', action);
return str;
}
public wrapMessageActionTextNew(message: any, plain: true): string;
public wrapMessageActionTextNew(message: any, plain?: false): HTMLElement;
public wrapMessageActionTextNew(message: any, plain: boolean): HTMLElement | string;
public wrapMessageActionTextNew(message: any, plain?: boolean): HTMLElement | string {
const element: HTMLElement = plain ? undefined : document.createElement('span');
const action = message.action as MessageAction;
@ -2705,7 +2679,7 @@ export class AppMessagesManager { @@ -2705,7 +2679,7 @@ export class AppMessagesManager {
let args: any[];
const getNameDivHTML = (peerId: number, plain: boolean) => {
return plain ? appPeersManager.getPeerTitle(peerId) + ' ' : (new PeerTitle({peerId})).element;
return plain ? appPeersManager.getPeerTitle(peerId, plain) + ' ' : (new PeerTitle({peerId})).element;
};
switch(action._) {
@ -2724,27 +2698,61 @@ export class AppMessagesManager { @@ -2724,27 +2698,61 @@ export class AppMessagesManager {
break;
}
case 'messageActionPinMessage':
case 'messageActionContactSignUp':
case 'messageActionChatLeave':
case 'messageActionChatJoined':
case 'messageActionChatCreate':
case 'messageActionChatJoinedByLink': {
case 'messageActionChatEditPhoto':
case 'messageActionChatDeletePhoto':
case 'messageActionChatEditVideo':
case 'messageActionChatJoinedByLink':
case 'messageActionChannelEditVideo':
case 'messageActionChannelDeletePhoto': {
langPackKey = langPack[_];
args = [getNameDivHTML(message.fromId, plain)];
break;
}
case 'messageActionChannelEditTitle':
case 'messageActionChatEditTitle': {
langPackKey = langPack[_];
args = [];
if(action._ === 'messageActionChatEditTitle') {
args.push(getNameDivHTML(message.fromId, plain));
}
args.push(plain ? action.title : RichTextProcessor.wrapEmojiText(action.title));
break;
}
case 'messageActionChatDeleteUser':
// @ts-ignore
case 'messageActionChatAddUsers':
case 'messageActionChatAddUser': {
const users: number[] = (action as MessageAction.messageActionChatAddUser).users
|| [(action as MessageAction.messageActionChatDeleteUser).user_id];
langPackKey = langPack[_];
args = [
getNameDivHTML(message.fromId, plain),
users.length > 1 ?
users.map((userId: number) => (getNameDivHTML(userId, true) as string).trim()).join(', ') :
getNameDivHTML(users[0], plain)
];
args = [getNameDivHTML(message.fromId, plain)];
if(users.length > 1) {
if(plain) {
args.push(...users.map((userId: number) => (getNameDivHTML(userId, true) as string).trim()).join(', '));
} else {
const fragment = document.createElement('span');
fragment.append(
...join(
users.map((userId: number) => getNameDivHTML(userId, false)) as HTMLElement[],
false
)
);
args.push(fragment);
}
} else {
args.push(getNameDivHTML(users[0], plain));
}
break;
}
@ -2756,9 +2764,11 @@ export class AppMessagesManager { @@ -2756,9 +2764,11 @@ export class AppMessagesManager {
offset: 0
}]
});
const node = htmlToDocumentFragment(anchorHTML);
langPackKey = langPack[_];
args = [anchorHTML];
args = [node];
break;
}
@ -2927,7 +2937,7 @@ export class AppMessagesManager { @@ -2927,7 +2937,7 @@ export class AppMessagesManager {
// * В эту функцию попадут только те диалоги, в которых есть read_inbox_max_id и read_outbox_max_id, в отличие от тех, что будут в getTopMessages
// ! fix 'dialogFolder', maybe there is better way to do it, this only can happen by 'messages.getPinnedDialogs' by folder_id: 0
dialogsResult.dialogs.forEachReverse((dialog, idx) => {
forEachReverse(dialogsResult.dialogs, (dialog, idx) => {
if(dialog._ === 'dialogFolder') {
dialogsResult.dialogs.splice(idx, 1);
}
@ -4779,7 +4789,7 @@ export class AppMessagesManager { @@ -4779,7 +4789,7 @@ export class AppMessagesManager {
if(message._ === 'message' && message.fwd_from && options.fwdCount) {
notificationMessage = 'Forwarded ' + options.fwdCount + ' messages';//fwdMessagesPluralize(options.fwd_count);
} else {
notificationMessage = this.getRichReplyText(message, undefined, undefined, true);
notificationMessage = this.wrapMessageForReply(message, undefined, undefined, true);
}
} else {
notificationMessage = 'New notification';

10
src/lib/appManagers/appStateManager.ts

@ -1,15 +1,15 @@ @@ -1,15 +1,15 @@
import type { Dialog } from './appMessagesManager';
import { UserAuth } from '../mtproto/mtproto_config';
import EventListenerBase from '../../helpers/eventListenerBase';
import rootScope from '../rootScope';
import sessionStorage from '../sessionStorage';
import { logger } from '../logger';
import type { UserAuth } from '../mtproto/mtproto_config';
import type { AppUsersManager } from './appUsersManager';
import type { AppChatsManager } from './appChatsManager';
import type { AuthState } from '../../types';
import type FiltersStorage from '../storages/filters';
import type DialogsStorage from '../storages/dialogs';
import type { AppDraftsManager } from './appDraftsManager';
import EventListenerBase from '../../helpers/eventListenerBase';
import rootScope from '../rootScope';
import sessionStorage from '../sessionStorage';
import { logger } from '../logger';
import { copy, setDeepProperty, validateInitObject } from '../../helpers/object';
import { getHeavyAnimationPromise } from '../../hooks/useHeavyAnimationCheck';
import App from '../../config/app';

3
src/lib/appManagers/appStickersManager.ts

@ -5,6 +5,7 @@ import rootScope from '../rootScope'; @@ -5,6 +5,7 @@ import rootScope from '../rootScope';
import appDocsManager from './appDocsManager';
import AppStorage from '../storage';
import { MOUNT_CLASS_TO } from '../../config/debug';
import { forEachReverse } from '../../helpers/array';
// TODO: если пак будет сохранён и потом обновлён, то недостающие стикеры не подгрузит
@ -33,7 +34,7 @@ export class AppStickersManager { @@ -33,7 +34,7 @@ export class AppStickersManager {
}
public saveStickers(docs: Document[]) {
docs.forEachReverse((doc, idx) => {
forEachReverse(docs, (doc, idx) => {
doc = appDocsManager.saveDoc(doc);
if(!doc) docs.splice(idx, 1);

10
src/lib/langPack.ts

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
import { MOUNT_CLASS_TO } from "../config/debug";
import DEBUG, { MOUNT_CLASS_TO } from "../config/debug";
import { safeAssign } from "../helpers/object";
import { capitalizeFirstLetter } from "../helpers/string";
import type lang from "../lang";
@ -11,9 +11,12 @@ export const langPack: {[actionType: string]: LangPackKey} = { @@ -11,9 +11,12 @@ export const langPack: {[actionType: string]: LangPackKey} = {
"messageActionChatCreate": "ActionCreateGroup",
"messageActionChatEditTitle": "ActionChangedTitle",
"messageActionChatEditPhoto": "ActionChangedPhoto",
"messageActionChatEditVideo": "ActionChangedVideo",
"messageActionChatDeletePhoto": "ActionRemovedPhoto",
"messageActionChatReturn": "ActionAddUserSelf",
"messageActionChatReturnYou": "ActionAddUserSelfYou",
"messageActionChatJoined": "ActionAddUserSelfMega",
"messageActionChatJoinedYou": "ChannelMegaJoined",
"messageActionChatAddUser": "ActionAddUser",
"messageActionChatAddUsers": "ActionAddUser",
"messageActionChatLeave": "ActionLeftUser",
@ -24,6 +27,7 @@ export const langPack: {[actionType: string]: LangPackKey} = { @@ -24,6 +27,7 @@ export const langPack: {[actionType: string]: LangPackKey} = {
"messageActionChannelCreate": "ActionCreateChannel",
"messageActionChannelEditTitle": "Chat.Service.Channel.UpdatedTitle",
"messageActionChannelEditPhoto": "Chat.Service.Channel.UpdatedPhoto",
"messageActionChannelEditVideo": "Chat.Service.Channel.UpdatedVideo",
"messageActionChannelDeletePhoto": "Chat.Service.Channel.RemovedPhoto",
"messageActionHistoryClear": "HistoryCleared",
@ -51,6 +55,8 @@ namespace I18n { @@ -51,6 +55,8 @@ namespace I18n {
]).then(([langPack]) => {
if(!langPack/* || true */) {
return getLangPack('en');
} else if(DEBUG) {
return getLangPack(langPack.lang_code);
} else if(langPack.appVersion !== App.langPackVersion) {
return getLangPack(langPack.lang_code);
}
@ -177,7 +183,7 @@ namespace I18n { @@ -177,7 +183,7 @@ namespace I18n {
return '';
});
if(lastIndex !== (input.length - 1)) {
if(lastIndex !== input.length) {
out.push(input.slice(lastIndex));
}

3
src/lib/mtproto/networker.ts

@ -21,6 +21,7 @@ import HTTP from './transports/http'; @@ -21,6 +21,7 @@ import HTTP from './transports/http';
import type TcpObfuscated from './transports/tcpObfuscated';
import { bigInt2str, cmp, rightShift_, str2bigInt } from '../../vendor/leemon';
import { forEachReverse } from '../../helpers/array';
//console.error('networker included!', new Error().stack);
@ -196,7 +197,7 @@ export default class MTPNetworker { @@ -196,7 +197,7 @@ export default class MTPNetworker {
}
if(sentMessage.container) {
sentMessage.inner.forEachReverse((innerSentMessageId, idx) => {
forEachReverse(sentMessage.inner, (innerSentMessageId, idx) => {
const innerSentMessage = this.updateSentMessage(innerSentMessageId);
if(!innerSentMessage) {
sentMessage.inner.splice(idx, 1);

8
src/lib/polyfill.ts

@ -36,13 +36,6 @@ Uint8Array.prototype.toJSON = function() { @@ -36,13 +36,6 @@ Uint8Array.prototype.toJSON = function() {
//return {type: 'bytes', value: [...this]};
};
Array.prototype.forEachReverse = function<T>(callback: (value: T, index?: number, array?: Array<T>) => void) {
let length = this.length;
for(var i = length - 1; i >= 0; --i) {
callback(this[i], i, this);
}
};
Array.prototype.findAndSplice = function<T>(verify: (value: T, index?: number, array?: Array<T>) => boolean) {
let index = this.findIndex(verify);
return index !== -1 ? this.splice(index, 1)[0] : undefined;
@ -88,7 +81,6 @@ declare global { @@ -88,7 +81,6 @@ declare global {
}
interface Array<T> {
forEachReverse(callback: (value: T, index?: number, array?: Array<T>) => void): void;
findAndSplice(verify: (value: T, index?: number, array?: Array<T>) => boolean): T;
}

6
src/lib/rootScope.ts

@ -6,10 +6,10 @@ import type { MyDialogFilter } from "./storages/filters"; @@ -6,10 +6,10 @@ import type { MyDialogFilter } from "./storages/filters";
import type { ConnectionStatusChange } from "../types";
import type { UserTyping } from "./appManagers/appChatsManager";
import type Chat from "../components/chat/chat";
import { UserAuth } from "./mtproto/mtproto_config";
import { State } from "./appManagers/appStateManager";
import type { UserAuth } from "./mtproto/mtproto_config";
import type { State } from "./appManagers/appStateManager";
import type { MyDraftMessage } from "./appManagers/appDraftsManager";
import EventListenerBase from "../helpers/eventListenerBase";
import { MyDraftMessage } from "./appManagers/appDraftsManager";
import { MOUNT_CLASS_TO } from "../config/debug";
export type BroadcastEvents = {

5
src/lib/storages/filters.ts

@ -7,6 +7,7 @@ import type { AppUsersManager } from "../appManagers/appUsersManager"; @@ -7,6 +7,7 @@ import type { AppUsersManager } from "../appManagers/appUsersManager";
import type _rootScope from "../rootScope";
import type {Dialog} from '../appManagers/appMessagesManager';
import apiManager from "../mtproto/mtprotoworker";
import { forEachReverse } from "../../helpers/array";
export type MyDialogFilter = Modify<DialogFilter, {
pinned_peers: number[],
@ -199,7 +200,7 @@ export default class FiltersStorage { @@ -199,7 +200,7 @@ export default class FiltersStorage {
c[key] = c[key].map((peerId: number) => this.appPeersManager.getInputPeerById(peerId));
});
c.include_peers.forEachReverse((peerId, idx) => {
forEachReverse(c.include_peers, (peerId, idx) => {
if(c.pinned_peers.includes(peerId)) {
c.include_peers.splice(idx, 1);
}
@ -229,7 +230,7 @@ export default class FiltersStorage { @@ -229,7 +230,7 @@ export default class FiltersStorage {
filter[key] = filter[key].map((peer: any) => this.appPeersManager.getPeerId(peer));
});
filter.include_peers.forEachReverse((peerId, idx) => {
forEachReverse(filter.include_peers, (peerId, idx) => {
if(filter.pinned_peers.includes(peerId)) {
filter.include_peers.splice(idx, 1);
}

64
src/scripts/in/schema_additional_params.json

@ -144,4 +144,68 @@ @@ -144,4 +144,68 @@
"params": [
{"name": "rTitle", "type": "string"}
]
}, {
"predicate": "messageActionChatLeave",
"params": [
{"name": "user_id", "type": "number"}
],
"type": "MessageAction"
}, {
"predicate": "messageActionChannelDeletePhoto",
"params": [],
"type": "MessageAction"
}, {
"predicate": "messageActionChannelEditTitle",
"params": [
{"name": "title", "type": "string"}
],
"type": "MessageAction"
}, {
"predicate": "messageActionChannelEditPhoto",
"params": [
{"name": "photo", "type": "Photo"}
],
"type": "MessageAction"
}, {
"predicate": "messageActionChannelEditVideo",
"params": [
{"name": "photo", "type": "Photo"}
],
"type": "MessageAction"
}, {
"predicate": "messageActionChatEditVideo",
"params": [
{"name": "photo", "type": "Photo"}
],
"type": "MessageAction"
}, {
"predicate": "messageActionChatAddUsers",
"params": [
{"name": "users", "type": "Array<number>"}
],
"type": "MessageAction"
}, {
"predicate": "messageActionChatJoined",
"params": [
{"name": "users", "type": "Array<number>"}
],
"type": "MessageAction"
}, {
"predicate": "messageActionChatReturn",
"params": [
{"name": "users", "type": "Array<number>"}
],
"type": "MessageAction"
}, {
"predicate": "messageActionChatJoinedYou",
"params": [
{"name": "users", "type": "Array<number>"}
],
"type": "MessageAction"
}, {
"predicate": "messageActionChatReturnYou",
"params": [
{"name": "users", "type": "Array<number>"}
],
"type": "MessageAction"
}]

7
src/scss/partials/_chatlist.scss

@ -156,7 +156,6 @@ ul.chatlist { @@ -156,7 +156,6 @@ ul.chatlist {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
vertical-align: middle;
//margin: .1rem 0;
line-height: 27px;
}
@ -286,6 +285,8 @@ ul.chatlist { @@ -286,6 +285,8 @@ ul.chatlist {
margin-right: .1rem;
//margin-top: .3rem;
margin-top: -.3rem;
display: inline-block;
vertical-align: middle;
&[class*=" tgico-"] {
color: $color-green;
@ -297,6 +298,10 @@ ul.chatlist { @@ -297,6 +298,10 @@ ul.chatlist {
}
}
.message-time {
vertical-align: middle;
}
.dialog-subtitle-badge {
margin-top: 4px;
margin-right: -3px;

Loading…
Cancel
Save