Browse Source

Select peers search by non-contact

master
morethanwords 4 years ago
parent
commit
837fcbf13c
  1. 2
      src/components/appForward.ts
  2. 79
      src/components/appSelectPeers.ts
  3. 14
      src/components/sidebarLeft/addMembers.ts
  4. 7
      src/components/sidebarLeft/editFolder.ts
  5. 2
      src/components/sidebarLeft/includedChats.ts
  6. 55
      src/lib/appManagers/appDialogsManager.ts
  7. 13
      src/lib/appManagers/appDocsManager.ts
  8. 2
      src/lib/appManagers/appMediaViewer.ts
  9. 40
      src/lib/appManagers/appMessagesManager.ts
  10. 2
      src/lib/appManagers/appPhotosManager.ts
  11. 12
      src/lib/appManagers/appStateManager.ts
  12. 25
      src/lib/appManagers/appUsersManager.ts
  13. 2
      src/lib/config.ts
  14. 3
      src/lib/mtproto/mtprotoworker.ts
  15. 22
      src/lib/utils.ts
  16. 7
      src/scss/partials/_chatBubble.scss
  17. 4
      src/scss/partials/_leftSidebar.scss
  18. 9
      src/scss/partials/_rightSidebar.scss
  19. 24
      src/scss/style.scss
  20. 2
      webpack.common.js

2
src/components/appForward.ts

@ -73,7 +73,7 @@ class AppForward {
} else { } else {
this.sendBtn.classList.remove('is-visible'); this.sendBtn.classList.remove('is-visible');
} }
}, 'both', () => { }, ['dialogs', 'contacts'], () => {
//console.log('forward rendered:', this.container.querySelector('.selector ul').childElementCount); //console.log('forward rendered:', this.container.querySelector('.selector ul').childElementCount);
this.sidebarWasActive = appSidebarRight.sidebarEl.classList.contains('active'); this.sidebarWasActive = appSidebarRight.sidebarEl.classList.contains('active');
appSidebarRight.toggleSidebar(true); appSidebarRight.toggleSidebar(true);

79
src/components/appSelectPeers.ts

@ -1,12 +1,17 @@
import Scrollable from "./scrollable_new"; import Scrollable from "./scrollable_new";
import appMessagesManager, { Dialog } from "../lib/appManagers/appMessagesManager"; import appMessagesManager, { Dialog } from "../lib/appManagers/appMessagesManager";
import { $rootScope, cancelEvent, findUpClassName, findUpTag, findUpAttribute } from "../lib/utils"; import { $rootScope, cancelEvent, findUpClassName, findUpAttribute } from "../lib/utils";
import appDialogsManager from "../lib/appManagers/appDialogsManager"; import appDialogsManager from "../lib/appManagers/appDialogsManager";
import appChatsManager from "../lib/appManagers/appChatsManager"; import appChatsManager from "../lib/appManagers/appChatsManager";
import appUsersManager from "../lib/appManagers/appUsersManager"; import appUsersManager from "../lib/appManagers/appUsersManager";
import appPeersManager from "../lib/appManagers/appPeersManager"; import appPeersManager from "../lib/appManagers/appPeersManager";
import appPhotosManager from "../lib/appManagers/appPhotosManager"; import appPhotosManager from "../lib/appManagers/appPhotosManager";
type PeerType = 'contacts' | 'dialogs';
// TODO: правильная сортировка для addMembers, т.е. для peerType: 'contacts', потому что там идут сначала контакты - потом неконтакты, а должно всё сортироваться по имени
let loadedAllDialogs = false;
export class AppSelectPeers { export class AppSelectPeers {
public container = document.createElement('div'); public container = document.createElement('div');
public list = document.createElement('ul'); public list = document.createElement('ul');
@ -22,8 +27,6 @@ export class AppSelectPeers {
public freezed = false; public freezed = false;
private myID = $rootScope.myID;
private folderID = 0; private folderID = 0;
private offsetIndex = 0; private offsetIndex = 0;
private promise: Promise<any>; private promise: Promise<any>;
@ -33,7 +36,7 @@ export class AppSelectPeers {
private loadedWhat: Partial<{[k in 'dialogs' | 'archived' | 'contacts']: true}> = {}; private loadedWhat: Partial<{[k in 'dialogs' | 'archived' | 'contacts']: true}> = {};
constructor(private appendTo: HTMLElement, private onChange?: (length: number) => void, private peerType: 'contacts' | 'dialogs' | 'both' = 'dialogs', onFirstRender?: () => void, private renderResultsFunc?: (peerIDs: number[]) => void) { constructor(private appendTo: HTMLElement, private onChange?: (length: number) => void, private peerType: PeerType[] = ['dialogs'], onFirstRender?: () => void, private renderResultsFunc?: (peerIDs: number[]) => void) {
this.container.classList.add('selector'); this.container.classList.add('selector');
if(!this.renderResultsFunc) { if(!this.renderResultsFunc) {
@ -44,7 +47,7 @@ export class AppSelectPeers {
topContainer.classList.add('selector-search-container'); topContainer.classList.add('selector-search-container');
this.selectedContainer.classList.add('selector-search'); this.selectedContainer.classList.add('selector-search');
this.input.placeholder = peerType == 'contacts' ? 'Add People...' : 'Select chat'; this.input.placeholder = !peerType.includes('dialogs') ? 'Add People...' : 'Select chat';
this.input.type = 'text'; this.input.type = 'text';
this.selectedContainer.append(this.input); this.selectedContainer.append(this.input);
topContainer.append(this.selectedContainer); topContainer.append(this.selectedContainer);
@ -94,27 +97,23 @@ export class AppSelectPeers {
}); });
this.input.addEventListener('input', () => { this.input.addEventListener('input', () => {
let value = this.input.value; const value = this.input.value;
if(this.query != value) { if(this.query != value) {
if(this.peerType == 'contacts' || this.peerType == 'both') { if(this.peerType.includes('contacts')) {
delete this.loadedWhat.contacts; delete this.loadedWhat.contacts;
this.cachedContacts = null; this.cachedContacts = null;
} }
if(this.peerType == 'dialogs' || this.peerType == 'both') { //if(this.peerType.includes('dialogs')) {
delete this.loadedWhat.dialogs; delete this.loadedWhat.dialogs;
delete this.loadedWhat.archived; delete this.loadedWhat.archived;
this.folderID = 0; this.folderID = 0;
this.offsetIndex = 0; this.offsetIndex = 0;
} //}
this.promise = null; this.promise = null;
this.list.innerHTML = ''; this.list.innerHTML = '';
this.query = value; this.query = value;
if(this.query && 'saved messages'.includes(this.query.toLowerCase())) {
this.renderResultsFunc([$rootScope.myID]);
}
//console.log('selectPeers input:', this.query); //console.log('selectPeers input:', this.query);
this.getMoreResults(); this.getMoreResults();
@ -151,15 +150,20 @@ export class AppSelectPeers {
this.promise = appMessagesManager.getConversations(this.query, this.offsetIndex, pageCount, this.folderID); this.promise = appMessagesManager.getConversations(this.query, this.offsetIndex, pageCount, this.folderID);
const value = await this.promise; const value = await this.promise;
this.promise = null;
let dialogs = value.dialogs as Dialog[]; let dialogs = value.dialogs as Dialog[];
if(dialogs.length) { if(dialogs.length) {
const newOffsetIndex = dialogs[dialogs.length - 1].index || 0; const newOffsetIndex = dialogs[dialogs.length - 1].index || 0;
dialogs = dialogs.filter(d => d.peerID != this.myID); dialogs = dialogs.slice();
if(!this.offsetIndex && this.folderID == 0 && !this.query) { dialogs.findAndSplice(d => d.peerID == $rootScope.myID); // no my account
if(!this.offsetIndex && this.folderID == 0 &&
(!this.query || 'saved messages'.includes(this.query.toLowerCase())) &&
this.peerType.includes('dialogs')) {
dialogs.unshift({ dialogs.unshift({
peerID: this.myID, peerID: $rootScope.myID,
pFlags: {} pFlags: {}
} as any); } as any);
} }
@ -173,19 +177,15 @@ export class AppSelectPeers {
this.offsetIndex = 0; this.offsetIndex = 0;
this.folderID = 1; this.folderID = 1;
this.promise = null;
return this.getMoreDialogs(); return this.getMoreDialogs();
} else { } else {
this.loadedWhat.archived = true; this.loadedWhat.archived = true;
if(!this.loadedWhat.contacts && this.peerType == 'both') { if(!this.loadedWhat.contacts && this.peerType.includes('contacts')) {
this.promise = null;
return this.getMoreContacts(); return this.getMoreContacts();
} }
} }
} }
this.promise = null;
} }
private async getMoreContacts() { private async getMoreContacts() {
@ -196,9 +196,16 @@ export class AppSelectPeers {
} }
if(!this.cachedContacts) { if(!this.cachedContacts) {
/* const promises: Promise<any>[] = [appUsersManager.getContacts(this.query)];
if(!this.peerType.includes('dialogs')) {
promises.push(appMessagesManager.getConversationsAll());
}
this.promise = Promise.all(promises);
this.cachedContacts = (await this.promise)[0].slice(); */
this.promise = appUsersManager.getContacts(this.query); this.promise = appUsersManager.getContacts(this.query);
this.cachedContacts = (await this.promise).slice(); this.cachedContacts = (await this.promise).slice();
this.cachedContacts.findAndSplice(userID => userID == this.myID); // no my account this.cachedContacts.findAndSplice(userID => userID == $rootScope.myID); // no my account
this.promise = null; this.promise = null;
} }
@ -206,14 +213,26 @@ export class AppSelectPeers {
const pageCount = appPhotosManager.windowH / 72 * 1.25 | 0; const pageCount = appPhotosManager.windowH / 72 * 1.25 | 0;
const arr = this.cachedContacts.splice(0, pageCount); const arr = this.cachedContacts.splice(0, pageCount);
this.renderResultsFunc(arr); this.renderResultsFunc(arr);
} else { }
if(!this.cachedContacts.length) {
this.loadedWhat.contacts = true; this.loadedWhat.contacts = true;
// need to load non-contacts
if(!this.peerType.includes('dialogs')) {
return this.getMoreDialogs();
}
} }
} }
private getMoreResults() { private getMoreResults() {
const promises: Promise<any>[] = []; const promises: Promise<any>[] = [];
if(this.peerType == 'dialogs' || this.peerType == 'both') {
if(!loadedAllDialogs) {
promises.push(appMessagesManager.getConversationsAll());
}
if((this.peerType.includes('dialogs') || this.loadedWhat.contacts) && !this.loadedWhat.archived) { // to load non-contacts
promises.push(this.getMoreDialogs()); promises.push(this.getMoreDialogs());
if(!this.loadedWhat.archived) { if(!this.loadedWhat.archived) {
@ -221,7 +240,7 @@ export class AppSelectPeers {
} }
} }
if(this.peerType == 'contacts' || this.peerType == 'both') { if(this.peerType.includes('contacts') && !this.loadedWhat.contacts) {
promises.push(this.getMoreContacts()); promises.push(this.getMoreContacts());
} }
@ -230,6 +249,14 @@ export class AppSelectPeers {
private renderResults(peerIDs: number[]) { private renderResults(peerIDs: number[]) {
//console.log('will renderResults:', peerIDs); //console.log('will renderResults:', peerIDs);
// оставим только неконтакты с диалогов
if(!this.peerType.includes('dialogs') && this.loadedWhat.contacts) {
peerIDs = peerIDs.filter(peerID => {
return appUsersManager.isNonContactUser(peerID);
});
}
peerIDs.forEach(peerID => { peerIDs.forEach(peerID => {
const {dom} = appDialogsManager.addDialog(peerID, this.scrollable, false, false); const {dom} = appDialogsManager.addDialog(peerID, this.scrollable, false, false);
@ -240,7 +267,7 @@ export class AppSelectPeers {
let subtitle = ''; let subtitle = '';
if(peerID < 0) { if(peerID < 0) {
subtitle = appChatsManager.getChatMembersString(-peerID); subtitle = appChatsManager.getChatMembersString(-peerID);
} else if(peerID == this.myID) { } else if(peerID == $rootScope.myID) {
subtitle = 'chat with yourself'; subtitle = 'chat with yourself';
} else { } else {
subtitle = appUsersManager.getUserStatusString(peerID); subtitle = appUsersManager.getUserStatusString(peerID);

14
src/components/sidebarLeft/addMembers.ts

@ -56,21 +56,13 @@ export default class AppAddMembersTab implements SliderTab {
this.onCloseAfterTimeout(); this.onCloseAfterTimeout();
this.selector = new AppSelectPeers(this.contentDiv, skippable ? null : (length) => { this.selector = new AppSelectPeers(this.contentDiv, skippable ? null : (length) => {
if(length) { this.nextBtn.classList.toggle('is-visible', !!length);
this.nextBtn.classList.add('is-visible'); }, ['contacts']);
} else {
this.nextBtn.classList.remove('is-visible');
}
}, 'contacts');
this.nextBtn.innerHTML = ''; this.nextBtn.innerHTML = '';
this.nextBtn.disabled = false; this.nextBtn.disabled = false;
this.nextBtn.classList.add('tgico-next'); this.nextBtn.classList.add('tgico-next');
if(skippable) { this.nextBtn.classList.toggle('is-visible', skippable);
this.nextBtn.classList.add('is-visible');
} else {
this.nextBtn.classList.remove('is-visible');
}
appSidebarLeft.selectTab(AppSidebarLeft.SLIDERITEMSIDS.addMembers); appSidebarLeft.selectTab(AppSidebarLeft.SLIDERITEMSIDS.addMembers);
} }

7
src/components/sidebarLeft/editFolder.ts

@ -8,6 +8,8 @@ import { copy, deepEqual } from "../../lib/utils";
import { toast } from "../toast"; import { toast } from "../toast";
import { ripple } from "../ripple"; import { ripple } from "../ripple";
const MAX_FOLDER_NAME_LENGTH = 12;
export default class AppEditFolderTab implements SliderTab { export default class AppEditFolderTab implements SliderTab {
public container: HTMLElement; public container: HTMLElement;
private closeBtn: HTMLElement; private closeBtn: HTMLElement;
@ -120,6 +122,11 @@ export default class AppEditFolderTab implements SliderTab {
}); });
this.nameInput.addEventListener('input', () => { this.nameInput.addEventListener('input', () => {
if(this.nameInput.value.length > MAX_FOLDER_NAME_LENGTH) {
this.nameInput.value = this.nameInput.value.slice(0, MAX_FOLDER_NAME_LENGTH);
return;
}
this.filter.title = this.nameInput.value; this.filter.title = this.nameInput.value;
this.nameInput.classList.remove('error'); this.nameInput.classList.remove('error');

2
src/components/sidebarLeft/includedChats.ts

@ -155,7 +155,7 @@ export default class AppIncludedChatsTab implements SliderTab {
const selectedPeers = (this.type == 'included' ? filter.include_peers : filter.exclude_peers).slice(); const selectedPeers = (this.type == 'included' ? filter.include_peers : filter.exclude_peers).slice();
this.selector = new AppSelectPeers(this.container, this.onSelectChange, 'dialogs', null, this.renderResults); this.selector = new AppSelectPeers(this.container, this.onSelectChange, ['dialogs'], null, this.renderResults);
this.selector.selected = new Set(selectedPeers); this.selector.selected = new Set(selectedPeers);
this.selector.input.placeholder = 'Search'; this.selector.input.placeholder = 'Search';

55
src/lib/appManagers/appDialogsManager.ts

@ -1,4 +1,4 @@
import { findUpClassName, $rootScope, escapeRegExp, whichChild, findUpTag, cancelEvent } from "../utils"; import { findUpClassName, $rootScope, escapeRegExp, whichChild, findUpTag, cancelEvent, positionElementByIndex } from "../utils";
import appImManager, { AppImManager } from "./appImManager"; import appImManager, { AppImManager } from "./appImManager";
import appPeersManager from './appPeersManager'; import appPeersManager from './appPeersManager';
import appMessagesManager, { AppMessagesManager, Dialog, DialogFilter } from "./appMessagesManager"; import appMessagesManager, { AppMessagesManager, Dialog, DialogFilter } from "./appMessagesManager";
@ -357,7 +357,8 @@ export class AppDialogsManager {
[filterID: string]: { [filterID: string]: {
menu: HTMLElement, menu: HTMLElement,
container: HTMLElement, container: HTMLElement,
unread: HTMLElement unread: HTMLElement,
title: HTMLElement
} }
} = {}; } = {};
private showFiltersTimeout: number; private showFiltersTimeout: number;
@ -407,7 +408,7 @@ export class AppDialogsManager {
this.setListClickListener(this.chatList, null, true); this.setListClickListener(this.chatList, null, true);
if(testScroll) { /* if(testScroll) {
let i = 0; let i = 0;
let add = () => { let add = () => {
let li = document.createElement('li'); let li = document.createElement('li');
@ -421,7 +422,7 @@ export class AppDialogsManager {
add(); add();
} }
(window as any).addElement = add; (window as any).addElement = add;
} } */
$rootScope.$on('user_update', (e: CustomEvent) => { $rootScope.$on('user_update', (e: CustomEvent) => {
let userID = e.detail; let userID = e.detail;
@ -543,6 +544,7 @@ export class AppDialogsManager {
const filter: DialogFilter = e.detail; const filter: DialogFilter = e.detail;
if(!this.filtersRendered[filter.id]) { if(!this.filtersRendered[filter.id]) {
this.addFilter(filter); this.addFilter(filter);
return;
} else if(filter.id == this.filterID) { // это нет тут смысла вызывать, так как будет dialogs_multiupdate } else if(filter.id == this.filterID) { // это нет тут смысла вызывать, так как будет dialogs_multiupdate
//this.validateForFilter(); //this.validateForFilter();
const folder = appMessagesManager.dialogsStorage.getFolder(filter.id); const folder = appMessagesManager.dialogsStorage.getFolder(filter.id);
@ -553,6 +555,9 @@ export class AppDialogsManager {
} }
this.setFiltersUnreadCount(); this.setFiltersUnreadCount();
} }
const elements = this.filtersRendered[filter.id];
elements.title.innerHTML = RichTextProcessor.wrapEmojiText(filter.title);
}); });
$rootScope.$on('filter_delete', (e: CustomEvent) => { $rootScope.$on('filter_delete', (e: CustomEvent) => {
@ -704,21 +709,25 @@ export class AppDialogsManager {
const li = document.createElement('li'); const li = document.createElement('li');
const span = document.createElement('span'); const span = document.createElement('span');
span.innerHTML = RichTextProcessor.wrapEmojiText(filter.title); const titleSpan = document.createElement('span');
titleSpan.innerHTML = RichTextProcessor.wrapEmojiText(filter.title);
const unreadSpan = document.createElement('span'); const unreadSpan = document.createElement('span');
unreadSpan.classList.add('unread-count'); unreadSpan.classList.add('unread-count');
const i = document.createElement('i'); const i = document.createElement('i');
span.append(unreadSpan, i); span.append(titleSpan, unreadSpan, i);
li.append(span); li.append(span);
ripple(li); ripple(li);
this.folders.menu.firstElementChild.append(li); const containerToAppend = this.folders.menu.firstElementChild as HTMLUListElement;
positionElementByIndex(li, containerToAppend, filter.orderIndex + 1); // because 0 is All
//containerToAppend.append(li);
const ul = document.createElement('ul'); const ul = document.createElement('ul');
const div = document.createElement('div'); const div = document.createElement('div');
div.append(ul); div.append(ul);
div.dataset.filterID = '' + filter.id; div.dataset.filterID = '' + filter.id;
this.folders.container.append(div); //this.folders.container.append(div);
positionElementByIndex(div, this.folders.container, filter.orderIndex + 1); // because 0 is All
this.chatLists[filter.id] = ul; this.chatLists[filter.id] = ul;
this.setListClickListener(ul, null, true); this.setListClickListener(ul, null, true);
@ -734,7 +743,8 @@ export class AppDialogsManager {
this.filtersRendered[filter.id] = { this.filtersRendered[filter.id] = {
menu: li, menu: li,
container: div, container: div,
unread: unreadSpan unread: unreadSpan,
title: titleSpan
}; };
} }
@ -750,6 +760,8 @@ export class AppDialogsManager {
container.append(this.chatsPreloader); container.append(this.chatsPreloader);
} }
//return;
const storage = appMessagesManager.dialogsStorage.getFolder(folderID); const storage = appMessagesManager.dialogsStorage.getFolder(folderID);
let offsetIndex = 0; let offsetIndex = 0;
@ -862,28 +874,11 @@ export class AppDialogsManager {
pos = appMessagesManager.dialogsStorage.getDialog(dialog.peerID, this.filterID)[1]; pos = appMessagesManager.dialogsStorage.getDialog(dialog.peerID, this.filterID)[1];
} }
let prevPos = whichChild(dom.listEl); if(positionElementByIndex(dom.listEl, this.chatList, pos)) {
this.scroll.reorder();
/* let wrongFolder = (dialog.folder_id == 1 && this.chatList == dom.listEl.parentElement) || (dialog.folder_id == 0 && this.chatListArchived == dom.listEl.parentElement);
let wrongFolder = false;
if(wrongFolder) prevPos = 0xFFFF; */
if(prevPos == pos) { this.log.debug('setDialogPosition:', dialog, dom, pos);
return;
} else if(prevPos < pos) { // was higher
pos += 1;
}
const chatList = this.chatList;
if(chatList.childElementCount > pos) {
chatList.insertBefore(dom.listEl, chatList.children[pos]);
} else {
chatList.append(dom.listEl);
} }
this.scroll.reorder();
this.log.debug('setDialogPosition:', dialog, dom, pos);
} }
/* public setPinnedDelimiter() { /* public setPinnedDelimiter() {

13
src/lib/appManagers/appDocsManager.ts

@ -5,6 +5,7 @@ import { MTDocument, inputDocumentFileLocation, MTPhotoSize } from '../../types'
import { getFileNameByLocation } from '../bin_utils'; import { getFileNameByLocation } from '../bin_utils';
import appDownloadManager, { DownloadBlob } from './appDownloadManager'; import appDownloadManager, { DownloadBlob } from './appDownloadManager';
import appPhotosManager from './appPhotosManager'; import appPhotosManager from './appPhotosManager';
import { isServiceWorkerSupported } from '../config';
class AppDocsManager { class AppDocsManager {
private docs: {[docID: string]: MTDocument} = {}; private docs: {[docID: string]: MTDocument} = {};
@ -122,11 +123,13 @@ class AppDocsManager {
} }
} }
if((doc.type == 'gif' && doc.size > 8e6) || doc.type == 'audio' || doc.type == 'video') { if(isServiceWorkerSupported) {
doc.supportsStreaming = true; if((doc.type == 'gif' && doc.size > 8e6) || doc.type == 'audio' || doc.type == 'video') {
doc.supportsStreaming = true;
if(!doc.url) {
doc.url = this.getFileURL(doc); if(!doc.url) {
doc.url = this.getFileURL(doc);
}
} }
} }

2
src/lib/appManagers/appMediaViewer.ts

@ -818,7 +818,7 @@ export class AppMediaViewer {
this.log('openMedia doc:', message); this.log('openMedia doc:', message);
const media = message.media.photo || message.media.document || message.media.webpage.document || message.media.webpage.photo; const media = message.media.photo || message.media.document || message.media.webpage.document || message.media.webpage.photo;
const isVideo = media.mime_type == 'video/mp4'; const isVideo = (media as MTDocument).type == 'video';
const isFirstOpen = !this.peerID; const isFirstOpen = !this.peerID;
if(isFirstOpen) { if(isFirstOpen) {

40
src/lib/appManagers/appMessagesManager.ts

@ -255,10 +255,13 @@ export type DialogFilter = {
emoticon?: string, emoticon?: string,
pinned_peers: number[], pinned_peers: number[],
include_peers: number[], include_peers: number[],
exclude_peers: number[] exclude_peers: number[],
orderIndex?: number
}; };
export class FiltersStorage { export class FiltersStorage {
public filters: {[filterID: string]: DialogFilter} = {}; public filters: {[filterID: string]: DialogFilter} = {};
public orderIndex = 0;
constructor() { constructor() {
$rootScope.$on('apiUpdate', (e: CustomEvent) => { $rootScope.$on('apiUpdate', (e: CustomEvent) => {
@ -269,7 +272,7 @@ export class FiltersStorage {
public handleUpdate(update: any) { public handleUpdate(update: any) {
switch(update._) { switch(update._) {
case 'updateDialogFilter': { case 'updateDialogFilter': {
console.log('updateDialogFilter', update); //console.log('updateDialogFilter', update);
if(update.filter) { if(update.filter) {
this.saveDialogFilter(update.filter); this.saveDialogFilter(update.filter);
} else if(this.filters[update.id]) { // Папка удалена } else if(this.filters[update.id]) { // Папка удалена
@ -433,7 +436,7 @@ export class FiltersStorage {
id: filter.id, id: filter.id,
filter: remove ? undefined : this.getOutputDialogFilter(filter) filter: remove ? undefined : this.getOutputDialogFilter(filter)
}).then((bool: boolean) => { // возможно нужна проверка и откат, если результат не ТРУ }).then((bool: boolean) => { // возможно нужна проверка и откат, если результат не ТРУ
console.log('updateDialogFilter bool:', bool); //console.log('updateDialogFilter bool:', bool);
if(bool) { if(bool) {
/* if(!this.filters[filter.id]) { /* if(!this.filters[filter.id]) {
@ -543,10 +546,22 @@ export class FiltersStorage {
this.filters[filter.id] = filter; this.filters[filter.id] = filter;
} }
this.setOrderIndex(filter);
if(update) { if(update) {
$rootScope.$broadcast('filter_update', filter); $rootScope.$broadcast('filter_update', filter);
} }
} }
public setOrderIndex(filter: DialogFilter) {
if(filter.hasOwnProperty('orderIndex')) {
if(filter.orderIndex > this.orderIndex) {
this.orderIndex = filter.orderIndex;
}
} else {
filter.orderIndex = this.orderIndex++;
}
}
} }
export class AppMessagesManager { export class AppMessagesManager {
@ -1848,6 +1863,25 @@ export class AppMessagesManager {
return false; return false;
} }
public async getConversationsAll(query = '') {
const limit = 100, outDialogs: Dialog[] = [];
for(let folderID = 0; folderID < 2; ++folderID) {
let offsetIndex = 0;
for(;;) {
const {dialogs} = await appMessagesManager.getConversations(query, offsetIndex, limit, folderID);
if(dialogs.length) {
outDialogs.push(...dialogs);
offsetIndex = dialogs[dialogs.length - 1].index || 0;
} else {
break;
}
}
}
return outDialogs;
}
public getConversations(query = '', offsetIndex?: number, limit = 20, folderID = 0) { public getConversations(query = '', offsetIndex?: number, limit = 20, folderID = 0) {
const realFolderID = folderID > 1 ? 0 : folderID; const realFolderID = folderID > 1 ? 0 : folderID;
let curDialogStorage = this.dialogsStorage.getFolder(folderID); let curDialogStorage = this.dialogsStorage.getFolder(folderID);

2
src/lib/appManagers/appPhotosManager.ts

@ -176,7 +176,7 @@ export class AppPhotosManager {
//console.log('setAttachmentSize', photo, photo.sizes[0].bytes, div); //console.log('setAttachmentSize', photo, photo.sizes[0].bytes, div);
let sizes = (photo as MTPhoto).sizes || (photo as MTDocument).thumbs; let sizes = (photo as MTPhoto).sizes || (photo as MTDocument).thumbs;
if((!photo.downloaded || (photo as MTDocument).type == 'video' || (photo as MTDocument).type == 'gif') && !isSticker && sizes && sizes[0].bytes && !dontRenderPreview) { if((!photo.downloaded || (photo as MTDocument).type == 'video' || (photo as MTDocument).type == 'gif') && !isSticker && sizes?.length && sizes[0].bytes && !dontRenderPreview) {
this.setAttachmentPreview(sizes[0].bytes, element, isSticker); this.setAttachmentPreview(sizes[0].bytes, element, isSticker);
} }

12
src/lib/appManagers/appStateManager.ts

@ -23,7 +23,7 @@ type State = Partial<{
recentEmoji: string[], recentEmoji: string[],
topPeers: number[], topPeers: number[],
recentSearch: number[] recentSearch: number[]
}> }>;
export class AppStateManager { export class AppStateManager {
public loaded: Promise<any>; public loaded: Promise<any>;
@ -42,7 +42,11 @@ export class AppStateManager {
const time = Date.now(); const time = Date.now();
if((state?.stateCreatedTime ?? 0) + REFRESH_EVERY < time) { if((state?.stateCreatedTime ?? 0) + REFRESH_EVERY < time) {
this.log('will refresh state', state.stateCreatedTime, time); this.log('will refresh state', state.stateCreatedTime, time);
state = {}; (['dialogs', 'allDialogsLoaded', 'messages', 'contactsList', 'stateCreatedTime',
'updates', 'maxSeenMsgID', 'filters', 'topPeers'] as any as Array<keyof State>).forEach(key => {
delete state[key];
});
//state = {};
} }
const {dialogs, allDialogsLoaded, peers, messages, contactsList, maxSeenMsgID, updates, filters} = state; const {dialogs, allDialogsLoaded, peers, messages, contactsList, maxSeenMsgID, updates, filters} = state;
@ -212,4 +216,8 @@ export class AppStateManager {
} }
const appStateManager = new AppStateManager(); const appStateManager = new AppStateManager();
// @ts-ignore
if(process.env.NODE_ENV != 'production') {
(window as any).appStateManager = appStateManager;
}
export default appStateManager; export default appStateManager;

25
src/lib/appManagers/appUsersManager.ts

@ -108,9 +108,9 @@ export class AppUsersManager {
} else console.warn('No user by id:', userID); } else console.warn('No user by id:', userID);
break break
case 'updateContactLink': /* case 'updateContactLink':
this.onContactUpdated(update.user_id, update.my_link._ == 'contactLinkContact'); this.onContactUpdated(update.user_id, update.my_link._ == 'contactLinkContact');
break; break; */
} }
}); });
} }
@ -382,6 +382,19 @@ export class AppUsersManager {
return this.users[id] && this.users[id].pFlags.bot; return this.users[id] && this.users[id].pFlags.bot;
} }
public isContact(id: number) {
return this.contactsList.has(id);
}
public isRegularUser(id: number) {
const user = this.users[id];
return user && !this.isBot(id) && !user.pFlags.deleted && !user.pFlags.support;
}
public isNonContactUser(id: number) {
return this.isRegularUser(id) && !this.isContact(id) && id != $rootScope.myID;
}
public hasUser(id: number, allowMin?: boolean) { public hasUser(id: number, allowMin?: boolean) {
var user = this.users[id]; var user = this.users[id];
return isObject(user) && (allowMin || !user.pFlags.min); return isObject(user) && (allowMin || !user.pFlags.min);
@ -512,7 +525,7 @@ export class AppUsersManager {
}) })
} */ } */
public deleteContacts(userIDs: number[]) { /* public deleteContacts(userIDs: number[]) {
var ids: any[] = []; var ids: any[] = [];
userIDs.forEach((userID) => { userIDs.forEach((userID) => {
ids.push(this.getUserInput(userID)); ids.push(this.getUserInput(userID));
@ -525,7 +538,7 @@ export class AppUsersManager {
this.onContactUpdated(userID, false); this.onContactUpdated(userID, false);
}); });
}); });
} } */
public getTopPeers(): Promise<number[]> { public getTopPeers(): Promise<number[]> {
if(this.getPeersPromise) return this.getPeersPromise; if(this.getPeersPromise) return this.getPeersPromise;
@ -576,7 +589,7 @@ export class AppUsersManager {
}); });
} }
public onContactUpdated(userID: number, isContact: boolean) { /* public onContactUpdated(userID: number, isContact: boolean) {
userID = parseInt('' + userID); userID = parseInt('' + userID);
if(Array.isArray(this.contactsList)) { if(Array.isArray(this.contactsList)) {
@ -594,7 +607,7 @@ export class AppUsersManager {
$rootScope.$broadcast('contacts_update', userID); $rootScope.$broadcast('contacts_update', userID);
} }
} }
} } */
public setUserStatus(userID: number, offline: boolean) { public setUserStatus(userID: number, offline: boolean) {
if(this.isBot(userID)) { if(this.isBot(userID)) {

2
src/lib/config.ts

@ -96,6 +96,8 @@ export const mediaSizes = new MediaSizes();
// @ts-ignore // @ts-ignore
export const touchSupport = ('ontouchstart' in window) || (window.DocumentTouch && document instanceof DocumentTouch); export const touchSupport = ('ontouchstart' in window) || (window.DocumentTouch && document instanceof DocumentTouch);
export const isServiceWorkerSupported = 'serviceWorker' in navigator;
const Config = { const Config = {
Emoji, Emoji,
LatinizeMap, LatinizeMap,

3
src/lib/mtproto/mtprotoworker.ts

@ -6,6 +6,7 @@ import webpWorkerController from '../webp/webpWorkerController';
import MTProtoWorker from 'worker-loader!./mtproto.worker'; import MTProtoWorker from 'worker-loader!./mtproto.worker';
import type { DownloadOptions } from './apiFileManager'; import type { DownloadOptions } from './apiFileManager';
import type { ServiceWorkerTask, ServiceWorkerTaskResponse } from './mtproto.service'; import type { ServiceWorkerTask, ServiceWorkerTaskResponse } from './mtproto.service';
import { isServiceWorkerSupported } from '../config';
type Task = { type Task = {
taskID: number, taskID: number,
@ -42,6 +43,8 @@ class ApiManagerProxy extends CryptoWorkerMethods {
} }
private registerServiceWorker() { private registerServiceWorker() {
if(!isServiceWorkerSupported) return;
navigator.serviceWorker.register('./sw.js', {scope: './'}).then(registration => { navigator.serviceWorker.register('./sw.js', {scope: './'}).then(registration => {
}, (err) => { }, (err) => {

22
src/lib/utils.ts

@ -375,6 +375,10 @@ export function getObjectKeysAndSort(object: any, sort: 'asc' | 'desc' = 'asc')
} }
export function whichChild(elem: Node) { export function whichChild(elem: Node) {
if(!elem.parentNode) {
return -1;
}
let i = 0; let i = 0;
// @ts-ignore // @ts-ignore
while((elem = elem.previousElementSibling) != null) ++i; while((elem = elem.previousElementSibling) != null) ++i;
@ -533,3 +537,21 @@ export function getFileURL(type: FileURLType, options: DownloadOptions) {
return '/' + type + '/' + encoded; return '/' + type + '/' + encoded;
} }
export function positionElementByIndex(element: HTMLElement, container: HTMLElement, pos: number) {
const prevPos = whichChild(element);
if(prevPos == pos) {
return false;
} else if(prevPos != -1 && prevPos < pos) { // was higher
pos += 1;
}
if(container.childElementCount > pos) {
container.insertBefore(element, container.children[pos]);
} else {
container.append(element);
}
return true;
}

7
src/scss/partials/_chatBubble.scss

@ -813,6 +813,13 @@ $bubble-margin: .25rem;
.time { .time {
width: unset; width: unset;
} }
/* @include respond-to(handhelds) {
.preloader-container .you-spin-me-round {
margin-top: 1px;
margin-left: 2px;
}
} */
} }
.message.contact-message { .message.contact-message {

4
src/scss/partials/_leftSidebar.scss

@ -70,6 +70,10 @@
position: relative; position: relative;
} }
#folders-container {
min-height: 100%;
}
.sidebar-slider { .sidebar-slider {
height: 100%; height: 100%;
} }

9
src/scss/partials/_rightSidebar.scss

@ -411,6 +411,15 @@
min-height: 60px; min-height: 60px;
} }
@include respond-to(handhelds) {
.preloader-container {
width: 40px;
height: 40px;
top: 9px;
left: 2px;
}
}
.audio { .audio {
padding-bottom: 26px; padding-bottom: 26px;
padding-left: 61px; padding-left: 61px;

24
src/scss/style.scss

@ -767,6 +767,21 @@ avatar-element {
max-width: 100%; max-width: 100%;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
@include respond-to(handhelds) {
&-download {
/* background: transparent; */
margin-left: 2px;
margin-top: 1px;
}
&.is-voice {
.audio-download {
margin: 0;
}
}
}
} }
.avatar-edit { .avatar-edit {
@ -1445,15 +1460,6 @@ img.emoji {
// } // }
// } // }
.profile-content #content-audio .preloader-container {
@include respond-to(handhelds) {
width: 40px;
height: 40px;
top: 10px;
left: 3px;
}
}
.btn-disabled { .btn-disabled {
pointer-events: none !important; pointer-events: none !important;
cursor: default !important; cursor: default !important;

2
webpack.common.js

@ -6,7 +6,7 @@ const postcssPresetEnv = require('postcss-preset-env');
const ServiceWorkerWebpackPlugin = require('serviceworker-webpack-plugin'); const ServiceWorkerWebpackPlugin = require('serviceworker-webpack-plugin');
const fs = require('fs'); const fs = require('fs');
const allowedIPs = ['195.66.140.39', '192.168.31.144', '127.0.0.1', '192.168.31.1', '192.168.31.192', '176.100.18.181', '46.219.250.22', '193.42.119.184', '46.133.168.67', '78.26.144.197', '46.133.225.88']; const allowedIPs = ['195.66.140.39', '192.168.31.144', '127.0.0.1', '192.168.31.1', '192.168.31.192', '176.100.18.181', '46.219.250.22', '193.42.119.184', '46.133.168.67', '78.26.144.197', '46.133.225.88', '128.124.170.79'];
const devMode = process.env.NODE_ENV !== 'production'; const devMode = process.env.NODE_ENV !== 'production';
const useLocal = false; const useLocal = false;

Loading…
Cancel
Save