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. 51
      src/lib/appManagers/appDialogsManager.ts
  7. 3
      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 { @@ -73,7 +73,7 @@ class AppForward {
} else {
this.sendBtn.classList.remove('is-visible');
}
}, 'both', () => {
}, ['dialogs', 'contacts'], () => {
//console.log('forward rendered:', this.container.querySelector('.selector ul').childElementCount);
this.sidebarWasActive = appSidebarRight.sidebarEl.classList.contains('active');
appSidebarRight.toggleSidebar(true);

79
src/components/appSelectPeers.ts

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

14
src/components/sidebarLeft/addMembers.ts

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

7
src/components/sidebarLeft/editFolder.ts

@ -8,6 +8,8 @@ import { copy, deepEqual } from "../../lib/utils"; @@ -8,6 +8,8 @@ import { copy, deepEqual } from "../../lib/utils";
import { toast } from "../toast";
import { ripple } from "../ripple";
const MAX_FOLDER_NAME_LENGTH = 12;
export default class AppEditFolderTab implements SliderTab {
public container: HTMLElement;
private closeBtn: HTMLElement;
@ -120,6 +122,11 @@ export default class AppEditFolderTab implements SliderTab { @@ -120,6 +122,11 @@ export default class AppEditFolderTab implements SliderTab {
});
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.nameInput.classList.remove('error');

2
src/components/sidebarLeft/includedChats.ts

@ -155,7 +155,7 @@ export default class AppIncludedChatsTab implements SliderTab { @@ -155,7 +155,7 @@ export default class AppIncludedChatsTab implements SliderTab {
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.input.placeholder = 'Search';

51
src/lib/appManagers/appDialogsManager.ts

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

3
src/lib/appManagers/appDocsManager.ts

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

2
src/lib/appManagers/appMediaViewer.ts

@ -818,7 +818,7 @@ export class AppMediaViewer { @@ -818,7 +818,7 @@ export class AppMediaViewer {
this.log('openMedia doc:', message);
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;
if(isFirstOpen) {

40
src/lib/appManagers/appMessagesManager.ts

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

2
src/lib/appManagers/appPhotosManager.ts

@ -176,7 +176,7 @@ export class AppPhotosManager { @@ -176,7 +176,7 @@ export class AppPhotosManager {
//console.log('setAttachmentSize', photo, photo.sizes[0].bytes, div);
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);
}

12
src/lib/appManagers/appStateManager.ts

@ -23,7 +23,7 @@ type State = Partial<{ @@ -23,7 +23,7 @@ type State = Partial<{
recentEmoji: string[],
topPeers: number[],
recentSearch: number[]
}>
}>;
export class AppStateManager {
public loaded: Promise<any>;
@ -42,7 +42,11 @@ export class AppStateManager { @@ -42,7 +42,11 @@ export class AppStateManager {
const time = Date.now();
if((state?.stateCreatedTime ?? 0) + REFRESH_EVERY < 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;
@ -212,4 +216,8 @@ export class AppStateManager { @@ -212,4 +216,8 @@ export class AppStateManager {
}
const appStateManager = new AppStateManager();
// @ts-ignore
if(process.env.NODE_ENV != 'production') {
(window as any).appStateManager = appStateManager;
}
export default appStateManager;

25
src/lib/appManagers/appUsersManager.ts

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

2
src/lib/config.ts

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

3
src/lib/mtproto/mtprotoworker.ts

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

22
src/lib/utils.ts

@ -375,6 +375,10 @@ export function getObjectKeysAndSort(object: any, sort: 'asc' | 'desc' = 'asc') @@ -375,6 +375,10 @@ export function getObjectKeysAndSort(object: any, sort: 'asc' | 'desc' = 'asc')
}
export function whichChild(elem: Node) {
if(!elem.parentNode) {
return -1;
}
let i = 0;
// @ts-ignore
while((elem = elem.previousElementSibling) != null) ++i;
@ -533,3 +537,21 @@ export function getFileURL(type: FileURLType, options: DownloadOptions) { @@ -533,3 +537,21 @@ export function getFileURL(type: FileURLType, options: DownloadOptions) {
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; @@ -813,6 +813,13 @@ $bubble-margin: .25rem;
.time {
width: unset;
}
/* @include respond-to(handhelds) {
.preloader-container .you-spin-me-round {
margin-top: 1px;
margin-left: 2px;
}
} */
}
.message.contact-message {

4
src/scss/partials/_leftSidebar.scss

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

9
src/scss/partials/_rightSidebar.scss

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

24
src/scss/style.scss

@ -767,6 +767,21 @@ avatar-element { @@ -767,6 +767,21 @@ avatar-element {
max-width: 100%;
text-overflow: ellipsis;
}
@include respond-to(handhelds) {
&-download {
/* background: transparent; */
margin-left: 2px;
margin-top: 1px;
}
&.is-voice {
.audio-download {
margin: 0;
}
}
}
}
.avatar-edit {
@ -1445,15 +1460,6 @@ img.emoji { @@ -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 {
pointer-events: none !important;
cursor: default !important;

2
webpack.common.js

@ -6,7 +6,7 @@ const postcssPresetEnv = require('postcss-preset-env'); @@ -6,7 +6,7 @@ const postcssPresetEnv = require('postcss-preset-env');
const ServiceWorkerWebpackPlugin = require('serviceworker-webpack-plugin');
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 useLocal = false;

Loading…
Cancel
Save