Browse Source

Fix document name XSS

master
Eduard Kuzmenko 3 years ago
parent
commit
25e5bcf22f
  1. 3
      src/components/appSearchSuper..ts
  2. 2
      src/components/audio.ts
  3. 2
      src/components/chat/audio.ts
  4. 2
      src/components/popups/newMedia.ts
  5. 14
      src/components/sidebarLeft/index.ts
  6. 2
      src/components/sidebarLeft/tabs/archivedTab.ts
  7. 37
      src/components/sidebarLeft/tabs/contacts.ts
  8. 2
      src/components/sidebarRight/tabs/groupPermissions.ts
  9. 7
      src/components/sidebarRight/tabs/sharedMedia.ts
  10. 2
      src/components/sidebarRight/tabs/userPermissions.ts
  11. 27
      src/components/sortedUserList.ts
  12. 2
      src/components/wrappers.ts
  13. 1
      src/layer.d.ts
  14. 112
      src/lib/appManagers/appDialogsManager.ts
  15. 9
      src/lib/appManagers/appDocsManager.ts
  16. 2
      src/lib/appManagers/appMessagesManager.ts
  17. 33
      src/lib/appManagers/appUsersManager.ts
  18. 20
      src/lib/richtextprocessor.ts
  19. 1
      src/scripts/in/schema_additional_params.json
  20. 83
      src/scss/partials/_chatlist.scss
  21. 8
      src/scss/partials/_leftSidebar.scss
  22. 29
      src/scss/partials/_rightSidebar.scss
  23. 4
      src/scss/partials/_slider.scss
  24. 1
      src/scss/style.scss

3
src/components/appSearchSuper..ts

@ -868,8 +868,7 @@ export default class AppSearchSuper { @@ -868,8 +868,7 @@ export default class AppSearchSuper {
}
if(!this.membersList) {
this.membersList = new SortedUserList();
this.membersList.lazyLoadQueue = this.lazyLoadQueue;
this.membersList = new SortedUserList({lazyLoadQueue: this.lazyLoadQueue, rippleEnabled: false});
this.membersList.list.addEventListener('click', (e) => {
const li = findUpTag(e.target, 'LI');
if(!li) {

2
src/components/audio.ts

@ -272,7 +272,7 @@ function wrapAudio(audioEl: AudioElement) { @@ -272,7 +272,7 @@ function wrapAudio(audioEl: AudioElement) {
const senderTitle = audioEl.showSender ? appMessagesManager.getSenderToPeerText(message) : '';
let title = doc.type === 'voice' ? senderTitle : (doc.audioTitle || doc.file_name);
let title = doc.type === 'voice' ? senderTitle : (doc.audioTitle || doc.fileName);
let subtitle: string;
if(doc.type === 'voice') {

2
src/components/chat/audio.ts

@ -56,7 +56,7 @@ export default class ChatAudio extends PinnedContainer { @@ -56,7 +56,7 @@ export default class ChatAudio extends PinnedContainer {
//subtitle = 'Voice message';
subtitle = formatDate(message.date, false, false);
} else {
title = doc.audioTitle || doc.file_name;
title = doc.audioTitle || doc.fileName;
subtitle = doc.audioPerformer ? RichTextProcessor.wrapPlainText(doc.audioPerformer) : 'Unknown Artist';
}

2
src/components/popups/newMedia.ts

@ -20,6 +20,7 @@ import calcImageInBox from "../../helpers/calcImageInBox"; @@ -20,6 +20,7 @@ import calcImageInBox from "../../helpers/calcImageInBox";
import isSendShortcutPressed from "../../helpers/dom/isSendShortcutPressed";
import placeCaretAtEnd from "../../helpers/dom/placeCaretAtEnd";
import rootScope from "../../lib/rootScope";
import RichTextProcessor from "../../lib/richtextprocessor";
type SendFileParams = Partial<{
file: File,
@ -298,6 +299,7 @@ export default class PopupNewMedia extends PopupElement { @@ -298,6 +299,7 @@ export default class PopupNewMedia extends PopupElement {
_: 'document',
file: file,
file_name: file.name || '',
fileName: file.name ? RichTextProcessor.wrapEmojiText(file.name) : '',
size: file.size,
type: isPhoto ? 'photo' : 'doc'
} as MyDocument;

14
src/components/sidebarLeft/index.ts

@ -575,12 +575,16 @@ export class SettingSection { @@ -575,12 +575,16 @@ export class SettingSection {
constructor(options: {
name?: LangPackKey,
caption?: LangPackKey | true,
noDelimiter?: boolean
noDelimiter?: boolean,
fakeGradientDelimiter?: boolean
}) {
this.container = document.createElement('div');
this.container.classList.add('sidebar-left-section');
if(!options.noDelimiter) {
if(options.fakeGradientDelimiter) {
this.container.append(generateDelimiter());
this.container.classList.add('with-fake-delimiter');
} else if(!options.noDelimiter) {
const hr = document.createElement('hr');
this.container.append(hr);
} else {
@ -620,6 +624,12 @@ export const generateSection = (appendTo: Scrollable, name?: LangPackKey, captio @@ -620,6 +624,12 @@ export const generateSection = (appendTo: Scrollable, name?: LangPackKey, captio
return section.content;
};
export const generateDelimiter = () => {
const delimiter = document.createElement('div');
delimiter.classList.add('gradient-delimiter');
return delimiter;
};
const appSidebarLeft = new AppSidebarLeft();
MOUNT_CLASS_TO.appSidebarLeft = appSidebarLeft;
export default appSidebarLeft;

2
src/components/sidebarLeft/tabs/archivedTab.ts

@ -17,7 +17,7 @@ export default class AppArchivedTab extends SliderSuperTab { @@ -17,7 +17,7 @@ export default class AppArchivedTab extends SliderSuperTab {
if(!appDialogsManager.chatLists[AppArchivedTab.filterId]) {
const chatList = appDialogsManager.createChatList();
appDialogsManager.generateScrollable(chatList, AppArchivedTab.filterId);
appDialogsManager.generateScrollable(chatList, AppArchivedTab.filterId).container.append(chatList);
appDialogsManager.setListClickListener(chatList, null, true);
//appDialogsManager.setListClickListener(archivedChatList, null, true); // * to test peer changing
}

37
src/components/sidebarLeft/tabs/contacts.ts

@ -8,7 +8,6 @@ import { SliderSuperTab } from "../../slider"; @@ -8,7 +8,6 @@ import { SliderSuperTab } from "../../slider";
import appDialogsManager from "../../../lib/appManagers/appDialogsManager";
import appUsersManager from "../../../lib/appManagers/appUsersManager";
import appPhotosManager from "../../../lib/appManagers/appPhotosManager";
import rootScope from "../../../lib/rootScope";
import InputSearch from "../../inputSearch";
import { isMobile } from "../../../helpers/userAgent";
import { canFocus } from "../../../helpers/dom/canFocus";
@ -67,7 +66,7 @@ export default class AppContactsTab extends SliderSuperTab { @@ -67,7 +66,7 @@ export default class AppContactsTab extends SliderSuperTab {
if(this.promise) return this.promise;
this.scrollable.onScrolledBottom = null;
this.promise = appUsersManager.getContacts(query).then(_contacts => {
this.promise = appUsersManager.getContacts(query, undefined, 'online').then(contacts => {
this.promise = null;
if(!this.alive) {
@ -75,42 +74,26 @@ export default class AppContactsTab extends SliderSuperTab { @@ -75,42 +74,26 @@ export default class AppContactsTab extends SliderSuperTab {
return;
}
const contacts = [..._contacts];
if(!query) {
contacts.findAndSplice(u => u === rootScope.myId);
}
/* if(query && 'saved messages'.includes(query.toLowerCase())) {
contacts.unshift(rootScope.myID);
} */
let sorted = contacts
.map(userId => {
let user = appUsersManager.getUser(userId);
let status = appUsersManager.getUserStatusForSort(user.status);
return {user, status};
})
.sort((a, b) => b.status - a.status);
let renderPage = () => {
let pageCount = appPhotosManager.windowH / 72 * 1.25 | 0;
let arr = sorted.splice(0, pageCount); // надо splice!
const pageCount = appPhotosManager.windowH / 72 * 1.25 | 0;
const arr = contacts.splice(0, pageCount); // надо splice!
arr.forEach(({user}) => {
let {dialog, dom} = appDialogsManager.addDialogNew({
dialog: user.id,
arr.forEach((peerId) => {
const {dom} = appDialogsManager.addDialogNew({
dialog: peerId,
container: this.list,
drawStatus: false,
avatarSize: 48,
autonomous: true
});
let status = appUsersManager.getUserStatusString(user.id);
const status = appUsersManager.getUserStatusString(peerId);
dom.lastMessageSpan.append(status);
});
if(!sorted.length) renderPage = undefined;
if(!contacts.length) {
renderPage = undefined;
}
};
renderPage();

2
src/components/sidebarRight/tabs/groupPermissions.ts

@ -201,7 +201,7 @@ export default class AppGroupPermissionsTab extends SliderSuperTabEventable { @@ -201,7 +201,7 @@ export default class AppGroupPermissionsTab extends SliderSuperTabEventable {
const c = section.generateContentElement();
c.classList.add('chatlist-container');
const list = appDialogsManager.createChatList();
const list = appDialogsManager.createChatList({new: true});
c.append(list);
attachClickEvent(list, (e) => {

7
src/components/sidebarRight/tabs/sharedMedia.ts

@ -26,7 +26,7 @@ import { Chat, Message, MessageAction, ChatFull, Photo } from "../../../layer"; @@ -26,7 +26,7 @@ import { Chat, Message, MessageAction, ChatFull, Photo } from "../../../layer";
import Button from "../../button";
import ButtonIcon from "../../buttonIcon";
import I18n, { i18n, LangPackKey } from "../../../lib/langPack";
import { SettingSection } from "../../sidebarLeft";
import { generateDelimiter, SettingSection } from "../../sidebarLeft";
import Row from "../../row";
import { copyTextToClipboard } from "../../../helpers/clipboard";
import { toast, toastNew } from "../../toast";
@ -572,10 +572,7 @@ class PeerProfile { @@ -572,10 +572,7 @@ class PeerProfile {
this.section.content.append(this.phone.container, this.username.container, this.bio.container, this.notifications.container);
const delimiter = document.createElement('div');
delimiter.classList.add('gradient-delimiter');
this.element.append(this.section.container, delimiter);
this.element.append(this.section.container, generateDelimiter());
this.notifications.checkboxField.input.addEventListener('change', (e) => {
if(!e.isTrusted) {

2
src/components/sidebarRight/tabs/userPermissions.ts

@ -36,7 +36,7 @@ export default class AppUserPermissionsTab extends SliderSuperTabEventable { @@ -36,7 +36,7 @@ export default class AppUserPermissionsTab extends SliderSuperTabEventable {
div.classList.add('chatlist-container');
section.content.insertBefore(div, section.title);
const list = appDialogsManager.createChatList();
const list = appDialogsManager.createChatList({new: true});
div.append(list);
const {dom} = appDialogsManager.addDialogNew({

27
src/components/sortedUserList.ts

@ -12,6 +12,7 @@ import { insertInDescendSortedArray } from "../helpers/array"; @@ -12,6 +12,7 @@ import { insertInDescendSortedArray } from "../helpers/array";
import isInDOM from "../helpers/dom/isInDOM";
import positionElementByIndex from "../helpers/dom/positionElementByIndex";
import replaceContent from "../helpers/dom/replaceContent";
import { safeAssign } from "../helpers/object";
type SortedUser = {
peerId: number,
@ -19,14 +20,24 @@ type SortedUser = { @@ -19,14 +20,24 @@ type SortedUser = {
dom: DialogDom
};
export default class SortedUserList {
public static SORT_INTERVAL = 30e3;
protected static SORT_INTERVAL = 30e3;
protected users: Map<number, SortedUser>;
protected sorted: Array<SortedUser>;
public list: HTMLUListElement;
public users: Map<number, SortedUser>;
public sorted: Array<SortedUser>;
public lazyLoadQueue: LazyLoadQueueIntersector;
protected lazyLoadQueue: LazyLoadQueueIntersector;
protected avatarSize = 48;
protected rippleEnabled = true;
constructor() {
this.list = appDialogsManager.createChatList();
constructor(options: Partial<{
lazyLoadQueue: SortedUserList['lazyLoadQueue'],
avatarSize: SortedUserList['avatarSize'],
rippleEnabled: SortedUserList['rippleEnabled'],
new: boolean
}> = {}) {
safeAssign(this, options);
this.list = appDialogsManager.createChatList({new: options.new});
this.users = new Map();
this.sorted = [];
@ -76,10 +87,10 @@ export default class SortedUserList { @@ -76,10 +87,10 @@ export default class SortedUserList {
dialog: peerId,
container: false,
drawStatus: false,
avatarSize: 48,
avatarSize: this.avatarSize,
autonomous: true,
meAsSaved: false,
rippleEnabled: false,
rippleEnabled: this.rippleEnabled,
lazyLoadQueue: this.lazyLoadQueue
});

2
src/components/wrappers.ts

@ -507,7 +507,7 @@ export function wrapDocument({message, withTime, fontWeight, voiceAsMusic, showS @@ -507,7 +507,7 @@ export function wrapDocument({message, withTime, fontWeight, voiceAsMusic, showS
}
//let fileName = stringMiddleOverflow(doc.file_name || 'Unknown.file', 26);
let fileName = doc.file_name || 'Unknown.file';
let fileName = doc.fileName || 'Unknown.file';
let size = formatBytes(doc.size);
if(withTime) {

1
src/layer.d.ts vendored

@ -3133,6 +3133,7 @@ export namespace Document { @@ -3133,6 +3133,7 @@ export namespace Document {
h?: number,
w?: number,
file_name?: string,
fileName?: string,
file?: File,
duration?: number,
audioTitle?: string,

112
src/lib/appManagers/appDialogsManager.ts

@ -35,7 +35,7 @@ import { LazyLoadQueueIntersector } from "../../components/lazyLoadQueue"; @@ -35,7 +35,7 @@ import { LazyLoadQueueIntersector } from "../../components/lazyLoadQueue";
import lottieLoader from "../lottieLoader";
import { wrapLocalSticker } from "../../components/wrappers";
import AppEditFolderTab from "../../components/sidebarLeft/tabs/editFolder";
import appSidebarLeft from "../../components/sidebarLeft";
import appSidebarLeft, { SettingSection } from "../../components/sidebarLeft";
import { attachClickEvent } from "../../helpers/dom/clickEvent";
import positionElementByIndex from "../../helpers/dom/positionElementByIndex";
import replaceContent from "../../helpers/dom/replaceContent";
@ -43,6 +43,8 @@ import ConnectionStatusComponent from "../../components/connectionStatus"; @@ -43,6 +43,8 @@ import ConnectionStatusComponent from "../../components/connectionStatus";
import appChatsManager from "./appChatsManager";
import { renderImageFromUrlPromise } from "../../helpers/dom/renderImageFromUrl";
import { fastRafPromise } from "../../helpers/schedulers";
import appPhotosManager from "./appPhotosManager";
import SortedUserList from "../../components/sortedUserList";
export type DialogDom = {
avatarEl: AvatarElement,
@ -106,6 +108,7 @@ export class AppDialogsManager { @@ -106,6 +108,7 @@ export class AppDialogsManager {
private lastActiveElements: Set<HTMLElement> = new Set();
private offsets: {top: number, bottom: number} = {top: 0, bottom: 0};
loadContacts: () => void;
constructor() {
this.chatsPreloader = putPreloader(null, true);
@ -436,7 +439,7 @@ export class AppDialogsManager { @@ -436,7 +439,7 @@ export class AppDialogsManager {
appDraftsManager.addMissedDialogs();
}
return this.loadDialogs();
return this.onChatsScroll();
}
/* private getOffset(side: 'top' | 'bottom'): {index: number, pos: number} {
@ -533,7 +536,7 @@ export class AppDialogsManager { @@ -533,7 +536,7 @@ export class AppDialogsManager {
this.offsets.top = this.offsets.bottom = 0;
this.loadDialogsPromise = undefined;
this.chatList = this.chatLists[this.filterId];
this.loadDialogs();
this.onChatsScroll();
};
private setFilterUnreadCount(filterId: number, folder?: Dialog[]) {
@ -593,7 +596,6 @@ export class AppDialogsManager { @@ -593,7 +596,6 @@ export class AppDialogsManager {
const scrollable = new Scrollable(null, 'CL', 500);
scrollable.container.addEventListener('scroll', this.onChatsRegularScroll);
scrollable.container.dataset.filterId = '' + filterId;
scrollable.container.append(list);
scrollable.onScrolledTop = this.onChatsScrollTop;
scrollable.onScrolledBottom = this.onChatsScroll;
scrollable.setVirtualContainer(list);
@ -627,6 +629,23 @@ export class AppDialogsManager { @@ -627,6 +629,23 @@ export class AppDialogsManager {
const ul = this.createChatList();
const scrollable = this.generateScrollable(ul, filter.id);
scrollable.container.classList.add('chatlist-parts');
/* const parts = document.createElement('div');
parts.classList.add('chatlist-parts'); */
const top = document.createElement('div');
top.classList.add('chatlist-top');
const bottom = document.createElement('div');
bottom.classList.add('chatlist-bottom');
top.append(ul);
scrollable.container.append(top, bottom);
/* parts.append(top, bottom);
scrollable.container.append(parts); */
const div = scrollable.container;
//this.folders.container.append(div);
positionElementByIndex(scrollable.container, this.folders.container, filter.orderIndex);
@ -654,7 +673,7 @@ export class AppDialogsManager { @@ -654,7 +673,7 @@ export class AppDialogsManager {
}
}
private loadDialogs(side: SliceSides = 'bottom') {
private loadDialogs(side: SliceSides) {
/* if(testScroll) {
return;
} */
@ -779,13 +798,13 @@ export class AppDialogsManager { @@ -779,13 +798,13 @@ export class AppDialogsManager {
return {container, header, subtitle};
}
private onListLengthChange = () => {
//return;
private checkIfPlaceholderNeeded() {
if(this.filterId === 1) {
return;
}
let placeholderContainer = (Array.from(this.chatList.parentElement.children) as HTMLElement[]).find(el => el.matches('.empty-placeholder'));
const part = this.chatList.parentElement as HTMLElement;
let placeholderContainer = (Array.from(part.children) as HTMLElement[]).find(el => el.matches('.empty-placeholder'));
const needPlaceholder = this.scroll.loadedAll.bottom && !this.chatList.childElementCount/* || true */;
// this.chatList.style.display = 'none';
@ -793,6 +812,7 @@ export class AppDialogsManager { @@ -793,6 +812,7 @@ export class AppDialogsManager {
return;
} else if(!needPlaceholder) {
if(placeholderContainer) {
part.classList.remove('with-placeholder');
placeholderContainer.remove();
}
@ -863,7 +883,55 @@ export class AppDialogsManager { @@ -863,7 +883,55 @@ export class AppDialogsManager {
placeholderContainer.append(button);
}
this.chatList.parentElement.append(placeholderContainer);
part.append(placeholderContainer);
part.classList.add('with-placeholder');
}
private onListLengthChange = () => {
return;
this.checkIfPlaceholderNeeded();
if(this.filterId > 0) return;
const bottom = this.chatList.parentElement.nextElementSibling as HTMLElement;
if(bottom.childElementCount) return;
bottom.parentElement.classList.add('with-contacts');
const section = new SettingSection({
name: 'Contacts',
noDelimiter: true,
fakeGradientDelimiter: true
});
section.container.classList.add('hide');
appUsersManager.getContacts(undefined, undefined, 'online').then(contacts => {
const sortedUserList = new SortedUserList({avatarSize: 42, new: true});
this.loadContacts = () => {
const pageCount = appPhotosManager.windowH / 60 | 0;
const arr = contacts.splice(0, pageCount);
arr.forEach((peerId) => {
sortedUserList.add(peerId);
});
if(!contacts.length) {
this.loadContacts = undefined;
}
};
this.loadContacts();
const list = sortedUserList.list;
list.classList.add('chatlist-new');
this.setListClickListener(list);
section.content.append(list);
section.container.classList.remove('hide');
});
bottom.append(section.container);
};
public onChatsRegularScroll = () => {
@ -987,9 +1055,16 @@ export class AppDialogsManager { @@ -987,9 +1055,16 @@ export class AppDialogsManager {
};
public onChatsScroll = (side: SliceSides = 'bottom') => {
if(this.scroll.loadedAll[side] || this.loadDialogsPromise) return;
if(this.scroll.loadedAll[side]) {
if(this.loadContacts) {
this.loadContacts();
}
return;
} else if(this.loadDialogsPromise) return this.loadDialogsPromise;
this.log('onChatsScroll', side);
this.loadDialogs(side);
return this.loadDialogs(side);
};
public setListClickListener(list: HTMLUListElement, onFound?: () => void, withContext = false, autonomous = false, openInner = false) {
@ -1050,15 +1125,20 @@ export class AppDialogsManager { @@ -1050,15 +1125,20 @@ export class AppDialogsManager {
}
}
public createChatList(/* options: {
avatarSize?: number,
handheldsSize?: number,
//size?: number,
} = {} */) {
public createChatList(options: {
// avatarSize?: number,
// handheldsSize?: number,
// size?: number,
new?: boolean
} = {}) {
const list = document.createElement('ul');
list.classList.add('chatlist'/* ,
'chatlist-avatar-' + (options.avatarSize || 54) *//* , 'chatlist-' + (options.size || 72) */);
if(options.new) {
list.classList.add('chatlist-new');
}
/* if(options.handheldsSize) {
list.classList.add('chatlist-handhelds-' + options.handheldsSize);
} */

9
src/lib/appManagers/appDocsManager.ts

@ -93,12 +93,13 @@ export class AppDocsManager { @@ -93,12 +93,13 @@ export class AppDocsManager {
switch(attribute._) {
case 'documentAttributeFilename':
doc.file_name = RichTextProcessor.wrapPlainText(attribute.file_name);
doc.fileName = RichTextProcessor.wrapEmojiText(attribute.file_name);
break;
case 'documentAttributeAudio':
doc.duration = attribute.duration;
doc.audioTitle = attribute.title;
doc.audioPerformer = attribute.performer;
doc.audioTitle = RichTextProcessor.wrapEmojiText(attribute.title);
doc.audioPerformer = RichTextProcessor.wrapEmojiText(attribute.performer);
doc.type = attribute.pFlags.voice && doc.mime_type === 'audio/ogg' ? 'voice' : 'audio';
/* if(apiDoc.type === 'audio') {
apiDoc.supportsStreaming = true;
@ -182,7 +183,7 @@ export class AppDocsManager { @@ -182,7 +183,7 @@ export class AppDocsManager {
if(doc.type === 'voice' || doc.type === 'round') {
// browser will identify extension
doc.file_name = doc.type + '_' + getFullDate(new Date(doc.date * 1000), {monthAsNumber: true, leadingZero: true}).replace(/[:\.]/g, '-').replace(', ', '_');
doc.file_name = doc.fileName = doc.type + '_' + getFullDate(new Date(doc.date * 1000), {monthAsNumber: true, leadingZero: true}).replace(/[:\.]/g, '-').replace(', ', '_');
}
if(apiManager.isServiceWorkerOnline()) {
@ -201,7 +202,7 @@ export class AppDocsManager { @@ -201,7 +202,7 @@ export class AppDocsManager {
// doc.url = ''; // * this will break upload urls
if(!doc.file_name) {
doc.file_name = '';
doc.file_name = doc.fileName = '';
}
if(doc.mime_type === 'application/x-tgsticker' && doc.file_name === 'AnimatedSticker.tgs') {

2
src/lib/appManagers/appMessagesManager.ts

@ -2626,7 +2626,7 @@ export class AppMessagesManager { @@ -2626,7 +2626,7 @@ export class AppMessagesManager {
addPart(undefined, ((plain ? document.stickerEmojiRaw : document.stickerEmoji) || '') + 'Sticker');
text = '';
} else {
addPart(document.file_name, undefined, message.message);
addPart(undefined, plain ? document.file_name : RichTextProcessor.wrapEmojiText(document.file_name), message.message);
}
break;

33
src/lib/appManagers/appUsersManager.ts

@ -261,7 +261,7 @@ export class AppUsersManager { @@ -261,7 +261,7 @@ export class AppUsersManager {
return arr.filter(Boolean).join(' ');
}
public getContacts(query?: string, includeSaved = false) {
public getContacts(query?: string, includeSaved = false, sortBy: 'name' | 'online' | 'none' = 'name') {
return this.fillContacts().then(_contactsList => {
let contactsList = [..._contactsList];
if(query) {
@ -271,30 +271,27 @@ export class AppUsersManager { @@ -271,30 +271,27 @@ export class AppUsersManager {
contactsList = filteredContactsList;
}
contactsList.sort((userId1: number, userId2: number) => {
const sortName1 = (this.users[userId1] || {}).sortName || '';
const sortName2 = (this.users[userId2] || {}).sortName || '';
return sortName1.localeCompare(sortName2);
});
if(sortBy === 'name') {
contactsList.sort((userId1, userId2) => {
const sortName1 = (this.users[userId1] || {}).sortName || '';
const sortName2 = (this.users[userId2] || {}).sortName || '';
return sortName1.localeCompare(sortName2);
});
} else if(sortBy === 'online') {
contactsList.sort((userId1, userId2) => {
const status1 = appUsersManager.getUserStatusForSort(appUsersManager.getUser(userId1).status);
const status2 = appUsersManager.getUserStatusForSort(appUsersManager.getUser(userId2).status);
return status2 - status1;
});
}
contactsList.findAndSplice(p => p === rootScope.myId);
if(includeSaved) {
if(this.testSelfSearch(query)) {
contactsList.findAndSplice(p => p === rootScope.myId);
contactsList.unshift(rootScope.myId);
}
}
/* contactsList.sort((userId1: number, userId2: number) => {
const sortName1 = (this.users[userId1] || {}).sortName || '';
const sortName2 = (this.users[userId2] || {}).sortName || '';
if(sortName1 === sortName2) {
return 0;
}
return sortName1 > sortName2 ? 1 : -1;
}); */
return contactsList;
});
}

20
src/lib/richtextprocessor.ts

@ -748,7 +748,7 @@ namespace RichTextProcessor { @@ -748,7 +748,7 @@ namespace RichTextProcessor {
});
}
export function wrapPlainText(text: any) {
export function wrapPlainText(text: string) {
if(emojiSupported) {
return text;
}
@ -757,32 +757,32 @@ namespace RichTextProcessor { @@ -757,32 +757,32 @@ namespace RichTextProcessor {
return '';
}
text = text.replace(/\ufe0f/g, '', text);
text = text.replace(/\ufe0f/g, '');
var match;
var raw = text;
var text: any = [],
emojiTitle;
const arr: string[] = [];
let emojiTitle;
fullRegExp.lastIndex = 0;
while((match = raw.match(fullRegExp))) {
text.push(raw.substr(0, match.index))
arr.push(raw.substr(0, match.index))
if(match[8]) {
// @ts-ignore
const emojiCode = EmojiHelper.emojiMap[match[8]];
if(emojiCode &&
// @ts-ignore
(emojiTitle = emojiData[emojiCode][1][0])) {
text.push(':' + emojiTitle + ':');
arr.push(':' + emojiTitle + ':');
} else {
text.push(match[0]);
arr.push(match[0]);
}
} else {
text.push(match[0]);
arr.push(match[0]);
}
raw = raw.substr(match.index + match[0].length);
}
text.push(raw);
return text.join('');
arr.push(raw);
return arr.join('');
}
export function wrapEmojiText(text: string) {

1
src/scripts/in/schema_additional_params.json

@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
{"name": "h", "type": "number"},
{"name": "w", "type": "number"},
{"name": "file_name", "type": "string"},
{"name": "fileName", "type": "string"},
{"name": "file", "type": "File"},
{"name": "duration", "type": "number"},
{"name": "audioTitle", "type": "string"},

83
src/scss/partials/_chatlist.scss

@ -399,6 +399,89 @@ ul.chatlist { @@ -399,6 +399,89 @@ ul.chatlist {
li.is-muted .unread {
background-color: var(--secondary-color);
}
&-parts {
/* width: 100%;
min-height: 100%;
display: flex;
flex-direction: column; */
&.with-contacts {
.chatlist-top:not(.with-placeholder) {
height: auto;
padding-bottom: .5rem;
}
.chatlist-top.with-placeholder {
height: 24.125rem;
.empty-placeholder-dialogs {
top: 50%;
}
}
}
}
// do not set position: relative here. will break chatlist slicing.
&-top {
// flex: 0 0 auto;
height: 100%;
}
&-bottom {
// flex: 1 1 auto;
max-height: 36.375rem;
.sidebar-left-section {
padding-bottom: 0;
}
.chatlist-new {
padding: 0;
margin-top: -.5rem;
li {
height: 3.5rem;
}
.user-caption {
padding-left: 1.125rem;
}
.dialog-subtitle {
margin-top: .0625rem;
}
}
}
// * supernew correct layout
&-new {
li {
height: 4.5rem;
padding: 0 .75rem;
align-items: center;
}
.user-caption {
padding-left: .75rem;
}
p {
height: auto !important;
}
span {
line-height: var(--line-height) !important;
}
.dialog-subtitle {
margin-top: .125rem;
}
.user-last-message {
font-size: .875rem;
}
}
}
// use together like class="chatlist-container contacts-container"

8
src/scss/partials/_leftSidebar.scss

@ -830,6 +830,10 @@ @@ -830,6 +830,10 @@
user-select: none;
padding: .5rem 0 1rem;
&.with-fake-delimiter {
padding-top: 0;
}
@include respond-to(handhelds) {
padding-bottom: .5rem;
}
@ -1182,6 +1186,9 @@ @@ -1182,6 +1186,9 @@
}
.empty-placeholder {
// left: 50%;
// transform: translate(-50%, -50%);
// position: absolute;
top: 40%;
transform: translateY(-50%);
text-align: center;
@ -1190,6 +1197,7 @@ @@ -1190,6 +1197,7 @@
width: 21rem !important;
margin: 0 auto;
padding: 0 1rem;
position: relative;
.media-sticker-wrapper {
width: 128px;

29
src/scss/partials/_rightSidebar.scss

@ -708,35 +708,8 @@ @@ -708,35 +708,8 @@
padding: 0 0 .5rem;
}
// * supernew and correct layout
.chatlist {
.chatlist-new {
padding: 0;
li {
height: 72px;
padding: 0 .75rem;
align-items: center;
}
.user-caption {
padding-left: .75rem;
}
p {
height: auto;
}
span {
line-height: 1.3125;
}
.dialog-subtitle {
margin-top: .125rem;
}
.user-last-message {
font-size: .875rem;
}
}
}

4
src/scss/partials/_slider.scss

@ -147,12 +147,12 @@ @@ -147,12 +147,12 @@
display: flex;
}
> div:not(.scroll-padding) {
/* > div:not(.scroll-padding) {
width: 100%;
max-width: 100%;
//overflow: hidden;
position: relative;
}
} */
}
/* &[data-animation="tabs"] {

1
src/scss/style.scss

@ -1212,7 +1212,6 @@ middle-ellipsis-element { @@ -1212,7 +1212,6 @@ middle-ellipsis-element {
.gradient-delimiter {
width: 100%;
height: .75rem;
display: flex;
background-color: var(--background-color-true);
position: relative;

Loading…
Cancel
Save