Folders almost ready
New CSS Polls
This commit is contained in:
parent
15b114d425
commit
b2ef3c8bda
BIN
public/assets/img/Folders_1.tgs
Normal file
BIN
public/assets/img/Folders_1.tgs
Normal file
Binary file not shown.
BIN
public/assets/img/Folders_2.tgs
Normal file
BIN
public/assets/img/Folders_2.tgs
Normal file
Binary file not shown.
|
@ -1,6 +1,6 @@
|
||||||
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, findUpTag, findUpClassName } from "../lib/utils";
|
import { $rootScope, cancelEvent, findUpClassName, findUpTag, 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";
|
||||||
|
@ -9,15 +9,16 @@ import appPhotosManager from "../lib/appManagers/appPhotosManager";
|
||||||
|
|
||||||
export class AppSelectPeers {
|
export class AppSelectPeers {
|
||||||
public container = document.createElement('div');
|
public container = document.createElement('div');
|
||||||
private list = document.createElement('ul');
|
public list = document.createElement('ul');
|
||||||
private chatsContainer = document.createElement('div');
|
public chatsContainer = document.createElement('div');
|
||||||
private scrollable: Scrollable;
|
public scrollable: Scrollable;
|
||||||
private selectedScrollable: Scrollable;
|
public selectedScrollable: Scrollable;
|
||||||
|
|
||||||
private selectedContainer = document.createElement('div');
|
public selectedContainer = document.createElement('div');
|
||||||
private input = document.createElement('input');
|
public input = document.createElement('input');
|
||||||
|
|
||||||
private selected: {[peerID: number]: HTMLDivElement} = {};
|
//public selected: {[peerID: number]: HTMLElement} = {};
|
||||||
|
public selected = new Set<any>();
|
||||||
|
|
||||||
public freezed = false;
|
public freezed = false;
|
||||||
|
|
||||||
|
@ -29,9 +30,13 @@ export class AppSelectPeers {
|
||||||
private query = '';
|
private query = '';
|
||||||
private cachedContacts: number[];
|
private cachedContacts: number[];
|
||||||
|
|
||||||
constructor(private appendTo: HTMLDivElement, private onChange?: (length: number) => void, private peerType: 'contacts' | 'dialogs' = 'dialogs', onFirstRender?: () => void) {
|
constructor(private appendTo: HTMLElement, private onChange?: (length: number) => void, private peerType: 'contacts' | 'dialogs' = 'dialogs', onFirstRender?: () => void, private renderResultsFunc?: (peerIDs: number[]) => void) {
|
||||||
this.container.classList.add('selector');
|
this.container.classList.add('selector');
|
||||||
|
|
||||||
|
if(!this.renderResultsFunc) {
|
||||||
|
this.renderResultsFunc = this.renderResults;
|
||||||
|
}
|
||||||
|
|
||||||
let topContainer = document.createElement('div');
|
let topContainer = document.createElement('div');
|
||||||
topContainer.classList.add('selector-search-container');
|
topContainer.classList.add('selector-search-container');
|
||||||
|
|
||||||
|
@ -49,27 +54,23 @@ export class AppSelectPeers {
|
||||||
this.scrollable = new Scrollable(this.chatsContainer);
|
this.scrollable = new Scrollable(this.chatsContainer);
|
||||||
this.scrollable.setVirtualContainer(this.list);
|
this.scrollable.setVirtualContainer(this.list);
|
||||||
|
|
||||||
this.list.addEventListener('click', (e) => {
|
this.chatsContainer.addEventListener('click', (e) => {
|
||||||
let target = e.target as HTMLElement;
|
const target = findUpAttribute(e.target, 'data-peerID') as HTMLElement;
|
||||||
cancelEvent(e);
|
cancelEvent(e);
|
||||||
|
|
||||||
|
if(!target) return;
|
||||||
if(this.freezed) return;
|
if(this.freezed) return;
|
||||||
|
|
||||||
if(target.tagName != 'LI') {
|
let key: any = target.getAttribute('data-peerID');
|
||||||
target = findUpTag(target, 'LI');
|
key = +key || key;
|
||||||
}
|
|
||||||
|
|
||||||
if(!target) return;
|
|
||||||
|
|
||||||
let peerID = +target.getAttribute('data-peerID');
|
|
||||||
target.classList.toggle('active');
|
target.classList.toggle('active');
|
||||||
if(peerID in this.selected) {
|
if(this.selected.has(key)) {
|
||||||
this.remove(peerID);
|
this.remove(key);
|
||||||
} else {
|
} else {
|
||||||
this.add(peerID);
|
this.add(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
let checkbox = target.querySelector('input') as HTMLInputElement;
|
const checkbox = target.querySelector('input') as HTMLInputElement;
|
||||||
checkbox.checked = !checkbox.checked;
|
checkbox.checked = !checkbox.checked;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -80,9 +81,13 @@ export class AppSelectPeers {
|
||||||
|
|
||||||
if(!target) return;
|
if(!target) return;
|
||||||
|
|
||||||
let peerID = target.dataset.peerID;
|
const peerID = target.dataset.key;
|
||||||
let li = this.list.querySelector('[data-peerid="' + peerID + '"]') as HTMLElement;
|
const li = this.chatsContainer.querySelector('[data-peerid="' + peerID + '"]') as HTMLElement;
|
||||||
li.click();
|
if(!li) {
|
||||||
|
this.remove(+peerID || peerID);
|
||||||
|
} else {
|
||||||
|
li.click();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.input.addEventListener('input', () => {
|
this.input.addEventListener('input', () => {
|
||||||
|
@ -110,12 +115,15 @@ export class AppSelectPeers {
|
||||||
this.container.append(topContainer, delimiter, this.chatsContainer);
|
this.container.append(topContainer, delimiter, this.chatsContainer);
|
||||||
appendTo.append(this.container);
|
appendTo.append(this.container);
|
||||||
|
|
||||||
let getResultsPromise = this.getMoreResults() as Promise<any>;
|
// WARNING TIMEOUT
|
||||||
if(onFirstRender) {
|
setTimeout(() => {
|
||||||
getResultsPromise.then(() => {
|
let getResultsPromise = this.getMoreResults() as Promise<any>;
|
||||||
onFirstRender();
|
if(onFirstRender) {
|
||||||
});
|
getResultsPromise.then(() => {
|
||||||
}
|
onFirstRender();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getMoreDialogs() {
|
private async getMoreDialogs() {
|
||||||
|
@ -144,7 +152,7 @@ export class AppSelectPeers {
|
||||||
|
|
||||||
this.offsetIndex = newOffsetIndex;
|
this.offsetIndex = newOffsetIndex;
|
||||||
|
|
||||||
this.renderResults(dialogs.map(dialog => dialog.peerID));
|
this.renderResultsFunc(dialogs.map(dialog => dialog.peerID));
|
||||||
|
|
||||||
this.promise = null;
|
this.promise = null;
|
||||||
}
|
}
|
||||||
|
@ -162,7 +170,7 @@ export class AppSelectPeers {
|
||||||
if(this.cachedContacts.length) {
|
if(this.cachedContacts.length) {
|
||||||
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.renderResults(arr);
|
this.renderResultsFunc(arr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +186,10 @@ export class AppSelectPeers {
|
||||||
//console.log('will renderResults:', peerIDs);
|
//console.log('will renderResults:', peerIDs);
|
||||||
peerIDs.forEach(peerID => {
|
peerIDs.forEach(peerID => {
|
||||||
const {dom} = appDialogsManager.addDialog(peerID, this.scrollable, false, false);
|
const {dom} = appDialogsManager.addDialog(peerID, this.scrollable, false, false);
|
||||||
dom.containerEl.insertAdjacentHTML('afterbegin', '<div class="checkbox"><label><input type="checkbox"><span></span></label></div>');
|
|
||||||
|
const selected = this.selected.has(peerID);
|
||||||
|
dom.containerEl.insertAdjacentHTML('afterbegin', `<div class="checkbox"><label><input type="checkbox" ${selected ? 'checked' : ''}><span></span></label></div>`);
|
||||||
|
if(selected) dom.listEl.classList.add('active');
|
||||||
|
|
||||||
let subtitle = '';
|
let subtitle = '';
|
||||||
if(peerID < 0) {
|
if(peerID < 0) {
|
||||||
|
@ -196,40 +207,53 @@ export class AppSelectPeers {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private add(peerID: number) {
|
public add(peerID: any, title?: string) {
|
||||||
|
console.trace('add');
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
div.classList.add('selector-user', 'scale-in');
|
div.classList.add('selector-user', 'scale-in');
|
||||||
div.dataset.peerID = '' + peerID;
|
|
||||||
this.selected[peerID] = div;
|
|
||||||
|
|
||||||
const title = appPeersManager.getPeerTitle(peerID, false, true);
|
|
||||||
|
|
||||||
const avatarEl = document.createElement('avatar-element');
|
const avatarEl = document.createElement('avatar-element');
|
||||||
avatarEl.classList.add('selector-user-avatar', 'tgico');
|
avatarEl.classList.add('selector-user-avatar', 'tgico');
|
||||||
avatarEl.setAttribute('dialog', '1');
|
avatarEl.setAttribute('dialog', '1');
|
||||||
avatarEl.setAttribute('peer', '' + peerID);
|
|
||||||
|
|
||||||
div.innerHTML = title;
|
div.dataset.key = '' + peerID;
|
||||||
|
this.selected.add(peerID);
|
||||||
|
if(typeof(peerID) === 'number') {
|
||||||
|
if(title === undefined) {
|
||||||
|
title = peerID == $rootScope.myID ? 'Saved' : appPeersManager.getPeerTitle(peerID, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
avatarEl.setAttribute('peer', '' + peerID);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(title) {
|
||||||
|
div.innerHTML = title;
|
||||||
|
}
|
||||||
|
|
||||||
div.insertAdjacentElement('afterbegin', avatarEl);
|
div.insertAdjacentElement('afterbegin', avatarEl);
|
||||||
|
|
||||||
this.selectedContainer.insertBefore(div, this.input);
|
this.selectedContainer.insertBefore(div, this.input);
|
||||||
this.selectedScrollable.scrollTop = this.selectedScrollable.scrollHeight;
|
//this.selectedScrollable.scrollTop = this.selectedScrollable.scrollHeight;
|
||||||
this.onChange && this.onChange(Object.keys(this.selected).length);
|
this.selectedScrollable.scrollTo(this.selectedScrollable.scrollHeight, true, true);
|
||||||
|
this.onChange && this.onChange(this.selected.size);
|
||||||
|
|
||||||
|
return div;
|
||||||
}
|
}
|
||||||
|
|
||||||
private remove(peerID: number) {
|
public remove(key: any) {
|
||||||
const div = this.selected[peerID];
|
//const div = this.selected[peerID];
|
||||||
|
const div = this.selectedContainer.querySelector(`[data-key="${key}"]`) as HTMLElement;
|
||||||
div.classList.remove('scale-in');
|
div.classList.remove('scale-in');
|
||||||
void div.offsetWidth;
|
void div.offsetWidth;
|
||||||
div.classList.add('scale-out');
|
div.classList.add('scale-out');
|
||||||
div.addEventListener('animationend', () => {
|
div.addEventListener('animationend', () => {
|
||||||
delete this.selected[peerID];
|
this.selected.delete(key);
|
||||||
div.remove();
|
div.remove();
|
||||||
this.onChange && this.onChange(Object.keys(this.selected).length);
|
this.onChange && this.onChange(this.selected.size);
|
||||||
}, {once: true});
|
}, {once: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
public getSelected() {
|
public getSelected() {
|
||||||
return Object.keys(this.selected).map(p => +p);
|
return [...this.selected];
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -320,8 +320,8 @@ class StickersTab implements EmoticonsTab {
|
||||||
loop: true,
|
loop: true,
|
||||||
autoplay: false,
|
autoplay: false,
|
||||||
animationData: JSON.parse(json),
|
animationData: JSON.parse(json),
|
||||||
width: 40,
|
width: 32,
|
||||||
height: 40
|
height: 32
|
||||||
}, EMOTICONSSTICKERGROUP);
|
}, EMOTICONSSTICKERGROUP);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ let rippleClickID = 0;
|
||||||
export function ripple(elem: HTMLElement, callback: (id: number) => Promise<boolean | void> = () => Promise.resolve(), onEnd: (id: number) => void = null) {
|
export function ripple(elem: HTMLElement, callback: (id: number) => Promise<boolean | void> = () => Promise.resolve(), onEnd: (id: number) => void = null) {
|
||||||
//return;
|
//return;
|
||||||
if(elem.querySelector('.c-ripple')) return;
|
if(elem.querySelector('.c-ripple')) return;
|
||||||
|
elem.classList.add('rp');
|
||||||
|
|
||||||
let r = document.createElement('div');
|
let r = document.createElement('div');
|
||||||
r.classList.add('c-ripple');
|
r.classList.add('c-ripple');
|
||||||
|
@ -250,13 +251,28 @@ export function horizontalMenu(tabs: HTMLElement, content: HTMLElement, onClick?
|
||||||
let prevTabContent: HTMLElement = null;
|
let prevTabContent: HTMLElement = null;
|
||||||
let prevId = -1;
|
let prevId = -1;
|
||||||
|
|
||||||
const selectTab = async(id: number) => {
|
const selectTab = (id: number) => {
|
||||||
if(id == prevId) return false;
|
if(id == prevId) return false;
|
||||||
|
|
||||||
//console.log('selectTab id:', id);
|
//console.log('selectTab id:', id);
|
||||||
|
|
||||||
const p = prevTabContent;
|
const p = prevTabContent;
|
||||||
const tabContent = content.children[id] as HTMLElement;
|
const tabContent = content.children[id] as HTMLElement;
|
||||||
|
|
||||||
|
if(content.dataset.slider == 'none') {
|
||||||
|
if(p) {
|
||||||
|
p.classList.remove('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
tabContent.classList.add('active');
|
||||||
|
|
||||||
|
prevId = id;
|
||||||
|
prevTabContent = tabContent;
|
||||||
|
|
||||||
|
if(onTransitionEnd) onTransitionEnd();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const toRight = prevId < id;
|
const toRight = prevId < id;
|
||||||
if(prevId != -1) {
|
if(prevId != -1) {
|
||||||
if(tabs || content.dataset.slider == 'tabs') {
|
if(tabs || content.dataset.slider == 'tabs') {
|
||||||
|
|
|
@ -241,6 +241,10 @@ export default class PollElement extends HTMLElement {
|
||||||
this.classList.add('is-quiz');
|
this.classList.add('is-quiz');
|
||||||
|
|
||||||
if(poll.close_period && poll.close_date) {
|
if(poll.close_period && poll.close_date) {
|
||||||
|
const timeLeftDiv = document.createElement('div');
|
||||||
|
timeLeftDiv.classList.add('poll-time');
|
||||||
|
this.descDiv.append(timeLeftDiv);
|
||||||
|
|
||||||
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||||
//svg.setAttributeNS(null, 'viewBox', '0 0 15 15');
|
//svg.setAttributeNS(null, 'viewBox', '0 0 15 15');
|
||||||
svg.classList.add('poll-quiz-timer');
|
svg.classList.add('poll-quiz-timer');
|
||||||
|
@ -248,30 +252,52 @@ export default class PollElement extends HTMLElement {
|
||||||
this.quizTimer = svg;
|
this.quizTimer = svg;
|
||||||
|
|
||||||
const strokeWidth = 2;
|
const strokeWidth = 2;
|
||||||
const radius = (15 / 2) - (strokeWidth * 2);
|
const radius = 7;
|
||||||
const circumference = 2 * Math.PI * radius;
|
const circumference = 2 * Math.PI * radius;
|
||||||
|
|
||||||
const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
|
const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
|
||||||
circle.classList.add('poll-quiz-timer-circle');
|
circle.classList.add('poll-quiz-timer-circle');
|
||||||
circle.setAttributeNS(null, 'cx', '15');
|
circle.setAttributeNS(null, 'cx', '16');
|
||||||
circle.setAttributeNS(null, 'cy', '15');
|
circle.setAttributeNS(null, 'cy', '16');
|
||||||
circle.setAttributeNS(null, 'r', '' + radius);
|
circle.setAttributeNS(null, 'r', '' + radius);
|
||||||
|
circle.setAttributeNS(null, 'stroke-width', '' + strokeWidth);
|
||||||
|
|
||||||
svg.append(circle);
|
svg.append(circle);
|
||||||
|
|
||||||
this.descDiv.append(svg);
|
this.descDiv.append(svg);
|
||||||
|
|
||||||
const period = poll.close_period * 1000;
|
const period = poll.close_period * 1000;
|
||||||
const closeTime = (poll.close_date - serverTimeManager.serverTimeOffset) * 1000;
|
const closeTime = (poll.close_date - serverTimeManager.serverTimeOffset) * 1000;
|
||||||
|
|
||||||
|
// let time = Date.now();
|
||||||
|
// let percents = (closeTime - time) / period;
|
||||||
|
|
||||||
|
// timeLeftDiv.innerHTML = String((closeTime - time) / 1000 + 1 | 0).toHHMMSS();
|
||||||
|
|
||||||
|
// // @ts-ignore
|
||||||
|
// circle.style.strokeDashoffset = circumference + percents * circumference;
|
||||||
|
// circle.style.strokeDasharray = ${circumference} ${circumference};
|
||||||
|
|
||||||
this.quizInterval = setInterval(() => {
|
this.quizInterval = setInterval(() => {
|
||||||
const time = Date.now();
|
const time = Date.now();
|
||||||
|
|
||||||
const totalLength = circle.getTotalLength();
|
|
||||||
const percents = (closeTime - time) / period;
|
const percents = (closeTime - time) / period;
|
||||||
circle.style.strokeDasharray = '' + (percents * totalLength) + ', ' + circumference;
|
const timeLeft = (closeTime - time) / 1000 + 1 | 0;
|
||||||
|
timeLeftDiv.innerHTML = String(timeLeft).toHHMMSS();
|
||||||
|
|
||||||
|
if (timeLeft <= 5) {
|
||||||
|
timeLeftDiv.style.color = '#ee545c';
|
||||||
|
circle.style.stroke = '#ee545c';
|
||||||
|
}
|
||||||
|
//timeLeftDiv.style.visibility = 'visible';
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
circle.style.strokeDashoffset = circumference + percents * circumference;
|
||||||
|
circle.style.strokeDasharray = `${circumference} ${circumference}`;
|
||||||
|
|
||||||
if(time >= closeTime) {
|
if(time >= closeTime) {
|
||||||
clearInterval(this.quizInterval);
|
clearInterval(this.quizInterval);
|
||||||
|
timeLeftDiv.innerHTML = '';
|
||||||
|
// @ts-ignore
|
||||||
|
circle.style.strokeDashoffset = circumference;
|
||||||
this.quizInterval = 0;
|
this.quizInterval = 0;
|
||||||
|
|
||||||
// нужно запросить апдейт чтобы опрос обновился
|
// нужно запросить апдейт чтобы опрос обновился
|
||||||
|
@ -487,7 +513,7 @@ export default class PollElement extends HTMLElement {
|
||||||
* все приложения накладывают аватарку первую на вторую, а в макете зато вторая на первую, ЛОЛ!
|
* все приложения накладывают аватарку первую на вторую, а в макете зато вторая на первую, ЛОЛ!
|
||||||
*/
|
*/
|
||||||
results.recent_voters/* .slice().reverse() */.forEach((userID, idx) => {
|
results.recent_voters/* .slice().reverse() */.forEach((userID, idx) => {
|
||||||
const style = idx == 0 ? '' : `style="transform: translateX(-${idx * 5}px);"`;
|
const style = idx == 0 ? '' : `style="transform: translateX(-${idx * 3}px);"`;
|
||||||
html += `<avatar-element dialog="0" peer="${userID}" ${style}></avatar-element>`;
|
html += `<avatar-element dialog="0" peer="${userID}" ${style}></avatar-element>`;
|
||||||
});
|
});
|
||||||
this.avatarsDiv.innerHTML = html;
|
this.avatarsDiv.innerHTML = html;
|
||||||
|
|
|
@ -29,17 +29,20 @@ export default class PopupCreatePoll extends PopupElement {
|
||||||
|
|
||||||
this.title.innerText = 'New Poll';
|
this.title.innerText = 'New Poll';
|
||||||
|
|
||||||
const questionField = InputField('Ask a question', 'Ask a question', 'question');
|
const questionField = InputField('Ask a Question', 'Ask a Question', 'question');
|
||||||
this.questionInput = questionField.firstElementChild as HTMLInputElement;
|
this.questionInput = questionField.firstElementChild as HTMLInputElement;
|
||||||
|
|
||||||
this.header.append(questionField);
|
this.header.append(questionField);
|
||||||
|
|
||||||
|
const hr = document.createElement('hr');
|
||||||
const d = document.createElement('div');
|
const d = document.createElement('div');
|
||||||
|
d.classList.add('caption');
|
||||||
d.innerText = 'Options';
|
d.innerText = 'Options';
|
||||||
|
|
||||||
this.questions = document.createElement('div');
|
this.questions = document.createElement('div');
|
||||||
this.questions.classList.add('poll-create-questions');
|
this.questions.classList.add('poll-create-questions');
|
||||||
|
|
||||||
|
this.body.parentElement.insertBefore(hr, this.body);
|
||||||
this.body.append(d, this.questions);
|
this.body.append(d, this.questions);
|
||||||
|
|
||||||
this.confirmBtn.addEventListener('click', this.onSubmitClick);
|
this.confirmBtn.addEventListener('click', this.onSubmitClick);
|
||||||
|
|
|
@ -82,6 +82,8 @@ export default class Scrollable {
|
||||||
public scrollLocked = 0;
|
public scrollLocked = 0;
|
||||||
public isVisible = false;
|
public isVisible = false;
|
||||||
|
|
||||||
|
private reorderTimeout: number;
|
||||||
|
|
||||||
private setVisible(element: HTMLElement) {
|
private setVisible(element: HTMLElement) {
|
||||||
if(this.visible.has(element)) return;
|
if(this.visible.has(element)) return;
|
||||||
|
|
||||||
|
@ -373,9 +375,15 @@ export default class Scrollable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public reorder() {
|
public reorder() {
|
||||||
(Array.from(this.splitUp.children) as HTMLElement[]).forEach((el, idx) => {
|
if(!this.splitUp || this.reorderTimeout) return;
|
||||||
el.dataset.virtual = '' + idx;
|
|
||||||
});
|
this.reorderTimeout = setTimeout(() => {
|
||||||
|
this.reorderTimeout = 0;
|
||||||
|
|
||||||
|
(Array.from(this.splitUp.children) as HTMLElement[]).forEach((el, idx) => {
|
||||||
|
el.dataset.virtual = '' + idx;
|
||||||
|
});
|
||||||
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateElement(element: HTMLElement) {
|
public updateElement(element: HTMLElement) {
|
||||||
|
|
187
src/components/sidebarLeft/chatFolders.ts
Normal file
187
src/components/sidebarLeft/chatFolders.ts
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
import { SliderTab } from "../slider";
|
||||||
|
import lottieLoader, { RLottiePlayer } from "../../lib/lottieLoader";
|
||||||
|
import apiManager from "../../lib/mtproto/mtprotoworker";
|
||||||
|
import appMessagesManager, { DialogFilter } from "../../lib/appManagers/appMessagesManager";
|
||||||
|
import { RichTextProcessor } from "../../lib/richtextprocessor";
|
||||||
|
import appPeersManager from "../../lib/appManagers/appPeersManager";
|
||||||
|
import { ripple } from "../misc";
|
||||||
|
import { $rootScope, cancelEvent } from "../../lib/utils";
|
||||||
|
import appSidebarLeft from "../../lib/appManagers/appSidebarLeft";
|
||||||
|
|
||||||
|
type DialogFilterSuggested = {
|
||||||
|
_: 'dialogFilterSuggested',
|
||||||
|
filter: DialogFilter,
|
||||||
|
description: string
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class AppChatFoldersTab implements SliderTab {
|
||||||
|
public container: HTMLElement;
|
||||||
|
public createFolderBtn: HTMLElement;
|
||||||
|
private foldersContainer: HTMLElement;
|
||||||
|
private suggestedContainer: HTMLElement;
|
||||||
|
private stickerContainer: HTMLElement;
|
||||||
|
private animation: RLottiePlayer;
|
||||||
|
|
||||||
|
private filtersRendered: {[filterID: number]: HTMLElement} = {};
|
||||||
|
|
||||||
|
private renderFolder(dialogFilter: DialogFilterSuggested | DialogFilter, container?: HTMLElement, div: HTMLElement = document.createElement('div')) {
|
||||||
|
let filter: DialogFilter;
|
||||||
|
let description = '';
|
||||||
|
let d: string[] = [];
|
||||||
|
if(dialogFilter._ == 'dialogFilterSuggested') {
|
||||||
|
filter = dialogFilter.filter;
|
||||||
|
description = dialogFilter.description;
|
||||||
|
} else {
|
||||||
|
filter = dialogFilter;
|
||||||
|
description = '';
|
||||||
|
|
||||||
|
const filterID = filter.id;
|
||||||
|
if(!this.filtersRendered.hasOwnProperty(filter.id)) {
|
||||||
|
div.addEventListener('click', () => {
|
||||||
|
appSidebarLeft.editFolderTab.open(appMessagesManager.filtersStorage.filters[filterID]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.filtersRendered[filter.id] = div;
|
||||||
|
|
||||||
|
let enabledFilters = Object.keys(filter.pFlags).length;
|
||||||
|
/* (['include_peers', 'exclude_peers'] as ['include_peers', 'exclude_peers']).forEach(key => {
|
||||||
|
enabledFilters += +!!filter[key].length;
|
||||||
|
}); */
|
||||||
|
|
||||||
|
if(enabledFilters == 1) {
|
||||||
|
description = 'All ';
|
||||||
|
|
||||||
|
const pFlags = filter.pFlags;
|
||||||
|
if(pFlags.contacts) description += 'Contacts';
|
||||||
|
else if(pFlags.non_contacts) description += 'Non-Contacts';
|
||||||
|
else if(pFlags.groups) description += 'Groups';
|
||||||
|
else if(pFlags.broadcasts) description += 'Channels';
|
||||||
|
else if(pFlags.bots) description += 'Bots';
|
||||||
|
else if(pFlags.exclude_muted) description += 'Unmuted';
|
||||||
|
else if(pFlags.exclude_read) description += 'Unread';
|
||||||
|
else if(pFlags.exclude_archived) description += 'Unarchived';
|
||||||
|
d.push(description);
|
||||||
|
} else {
|
||||||
|
const folder = appMessagesManager.dialogsStorage.getFolder(filter.id);
|
||||||
|
let chats = 0, channels = 0, groups = 0;
|
||||||
|
for(const dialog of folder) {
|
||||||
|
if(appPeersManager.isAnyGroup(dialog.peerID)) groups++;
|
||||||
|
else if(appPeersManager.isBroadcast(dialog.peerID)) channels++;
|
||||||
|
else chats++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(chats) d.push(chats + ' chats');
|
||||||
|
if(channels) d.push(channels + ' channels');
|
||||||
|
if(groups) d.push(groups + ' groups');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
div.classList.add('category');
|
||||||
|
div.innerHTML = `
|
||||||
|
<div>
|
||||||
|
<p>${RichTextProcessor.wrapEmojiText(filter.title)}</p>
|
||||||
|
<p>${d.length ? d.join(', ') : description}</p>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
ripple(div);
|
||||||
|
|
||||||
|
if(container) container.append(div);
|
||||||
|
return div;
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.container = document.querySelector('.chat-folders-container');
|
||||||
|
this.stickerContainer = this.container.querySelector('.sticker-container');
|
||||||
|
this.foldersContainer = this.container.querySelector('.folders-my');
|
||||||
|
this.suggestedContainer = this.container.querySelector('.folders-suggested');
|
||||||
|
this.createFolderBtn = this.container.querySelector('.btn-create-folder');
|
||||||
|
|
||||||
|
this.createFolderBtn.addEventListener('click', () => {
|
||||||
|
appSidebarLeft.editFolderTab.open();
|
||||||
|
});
|
||||||
|
|
||||||
|
lottieLoader.loadAnimationFromURL({
|
||||||
|
container: this.stickerContainer,
|
||||||
|
loop: false,
|
||||||
|
autoplay: true,
|
||||||
|
width: 86,
|
||||||
|
height: 86
|
||||||
|
}, 'assets/img/Folders_1.tgs').then(player => {
|
||||||
|
this.animation = player;
|
||||||
|
});
|
||||||
|
|
||||||
|
appMessagesManager.filtersStorage.getDialogFilters().then(filters => {
|
||||||
|
for(const filterID in filters) {
|
||||||
|
const filter = filters[filterID];
|
||||||
|
this.renderFolder(filter, this.foldersContainer);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$rootScope.$on('filter_update', (e: CustomEvent) => {
|
||||||
|
const filter: DialogFilter = e.detail;
|
||||||
|
if(this.filtersRendered.hasOwnProperty(filter.id)) {
|
||||||
|
this.renderFolder(filter, null, this.filtersRendered[filter.id]);
|
||||||
|
} else {
|
||||||
|
this.renderFolder(filter, this.foldersContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getSuggestedFilters();
|
||||||
|
});
|
||||||
|
|
||||||
|
$rootScope.$on('filter_delete', (e: CustomEvent) => {
|
||||||
|
const filter: DialogFilter = e.detail;
|
||||||
|
if(this.filtersRendered.hasOwnProperty(filter.id)) {
|
||||||
|
/* for(const suggested of this.suggestedFilters) {
|
||||||
|
if(deepEqual(suggested.filter, filter)) {
|
||||||
|
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
this.getSuggestedFilters();
|
||||||
|
|
||||||
|
this.filtersRendered[filter.id].remove();
|
||||||
|
delete this.filtersRendered[filter.id]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private getSuggestedFilters() {
|
||||||
|
apiManager.invokeApi('messages.getSuggestedDialogFilters').then(suggestedFilters => {
|
||||||
|
this.suggestedContainer.style.display = suggestedFilters.length ? '' : 'none';
|
||||||
|
Array.from(this.suggestedContainer.children).slice(1).forEach(el => el.remove());
|
||||||
|
|
||||||
|
(suggestedFilters as DialogFilterSuggested[]).forEach(filter => {
|
||||||
|
const div = this.renderFolder(filter);
|
||||||
|
const button = document.createElement('button');
|
||||||
|
button.classList.add('btn-primary');
|
||||||
|
button.innerText = 'Add';
|
||||||
|
div.append(button);
|
||||||
|
this.suggestedContainer.append(div);
|
||||||
|
|
||||||
|
button.addEventListener('click', (e) => {
|
||||||
|
cancelEvent(e);
|
||||||
|
button.setAttribute('disabled', 'true');
|
||||||
|
|
||||||
|
appMessagesManager.filtersStorage.createDialogFilter(filter.filter).then(bool => {
|
||||||
|
if(bool) {
|
||||||
|
div.remove();
|
||||||
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
button.removeAttribute('disabled');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onOpen() {
|
||||||
|
if(this.init) {
|
||||||
|
this.init();
|
||||||
|
this.init = null;
|
||||||
|
} else {
|
||||||
|
if(this.animation) {
|
||||||
|
this.animation.restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,7 +27,7 @@ export default class AppContactsTab implements SliderTab {
|
||||||
this.container.firstElementChild.append(this.searchInput.container);
|
this.container.firstElementChild.append(this.searchInput.container);
|
||||||
|
|
||||||
// preload contacts
|
// preload contacts
|
||||||
appUsersManager.getContacts();
|
// appUsersManager.getContacts();
|
||||||
}
|
}
|
||||||
|
|
||||||
// need to clear, and left 1 page for smooth slide
|
// need to clear, and left 1 page for smooth slide
|
||||||
|
@ -49,7 +49,7 @@ export default class AppContactsTab implements SliderTab {
|
||||||
if(this.promise) return this.promise;
|
if(this.promise) return this.promise;
|
||||||
this.scrollable.onScrolledBottom = null;
|
this.scrollable.onScrolledBottom = null;
|
||||||
|
|
||||||
this.promise = appUsersManager.getContacts(query).then(contacts => {
|
this.promise = appUsersManager.getContacts(query).then(_contacts => {
|
||||||
this.promise = null;
|
this.promise = null;
|
||||||
|
|
||||||
if(appSidebarLeft.historyTabIDs[appSidebarLeft.historyTabIDs.length - 1] != AppSidebarLeft.SLIDERITEMSIDS.contacts) {
|
if(appSidebarLeft.historyTabIDs[appSidebarLeft.historyTabIDs.length - 1] != AppSidebarLeft.SLIDERITEMSIDS.contacts) {
|
||||||
|
@ -57,7 +57,7 @@ export default class AppContactsTab implements SliderTab {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
contacts = contacts.slice();
|
const contacts = [..._contacts];
|
||||||
contacts.findAndSplice(u => u == $rootScope.myID);
|
contacts.findAndSplice(u => u == $rootScope.myID);
|
||||||
|
|
||||||
let sorted = contacts
|
let sorted = contacts
|
||||||
|
|
249
src/components/sidebarLeft/editFolder.ts
Normal file
249
src/components/sidebarLeft/editFolder.ts
Normal file
|
@ -0,0 +1,249 @@
|
||||||
|
import { SliderTab } from "../slider";
|
||||||
|
import appSidebarLeft, { AppSidebarLeft } from "../../lib/appManagers/appSidebarLeft";
|
||||||
|
import lottieLoader, { RLottiePlayer } from "../../lib/lottieLoader";
|
||||||
|
import appMessagesManager, { DialogFilter, Dialog } from "../../lib/appManagers/appMessagesManager";
|
||||||
|
import { parseMenuButtonsTo, ripple, toast } from "../misc";
|
||||||
|
import appDialogsManager from "../../lib/appManagers/appDialogsManager";
|
||||||
|
import { copy, deepEqual } from "../../lib/utils";
|
||||||
|
|
||||||
|
export default class AppEditFolderTab implements SliderTab {
|
||||||
|
public container: HTMLElement;
|
||||||
|
private closeBtn: HTMLElement;
|
||||||
|
private title: HTMLElement;
|
||||||
|
private caption: HTMLElement;
|
||||||
|
private stickerContainer: HTMLElement;
|
||||||
|
|
||||||
|
private confirmBtn: HTMLElement;
|
||||||
|
private menuBtn: HTMLElement;
|
||||||
|
private deleteFolderBtn: HTMLElement;
|
||||||
|
private nameInput: HTMLInputElement;
|
||||||
|
|
||||||
|
private include_peers: HTMLElement;
|
||||||
|
private exclude_peers: HTMLElement;
|
||||||
|
private flags: {[k in 'contacts' | 'non_contacts' | 'groups' | 'broadcasts' | 'bots' | 'exclude_muted' | 'exclude_archived' | 'exclude_read']: HTMLElement} = {} as any;
|
||||||
|
|
||||||
|
private animation: RLottiePlayer;
|
||||||
|
private filter: DialogFilter;
|
||||||
|
private originalFilter: DialogFilter;
|
||||||
|
|
||||||
|
private type: 'edit' | 'create';
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.container = document.querySelector('.edit-folder-container');
|
||||||
|
this.closeBtn = this.container.querySelector('.sidebar-close-button');
|
||||||
|
this.title = this.container.querySelector('.sidebar-header__title');
|
||||||
|
this.caption = this.container.querySelector('.caption');
|
||||||
|
this.stickerContainer = this.container.querySelector('.sticker-container');
|
||||||
|
|
||||||
|
this.confirmBtn = this.container.querySelector('.btn-confirm');
|
||||||
|
this.menuBtn = this.container.querySelector('.btn-menu-toggle');
|
||||||
|
this.deleteFolderBtn = this.menuBtn.querySelector('.menu-delete');
|
||||||
|
this.nameInput = this.container.querySelector('#folder-name');
|
||||||
|
|
||||||
|
this.include_peers = this.container.querySelector('.folder-list-included');
|
||||||
|
this.exclude_peers = this.container.querySelector('.folder-list-excluded');
|
||||||
|
|
||||||
|
const includedFlagsContainer = this.include_peers.querySelector('.folder-categories');
|
||||||
|
const excludedFlagsContainer = this.exclude_peers.querySelector('.folder-categories');
|
||||||
|
parseMenuButtonsTo(this.flags, includedFlagsContainer.children);
|
||||||
|
parseMenuButtonsTo(this.flags, excludedFlagsContainer.children);
|
||||||
|
|
||||||
|
includedFlagsContainer.firstElementChild.addEventListener('click', () => {
|
||||||
|
appSidebarLeft.includedChatsTab.open(this.filter, 'included');
|
||||||
|
});
|
||||||
|
|
||||||
|
excludedFlagsContainer.firstElementChild.addEventListener('click', () => {
|
||||||
|
appSidebarLeft.includedChatsTab.open(this.filter, 'excluded');
|
||||||
|
});
|
||||||
|
|
||||||
|
lottieLoader.loadAnimationFromURL({
|
||||||
|
container: this.stickerContainer,
|
||||||
|
loop: true,
|
||||||
|
autoplay: true,
|
||||||
|
width: 86,
|
||||||
|
height: 86
|
||||||
|
}, 'assets/img/Folders_2.tgs').then(player => {
|
||||||
|
this.animation = player;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.deleteFolderBtn.addEventListener('click', () => {
|
||||||
|
this.deleteFolderBtn.setAttribute('disabled', 'true');
|
||||||
|
appMessagesManager.filtersStorage.updateDialogFilter(this.filter, true).then(bool => {
|
||||||
|
if(bool) {
|
||||||
|
this.closeBtn.click();
|
||||||
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
this.deleteFolderBtn.removeAttribute('disabled');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.confirmBtn.addEventListener('click', () => {
|
||||||
|
if(!this.nameInput.value.trim()) {
|
||||||
|
this.nameInput.classList.add('error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let include = (Array.from(includedFlagsContainer.children) as HTMLElement[]).slice(1).reduce((acc, el) => acc + +!el.style.display, 0);
|
||||||
|
if(this.include_peers.lastElementChild.tagName == 'UL') {
|
||||||
|
include += this.include_peers.lastElementChild.childElementCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!include) {
|
||||||
|
toast('Please choose at least one chat for this folder.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.confirmBtn.setAttribute('disabled', 'true');
|
||||||
|
|
||||||
|
let promise: Promise<boolean>;
|
||||||
|
if(!this.filter.id) {
|
||||||
|
promise = appMessagesManager.filtersStorage.createDialogFilter(this.filter);
|
||||||
|
} else {
|
||||||
|
promise = appMessagesManager.filtersStorage.updateDialogFilter(this.filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
promise.then(bool => {
|
||||||
|
if(bool) {
|
||||||
|
this.closeBtn.click();
|
||||||
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
this.confirmBtn.removeAttribute('disabled');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.nameInput.addEventListener('input', () => {
|
||||||
|
this.filter.title = this.nameInput.value;
|
||||||
|
this.nameInput.classList.remove('error');
|
||||||
|
|
||||||
|
this.editCheckForChange();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onOpen() {
|
||||||
|
if(this.init) {
|
||||||
|
this.init();
|
||||||
|
this.init = null;
|
||||||
|
} else {
|
||||||
|
if(this.animation) {
|
||||||
|
this.animation.restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onCloseAfterTimeout() {
|
||||||
|
Array.from(this.container.querySelectorAll('ul, .show-more')).forEach(el => el.remove());
|
||||||
|
}
|
||||||
|
|
||||||
|
private onCreateOpen() {
|
||||||
|
this.caption.style.display = '';
|
||||||
|
this.title.innerText = 'New Folder';
|
||||||
|
this.menuBtn.classList.add('hide');
|
||||||
|
this.confirmBtn.classList.remove('hide');
|
||||||
|
this.nameInput.value = '';
|
||||||
|
|
||||||
|
for(const flag in this.flags) {
|
||||||
|
// @ts-ignore
|
||||||
|
this.flags[flag].style.display = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private onEditOpen() {
|
||||||
|
this.caption.style.display = 'none';
|
||||||
|
this.title.innerText = this.type == 'create' ? 'New Folder' : 'Edit Folder';
|
||||||
|
|
||||||
|
if(this.type == 'edit') {
|
||||||
|
this.menuBtn.classList.remove('hide');
|
||||||
|
this.confirmBtn.classList.add('hide');
|
||||||
|
}
|
||||||
|
|
||||||
|
const filter = this.filter;
|
||||||
|
this.nameInput.value = filter.title;
|
||||||
|
|
||||||
|
for(const flag in this.flags) {
|
||||||
|
// @ts-ignore
|
||||||
|
this.flags[flag].style.display = !!filter.pFlags[flag] ? '' : 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
(['include_peers', 'exclude_peers'] as ['include_peers', 'exclude_peers']).forEach(key => {
|
||||||
|
const container = this[key];
|
||||||
|
const ul = document.createElement('ul');
|
||||||
|
|
||||||
|
const peers = filter[key].slice();
|
||||||
|
|
||||||
|
const renderMore = (_length: number) => {
|
||||||
|
for(let i = 0, length = Math.min(peers.length, _length); i < length; ++i) {
|
||||||
|
const peerID = peers.shift();
|
||||||
|
|
||||||
|
const {dom} = appDialogsManager.addDialog(peerID, ul, false, false, undefined, true);
|
||||||
|
dom.lastMessageSpan.parentElement.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(peers.length) {
|
||||||
|
showMore.innerHTML = `<div class="tgico-down"></div><div>Show ${Math.min(20, peers.length)} more chat${peers.length > 1 ? 's' : ''}</div>`;
|
||||||
|
} else if(showMore) {
|
||||||
|
showMore.remove();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
container.append(ul);
|
||||||
|
|
||||||
|
let showMore: HTMLElement;
|
||||||
|
if(peers.length) {
|
||||||
|
showMore = document.createElement('div');
|
||||||
|
showMore.classList.add('show-more');
|
||||||
|
showMore.addEventListener('click', () => renderMore(20));
|
||||||
|
|
||||||
|
showMore.innerHTML = `<div class="tgico-down"></div><div>Show ${Math.min(20, peers.length)} more chat${peers.length > 1 ? 's' : ''}</div>`;
|
||||||
|
ripple(showMore);
|
||||||
|
container.append(showMore);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderMore(4);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
editCheckForChange() {
|
||||||
|
if(this.type == 'edit') {
|
||||||
|
const changed = !deepEqual(this.originalFilter, this.filter);
|
||||||
|
this.confirmBtn.classList.toggle('hide', !changed);
|
||||||
|
this.menuBtn.classList.toggle('hide', changed);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
setFilter(filter: DialogFilter, firstTime: boolean) {
|
||||||
|
// cleanup
|
||||||
|
this.onCloseAfterTimeout();
|
||||||
|
|
||||||
|
if(firstTime) {
|
||||||
|
this.originalFilter = filter;
|
||||||
|
this.filter = copy(filter);
|
||||||
|
} else {
|
||||||
|
this.filter = filter;
|
||||||
|
this.onEditOpen();
|
||||||
|
this.editCheckForChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open(filter?: DialogFilter) {
|
||||||
|
appSidebarLeft.selectTab(AppSidebarLeft.SLIDERITEMSIDS.editFolder);
|
||||||
|
|
||||||
|
if(filter === undefined) {
|
||||||
|
this.setFilter({
|
||||||
|
_: 'dialogFilter',
|
||||||
|
flags: 0,
|
||||||
|
id: 0,
|
||||||
|
title: '',
|
||||||
|
pFlags: {},
|
||||||
|
pinned_peers: [],
|
||||||
|
include_peers: [],
|
||||||
|
exclude_peers: []
|
||||||
|
}, true);
|
||||||
|
this.type = 'create';
|
||||||
|
this.onCreateOpen();
|
||||||
|
} else {
|
||||||
|
this.setFilter(filter, true);
|
||||||
|
this.type = 'edit';
|
||||||
|
this.onEditOpen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
186
src/components/sidebarLeft/includedChats.ts
Normal file
186
src/components/sidebarLeft/includedChats.ts
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
import { SliderTab } from "../slider";
|
||||||
|
import { AppSelectPeers } from "../appSelectPeers";
|
||||||
|
import appSidebarLeft, { AppSidebarLeft } from "../../lib/appManagers/appSidebarLeft";
|
||||||
|
import appDialogsManager from "../../lib/appManagers/appDialogsManager";
|
||||||
|
import appPeersManager from "../../lib/appManagers/appPeersManager";
|
||||||
|
import appUsersManager from "../../lib/appManagers/appUsersManager";
|
||||||
|
import { $rootScope, copy, deepEqual } from "../../lib/utils";
|
||||||
|
import { DialogFilter } from "../../lib/appManagers/appMessagesManager";
|
||||||
|
|
||||||
|
export default class AppIncludedChatsTab implements SliderTab {
|
||||||
|
public container: HTMLElement;
|
||||||
|
private closeBtn: HTMLElement;
|
||||||
|
private confirmBtn: HTMLElement;
|
||||||
|
private title: HTMLElement;
|
||||||
|
|
||||||
|
private selector: AppSelectPeers;
|
||||||
|
private type: 'included' | 'excluded';
|
||||||
|
private filter: DialogFilter;
|
||||||
|
private originalFilter: DialogFilter;
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.container = document.querySelector('.included-chats-container');
|
||||||
|
this.closeBtn = this.container.querySelector('.sidebar-close-button');
|
||||||
|
this.confirmBtn = this.container.querySelector('.btn-confirm');
|
||||||
|
this.title = this.container.querySelector('.sidebar-header__title');
|
||||||
|
|
||||||
|
this.confirmBtn.addEventListener('click', () => {
|
||||||
|
const selected = this.selector.getSelected();
|
||||||
|
|
||||||
|
this.filter.pFlags = {};
|
||||||
|
|
||||||
|
const peers: number[] = [];
|
||||||
|
for(const key of selected) {
|
||||||
|
if(typeof(key) === 'number') {
|
||||||
|
peers.push(key);
|
||||||
|
} else {
|
||||||
|
// @ts-ignore
|
||||||
|
this.filter.pFlags[key] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.filter[this.type == 'included' ? 'include_peers' : 'exclude_peers'] = peers;
|
||||||
|
|
||||||
|
appSidebarLeft.editFolderTab.setFilter(this.filter, false);
|
||||||
|
this.closeBtn.click();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
checkbox(selected?: boolean) {
|
||||||
|
return `<div class="checkbox"><label><input type="checkbox" ${selected ? 'checked' : ''}><span></span></label></div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderResults = (peerIDs: number[]) => {
|
||||||
|
const other = this.type == 'included' ? this.filter.exclude_peers : this.filter.include_peers;
|
||||||
|
|
||||||
|
peerIDs.forEach(peerID => {
|
||||||
|
if(other.includes(peerID)) return;
|
||||||
|
|
||||||
|
const {dom} = appDialogsManager.addDialog(peerID, this.selector.scrollable, false, false);
|
||||||
|
|
||||||
|
const selected = this.selector.selected.has(peerID);
|
||||||
|
dom.containerEl.insertAdjacentHTML('beforeend', this.checkbox(selected));
|
||||||
|
if(selected) dom.listEl.classList.add('active');
|
||||||
|
|
||||||
|
let subtitle = '';
|
||||||
|
|
||||||
|
if(peerID > 0) {
|
||||||
|
if(peerID == $rootScope.myID) {
|
||||||
|
subtitle = 'Chat with yourself';
|
||||||
|
} else if(appUsersManager.isBot(peerID)) {
|
||||||
|
subtitle = 'Bot';
|
||||||
|
} else {
|
||||||
|
subtitle = appUsersManager.contactsList.has(peerID) ? 'Contact' : 'Non-Contact';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
subtitle = appPeersManager.isBroadcast(peerID) ? 'Channel' : 'Group';
|
||||||
|
}
|
||||||
|
|
||||||
|
dom.lastMessageSpan.innerHTML = subtitle;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onOpen() {
|
||||||
|
if(this.init) {
|
||||||
|
this.init();
|
||||||
|
this.init = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.confirmBtn.style.display = this.type == 'excluded' ? '' : 'none';
|
||||||
|
this.title.innerText = this.type == 'included' ? 'Included Chats' : 'Excluded Chats';
|
||||||
|
|
||||||
|
const filter = this.filter;
|
||||||
|
|
||||||
|
const fragment = document.createDocumentFragment();
|
||||||
|
const dd = document.createElement('div');
|
||||||
|
dd.classList.add('sidebar-left-h2');
|
||||||
|
dd.innerText = 'Chat types';
|
||||||
|
|
||||||
|
const categories = document.createElement('div');
|
||||||
|
categories.classList.add('folder-categories');
|
||||||
|
|
||||||
|
let details: any;
|
||||||
|
if(this.type == 'excluded') {
|
||||||
|
details = {
|
||||||
|
exclude_muted: {ico: 'tgico-mute', text: 'Muted'},
|
||||||
|
exclude_archived: {ico: 'tgico-archive', text: 'Archived'},
|
||||||
|
exclude_read: {ico: 'tgico-readchats', text: 'Read'}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
details = {
|
||||||
|
contacts: {ico: 'tgico-newprivate', text: 'Contacts'},
|
||||||
|
non_contacts: {ico: 'tgico-noncontacts', text: 'Non-Contacts'},
|
||||||
|
groups: {ico: 'tgico-group', text: 'Groups'},
|
||||||
|
broadcasts: {ico: 'tgico-newchannel', text: 'Channels'},
|
||||||
|
bots: {ico: 'tgico-bots', text: 'Bots'}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let html = '';
|
||||||
|
for(const key in details) {
|
||||||
|
html += `<div class="folder-category-button ${details[key].ico}" data-peerID="${key}"><p>${details[key].text}</p>${this.checkbox()}</div>`;
|
||||||
|
}
|
||||||
|
categories.innerHTML = html;
|
||||||
|
|
||||||
|
const hr = document.createElement('hr');
|
||||||
|
hr.style.margin = '7px 0 9px';
|
||||||
|
|
||||||
|
const d = document.createElement('div');
|
||||||
|
d.classList.add('sidebar-left-h2');
|
||||||
|
d.innerText = 'Chats';
|
||||||
|
|
||||||
|
fragment.append(dd, categories, hr, d);
|
||||||
|
|
||||||
|
/////////////////
|
||||||
|
|
||||||
|
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.selected = new Set(selectedPeers);
|
||||||
|
this.selector.input.placeholder = 'Search';
|
||||||
|
|
||||||
|
const _add = this.selector.add.bind(this.selector);
|
||||||
|
this.selector.add = (peerID, title) => {
|
||||||
|
const div = _add(peerID, details[peerID]?.text);
|
||||||
|
if(details[peerID]) {
|
||||||
|
div.querySelector('avatar-element').classList.add(details[peerID].ico);
|
||||||
|
}
|
||||||
|
return div;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.selector.list.parentElement.insertBefore(fragment, this.selector.list);
|
||||||
|
|
||||||
|
selectedPeers.forEach(peerID => {
|
||||||
|
this.selector.add(peerID);
|
||||||
|
});
|
||||||
|
|
||||||
|
for(const flag in filter.pFlags) {
|
||||||
|
// @ts-ignore
|
||||||
|
if(details.hasOwnProperty(flag) && !!filter.pFlags[flag]) {
|
||||||
|
(categories.querySelector(`[data-peerID="${flag}"]`) as HTMLElement).click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onSelectChange = (length: number) => {
|
||||||
|
//const changed = !deepEqual(this.filter, this.originalFilter);
|
||||||
|
if(this.type == 'included') {
|
||||||
|
this.confirmBtn.style.display = length ? '' : 'none';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onCloseAfterTimeout() {
|
||||||
|
if(this.selector) {
|
||||||
|
this.selector.container.remove();
|
||||||
|
this.selector = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open(filter: DialogFilter, type: 'included' | 'excluded') {
|
||||||
|
this.originalFilter = filter;
|
||||||
|
this.filter = copy(this.originalFilter);
|
||||||
|
this.type = type;
|
||||||
|
|
||||||
|
appSidebarLeft.selectTab(AppSidebarLeft.SLIDERITEMSIDS.includedChats);
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,7 @@ export default class AppSettingsTab implements SliderTab {
|
||||||
|
|
||||||
private buttons: {
|
private buttons: {
|
||||||
edit: HTMLButtonElement,
|
edit: HTMLButtonElement,
|
||||||
|
folders: HTMLButtonElement,
|
||||||
general: HTMLButtonElement,
|
general: HTMLButtonElement,
|
||||||
notifications: HTMLButtonElement,
|
notifications: HTMLButtonElement,
|
||||||
privacy: HTMLButtonElement,
|
privacy: HTMLButtonElement,
|
||||||
|
@ -34,8 +35,12 @@ export default class AppSettingsTab implements SliderTab {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.buttons.edit.addEventListener('click', () => {
|
this.buttons.edit.addEventListener('click', () => {
|
||||||
appSidebarLeft.selectTab(AppSidebarLeft.SLIDERITEMSIDS.editProfile);
|
|
||||||
appSidebarLeft.editProfileTab.fillElements();
|
appSidebarLeft.editProfileTab.fillElements();
|
||||||
|
appSidebarLeft.selectTab(AppSidebarLeft.SLIDERITEMSIDS.editProfile);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.buttons.folders.addEventListener('click', () => {
|
||||||
|
appSidebarLeft.selectTab(AppSidebarLeft.SLIDERITEMSIDS.chatFolders);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,20 @@
|
||||||
import { horizontalMenu } from "./misc";
|
import { horizontalMenu } from "./misc";
|
||||||
|
|
||||||
export interface SliderTab {
|
export interface SliderTab {
|
||||||
|
onOpen?: () => void,
|
||||||
|
onOpenAfterTimeout?: () => void,
|
||||||
onClose?: () => void,
|
onClose?: () => void,
|
||||||
onCloseAfterTimeout?: () => void
|
onCloseAfterTimeout?: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TRANSITIONTIME = 420;
|
||||||
|
|
||||||
export default class SidebarSlider {
|
export default class SidebarSlider {
|
||||||
protected _selectTab: (id: number) => void;
|
protected _selectTab: (id: number) => void;
|
||||||
public historyTabIDs: number[] = [];
|
public historyTabIDs: number[] = [];
|
||||||
|
|
||||||
constructor(public sidebarEl: HTMLElement, public tabs: {[id: number]: SliderTab}) {
|
constructor(public sidebarEl: HTMLElement, public tabs: {[id: number]: SliderTab}) {
|
||||||
this._selectTab = horizontalMenu(null, this.sidebarEl.querySelector('.sidebar-slider') as HTMLDivElement, null, null, 420);
|
this._selectTab = horizontalMenu(null, this.sidebarEl.querySelector('.sidebar-slider') as HTMLDivElement, null, null, TRANSITIONTIME);
|
||||||
this._selectTab(0);
|
this._selectTab(0);
|
||||||
|
|
||||||
let onCloseBtnClick = () => {
|
let onCloseBtnClick = () => {
|
||||||
|
@ -28,6 +32,20 @@ export default class SidebarSlider {
|
||||||
if(this.historyTabIDs[this.historyTabIDs.length - 1] == id) {
|
if(this.historyTabIDs[this.historyTabIDs.length - 1] == id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const tab = this.tabs[id];
|
||||||
|
if(tab) {
|
||||||
|
if(tab.onOpen) {
|
||||||
|
tab.onOpen();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tab.onOpenAfterTimeout) {
|
||||||
|
setTimeout(() => {
|
||||||
|
tab.onOpenAfterTimeout();
|
||||||
|
}, TRANSITIONTIME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
this.historyTabIDs.push(id);
|
this.historyTabIDs.push(id);
|
||||||
this._selectTab(id);
|
this._selectTab(id);
|
||||||
|
@ -41,14 +59,14 @@ export default class SidebarSlider {
|
||||||
public onCloseTab(id: number) {
|
public onCloseTab(id: number) {
|
||||||
let tab = this.tabs[id];
|
let tab = this.tabs[id];
|
||||||
if(tab) {
|
if(tab) {
|
||||||
if('onClose' in tab) {
|
if(tab.onClose) {
|
||||||
tab.onClose();
|
tab.onClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
if('onCloseAfterTimeout' in tab) {
|
if(tab.onCloseAfterTimeout) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
tab.onCloseAfterTimeout();
|
tab.onCloseAfterTimeout();
|
||||||
}, 420);
|
}, TRANSITIONTIME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -210,7 +210,21 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="sidebar-content">
|
<div class="sidebar-content">
|
||||||
<div id="chats-container"><ul id="dialogs"></ul></div>
|
<div id="chats-container">
|
||||||
|
<div class="folders-tabs-scrollable">
|
||||||
|
<nav class="menu-horizontal" style="display: none;" id="folders-tabs">
|
||||||
|
<ul>
|
||||||
|
<li class="rp"><span>All</span></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
{{!-- <div class="tabs-container" id="folders-container" data-slider="none"> --}}
|
||||||
|
<div class="tabs-container" id="folders-container">
|
||||||
|
<div>
|
||||||
|
<ul id="dialogs"></ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="sidebar-search hide" id="search-container"></div>
|
<div class="sidebar-search hide" id="search-container"></div>
|
||||||
<button class="btn-primary btn-circle btn-icon rp btn-corner tgico-newchat_filled btn-menu-toggle" id="new-menu">
|
<button class="btn-primary btn-circle btn-icon rp btn-corner tgico-newchat_filled btn-menu-toggle" id="new-menu">
|
||||||
<div class="btn-menu top-left">
|
<div class="btn-menu top-left">
|
||||||
|
@ -311,6 +325,7 @@
|
||||||
<div class="profile-subtitle"></div>
|
<div class="profile-subtitle"></div>
|
||||||
<div class="profile-buttons">
|
<div class="profile-buttons">
|
||||||
<div class="profile-button menu-edit tgico-edit rp"><p>Edit Profile</p></div>
|
<div class="profile-button menu-edit tgico-edit rp"><p>Edit Profile</p></div>
|
||||||
|
<div class="profile-button menu-folders tgico-folder rp"><p>Chat Folders</p></div>
|
||||||
<div class="profile-button menu-general tgico-settings rp"><p>General Settings</p></div>
|
<div class="profile-button menu-general tgico-settings rp"><p>General Settings</p></div>
|
||||||
<div class="profile-button menu-notifications tgico-unmute rp"><p>Notifications</p></div>
|
<div class="profile-button menu-notifications tgico-unmute rp"><p>Notifications</p></div>
|
||||||
<div class="profile-button menu-privacy tgico-lock rp"><p>Privacy and Security</p></div>
|
<div class="profile-button menu-privacy tgico-lock rp"><p>Privacy and Security</p></div>
|
||||||
|
@ -360,6 +375,81 @@
|
||||||
<button class="btn-primary btn-circle btn-icon rp btn-corner tgico-check"></button>
|
<button class="btn-primary btn-circle btn-icon rp btn-corner tgico-check"></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="sidebar-slider-item chat-folders-container">
|
||||||
|
<div class="sidebar-header">
|
||||||
|
<button class="btn-icon rp tgico-back sidebar-close-button"></button>
|
||||||
|
<div class="sidebar-header__title">Chat Folders</div>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-content">
|
||||||
|
<div class="chat-folders scrollable scrollable-y">
|
||||||
|
<div class="sticker-container"></div>
|
||||||
|
<div class="caption">Create folders for different groups of chats<br>and quickly switch between them.</div>
|
||||||
|
<button class="btn-primary btn-create-folder rp">
|
||||||
|
<div class="tgico-add"></div>
|
||||||
|
Create Folder
|
||||||
|
</button>
|
||||||
|
<hr/>
|
||||||
|
<div class="folders-container folders-my">
|
||||||
|
<div class="sidebar-left-h2">Folders</div>
|
||||||
|
</div>
|
||||||
|
<hr/>
|
||||||
|
<div class="folders-container folders-suggested" style="display: none;">
|
||||||
|
<div class="sidebar-left-h2">Recommended folders</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-slider-item edit-folder-container">
|
||||||
|
<div class="sidebar-header">
|
||||||
|
<button class="btn-icon rp tgico-back sidebar-close-button"></button>
|
||||||
|
<div class="sidebar-header__title"></div>
|
||||||
|
<div class="btn-icon tgico-check1 btn-confirm rp hide"></div>
|
||||||
|
<div class="btn-icon btn-menu-toggle rp tgico-more hide">
|
||||||
|
<div class="btn-menu bottom-left">
|
||||||
|
<div class="btn-menu-item menu-delete tgico-delete danger rp">Delete Folder</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-content">
|
||||||
|
<div class="edit-folder scrollable scrollable-y">
|
||||||
|
<div class="sticker-container"></div>
|
||||||
|
<div class="caption">Choose chats and types of chats that will<br>appear and never appear in this folder.</div>
|
||||||
|
<div class="input-wrapper">
|
||||||
|
<div class="input-field">
|
||||||
|
<input type="text" name="folder-name" class="folder-name" autocomplete="aintCCZsofunnowhHQ" id="folder-name" required="">
|
||||||
|
<label for="folder-name">Folder Name</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="folder-list folder-list-included">
|
||||||
|
<div class="sidebar-left-h2">Included chats</div>
|
||||||
|
<div class="folder-categories">
|
||||||
|
<div class="folder-category-button blue tgico-add rp"><p>Add Chats</p></div>
|
||||||
|
<div class="folder-category-button menu-contacts tgico-group"><p>Contacts</p></div>
|
||||||
|
<div class="folder-category-button menu-non_contacts tgico-noncontacts"><p>Non-Contacts</p></div>
|
||||||
|
<div class="folder-category-button menu-groups tgico-group"><p>Groups</p></div>
|
||||||
|
<div class="folder-category-button menu-broadcasts tgico-channel"><p>Channels</p></div>
|
||||||
|
<div class="folder-category-button menu-bots tgico-bots"><p>Bots</p></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="folder-list folder-list-excluded">
|
||||||
|
<div class="sidebar-left-h2">Excluded chats</div>
|
||||||
|
<div class="folder-categories">
|
||||||
|
<div class="folder-category-button blue tgico-minus rp"><p>Remove Chats</p></div>
|
||||||
|
<div class="folder-category-button menu-exclude_muted tgico-mute"><p>Muted</p></div>
|
||||||
|
<div class="folder-category-button menu-exclude_archived tgico-archive"><p>Archived</p></div>
|
||||||
|
<div class="folder-category-button menu-exclude_read tgico-readchats"><p>Read</p></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-slider-item included-chats-container">
|
||||||
|
<div class="sidebar-header">
|
||||||
|
<button class="btn-icon rp tgico-back sidebar-close-button"></button>
|
||||||
|
<div class="sidebar-header__title"></div>
|
||||||
|
<div class="btn-icon tgico-check1 btn-confirm rp" style="display: none;"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-menu" id="dialogs-contextmenu">
|
<div class="btn-menu" id="dialogs-contextmenu">
|
||||||
<div class="btn-menu-item menu-unread tgico rp"></div>
|
<div class="btn-menu-item menu-unread tgico rp"></div>
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
import { findUpClassName, $rootScope, escapeRegExp, whichChild, findUpTag, cancelEvent, formatNumber } from "../utils";
|
import { findUpClassName, $rootScope, escapeRegExp, whichChild, findUpTag, cancelEvent, formatNumber } from "../utils";
|
||||||
import appImManager, { AppImManager } from "./appImManager";
|
import appImManager, { AppImManager } from "./appImManager";
|
||||||
import appPeersManager from './appPeersManager';
|
import appPeersManager from './appPeersManager';
|
||||||
import appMessagesManager, { AppMessagesManager, Dialog } from "./appMessagesManager";
|
import appMessagesManager, { AppMessagesManager, Dialog, DialogFilter } from "./appMessagesManager";
|
||||||
import appUsersManager, { User } from "./appUsersManager";
|
import appUsersManager, { User } from "./appUsersManager";
|
||||||
import { RichTextProcessor } from "../richtextprocessor";
|
import { RichTextProcessor } from "../richtextprocessor";
|
||||||
import { ripple, putPreloader, positionMenu, openBtnMenu, parseMenuButtonsTo } from "../../components/misc";
|
import { ripple, putPreloader, positionMenu, openBtnMenu, parseMenuButtonsTo, horizontalMenu } from "../../components/misc";
|
||||||
//import Scrollable from "../../components/scrollable";
|
//import Scrollable from "../../components/scrollable";
|
||||||
import Scrollable from "../../components/scrollable_new";
|
import Scrollable from "../../components/scrollable_new";
|
||||||
import { logger } from "../polyfill";
|
import { logger, LogLevels } from "../polyfill";
|
||||||
import appChatsManager from "./appChatsManager";
|
import appChatsManager from "./appChatsManager";
|
||||||
import AvatarElement from "../../components/avatar";
|
import AvatarElement from "../../components/avatar";
|
||||||
import { PopupButton, PopupPeer } from "../../components/popup";
|
import { PopupButton, PopupPeer } from "../../components/popup";
|
||||||
|
import { SliderTab } from "../../components/slider";
|
||||||
|
|
||||||
type DialogDom = {
|
type DialogDom = {
|
||||||
avatarEl: AvatarElement,
|
avatarEl: AvatarElement,
|
||||||
|
@ -39,106 +40,11 @@ class DialogsContextMenu {
|
||||||
} = {} as any;
|
} = {} as any;
|
||||||
private selectedID: number;
|
private selectedID: number;
|
||||||
private peerType: 'channel' | 'chat' | 'megagroup' | 'group' | 'saved';
|
private peerType: 'channel' | 'chat' | 'megagroup' | 'group' | 'saved';
|
||||||
|
private filterID: number;
|
||||||
|
|
||||||
constructor(private attachTo: HTMLElement[]) {
|
constructor() {
|
||||||
parseMenuButtonsTo(this.buttons, this.element.children);
|
parseMenuButtonsTo(this.buttons, this.element.children);
|
||||||
|
|
||||||
const onContextMenu = (e: MouseEvent) => {
|
|
||||||
let li: HTMLDivElement = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
li = findUpTag(e.target, 'LI');
|
|
||||||
} catch(e) {}
|
|
||||||
|
|
||||||
if(!li) return;
|
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
if(this.element.classList.contains('active')) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
e.cancelBubble = true;
|
|
||||||
|
|
||||||
this.selectedID = +li.getAttribute('data-peerID');
|
|
||||||
const dialog = appMessagesManager.getDialogByPeerID(this.selectedID)[0];
|
|
||||||
const notOurDialog = dialog.peerID != $rootScope.myID;
|
|
||||||
|
|
||||||
// archive button
|
|
||||||
if(notOurDialog) {
|
|
||||||
const button = this.buttons.archive;
|
|
||||||
const condition = dialog.folder_id == 1;
|
|
||||||
button.classList.toggle('flip-icon', condition);
|
|
||||||
button.innerText = condition ? 'Unarchive' : 'Archive';
|
|
||||||
this.buttons.archive.style.display = '';
|
|
||||||
} else {
|
|
||||||
this.buttons.archive.style.display = 'none';
|
|
||||||
}
|
|
||||||
|
|
||||||
// pin button
|
|
||||||
{
|
|
||||||
const button = this.buttons.pin;
|
|
||||||
const condition = dialog.pFlags?.pinned;
|
|
||||||
button.classList.toggle('flip-icon', condition);
|
|
||||||
button.innerText = condition ? 'Unpin' : 'Pin';
|
|
||||||
}
|
|
||||||
|
|
||||||
// mute button
|
|
||||||
if(notOurDialog) {
|
|
||||||
const button = this.buttons.mute;
|
|
||||||
const condition = dialog.notify_settings && dialog.notify_settings.mute_until > (Date.now() / 1000 | 0);
|
|
||||||
button.classList.toggle('flip-icon', condition);
|
|
||||||
button.innerText = condition ? 'Unmute' : 'Mute';
|
|
||||||
this.buttons.mute.style.display = '';
|
|
||||||
} else {
|
|
||||||
this.buttons.mute.style.display = 'none';
|
|
||||||
}
|
|
||||||
|
|
||||||
// unread button
|
|
||||||
{
|
|
||||||
const button = this.buttons.unread;
|
|
||||||
const condition = !!(dialog.pFlags?.unread_mark || dialog.unread_count);
|
|
||||||
button.classList.toggle('flip-icon', condition);
|
|
||||||
button.innerText = condition ? 'Mark as Read' : 'Mark as Unread';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* // clear history button
|
|
||||||
if(appPeersManager.isChannel(this.selectedID)) {
|
|
||||||
this.buttons.clear.style.display = 'none';
|
|
||||||
} else {
|
|
||||||
this.buttons.clear.style.display = '';
|
|
||||||
} */
|
|
||||||
|
|
||||||
// delete button
|
|
||||||
let deleteButtonText = '';
|
|
||||||
if(appPeersManager.isMegagroup(this.selectedID)) {
|
|
||||||
deleteButtonText = 'Leave';
|
|
||||||
//deleteButtonText = 'Leave group';
|
|
||||||
this.peerType = 'megagroup';
|
|
||||||
} else if(appPeersManager.isChannel(this.selectedID)) {
|
|
||||||
deleteButtonText = 'Leave';
|
|
||||||
//deleteButtonText = 'Leave channel';
|
|
||||||
this.peerType = 'channel';
|
|
||||||
} else if(this.selectedID < 0) {
|
|
||||||
deleteButtonText = 'Delete';
|
|
||||||
//deleteButtonText = 'Delete and leave';
|
|
||||||
this.peerType = 'group';
|
|
||||||
} else {
|
|
||||||
deleteButtonText = 'Delete';
|
|
||||||
//deleteButtonText = 'Delete chat';
|
|
||||||
this.peerType = this.selectedID == $rootScope.myID ? 'saved' : 'chat';
|
|
||||||
}
|
|
||||||
this.buttons.delete.innerText = deleteButtonText;
|
|
||||||
|
|
||||||
li.classList.add('menu-open');
|
|
||||||
positionMenu(e, this.element);
|
|
||||||
openBtnMenu(this.element, () => {
|
|
||||||
li.classList.remove('menu-open');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.attachTo.forEach(el => {
|
|
||||||
el.addEventListener('contextmenu', onContextMenu);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.buttons.archive.addEventListener('click', () => {
|
this.buttons.archive.addEventListener('click', () => {
|
||||||
let dialog = appMessagesManager.getDialogByPeerID(this.selectedID)[0];
|
let dialog = appMessagesManager.getDialogByPeerID(this.selectedID)[0];
|
||||||
if(dialog) {
|
if(dialog) {
|
||||||
|
@ -147,7 +53,7 @@ class DialogsContextMenu {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.buttons.pin.addEventListener('click', () => {
|
this.buttons.pin.addEventListener('click', () => {
|
||||||
appMessagesManager.toggleDialogPin(this.selectedID);
|
appMessagesManager.toggleDialogPin(this.selectedID, this.filterID);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.buttons.mute.addEventListener('click', () => {
|
this.buttons.mute.addEventListener('click', () => {
|
||||||
|
@ -255,11 +161,159 @@ class DialogsContextMenu {
|
||||||
popup.show();
|
popup.show();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onContextMenu = (e: MouseEvent) => {
|
||||||
|
let li: HTMLDivElement = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
li = findUpTag(e.target, 'LI');
|
||||||
|
} catch(e) {}
|
||||||
|
|
||||||
|
if(!li) return;
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
if(this.element.classList.contains('active')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
e.cancelBubble = true;
|
||||||
|
|
||||||
|
this.filterID = appDialogsManager.filterID;
|
||||||
|
|
||||||
|
this.selectedID = +li.getAttribute('data-peerID');
|
||||||
|
const dialog = appMessagesManager.getDialogByPeerID(this.selectedID)[0];
|
||||||
|
const notOurDialog = dialog.peerID != $rootScope.myID;
|
||||||
|
|
||||||
|
// archive button
|
||||||
|
if(notOurDialog) {
|
||||||
|
const button = this.buttons.archive;
|
||||||
|
const condition = dialog.folder_id == 1;
|
||||||
|
button.classList.toggle('flip-icon', condition);
|
||||||
|
button.innerText = condition ? 'Unarchive' : 'Archive';
|
||||||
|
this.buttons.archive.style.display = '';
|
||||||
|
} else {
|
||||||
|
this.buttons.archive.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
// pin button
|
||||||
|
{
|
||||||
|
const button = this.buttons.pin;
|
||||||
|
//const condition = !!dialog.pFlags?.pinned;
|
||||||
|
const condition = this.filterID > 1 ? appMessagesManager.filtersStorage.filters[this.filterID].pinned_peers.includes(dialog.peerID) : !!dialog.pFlags?.pinned;
|
||||||
|
button.classList.toggle('flip-icon', condition);
|
||||||
|
button.innerText = condition ? 'Unpin' : 'Pin';
|
||||||
|
}
|
||||||
|
|
||||||
|
// mute button
|
||||||
|
if(notOurDialog) {
|
||||||
|
const button = this.buttons.mute;
|
||||||
|
const condition = dialog.notify_settings && dialog.notify_settings.mute_until > (Date.now() / 1000 | 0);
|
||||||
|
button.classList.toggle('flip-icon', condition);
|
||||||
|
button.innerText = condition ? 'Unmute' : 'Mute';
|
||||||
|
this.buttons.mute.style.display = '';
|
||||||
|
} else {
|
||||||
|
this.buttons.mute.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
// unread button
|
||||||
|
{
|
||||||
|
const button = this.buttons.unread;
|
||||||
|
const condition = !!(dialog.pFlags?.unread_mark || dialog.unread_count);
|
||||||
|
button.classList.toggle('flip-icon', condition);
|
||||||
|
button.innerText = condition ? 'Mark as Read' : 'Mark as Unread';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* // clear history button
|
||||||
|
if(appPeersManager.isChannel(this.selectedID)) {
|
||||||
|
this.buttons.clear.style.display = 'none';
|
||||||
|
} else {
|
||||||
|
this.buttons.clear.style.display = '';
|
||||||
|
} */
|
||||||
|
|
||||||
|
// delete button
|
||||||
|
let deleteButtonText = '';
|
||||||
|
if(appPeersManager.isMegagroup(this.selectedID)) {
|
||||||
|
deleteButtonText = 'Leave';
|
||||||
|
//deleteButtonText = 'Leave group';
|
||||||
|
this.peerType = 'megagroup';
|
||||||
|
} else if(appPeersManager.isChannel(this.selectedID)) {
|
||||||
|
deleteButtonText = 'Leave';
|
||||||
|
//deleteButtonText = 'Leave channel';
|
||||||
|
this.peerType = 'channel';
|
||||||
|
} else if(this.selectedID < 0) {
|
||||||
|
deleteButtonText = 'Delete';
|
||||||
|
//deleteButtonText = 'Delete and leave';
|
||||||
|
this.peerType = 'group';
|
||||||
|
} else {
|
||||||
|
deleteButtonText = 'Delete';
|
||||||
|
//deleteButtonText = 'Delete chat';
|
||||||
|
this.peerType = this.selectedID == $rootScope.myID ? 'saved' : 'chat';
|
||||||
|
}
|
||||||
|
this.buttons.delete.innerText = deleteButtonText;
|
||||||
|
|
||||||
|
li.classList.add('menu-open');
|
||||||
|
positionMenu(e, this.element);
|
||||||
|
openBtnMenu(this.element, () => {
|
||||||
|
li.classList.remove('menu-open');
|
||||||
|
});
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class AppArchivedTab implements SliderTab {
|
||||||
|
public container = document.getElementById('chats-archived-container') as HTMLDivElement;
|
||||||
|
public chatList = document.getElementById('dialogs-archived') as HTMLUListElement;
|
||||||
|
public scroll: Scrollable = null;
|
||||||
|
public loadedAll: boolean;
|
||||||
|
public loadDialogsPromise: Promise<any>;
|
||||||
|
public wasFilterID: number;
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.scroll = new Scrollable(this.container, 'y', 'CLA', this.chatList, 500);
|
||||||
|
this.scroll.setVirtualContainer(this.chatList);
|
||||||
|
this.scroll.onScrolledBottom = appDialogsManager.onChatsScroll;
|
||||||
|
///this.scroll.attachSentinels();
|
||||||
|
|
||||||
|
appDialogsManager.setListClickListener(this.chatList);
|
||||||
|
this.chatList.addEventListener('contextmenu', appDialogsManager.contextMenu.onContextMenu);
|
||||||
|
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
setTimeout(appDialogsManager.onChatsScroll, 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onOpen() {
|
||||||
|
if(this.init) {
|
||||||
|
this.init();
|
||||||
|
this.init = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.wasFilterID = appDialogsManager.filterID;
|
||||||
|
appDialogsManager.scroll = this.scroll;
|
||||||
|
appDialogsManager.filterID = 1;
|
||||||
|
appDialogsManager.onTabChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
// вообще, так делать нельзя, но нет времени чтобы переделать главный чатлист на слайд...
|
||||||
|
onOpenAfterTimeout() {
|
||||||
|
appDialogsManager.chatLists[this.wasFilterID].innerHTML = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
onClose() {
|
||||||
|
appDialogsManager.scroll = appDialogsManager._scroll;
|
||||||
|
appDialogsManager.filterID = this.wasFilterID;
|
||||||
|
appDialogsManager.onTabChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
onCloseAfterTimeout() {
|
||||||
|
this.chatList.innerHTML = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const archivedTab = new AppArchivedTab();
|
||||||
|
|
||||||
export class AppDialogsManager {
|
export class AppDialogsManager {
|
||||||
public chatList = document.getElementById('dialogs') as HTMLUListElement;
|
public _chatList = document.getElementById('dialogs') as HTMLUListElement;
|
||||||
public chatListArchived = document.getElementById('dialogs-archived') as HTMLUListElement;
|
public chatList = this._chatList;
|
||||||
|
|
||||||
public pinnedDelimiter: HTMLDivElement;
|
public pinnedDelimiter: HTMLDivElement;
|
||||||
/* public chatsHidden: Scrollable["hiddenElements"];
|
/* public chatsHidden: Scrollable["hiddenElements"];
|
||||||
public chatsVisible: Scrollable["visibleElements"];
|
public chatsVisible: Scrollable["visibleElements"];
|
||||||
|
@ -267,51 +321,58 @@ export class AppDialogsManager {
|
||||||
public chatsArchivedVisible: Scrollable["visibleElements"]; */
|
public chatsArchivedVisible: Scrollable["visibleElements"]; */
|
||||||
|
|
||||||
public doms: {[peerID: number]: DialogDom} = {};
|
public doms: {[peerID: number]: DialogDom} = {};
|
||||||
public domsArchived: {[peerID: number]: DialogDom} = {};
|
|
||||||
public lastActiveListElement: HTMLElement = null;
|
public lastActiveListElement: HTMLElement = null;
|
||||||
|
|
||||||
/* private rippleCallback: (value?: boolean | PromiseLike<boolean>) => void = null;
|
/* private rippleCallback: (value?: boolean | PromiseLike<boolean>) => void = null;
|
||||||
private lastClickID = 0;
|
private lastClickID = 0;
|
||||||
private lastGoodClickID = 0; */
|
private lastGoodClickID = 0; */
|
||||||
|
|
||||||
public chatsArchivedContainer = document.getElementById('chats-archived-container') as HTMLDivElement;
|
|
||||||
public chatsContainer = document.getElementById('chats-container') as HTMLDivElement;
|
public chatsContainer = document.getElementById('chats-container') as HTMLDivElement;
|
||||||
private chatsPreloader: HTMLDivElement;
|
private chatsPreloader: HTMLDivElement;
|
||||||
//private chatsLoadCount = 0;
|
|
||||||
//private loadDialogsPromise: Promise<any>;
|
|
||||||
private loadDialogsPromise: ReturnType<AppMessagesManager["getConversations"]>;
|
|
||||||
|
|
||||||
private loadedAll = false;
|
public loadDialogsPromise: ReturnType<AppMessagesManager["getConversations"]>;
|
||||||
private loadedArchivedAll = false;
|
public loadedAll = false;
|
||||||
|
|
||||||
public scroll: Scrollable = null;
|
public scroll: Scrollable = null;
|
||||||
public scrollArchived: Scrollable = null;
|
public _scroll: Scrollable = null;
|
||||||
|
|
||||||
|
private log = logger('DIALOGS', LogLevels.log | LogLevels.error | LogLevels.warn | LogLevels.debug);
|
||||||
|
|
||||||
private log = logger('DIALOGS');
|
public contextMenu = new DialogsContextMenu();
|
||||||
|
|
||||||
private contextMenu = new DialogsContextMenu([this.chatList, this.chatListArchived]);
|
public chatLists: {[filterID: number]: HTMLUListElement} = {
|
||||||
|
0: this.chatList,
|
||||||
|
1: archivedTab.chatList
|
||||||
|
};
|
||||||
|
public filterID = 0;
|
||||||
|
private folders: {[k in 'menu' | 'container']: HTMLElement} = {
|
||||||
|
menu: document.getElementById('folders-tabs'),
|
||||||
|
container: document.getElementById('folders-container')
|
||||||
|
};
|
||||||
|
private filtersRendered: {
|
||||||
|
[filterID: string]: {
|
||||||
|
menu: HTMLElement, container: HTMLElement
|
||||||
|
}
|
||||||
|
} = {};
|
||||||
|
|
||||||
private debug = false;
|
private accumulateArchivedTimeout: number;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
this.chatList.addEventListener('contextmenu', this.contextMenu.onContextMenu);
|
||||||
this.chatsPreloader = putPreloader(null, true);
|
this.chatsPreloader = putPreloader(null, true);
|
||||||
|
|
||||||
this.pinnedDelimiter = document.createElement('div');
|
if(USEPINNEDDELIMITER) {
|
||||||
this.pinnedDelimiter.classList.add('pinned-delimiter');
|
this.pinnedDelimiter = document.createElement('div');
|
||||||
this.pinnedDelimiter.appendChild(document.createElement('span'));
|
this.pinnedDelimiter.classList.add('pinned-delimiter');
|
||||||
|
this.pinnedDelimiter.appendChild(document.createElement('span'));
|
||||||
|
}
|
||||||
|
|
||||||
this.scroll = new Scrollable(this.chatsContainer, 'y', 'CL', this.chatList, 500);
|
this.scroll = this._scroll = new Scrollable(this.chatsContainer, 'y', 'CL', this.chatList, 500);
|
||||||
|
this.scroll.onScrolledBottom = this.onChatsScroll;
|
||||||
this.scroll.setVirtualContainer(this.chatList);
|
this.scroll.setVirtualContainer(this.chatList);
|
||||||
this.scroll.onScrolledBottom = this.onChatsScroll.bind(this);
|
|
||||||
//this.scroll.attachSentinels();
|
//this.scroll.attachSentinels();
|
||||||
|
|
||||||
this.scrollArchived = new Scrollable(this.chatsArchivedContainer, 'y', 'CLA', this.chatListArchived, 500);
|
|
||||||
this.scrollArchived.setVirtualContainer(this.chatListArchived);
|
|
||||||
this.scrollArchived.onScrolledBottom = this.onChatsArchivedScroll.bind(this);
|
|
||||||
///this.scroll.attachSentinels();
|
|
||||||
|
|
||||||
this.setListClickListener(this.chatList);
|
this.setListClickListener(this.chatList);
|
||||||
this.setListClickListener(this.chatListArchived);
|
|
||||||
|
|
||||||
if(testScroll) {
|
if(testScroll) {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
|
@ -329,14 +390,6 @@ export class AppDialogsManager {
|
||||||
(window as any).addElement = add;
|
(window as any).addElement = add;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('resize', () => {
|
|
||||||
//this.chatsLoadCount = Math.round(document.body.scrollHeight / 70 * 1.5);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
this.onChatsArchivedScroll();
|
|
||||||
}, 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
$rootScope.$on('user_update', (e: CustomEvent) => {
|
$rootScope.$on('user_update', (e: CustomEvent) => {
|
||||||
let userID = e.detail;
|
let userID = e.detail;
|
||||||
|
|
||||||
|
@ -377,26 +430,20 @@ export class AppDialogsManager {
|
||||||
let dialog = appMessagesManager.getDialogByPeerID(peerID)[0];
|
let dialog = appMessagesManager.getDialogByPeerID(peerID)[0];
|
||||||
if(dialog) {
|
if(dialog) {
|
||||||
this.setLastMessage(dialog);
|
this.setLastMessage(dialog);
|
||||||
|
this.validateForFilter();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootScope.$on('dialogs_multiupdate', (e: CustomEvent) => {
|
$rootScope.$on('dialogs_multiupdate', (e: CustomEvent) => {
|
||||||
let dialogs = e.detail;
|
const dialogs = e.detail;
|
||||||
|
|
||||||
for(let id in dialogs) {
|
for(const id in dialogs) {
|
||||||
let dialog = dialogs[id];
|
const dialog = dialogs[id];
|
||||||
|
this.updateDialog(dialog);
|
||||||
/////console.log('updating dialog:', dialog);
|
|
||||||
|
|
||||||
if(!(dialog.peerID in this.doms)) {
|
|
||||||
this.addDialog(dialog);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setLastMessage(dialog);
|
|
||||||
this.setDialogPosition(dialog);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setPinnedDelimiter();
|
this.setPinnedDelimiter();
|
||||||
|
this.validateForFilter();
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootScope.$on('dialog_drop', (e: CustomEvent) => {
|
$rootScope.$on('dialog_drop', (e: CustomEvent) => {
|
||||||
|
@ -406,7 +453,7 @@ export class AppDialogsManager {
|
||||||
if(dom) {
|
if(dom) {
|
||||||
dom.listEl.remove();
|
dom.listEl.remove();
|
||||||
delete this.doms[peerID];
|
delete this.doms[peerID];
|
||||||
(dialog.folder_id == 1 ? this.scrollArchived : this.scroll).reorder();
|
this.scroll.reorder();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -423,6 +470,8 @@ export class AppDialogsManager {
|
||||||
if(dialog.peerID == $rootScope.selectedPeerID) {
|
if(dialog.peerID == $rootScope.selectedPeerID) {
|
||||||
appImManager.updateUnreadByDialog(dialog);
|
appImManager.updateUnreadByDialog(dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.validateForFilter();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -444,29 +493,190 @@ export class AppDialogsManager {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$rootScope.$on('filter_update', (e: CustomEvent) => {
|
||||||
|
const filter: DialogFilter = e.detail;
|
||||||
|
if(!this.filtersRendered[filter.id]) {
|
||||||
|
this.addFilter(filter);
|
||||||
|
} else if(filter.id == this.filterID) { // это нет тут смысла вызывать, так как будет dialogs_multiupdate
|
||||||
|
//this.validateForFilter();
|
||||||
|
const folder = appMessagesManager.dialogsStorage.getFolder(filter.id);
|
||||||
|
this.validateForFilter();
|
||||||
|
for(let i = 0, length = folder.length; i < length; ++i) {
|
||||||
|
const dialog = folder[i];
|
||||||
|
this.updateDialog(dialog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$rootScope.$on('filter_delete', (e: CustomEvent) => {
|
||||||
|
const filter: DialogFilter = e.detail;
|
||||||
|
const elements = this.filtersRendered[filter.id];
|
||||||
|
if(!elements) return;
|
||||||
|
|
||||||
|
// set tab
|
||||||
|
//(this.folders.menu.firstElementChild.children[Math.max(0, filter.id - 2)] as HTMLElement).click();
|
||||||
|
(this.folders.menu.firstElementChild.children[0] as HTMLElement).click();
|
||||||
|
|
||||||
|
elements.container.remove();
|
||||||
|
elements.menu.remove();
|
||||||
|
|
||||||
|
delete this.chatLists[filter.id];
|
||||||
|
delete this.filtersRendered[filter.id];
|
||||||
|
|
||||||
|
if(!Object.keys(this.filtersRendered).length) {
|
||||||
|
this.folders.menu.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/* $rootScope.$on('filter_pinned_order', (e: CustomEvent) => {
|
||||||
|
const {order, id} = e.detail as {order: number[], id: number};
|
||||||
|
if(this.prevTabID != id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const peerID of order) {
|
||||||
|
this.updateDialog(appMessagesManager.getDialogByPeerID(peerID)[0]);
|
||||||
|
}
|
||||||
|
}); */
|
||||||
|
|
||||||
|
new Scrollable(this.folders.menu.parentElement, 'x');
|
||||||
|
const selectTab = horizontalMenu(this.folders.menu, this.folders.container, (id, tabContent) => {
|
||||||
|
/* if(id != 0) {
|
||||||
|
id += 1;
|
||||||
|
} */
|
||||||
|
|
||||||
|
id = +tabContent.dataset.filterID || 0;
|
||||||
|
|
||||||
|
if(this.filterID == id) return;
|
||||||
|
|
||||||
|
this.scroll.setVirtualContainer(this.chatLists[id]);
|
||||||
|
this.filterID = id;
|
||||||
|
this.onTabChange();
|
||||||
|
}, () => {
|
||||||
|
for(const folderID in this.chatLists) {
|
||||||
|
if(+folderID != this.filterID) {
|
||||||
|
this.chatLists[folderID].innerHTML = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//selectTab(0);
|
||||||
|
(this.folders.menu.firstElementChild.firstElementChild as HTMLElement).click();
|
||||||
|
|
||||||
/* false && */appMessagesManager.loadSavedState().then(() => {
|
/* false && */appMessagesManager.loadSavedState().then(() => {
|
||||||
this.loadDialogs().then(result => {
|
return appMessagesManager.filtersStorage.getDialogFilters();
|
||||||
this.setPinnedDelimiter();
|
}).then(filters => {
|
||||||
//appSidebarLeft.onChatsScroll();
|
for(const filterID in filters) {
|
||||||
this.loadDialogs(true);
|
this.addFilter(filters[filterID]);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
return this.loadDialogs(this.filterID);
|
||||||
|
}).then(result => {
|
||||||
|
this.setPinnedDelimiter();
|
||||||
|
//appSidebarLeft.onChatsScroll();
|
||||||
|
this.loadDialogs(1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async loadDialogs(archived = false) {
|
private updateDialog(dialog: Dialog) {
|
||||||
|
if(!dialog) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!this.doms.hasOwnProperty(dialog.peerID)) {
|
||||||
|
this.addDialog(dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.getDialogDom(dialog.peerID)) {
|
||||||
|
this.setLastMessage(dialog);
|
||||||
|
this.setDialogPosition(dialog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onTabChange = () => {
|
||||||
|
this.doms = {};
|
||||||
|
this.loadedAll = false;
|
||||||
|
this.lastActiveListElement = null;
|
||||||
|
this.chatList = this.chatLists[this.filterID];
|
||||||
|
this.loadDialogs(this.filterID);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Удалит неподходящие чаты из списка, но не добавит их(!)
|
||||||
|
*/
|
||||||
|
public validateForFilter() {
|
||||||
|
if(this.filterID == 0) return;
|
||||||
|
|
||||||
|
const folder = appMessagesManager.dialogsStorage.getFolder(this.filterID);
|
||||||
|
let affected = false;
|
||||||
|
for(const _peerID in this.doms) {
|
||||||
|
const peerID = +_peerID;
|
||||||
|
|
||||||
|
// если больше не подходит по фильтру, удаляем
|
||||||
|
if(folder.findIndex((dialog) => dialog.peerID == peerID) === -1) {
|
||||||
|
const listEl = this.doms[peerID].listEl;
|
||||||
|
listEl.remove();
|
||||||
|
affected = true;
|
||||||
|
|
||||||
|
if(this.lastActiveListElement == listEl) {
|
||||||
|
this.lastActiveListElement = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(affected) {
|
||||||
|
this.scroll.reorder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public addFilter(filter: DialogFilter) {
|
||||||
|
if(this.filtersRendered[filter.id]) return;
|
||||||
|
|
||||||
|
const li = document.createElement('li');
|
||||||
|
const span = document.createElement('span');
|
||||||
|
span.innerHTML = RichTextProcessor.wrapEmojiText(filter.title);
|
||||||
|
li.append(span);
|
||||||
|
ripple(li);
|
||||||
|
|
||||||
|
this.folders.menu.firstElementChild.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.chatLists[filter.id] = ul;
|
||||||
|
this.setListClickListener(ul);
|
||||||
|
ul.addEventListener('contextmenu', this.contextMenu.onContextMenu);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.folders.menu.style.display = '';
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
this.filtersRendered[filter.id] = {
|
||||||
|
menu: li,
|
||||||
|
container: div
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async loadDialogs(folderID: number) {
|
||||||
if(testScroll) {
|
if(testScroll) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.loadDialogsPromise/* || 1 == 1 */) return this.loadDialogsPromise;
|
if(this.loadDialogsPromise/* || 1 == 1 */) return this.loadDialogsPromise;
|
||||||
|
|
||||||
(archived ? this.chatsArchivedContainer : this.chatsContainer).append(this.chatsPreloader);
|
if(!this.chatList.childElementCount) {
|
||||||
|
const container = this.chatList.parentElement;
|
||||||
|
container.append(this.chatsPreloader);
|
||||||
|
}
|
||||||
|
|
||||||
let storage = appMessagesManager.dialogsStorage[+archived] || [];
|
const storage = appMessagesManager.dialogsStorage.getFolder(folderID);
|
||||||
let offsetIndex = 0;
|
let offsetIndex = 0;
|
||||||
|
|
||||||
for(let i = storage.length - 1; i >= 0; --i) {
|
for(let i = storage.length - 1; i >= 0; --i) {
|
||||||
let dialog = storage[i];
|
const dialog = storage[i];
|
||||||
if(this.getDialogDom(dialog.peerID)) {
|
if(this.getDialogDom(dialog.peerID)) {
|
||||||
offsetIndex = dialog.index;
|
offsetIndex = dialog.index;
|
||||||
break;
|
break;
|
||||||
|
@ -477,10 +687,10 @@ export class AppDialogsManager {
|
||||||
try {
|
try {
|
||||||
//console.time('getDialogs time');
|
//console.time('getDialogs time');
|
||||||
|
|
||||||
let loadCount = 50/*this.chatsLoadCount */;
|
const loadCount = 50/*this.chatsLoadCount */;
|
||||||
this.loadDialogsPromise = appMessagesManager.getConversations('', offsetIndex, loadCount, +archived);
|
this.loadDialogsPromise = appMessagesManager.getConversations('', offsetIndex, loadCount, folderID);
|
||||||
|
|
||||||
let result = await this.loadDialogsPromise;
|
const result = await this.loadDialogsPromise;
|
||||||
|
|
||||||
//console.timeEnd('getDialogs time');
|
//console.timeEnd('getDialogs time');
|
||||||
|
|
||||||
|
@ -490,12 +700,11 @@ export class AppDialogsManager {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!result.dialogs.length || (archived ? this.scrollArchived.length == result.count : this.scroll.length == result.count)) { // loaded all
|
if(!result.dialogs.length || this.chatList.childElementCount == result.count) { // loaded all
|
||||||
if(archived) this.loadedArchivedAll = true;
|
this.loadedAll = true;
|
||||||
else this.loadedAll = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.debug && this.log('getDialogs ' + loadCount + ' dialogs by offset:', offsetIndex, result, this.scroll.length, archived);
|
this.log.debug('getDialogs ' + loadCount + ' dialogs by offset:', offsetIndex, result, this.chatList.childElementCount);
|
||||||
this.scroll.onScroll();
|
this.scroll.onScroll();
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
this.log.error(err);
|
this.log.error(err);
|
||||||
|
@ -505,18 +714,10 @@ export class AppDialogsManager {
|
||||||
this.loadDialogsPromise = undefined;
|
this.loadDialogsPromise = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
public onChatsScroll() {
|
onChatsScroll = () => {
|
||||||
if(this.loadedAll || this.loadDialogsPromise) return;
|
if(this.loadedAll || this.loadDialogsPromise) return;
|
||||||
|
|
||||||
this.log('onChatsScroll');
|
this.log('onChatsScroll');
|
||||||
|
this.loadDialogs(this.filterID);
|
||||||
this.loadDialogs();
|
|
||||||
}
|
|
||||||
|
|
||||||
public onChatsArchivedScroll() {
|
|
||||||
if(this.loadedArchivedAll || this.loadDialogsPromise) return;
|
|
||||||
|
|
||||||
this.loadDialogs(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public setListClickListener(list: HTMLUListElement, onFound?: () => void) {
|
public setListClickListener(list: HTMLUListElement, onFound?: () => void) {
|
||||||
|
@ -564,13 +765,21 @@ export class AppDialogsManager {
|
||||||
}, {capture: true});
|
}, {capture: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
public setDialogPosition(dialog: Dialog) {
|
public setDialogPosition(dialog: Dialog, pos?: number) {
|
||||||
let pos = appMessagesManager.getDialogByPeerID(dialog.peerID)[1];
|
const dom = this.getDialogDom(dialog.peerID);
|
||||||
let dom = this.getDialogDom(dialog.peerID);
|
if(!dom) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pos === undefined) {
|
||||||
|
pos = appMessagesManager.dialogsStorage.getDialog(dialog.peerID, this.filterID)[1];
|
||||||
|
}
|
||||||
|
|
||||||
let prevPos = whichChild(dom.listEl);
|
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 = (dialog.folder_id == 1 && this.chatList == dom.listEl.parentElement) || (dialog.folder_id == 0 && this.chatListArchived == dom.listEl.parentElement);
|
||||||
if(wrongFolder) prevPos = 0xFFFF;
|
let wrongFolder = false;
|
||||||
|
if(wrongFolder) prevPos = 0xFFFF; */
|
||||||
|
|
||||||
if(prevPos == pos) {
|
if(prevPos == pos) {
|
||||||
return;
|
return;
|
||||||
|
@ -578,23 +787,23 @@ export class AppDialogsManager {
|
||||||
pos += 1;
|
pos += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
let chatList = dialog.folder_id == 1 ? this.chatListArchived : this.chatList;
|
const chatList = this.chatList;
|
||||||
if(chatList.childElementCount > pos) {
|
if(chatList.childElementCount > pos) {
|
||||||
chatList.insertBefore(dom.listEl, chatList.children[pos]);
|
chatList.insertBefore(dom.listEl, chatList.children[pos]);
|
||||||
} else {
|
} else {
|
||||||
chatList.append(dom.listEl);
|
chatList.append(dom.listEl);
|
||||||
}
|
}
|
||||||
|
|
||||||
(dialog.folder_id == 1 ? this.scrollArchived : this.scroll).reorder();
|
this.scroll.reorder();
|
||||||
|
|
||||||
this.debug && this.log('setDialogPosition:', dialog, dom, pos);
|
this.log.debug('setDialogPosition:', dialog, dom, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
public setPinnedDelimiter() {
|
public setPinnedDelimiter() {
|
||||||
if(!USEPINNEDDELIMITER) return;
|
if(!USEPINNEDDELIMITER) return;
|
||||||
|
|
||||||
let index = -1;
|
let index = -1;
|
||||||
let dialogs = appMessagesManager.dialogsStorage[0];
|
let dialogs = appMessagesManager.dialogsStorage.getFolder(0);
|
||||||
for(let dialog of dialogs) {
|
for(let dialog of dialogs) {
|
||||||
if(dialog.pFlags?.pinned) {
|
if(dialog.pFlags?.pinned) {
|
||||||
index++;
|
index++;
|
||||||
|
@ -731,7 +940,7 @@ export class AppDialogsManager {
|
||||||
dom.lastTimeSpan.innerHTML = timeStr;
|
dom.lastTimeSpan.innerHTML = timeStr;
|
||||||
} else dom.lastTimeSpan.innerHTML = '';
|
} else dom.lastTimeSpan.innerHTML = '';
|
||||||
|
|
||||||
if((this.doms[peerID] || this.domsArchived[peerID]) == dom) {
|
if(this.doms[peerID] == dom) {
|
||||||
this.setUnreadMessages(dialog);
|
this.setUnreadMessages(dialog);
|
||||||
} else { // means search
|
} else { // means search
|
||||||
dom.listEl.dataset.mid = lastMessage.mid;
|
dom.listEl.dataset.mid = lastMessage.mid;
|
||||||
|
@ -739,18 +948,22 @@ export class AppDialogsManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public setUnreadMessages(dialog: Dialog) {
|
public setUnreadMessages(dialog: Dialog) {
|
||||||
let dom = this.getDialogDom(dialog.peerID);
|
const dom = this.getDialogDom(dialog.peerID);
|
||||||
|
|
||||||
|
if(dialog.folder_id == 1) {
|
||||||
|
this.accumulateArchivedUnread();
|
||||||
|
}
|
||||||
|
|
||||||
if(!dom) {
|
if(!dom) {
|
||||||
this.log.error('setUnreadMessages no dom!', dialog);
|
this.log.error('setUnreadMessages no dom!', dialog);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let lastMessage = appMessagesManager.getMessage(dialog.top_message);
|
const lastMessage = appMessagesManager.getMessage(dialog.top_message);
|
||||||
if(lastMessage._ != 'messageEmpty' && !lastMessage.deleted &&
|
if(lastMessage._ != 'messageEmpty' && !lastMessage.deleted &&
|
||||||
lastMessage.from_id == $rootScope.myID && lastMessage.peerID != $rootScope.myID &&
|
lastMessage.from_id == $rootScope.myID && lastMessage.peerID != $rootScope.myID &&
|
||||||
dialog.read_outbox_max_id) { // maybe comment, 06.20.2020
|
dialog.read_outbox_max_id) { // maybe comment, 06.20.2020
|
||||||
let outgoing = (lastMessage.pFlags && lastMessage.pFlags.unread)
|
const outgoing = (lastMessage.pFlags && lastMessage.pFlags.unread)
|
||||||
/* && dialog.read_outbox_max_id != 0 */; // maybe uncomment, 31.01.2020
|
/* && dialog.read_outbox_max_id != 0 */; // maybe uncomment, 31.01.2020
|
||||||
|
|
||||||
//console.log('outgoing', outgoing, lastMessage);
|
//console.log('outgoing', outgoing, lastMessage);
|
||||||
|
@ -766,34 +979,38 @@ export class AppDialogsManager {
|
||||||
|
|
||||||
dom.unreadMessagesSpan.innerText = '';
|
dom.unreadMessagesSpan.innerText = '';
|
||||||
dom.unreadMessagesSpan.classList.remove('tgico-pinnedchat');
|
dom.unreadMessagesSpan.classList.remove('tgico-pinnedchat');
|
||||||
|
|
||||||
|
const filter = appMessagesManager.filtersStorage.filters[this.filterID];
|
||||||
|
let isPinned: boolean;
|
||||||
|
if(filter) {
|
||||||
|
isPinned = filter.pinned_peers.findIndex(peerID => peerID == dialog.peerID) !== -1;
|
||||||
|
} else {
|
||||||
|
isPinned = !!dialog.pFlags.pinned;
|
||||||
|
}
|
||||||
|
|
||||||
if(dialog.unread_count || dialog.pFlags.unread_mark) {
|
if(dialog.unread_count || dialog.pFlags.unread_mark) {
|
||||||
//dom.unreadMessagesSpan.innerText = '' + (dialog.unread_count ? formatNumber(dialog.unread_count, 1) : ' ');
|
//dom.unreadMessagesSpan.innerText = '' + (dialog.unread_count ? formatNumber(dialog.unread_count, 1) : ' ');
|
||||||
dom.unreadMessagesSpan.innerText = '' + (dialog.unread_count || ' ');
|
dom.unreadMessagesSpan.innerText = '' + (dialog.unread_count || ' ');
|
||||||
//dom.unreadMessagesSpan.classList.remove('tgico-pinnedchat');
|
dom.unreadMessagesSpan.classList.add((dialog.notify_settings?.mute_until * 1000) > Date.now() ?
|
||||||
dom.unreadMessagesSpan.classList.add(new Date(dialog.notify_settings?.mute_until * 1000) > new Date() ?
|
|
||||||
'unread-muted' : 'unread');
|
'unread-muted' : 'unread');
|
||||||
} else if(dialog.pFlags.pinned && dialog.folder_id == 0) {
|
} else if(isPinned) {
|
||||||
dom.unreadMessagesSpan.classList.remove('unread', 'unread-muted');
|
dom.unreadMessagesSpan.classList.remove('unread', 'unread-muted');
|
||||||
dom.unreadMessagesSpan.classList.add('tgico-pinnedchat');
|
dom.unreadMessagesSpan.classList.add('tgico-pinnedchat');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// set archived new count
|
public accumulateArchivedUnread() {
|
||||||
if(dialog.folder_id == 1) {
|
if(this.accumulateArchivedTimeout) return;
|
||||||
let sum = Object.keys(this.domsArchived).map(p => +p).reduce((acc: number, peerID: number) => {
|
this.accumulateArchivedTimeout = setTimeout(() => {
|
||||||
let dialog = appMessagesManager.getDialogByPeerID(peerID)[0];
|
this.accumulateArchivedTimeout = 0;
|
||||||
if(dialog) {
|
const dialogs = appMessagesManager.dialogsStorage.getFolder(1);
|
||||||
return acc + dialog.unread_count;
|
const sum = dialogs.reduce((acc, dialog) => acc + dialog.unread_count, 0);
|
||||||
}
|
|
||||||
|
|
||||||
return acc;
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
$rootScope.$broadcast('dialogs_archived_unread', {count: sum});
|
$rootScope.$broadcast('dialogs_archived_unread', {count: sum});
|
||||||
}
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getDialogDom(peerID: number) {
|
public getDialogDom(peerID: number) {
|
||||||
return this.doms[peerID] || this.domsArchived[peerID];
|
return this.doms[peerID];
|
||||||
}
|
}
|
||||||
|
|
||||||
public addDialog(_dialog: Dialog | number, container?: HTMLUListElement | Scrollable, drawStatus = true, rippleEnabled = true, onlyFirstName = false, meAsSaved = true) {
|
public addDialog(_dialog: Dialog | number, container?: HTMLUListElement | Scrollable, drawStatus = true, rippleEnabled = true, onlyFirstName = false, meAsSaved = true) {
|
||||||
|
@ -815,7 +1032,14 @@ export class AppDialogsManager {
|
||||||
|
|
||||||
let peerID: number = dialog.peerID;
|
let peerID: number = dialog.peerID;
|
||||||
|
|
||||||
if((this.doms[peerID] || this.domsArchived[peerID]) && !container) return;
|
if(!container) {
|
||||||
|
if(this.doms[peerID]) return;
|
||||||
|
|
||||||
|
const filter = appMessagesManager.filtersStorage.filters[this.filterID];
|
||||||
|
if((filter && !appMessagesManager.filtersStorage.testDialogForFilter(dialog, filter)) || (!filter && this.filterID != dialog.folder_id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let title = appPeersManager.getPeerTitle(peerID, false, onlyFirstName);
|
let title = appPeersManager.getPeerTitle(peerID, false, onlyFirstName);
|
||||||
|
|
||||||
|
@ -848,15 +1072,18 @@ export class AppDialogsManager {
|
||||||
let titleSpan = document.createElement('span');
|
let titleSpan = document.createElement('span');
|
||||||
titleSpan.classList.add('user-title');
|
titleSpan.classList.add('user-title');
|
||||||
|
|
||||||
if(peerID < 0) {
|
// в других случаях иконка верификации не нужна (а первый - это главные чатлисты)
|
||||||
let chat = appChatsManager.getChat(-peerID);
|
if(!container) {
|
||||||
if(chat && chat.pFlags && chat.pFlags.verified) {
|
if(peerID < 0) {
|
||||||
titleSpan.classList.add('is-verified');
|
let chat = appChatsManager.getChat(-peerID);
|
||||||
}
|
if(chat && chat.pFlags && chat.pFlags.verified) {
|
||||||
} else {
|
titleSpan.classList.add('is-verified');
|
||||||
let user = appUsersManager.getUser(peerID);
|
}
|
||||||
if(user && user.pFlags && user.pFlags.verified) {
|
} else {
|
||||||
titleSpan.classList.add('is-verified');
|
let user = appUsersManager.getUser(peerID);
|
||||||
|
if(user && user.pFlags && user.pFlags.verified) {
|
||||||
|
titleSpan.classList.add('is-verified');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -932,14 +1159,20 @@ export class AppDialogsManager {
|
||||||
listEl: li
|
listEl: li
|
||||||
};
|
};
|
||||||
|
|
||||||
if(!container) {
|
/* let good = false;
|
||||||
if(dialog.folder_id && dialog.folder_id == 1) {
|
for(const folderID in this.chatLists) {
|
||||||
this.scrollArchived.append(li);
|
if(this.chatLists[folderID] == container) {
|
||||||
this.domsArchived[dialog.peerID] = dom;
|
good = true;
|
||||||
} else {
|
|
||||||
this.scroll.append(li);
|
|
||||||
this.doms[dialog.peerID] = dom;
|
|
||||||
}
|
}
|
||||||
|
} */
|
||||||
|
if(!container/* || good */) {
|
||||||
|
this.scroll.append(li);
|
||||||
|
|
||||||
|
this.doms[dialog.peerID] = dom;
|
||||||
|
|
||||||
|
/* if(container) {
|
||||||
|
container.append(li);
|
||||||
|
} */
|
||||||
|
|
||||||
this.setLastMessage(dialog);
|
this.setLastMessage(dialog);
|
||||||
} else {
|
} else {
|
||||||
|
@ -950,7 +1183,10 @@ export class AppDialogsManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public setTyping(dialog: Dialog, user: User) {
|
public setTyping(dialog: Dialog, user: User) {
|
||||||
let dom = this.getDialogDom(dialog.peerID);
|
const dom = this.getDialogDom(dialog.peerID);
|
||||||
|
if(!dom) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let str = '';
|
let str = '';
|
||||||
if(dialog.peerID < 0) {
|
if(dialog.peerID < 0) {
|
||||||
|
@ -959,7 +1195,7 @@ export class AppDialogsManager {
|
||||||
str = s + ' ';
|
str = s + ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
let senderBold = document.createElement('i');
|
const senderBold = document.createElement('i');
|
||||||
str += 'typing...';
|
str += 'typing...';
|
||||||
senderBold.innerHTML = str;
|
senderBold.innerHTML = str;
|
||||||
|
|
||||||
|
@ -969,10 +1205,15 @@ export class AppDialogsManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsetTyping(dialog: Dialog) {
|
public unsetTyping(dialog: Dialog) {
|
||||||
let dom = this.getDialogDom(dialog.peerID);
|
const dom = this.getDialogDom(dialog.peerID);
|
||||||
|
if(!dom) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dom.lastMessageSpan.classList.remove('user-typing');
|
dom.lastMessageSpan.classList.remove('user-typing');
|
||||||
this.setLastMessage(dialog, null, dom);
|
this.setLastMessage(dialog, null, dom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new AppDialogsManager();
|
const appDialogsManager = new AppDialogsManager();
|
||||||
|
export default appDialogsManager;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -97,13 +97,14 @@ const AppPeersManager = {
|
||||||
},
|
},
|
||||||
|
|
||||||
getPeerID: (peerString: any): number => {
|
getPeerID: (peerString: any): number => {
|
||||||
if(isObject(peerString)) {
|
if(typeof(peerString) === 'number') return peerString;
|
||||||
|
else if(isObject(peerString)) {
|
||||||
return peerString.user_id
|
return peerString.user_id
|
||||||
? peerString.user_id
|
? peerString.user_id
|
||||||
: -(peerString.channel_id || peerString.chat_id);
|
: -(peerString.channel_id || peerString.chat_id);
|
||||||
} else if(!peerString) return 0;
|
} else if(!peerString) return 0;
|
||||||
let isUser = peerString.charAt(0) == 'u';
|
const isUser = peerString.charAt(0) == 'u';
|
||||||
let peerParams = peerString.substr(1).split('_');
|
const peerParams = peerString.substr(1).split('_');
|
||||||
|
|
||||||
return isUser ? peerParams[0] : -peerParams[0] || 0;
|
return isUser ? peerParams[0] : -peerParams[0] || 0;
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//import { logger } from "../polyfill";
|
//import { logger } from "../polyfill";
|
||||||
import appDialogsManager from "./appDialogsManager";
|
import appDialogsManager, { AppArchivedTab, archivedTab } from "./appDialogsManager";
|
||||||
import { $rootScope } from "../utils";
|
import { $rootScope } from "../utils";
|
||||||
import appImManager from "./appImManager";
|
import appImManager from "./appImManager";
|
||||||
import AppSearch, { SearchGroup } from "../../components/appSearch";
|
import AppSearch, { SearchGroup } from "../../components/appSearch";
|
||||||
|
@ -14,6 +14,9 @@ import AppContactsTab from "../../components/sidebarLeft/contacts";
|
||||||
import AppNewGroupTab from "../../components/sidebarLeft/newGroup";
|
import AppNewGroupTab from "../../components/sidebarLeft/newGroup";
|
||||||
import AppSettingsTab from "../../components/sidebarLeft/settings";
|
import AppSettingsTab from "../../components/sidebarLeft/settings";
|
||||||
import AppEditProfileTab from "../../components/sidebarLeft/editProfile";
|
import AppEditProfileTab from "../../components/sidebarLeft/editProfile";
|
||||||
|
import AppChatFoldersTab from "../../components/sidebarLeft/chatFolders";
|
||||||
|
import AppEditFolderTab from "../../components/sidebarLeft/editFolder";
|
||||||
|
import AppIncludedChatsTab from "../../components/sidebarLeft/includedChats";
|
||||||
import SidebarSlider from "../../components/slider";
|
import SidebarSlider from "../../components/slider";
|
||||||
import SearchInput from "../../components/searchInput";
|
import SearchInput from "../../components/searchInput";
|
||||||
|
|
||||||
|
@ -25,6 +28,9 @@ const contactsTab = new AppContactsTab();
|
||||||
const newGroupTab = new AppNewGroupTab();
|
const newGroupTab = new AppNewGroupTab();
|
||||||
const settingsTab = new AppSettingsTab();
|
const settingsTab = new AppSettingsTab();
|
||||||
const editProfileTab = new AppEditProfileTab();
|
const editProfileTab = new AppEditProfileTab();
|
||||||
|
const chatFoldersTab = new AppChatFoldersTab();
|
||||||
|
const editFolderTab = new AppEditFolderTab();
|
||||||
|
const includedChatsTab = new AppIncludedChatsTab();
|
||||||
|
|
||||||
export class AppSidebarLeft extends SidebarSlider {
|
export class AppSidebarLeft extends SidebarSlider {
|
||||||
public static SLIDERITEMSIDS = {
|
public static SLIDERITEMSIDS = {
|
||||||
|
@ -35,6 +41,9 @@ export class AppSidebarLeft extends SidebarSlider {
|
||||||
newGroup: 5,
|
newGroup: 5,
|
||||||
settings: 6,
|
settings: 6,
|
||||||
editProfile: 7,
|
editProfile: 7,
|
||||||
|
chatFolders: 8,
|
||||||
|
editFolder: 9,
|
||||||
|
includedChats: 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
private toolsBtn: HTMLButtonElement;
|
private toolsBtn: HTMLButtonElement;
|
||||||
|
@ -61,17 +70,21 @@ export class AppSidebarLeft extends SidebarSlider {
|
||||||
privateChat: HTMLButtonElement,
|
privateChat: HTMLButtonElement,
|
||||||
} = {} as any;
|
} = {} as any;
|
||||||
|
|
||||||
|
public archivedTab: AppArchivedTab;
|
||||||
public newChannelTab: AppNewChannelTab;
|
public newChannelTab: AppNewChannelTab;
|
||||||
public addMembersTab: AppAddMembersTab;
|
public addMembersTab: AppAddMembersTab;
|
||||||
public contactsTab: AppContactsTab;
|
public contactsTab: AppContactsTab;
|
||||||
public newGroupTab: AppNewGroupTab;
|
public newGroupTab: AppNewGroupTab;
|
||||||
public settingsTab: AppSettingsTab;
|
public settingsTab: AppSettingsTab;
|
||||||
public editProfileTab: AppEditProfileTab;
|
public editProfileTab: AppEditProfileTab;
|
||||||
|
public chatFoldersTab: AppChatFoldersTab;
|
||||||
|
public editFolderTab: AppEditFolderTab;
|
||||||
|
public includedChatsTab: AppIncludedChatsTab;
|
||||||
|
|
||||||
//private log = logger('SL');
|
//private log = logger('SL');
|
||||||
|
|
||||||
private searchGroups = {
|
private searchGroups = {
|
||||||
contacts: new SearchGroup('Contacts and Chats', 'contacts'),
|
contacts: new SearchGroup('Chats', 'contacts'),
|
||||||
globalContacts: new SearchGroup('Global Search', 'contacts'),
|
globalContacts: new SearchGroup('Global Search', 'contacts'),
|
||||||
messages: new SearchGroup('Global Search', 'messages'),
|
messages: new SearchGroup('Global Search', 'messages'),
|
||||||
people: new SearchGroup('People', 'contacts', false, 'search-group-people'),
|
people: new SearchGroup('People', 'contacts', false, 'search-group-people'),
|
||||||
|
@ -81,13 +94,16 @@ export class AppSidebarLeft extends SidebarSlider {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super(document.getElementById('column-left') as HTMLDivElement, {
|
super(document.getElementById('column-left') as HTMLDivElement, {
|
||||||
//[AppSidebarLeft.SLIDERITEMSIDS.archived]: ,
|
[AppSidebarLeft.SLIDERITEMSIDS.archived]: archivedTab,
|
||||||
[AppSidebarLeft.SLIDERITEMSIDS.newChannel]: newChannelTab,
|
[AppSidebarLeft.SLIDERITEMSIDS.newChannel]: newChannelTab,
|
||||||
[AppSidebarLeft.SLIDERITEMSIDS.contacts]: contactsTab,
|
[AppSidebarLeft.SLIDERITEMSIDS.contacts]: contactsTab,
|
||||||
[AppSidebarLeft.SLIDERITEMSIDS.addMembers]: addMembersTab,
|
[AppSidebarLeft.SLIDERITEMSIDS.addMembers]: addMembersTab,
|
||||||
[AppSidebarLeft.SLIDERITEMSIDS.newGroup]: newGroupTab,
|
[AppSidebarLeft.SLIDERITEMSIDS.newGroup]: newGroupTab,
|
||||||
[AppSidebarLeft.SLIDERITEMSIDS.settings]: settingsTab,
|
[AppSidebarLeft.SLIDERITEMSIDS.settings]: settingsTab,
|
||||||
[AppSidebarLeft.SLIDERITEMSIDS.editProfile]: editProfileTab,
|
[AppSidebarLeft.SLIDERITEMSIDS.editProfile]: editProfileTab,
|
||||||
|
[AppSidebarLeft.SLIDERITEMSIDS.chatFolders]: chatFoldersTab,
|
||||||
|
[AppSidebarLeft.SLIDERITEMSIDS.editFolder]: editFolderTab,
|
||||||
|
[AppSidebarLeft.SLIDERITEMSIDS.includedChats]: includedChatsTab,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.searchInput = new SearchInput('Telegram Search');
|
this.searchInput = new SearchInput('Telegram Search');
|
||||||
|
@ -97,12 +113,16 @@ export class AppSidebarLeft extends SidebarSlider {
|
||||||
this.backBtn = this.sidebarEl.querySelector('.sidebar-back-button') as HTMLButtonElement;
|
this.backBtn = this.sidebarEl.querySelector('.sidebar-back-button') as HTMLButtonElement;
|
||||||
this.searchContainer = this.sidebarEl.querySelector('#search-container') as HTMLDivElement;
|
this.searchContainer = this.sidebarEl.querySelector('#search-container') as HTMLDivElement;
|
||||||
|
|
||||||
|
this.archivedTab = archivedTab;
|
||||||
this.newChannelTab = newChannelTab;
|
this.newChannelTab = newChannelTab;
|
||||||
this.addMembersTab = addMembersTab;
|
this.addMembersTab = addMembersTab;
|
||||||
this.contactsTab = contactsTab;
|
this.contactsTab = contactsTab;
|
||||||
this.newGroupTab = newGroupTab;
|
this.newGroupTab = newGroupTab;
|
||||||
this.settingsTab = settingsTab;
|
this.settingsTab = settingsTab;
|
||||||
this.editProfileTab = editProfileTab;
|
this.editProfileTab = editProfileTab;
|
||||||
|
this.chatFoldersTab = chatFoldersTab;
|
||||||
|
this.editFolderTab = editFolderTab;
|
||||||
|
this.includedChatsTab = includedChatsTab;
|
||||||
|
|
||||||
this.menuEl = this.toolsBtn.querySelector('.btn-menu');
|
this.menuEl = this.toolsBtn.querySelector('.btn-menu');
|
||||||
this.newBtnMenu = this.sidebarEl.querySelector('#new-menu');
|
this.newBtnMenu = this.sidebarEl.querySelector('#new-menu');
|
||||||
|
@ -157,7 +177,7 @@ export class AppSidebarLeft extends SidebarSlider {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.backBtn.addEventListener('click', (e) => {
|
this.backBtn.addEventListener('click', (e) => {
|
||||||
appDialogsManager.chatsArchivedContainer.classList.remove('active');
|
//appDialogsManager.chatsArchivedContainer.classList.remove('active');
|
||||||
this.toolsBtn.classList.add('active');
|
this.toolsBtn.classList.add('active');
|
||||||
this.backBtn.classList.remove('active');
|
this.backBtn.classList.remove('active');
|
||||||
this.searchContainer.classList.remove('active');
|
this.searchContainer.classList.remove('active');
|
||||||
|
|
|
@ -368,7 +368,7 @@ class AppPollResultsTab implements SliderTab {
|
||||||
if(left <= 0) return;
|
if(left <= 0) return;
|
||||||
|
|
||||||
const showMore = document.createElement('div');
|
const showMore = document.createElement('div');
|
||||||
showMore.classList.add('poll-results-more');
|
showMore.classList.add('poll-results-more', 'show-more');
|
||||||
showMore.addEventListener('click', load);
|
showMore.addEventListener('click', load);
|
||||||
|
|
||||||
showMore.innerHTML = `<div class="tgico-down"></div><div>Show ${Math.min(20, left)} more voter${left > 1 ? 's' : ''}</div>`;
|
showMore.innerHTML = `<div class="tgico-down"></div><div>Show ${Math.min(20, left)} more voter${left > 1 ? 's' : ''}</div>`;
|
||||||
|
|
|
@ -41,8 +41,8 @@ export class AppUsersManager {
|
||||||
public userAccess: {[userID: number]: string} = {};
|
public userAccess: {[userID: number]: string} = {};
|
||||||
public cachedPhotoLocations: any = {};
|
public cachedPhotoLocations: any = {};
|
||||||
public contactsIndex = searchIndexManager.createIndex();
|
public contactsIndex = searchIndexManager.createIndex();
|
||||||
public contactsFillPromise: Promise<number[]>;
|
public contactsFillPromise: Promise<Set<number>>;
|
||||||
public contactsList: number[];
|
public contactsList: Set<number> = new Set();
|
||||||
public myID: number;
|
public myID: number;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -119,20 +119,21 @@ export class AppUsersManager {
|
||||||
return this.contactsFillPromise = apiManager.invokeApi('contacts.getContacts', {
|
return this.contactsFillPromise = apiManager.invokeApi('contacts.getContacts', {
|
||||||
hash: 0
|
hash: 0
|
||||||
}).then((result: any) => {
|
}).then((result: any) => {
|
||||||
let userID: number;
|
|
||||||
this.contactsList = [];
|
|
||||||
this.saveApiUsers(result.users);
|
this.saveApiUsers(result.users);
|
||||||
|
|
||||||
result.contacts.forEach((contact: any) => {
|
result.contacts.forEach((contact: any) => {
|
||||||
userID = contact.user_id;
|
this.pushContact(contact.user_id);
|
||||||
this.contactsList.push(userID);
|
|
||||||
searchIndexManager.indexObject(userID, this.getUserSearchText(userID), this.contactsIndex);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.contactsList;
|
return this.contactsList;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public pushContact(userID: number) {
|
||||||
|
this.contactsList.add(userID);
|
||||||
|
searchIndexManager.indexObject(userID, this.getUserSearchText(userID), this.contactsIndex);
|
||||||
|
}
|
||||||
|
|
||||||
public getUserSearchText(id: number) {
|
public getUserSearchText(id: number) {
|
||||||
const user = this.users[id];
|
const user = this.users[id];
|
||||||
if(!user) {
|
if(!user) {
|
||||||
|
@ -148,10 +149,11 @@ export class AppUsersManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public getContacts(query?: string) {
|
public getContacts(query?: string) {
|
||||||
return this.fillContacts().then(contactsList => {
|
return this.fillContacts().then(_contactsList => {
|
||||||
|
let contactsList = [..._contactsList];
|
||||||
if(query) {
|
if(query) {
|
||||||
const results: any = searchIndexManager.search(query, this.contactsIndex);
|
const results: any = searchIndexManager.search(query, this.contactsIndex);
|
||||||
const filteredContactsList = contactsList.filter(id => !!results[id]);
|
const filteredContactsList = [...contactsList].filter(id => !!results[id]);
|
||||||
|
|
||||||
contactsList = filteredContactsList;
|
contactsList = filteredContactsList;
|
||||||
}
|
}
|
||||||
|
@ -300,13 +302,13 @@ export class AppUsersManager {
|
||||||
return 'bot';
|
return 'bot';
|
||||||
}
|
}
|
||||||
|
|
||||||
let user = this.getUser(userID);
|
const user = this.getUser(userID);
|
||||||
if(!user || !user.status) {
|
if(!user) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
let str = '';
|
let str = '';
|
||||||
switch(user.status._) {
|
switch(user.status?._) {
|
||||||
case 'userStatusRecently': {
|
case 'userStatusRecently': {
|
||||||
str = 'last seen recently';
|
str = 'last seen recently';
|
||||||
break;
|
break;
|
||||||
|
@ -325,19 +327,19 @@ export class AppUsersManager {
|
||||||
case 'userStatusOffline': {
|
case 'userStatusOffline': {
|
||||||
str = 'last seen ';
|
str = 'last seen ';
|
||||||
|
|
||||||
let date = user.status.was_online;
|
const date = user.status.was_online;
|
||||||
let now = Date.now() / 1000;
|
const now = Date.now() / 1000;
|
||||||
|
|
||||||
if((now - date) < 60) {
|
if((now - date) < 60) {
|
||||||
str += ' just now';
|
str += ' just now';
|
||||||
} else if((now - date) < 3600) {
|
} else if((now - date) < 3600) {
|
||||||
let c = (now - date) / 60 | 0;
|
const c = (now - date) / 60 | 0;
|
||||||
str += c + ' ' + (c == 1 ? 'minute' : 'minutes') + ' ago';
|
str += c + ' ' + (c == 1 ? 'minute' : 'minutes') + ' ago';
|
||||||
} else if(now - date < 86400) {
|
} else if(now - date < 86400) {
|
||||||
let c = (now - date) / 3600 | 0;
|
const c = (now - date) / 3600 | 0;
|
||||||
str += c + ' ' + (c == 1 ? 'hour' : 'hours') + ' ago';
|
str += c + ' ' + (c == 1 ? 'hour' : 'hours') + ' ago';
|
||||||
} else {
|
} else {
|
||||||
let d = new Date(date * 1000);
|
const d = new Date(date * 1000);
|
||||||
str += ('0' + d.getDate()).slice(-2) + '.' + ('0' + (d.getMonth() + 1)).slice(-2) + ' at ' +
|
str += ('0' + d.getDate()).slice(-2) + '.' + ('0' + (d.getMonth() + 1)).slice(-2) + ' at ' +
|
||||||
('0' + d.getHours()).slice(-2) + ':' + ('0' + d.getMinutes()).slice(-2);
|
('0' + d.getHours()).slice(-2) + ':' + ('0' + d.getMinutes()).slice(-2);
|
||||||
}
|
}
|
||||||
|
@ -349,6 +351,11 @@ export class AppUsersManager {
|
||||||
str = 'online';
|
str = 'online';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
str = 'last seen a long time ago';
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { isApple, mediaSizes, isSafari } from "./config";
|
import { isApple, mediaSizes, isSafari } from "./config";
|
||||||
import { logger, LogLevels } from "./polyfill";
|
import { logger, LogLevels } from "./polyfill";
|
||||||
import animationIntersector from "../components/animationIntersector";
|
import animationIntersector from "../components/animationIntersector";
|
||||||
|
import apiManager from "./mtproto/mtprotoworker";
|
||||||
|
|
||||||
let convert = (value: number) => {
|
let convert = (value: number) => {
|
||||||
return Math.round(Math.min(Math.max(value, 0), 1) * 255);
|
return Math.round(Math.min(Math.max(value, 0), 1) * 255);
|
||||||
|
@ -603,6 +604,19 @@ class LottieLoader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public loadAnimationFromURL(params: Omit<RLottieOptions, 'animationData'>, url: string) {
|
||||||
|
if(!this.loaded) {
|
||||||
|
this.loadLottieWorkers();
|
||||||
|
}
|
||||||
|
|
||||||
|
return fetch(url)
|
||||||
|
.then(res => res.arrayBuffer())
|
||||||
|
.then(data => apiManager.gzipUncompress<string>(data, true))
|
||||||
|
.then(str => {
|
||||||
|
return this.loadAnimationWorker(Object.assign(params, {animationData: JSON.parse(str)}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public async loadAnimationWorker(params: RLottieOptions, group = '', toneIndex = -1) {
|
public async loadAnimationWorker(params: RLottieOptions, group = '', toneIndex = -1) {
|
||||||
//params.autoplay = true;
|
//params.autoplay = true;
|
||||||
|
|
||||||
|
@ -638,6 +652,7 @@ class LottieLoader {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.log.debug('onPlayerLoaded');
|
||||||
rlPlayer.onLoad(frameCount, fps);
|
rlPlayer.onLoad(frameCount, fps);
|
||||||
//rlPlayer.addListener('firstFrame', () => {
|
//rlPlayer.addListener('firstFrame', () => {
|
||||||
//animationIntersector.addAnimation(player, group);
|
//animationIntersector.addAnimation(player, group);
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -297,6 +297,17 @@ export function findUpTag(el, tag) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function findUpAttribute(el, attribute) {
|
||||||
|
if(el.getAttribute(attribute) != null) return el; // 03.02.2020
|
||||||
|
|
||||||
|
while(el.parentElement) {
|
||||||
|
el = el.parentElement;
|
||||||
|
if(el.getAttribute(attribute) != null)
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
export function whichChild(elem/* : Node */) {
|
export function whichChild(elem/* : Node */) {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|
|
@ -236,35 +236,23 @@ let onFirstMount = (): Promise<any> => {
|
||||||
|
|
||||||
let imageDiv = page.pageEl.querySelector('.auth-image') as HTMLDivElement;
|
let imageDiv = page.pageEl.querySelector('.auth-image') as HTMLDivElement;
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
LottieLoader.loadLottieWorkers(),
|
LottieLoader.loadAnimationFromURL({
|
||||||
|
|
||||||
fetch('assets/img/TwoFactorSetupMonkeyIdle.tgs')
|
|
||||||
.then(res => res.arrayBuffer())
|
|
||||||
.then(data => apiManager.gzipUncompress<string>(data, true))
|
|
||||||
.then(str => LottieLoader.loadAnimationWorker({
|
|
||||||
container: imageDiv,
|
container: imageDiv,
|
||||||
loop: true,
|
loop: true,
|
||||||
autoplay: true,
|
autoplay: true,
|
||||||
animationData: JSON.parse(str),
|
|
||||||
width: 166,
|
width: 166,
|
||||||
height: 166
|
height: 166
|
||||||
}))
|
}, 'assets/img/TwoFactorSetupMonkeyIdle.tgs').then(animation => {
|
||||||
.then(animation => {
|
|
||||||
idleAnimation = animation;
|
idleAnimation = animation;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
/* false && */fetch('assets/img/TwoFactorSetupMonkeyTracking.tgs')
|
LottieLoader.loadAnimationFromURL({
|
||||||
.then(res => res.arrayBuffer())
|
|
||||||
.then(data => apiManager.gzipUncompress<string>(data, true))
|
|
||||||
.then(str => LottieLoader.loadAnimationWorker({
|
|
||||||
container: imageDiv,
|
container: imageDiv,
|
||||||
loop: false,
|
loop: false,
|
||||||
autoplay: false,
|
autoplay: false,
|
||||||
animationData: JSON.parse(str),
|
|
||||||
width: 166,
|
width: 166,
|
||||||
height: 166
|
height: 166
|
||||||
}))
|
}, 'assets/img/TwoFactorSetupMonkeyTracking.tgs').then(_animation => {
|
||||||
.then(_animation => {
|
|
||||||
animation = _animation;
|
animation = _animation;
|
||||||
|
|
||||||
if(!codeInput.value.length) {
|
if(!codeInput.value.length) {
|
||||||
|
@ -272,7 +260,7 @@ let onFirstMount = (): Promise<any> => {
|
||||||
}
|
}
|
||||||
|
|
||||||
animation.addListener('enterFrame', currentFrame => {
|
animation.addListener('enterFrame', currentFrame => {
|
||||||
console.log('enterFrame', currentFrame, needFrame);
|
//console.log('enterFrame', currentFrame, needFrame);
|
||||||
//let currentFrame = Math.round(e.currentTime);
|
//let currentFrame = Math.round(e.currentTime);
|
||||||
|
|
||||||
if((animation.direction == 1 && currentFrame >= needFrame) ||
|
if((animation.direction == 1 && currentFrame >= needFrame) ||
|
||||||
|
|
|
@ -91,20 +91,13 @@ let onFirstMount = (): Promise<any> => {
|
||||||
|
|
||||||
}); */
|
}); */
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
LottieLoader.loadLottieWorkers(),
|
LottieLoader.loadAnimationFromURL({
|
||||||
|
|
||||||
fetch('assets/img/TwoFactorSetupMonkeyClose.tgs')
|
|
||||||
.then(res => res.arrayBuffer())
|
|
||||||
.then(data => apiManager.gzipUncompress<string>(data, true))
|
|
||||||
.then(str => LottieLoader.loadAnimationWorker({
|
|
||||||
container: page.pageEl.querySelector('.auth-image'),
|
container: page.pageEl.querySelector('.auth-image'),
|
||||||
loop: false,
|
loop: false,
|
||||||
autoplay: false,
|
autoplay: false,
|
||||||
animationData: JSON.parse(str),
|
|
||||||
width: 166,
|
width: 166,
|
||||||
height: 166
|
height: 166
|
||||||
}))
|
}, 'assets/img/TwoFactorSetupMonkeyClose.tgs').then(_animation => {
|
||||||
.then(_animation => {
|
|
||||||
animation = _animation;
|
animation = _animation;
|
||||||
animation.addListener('enterFrame', currentFrame => {
|
animation.addListener('enterFrame', currentFrame => {
|
||||||
//console.log('enterFrame', e, needFrame);
|
//console.log('enterFrame', e, needFrame);
|
||||||
|
|
|
@ -3,13 +3,17 @@ $time-background: rgba(0, 0, 0, .35);
|
||||||
|
|
||||||
#bubble-contextmenu > div {
|
#bubble-contextmenu > div {
|
||||||
padding: 0 84px 0 16px;
|
padding: 0 84px 0 16px;
|
||||||
|
|
||||||
|
@include respond-to(handhelds) {
|
||||||
|
padding: 0 60px 0 16px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#topbar {
|
#topbar {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
box-shadow: 0px 1px 5px -1px rgba(0,0,0,0.18);
|
box-shadow: 0px 1px 5px -1px rgba(0,0,0,0.21);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
min-height: 56px;
|
min-height: 56px;
|
||||||
max-height: 56px;
|
max-height: 56px;
|
||||||
|
@ -62,6 +66,10 @@ $time-background: rgba(0, 0, 0, .35);
|
||||||
.btn-menu {
|
.btn-menu {
|
||||||
top: calc(100% + 7px);
|
top: calc(100% + 7px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@include respond-to(handhelds) {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-info {
|
.chat-info {
|
||||||
|
@ -73,7 +81,11 @@ $time-background: rgba(0, 0, 0, .35);
|
||||||
// padding-left: 17px;
|
// padding-left: 17px;
|
||||||
// line-height: 1.6;
|
// line-height: 1.6;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
line-height: 1.3;
|
//line-height: 1.3;
|
||||||
|
|
||||||
|
@include respond-to(handhelds) {
|
||||||
|
max-width: 208px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.person {
|
.person {
|
||||||
|
@ -88,7 +100,7 @@ $time-background: rgba(0, 0, 0, .35);
|
||||||
|
|
||||||
.bottom {
|
.bottom {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 18px;
|
//line-height: 18px;
|
||||||
color: #707579;
|
color: #707579;
|
||||||
|
|
||||||
.online {
|
.online {
|
||||||
|
@ -127,7 +139,7 @@ $time-background: rgba(0, 0, 0, .35);
|
||||||
|
|
||||||
|
|
||||||
@include respond-to(handhelds) {
|
@include respond-to(handhelds) {
|
||||||
padding: .35rem .5rem .5rem;
|
padding: 0 .5rem .5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include respond-to(not-handhelds) {
|
@include respond-to(not-handhelds) {
|
||||||
|
@ -214,7 +226,7 @@ $time-background: rgba(0, 0, 0, .35);
|
||||||
height: 10px;
|
height: 10px;
|
||||||
background-color: #e53935;
|
background-color: #e53935;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
margin: 0 .5rem;
|
margin: 0 9px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
animation: recordBlink 1.25s infinite;
|
animation: recordBlink 1.25s infinite;
|
||||||
}
|
}
|
||||||
|
@ -231,13 +243,20 @@ $time-background: rgba(0, 0, 0, .35);
|
||||||
left: -48px;
|
left: -48px;
|
||||||
transition: transform .03s, visibility .1s;
|
transition: transform .03s, visibility .1s;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
|
|
||||||
|
@include respond-to(handhelds) {
|
||||||
|
width: 300px;
|
||||||
|
height: 300px;
|
||||||
|
top: -124px;
|
||||||
|
left: -124px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.is-recording {
|
&.is-recording {
|
||||||
#btn-record-cancel {
|
#btn-record-cancel {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
margin-right: .5rem;
|
margin-right: 9px;
|
||||||
transition: width .1s, margin-right .1s, visibility 0s .1s, opacity .1s .1s;
|
transition: width .1s, margin-right .1s, visibility 0s .1s, opacity .1s .1s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,14 +298,24 @@ $time-background: rgba(0, 0, 0, .35);
|
||||||
|
|
||||||
#im-title {
|
#im-title {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin-top: -2px;
|
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
|
line-height: 24px;
|
||||||
|
|
||||||
|
@include respond-to(handhelds) {
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
span.emoji {
|
span.emoji {
|
||||||
vertical-align: inherit;
|
vertical-align: inherit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.info#im-subtitle {
|
||||||
|
margin-top: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
.chat-container {
|
.chat-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
// padding: 200px;
|
// padding: 200px;
|
||||||
|
@ -471,6 +500,14 @@ $time-background: rgba(0, 0, 0, .35);
|
||||||
// height: 100%;
|
// height: 100%;
|
||||||
height: 52px;
|
height: 52px;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
|
|
||||||
|
&-subtitle {
|
||||||
|
line-height: 13px !important;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
max-width: 280px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,9 +567,9 @@ $time-background: rgba(0, 0, 0, .35);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
@include respond-to(handhelds) {
|
// @include respond-to(handhelds) {
|
||||||
line-height: 13px;
|
// line-height: 13px;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
&-subtitle {
|
&-subtitle {
|
||||||
|
@ -765,6 +802,9 @@ $time-background: rgba(0, 0, 0, .35);
|
||||||
//flex-direction: unset;
|
//flex-direction: unset;
|
||||||
display: block;
|
display: block;
|
||||||
|
|
||||||
|
@include respond-to(handhelds) {
|
||||||
|
padding: 0 .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
/* display: flex;
|
/* display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -814,10 +854,12 @@ $time-background: rgba(0, 0, 0, .35);
|
||||||
|
|
||||||
&.is-chat {
|
&.is-chat {
|
||||||
.is-in .bubble__container {
|
.is-in .bubble__container {
|
||||||
margin-left: 3rem;
|
margin-left: 45px;
|
||||||
|
//margin-left: 3rem; #DO JS3
|
||||||
|
|
||||||
@include respond-to(handhelds) {
|
@include respond-to(handhelds) {
|
||||||
max-width: calc(100% - 3rem);
|
max-width: calc(100% - 3rem);
|
||||||
|
margin-left: 45px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -899,7 +941,7 @@ $time-background: rgba(0, 0, 0, .35);
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
box-shadow: 0px -1px 5px -1px rgba(0,0,0,0.18);
|
box-shadow: 0px -1px 5px -1px rgba(0,0,0,0.21);
|
||||||
|
|
||||||
.chat-search-count {
|
.chat-search-count {
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
|
@ -956,7 +998,7 @@ $time-background: rgba(0, 0, 0, .35);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
top: 10px;
|
top: 8px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
transform: translateY(calc(-100% - 10px));
|
transform: translateY(calc(-100% - 10px));
|
||||||
transition: transform .2s ease;
|
transition: transform .2s ease;
|
||||||
|
@ -969,7 +1011,7 @@ $time-background: rgba(0, 0, 0, .35);
|
||||||
background: rgba(0, 0, 0, .7);
|
background: rgba(0, 0, 0, .7);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: auto;
|
width: auto;
|
||||||
padding: 12px 18px 12px 48px;
|
padding: 10px 18px 12px 50px;
|
||||||
min-height: 48px;
|
min-height: 48px;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
|
@ -990,7 +1032,7 @@ $time-background: rgba(0, 0, 0, .35);
|
||||||
&:before {
|
&:before {
|
||||||
content: $tgico-info2;
|
content: $tgico-info2;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 12px;
|
left: 15px;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
top: 12px;
|
top: 12px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,10 @@ $bubble-margin: .25rem;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@include respond-to(handhelds) {
|
||||||
|
max-width: unquote("min(calc(100% - 46px), #{$chat-max-width})");
|
||||||
|
}
|
||||||
|
|
||||||
&.is-selected {
|
&.is-selected {
|
||||||
&:after {
|
&:after {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -67,6 +71,10 @@ $bubble-margin: .25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.is-first-unread {
|
&.is-first-unread {
|
||||||
|
@include respond-to(handhelds) {
|
||||||
|
max-width: unset;
|
||||||
|
}
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
content: "Unread messages";
|
content: "Unread messages";
|
||||||
height: 30px;
|
height: 30px;
|
||||||
|
@ -135,13 +143,18 @@ $bubble-margin: .25rem;
|
||||||
|
|
||||||
> .user-avatar {
|
> .user-avatar {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: -3rem;
|
left: -45px;
|
||||||
|
//left: -3rem; # DO JS3
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
// @include respond-to(handhelds) {
|
||||||
|
// left: -45px;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -630,6 +643,11 @@ $bubble-margin: .25rem;
|
||||||
top: 0;
|
top: 0;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
|
||||||
|
@include respond-to(handhelds) {
|
||||||
|
padding: 8px 6px 8px 8px;
|
||||||
|
max-width: 94px;
|
||||||
|
}
|
||||||
|
|
||||||
.reply-content {
|
.reply-content {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
@ -1088,6 +1106,10 @@ $bubble-margin: .25rem;
|
||||||
.reply {
|
.reply {
|
||||||
left: calc(100% + 10px);
|
left: calc(100% + 10px);
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
|
||||||
|
@include respond-to(handhelds) {
|
||||||
|
left: calc(100% + 1px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1443,7 +1465,8 @@ $bubble-margin: .25rem;
|
||||||
poll-element {
|
poll-element {
|
||||||
margin-top: -1px;
|
margin-top: -1px;
|
||||||
display: block;
|
display: block;
|
||||||
min-width: 280px;
|
//min-width: 280px;
|
||||||
|
min-width: 330px;
|
||||||
|
|
||||||
&:not(.is-closed):not(.is-voted) .poll-answer {
|
&:not(.is-closed):not(.is-voted) .poll-answer {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -1458,6 +1481,7 @@ poll-element {
|
||||||
&-desc {
|
&-desc {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #707579;
|
color: #707579;
|
||||||
|
margin-top: 2px;
|
||||||
margin-bottom: 7px;
|
margin-bottom: 7px;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -1466,8 +1490,9 @@ poll-element {
|
||||||
|
|
||||||
&-hint {
|
&-hint {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
|
top: -4px;
|
||||||
|
right: 2px;
|
||||||
color: #50a2e9;
|
color: #50a2e9;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
|
@ -1485,18 +1510,19 @@ poll-element {
|
||||||
|
|
||||||
&-avatars {
|
&-avatars {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-left: 1rem;
|
margin-left: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-answer {
|
&-answer {
|
||||||
display: flex;
|
display: flex;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-bottom: 20px;
|
padding-bottom: 20px;
|
||||||
padding-left: 34px;
|
padding-left: 28px;
|
||||||
|
margin-top: 1px;
|
||||||
|
|
||||||
&-text {
|
&-text {
|
||||||
margin-top: 7px;
|
margin-top: 6px;
|
||||||
margin-left: 14px;
|
margin-left: 12px;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1507,8 +1533,9 @@ poll-element {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
margin-top: 7px;
|
margin-top: 7px;
|
||||||
|
font-size: 14px;
|
||||||
transition: .34s opacity;
|
transition: .34s opacity;
|
||||||
margin-left: -3px;
|
margin-left: -9px;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
@ -1517,7 +1544,7 @@ poll-element {
|
||||||
&-selected {
|
&-selected {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 1px;
|
bottom: 1px;
|
||||||
left: 22px;
|
left: 15px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background: #50a2e9;
|
background: #50a2e9;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
@ -1577,12 +1604,13 @@ poll-element {
|
||||||
color: #707579;
|
color: #707579;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
padding-top: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-line {
|
&-line {
|
||||||
height: 35px;
|
height: 35px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 17.5px;
|
left: 10px;
|
||||||
bottom: 2px;
|
bottom: 2px;
|
||||||
transition: stroke-dashoffset .34s linear, stroke-dasharray .34s linear;
|
transition: stroke-dashoffset .34s linear, stroke-dasharray .34s linear;
|
||||||
stroke-dashoffset: 0;
|
stroke-dashoffset: 0;
|
||||||
|
@ -1623,12 +1651,23 @@ poll-element {
|
||||||
}
|
}
|
||||||
|
|
||||||
&-quiz-timer {
|
&-quiz-timer {
|
||||||
width: 30px;
|
width: 32px;
|
||||||
height: 30px;
|
height: 32px;
|
||||||
stroke: #DF3F40;
|
stroke: #a3adb6;
|
||||||
|
transform: rotate(270deg);
|
||||||
|
top: -7px;
|
||||||
fill: none;
|
fill: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: -2px;
|
||||||
|
stroke-linecap: round;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-time {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
position: absolute;
|
||||||
|
right: 27px;
|
||||||
|
color: #a3adb6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1641,7 +1680,7 @@ poll-element {
|
||||||
|
|
||||||
.poll-answer-selected {
|
.poll-answer-selected {
|
||||||
background: #DF3F40;
|
background: #DF3F40;
|
||||||
line-height: 16px;
|
//line-height: 16px;
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
content: $tgico-close;
|
content: $tgico-close;
|
||||||
|
@ -1660,8 +1699,8 @@ poll-element {
|
||||||
}
|
}
|
||||||
|
|
||||||
avatar-element {
|
avatar-element {
|
||||||
width: 20px;
|
width: 18px;
|
||||||
height: 20px;
|
height: 18px;
|
||||||
border: 1px solid #fff;
|
border: 1px solid #fff;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
|
@ -1680,10 +1719,9 @@ poll-element {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 34px;
|
width: 34px;
|
||||||
height: 34px;
|
height: 34px;
|
||||||
margin-left: 5px;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: -1px;
|
||||||
top: 0;
|
top: -1px;
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
transition: .1s transform;
|
transition: .1s transform;
|
||||||
|
|
||||||
|
@ -1693,9 +1731,9 @@ poll-element {
|
||||||
left: 50%;
|
left: 50%;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
width: 16px;
|
width: 20px;
|
||||||
height: 16px;
|
height: 20px;
|
||||||
font-size: 16px;
|
font-size: 20px;
|
||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
animation: none;
|
animation: none;
|
||||||
transition: opacity .2s ease;
|
transition: opacity .2s ease;
|
||||||
|
@ -1727,7 +1765,7 @@ poll-element {
|
||||||
stroke-dashoffset: 0;
|
stroke-dashoffset: 0;
|
||||||
stroke-opacity: 1;
|
stroke-opacity: 1;
|
||||||
stroke-width: 2;
|
stroke-width: 2;
|
||||||
stroke: #8d969c;
|
stroke: #dadbdc;
|
||||||
fill: transparent;
|
fill: transparent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@
|
||||||
|
|
||||||
li {
|
li {
|
||||||
//padding: 0 0 2px 0;
|
//padding: 0 0 2px 0;
|
||||||
padding-bottom: 4px;
|
//padding-bottom: 4px; - DO MAKETA JS3
|
||||||
//overflow: hidden;
|
//overflow: hidden;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 9px 8.5px;
|
padding: 9px 8.5px;
|
||||||
margin: 0px 8px 0px 7px;
|
margin: 0px 8px 0px 8px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
@media not all and (min-resolution:.001dpcm)
|
@media not all and (min-resolution:.001dpcm)
|
||||||
|
@ -116,8 +116,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@include respond-to(handhelds) {
|
@include respond-to(handhelds) {
|
||||||
padding: 9px 0 0 0;
|
padding: 9px 12px 0 9px;
|
||||||
margin: 0px 11.5px 0px 9px;
|
border-radius: 0;
|
||||||
|
margin: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,8 +190,8 @@
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
color: $color-gray;
|
color: $color-gray;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
padding: 1px 3.5px 1px 9px;
|
//padding: 1px 3.5px 1px 9px; - DO MAKETA JS3
|
||||||
|
padding: 1px 8.5px 1px 9px; // JS3
|
||||||
p:last-child {
|
p:last-child {
|
||||||
margin-top: -3px;
|
margin-top: -3px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
@include respond-to(not-handhelds) {
|
@include respond-to(not-handhelds) {
|
||||||
position: absolute !important;
|
position: absolute !important;
|
||||||
left: 0;
|
left: 0;
|
||||||
bottom: calc(82px);
|
bottom: calc(85px);
|
||||||
width: 420px !important;
|
width: 420px !important;
|
||||||
height: 420px;
|
height: 420px;
|
||||||
box-shadow: 0px 5px 10px 5px rgba(16, 35, 47, 0.14);
|
box-shadow: 0px 5px 10px 5px rgba(16, 35, 47, 0.14);
|
||||||
|
@ -30,6 +30,7 @@
|
||||||
> .menu-horizontal {
|
> .menu-horizontal {
|
||||||
//font-weight: 500;
|
//font-weight: 500;
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.emoji-container {
|
.emoji-container {
|
||||||
|
@ -51,11 +52,13 @@
|
||||||
&-search {
|
&-search {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
margin-left: 4px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-delete {
|
&-delete {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
margin-right: 4px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,18 +67,21 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
.category-title {
|
.category-title {
|
||||||
position: sticky;
|
//position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
font-size: .85rem;
|
//font-size: .85rem;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
color: $color-gray;
|
color: $color-gray;
|
||||||
background: linear-gradient(to bottom,#fff 0,rgba(255,255,255,.9) 60%,rgba(255,255,255,0) 100%);
|
//background: linear-gradient(to bottom,#fff 0,rgba(255,255,255,.9) 60%,rgba(255,255,255,0) 100%);
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
padding: .53333rem 6PX .66667rem;
|
//padding: .53333rem 6PX .66667rem;
|
||||||
|
padding: 12px 6px 6px 6px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.emoji-category {
|
.emoji-category {
|
||||||
padding-top: 1px;
|
//padding-top: 1px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.category-items {
|
.category-items {
|
||||||
|
@ -109,7 +115,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
padding-top: 5px;
|
//padding-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* &::after {
|
/* &::after {
|
||||||
|
@ -188,35 +194,42 @@
|
||||||
|
|
||||||
.emoji-padding {
|
.emoji-padding {
|
||||||
.menu-horizontal {
|
.menu-horizontal {
|
||||||
border-bottom: 1px solid $lightgrey;
|
//border-bottom: 1px solid $lightgrey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.emoji-padding, .stickers-padding {
|
.emoji-padding, .stickers-padding {
|
||||||
.menu-horizontal {
|
.menu-horizontal {
|
||||||
height: 47px;
|
height: 48px;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
padding: 2px 2px 2px 2px;
|
padding: 2px 2px 2px 2px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
box-shadow: 0px 1px 5px -1px rgba(0, 0, 0, 0.21);
|
||||||
|
z-index: 4;
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#content-stickers {
|
#content-stickers {
|
||||||
.scrollable {
|
.scrollable {
|
||||||
padding: 15px 5px 0;
|
padding: 0px 5px 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-horizontal {
|
.menu-horizontal {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 50px;
|
height: 48px;
|
||||||
|
box-shadow: 0px -2px 5px -1px rgba(0, 0, 0, 0.21);
|
||||||
|
|
||||||
li {
|
li {
|
||||||
font-size: 1.65rem;
|
font-size: 1.5rem;
|
||||||
padding: 0;
|
margin: 0 12px;
|
||||||
width: 50px;
|
width: 48px;
|
||||||
height: 50px;
|
height: 48px;
|
||||||
line-height: 50px;
|
line-height: 48px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
|
@ -224,11 +237,30 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.stickers-padding {
|
.stickers-padding {
|
||||||
|
&.active {
|
||||||
|
.scrollable {
|
||||||
|
padding: 0;
|
||||||
|
box-shadow: 0px 1px 5px -1px rgba(0, 0, 0, 0.21);
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-horizontal {
|
||||||
|
box-shadow: none;
|
||||||
|
|
||||||
|
& li {
|
||||||
|
height: 48px;
|
||||||
|
width: 48px;
|
||||||
|
padding: 0;
|
||||||
|
margin-right: 1px;
|
||||||
|
margin-left: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.menu-wrapper {
|
.menu-wrapper {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
height: 50px;
|
height: 48px;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
border-top: 1px solid $lightgrey;
|
//border-top: 1px solid $lightgrey;
|
||||||
}
|
}
|
||||||
|
|
||||||
li {
|
li {
|
||||||
|
@ -242,7 +274,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
> canvas, > img {
|
> canvas, > img {
|
||||||
padding: .75rem;
|
//padding: .75rem;
|
||||||
|
padding: 8px;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
@ -6,6 +6,24 @@
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
.folders-tabs-scrollable {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
.scrollable {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-horizontal {
|
||||||
|
background: #fff;
|
||||||
|
|
||||||
|
ul {
|
||||||
|
justify-content: space-between
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-slider {
|
.sidebar-slider {
|
||||||
|
@ -46,6 +64,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-menu {
|
||||||
|
@include respond-to(handhelds) {
|
||||||
|
margin-top: -4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-tools-button .btn-menu {
|
.sidebar-tools-button .btn-menu {
|
||||||
|
@ -64,6 +88,11 @@
|
||||||
justify-self: flex-end;
|
justify-self: flex-end;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 16px;
|
right: 16px;
|
||||||
|
|
||||||
|
@include respond-to(handhelds) {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.archived-count:empty {
|
.archived-count:empty {
|
||||||
|
@ -219,6 +248,13 @@
|
||||||
border-radius: 0.625rem;
|
border-radius: 0.625rem;
|
||||||
margin: 0px 0.5rem 0px 0.4375rem;
|
margin: 0px 0.5rem 0px 0.4375rem;
|
||||||
|
|
||||||
|
@include respond-to(handhelds) {
|
||||||
|
padding: 0.75rem 0.625rem;
|
||||||
|
height: 48px;
|
||||||
|
margin: 0 0 2px 0;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
html.no-touch &:hover {
|
html.no-touch &:hover {
|
||||||
background: rgba(112, 117, 121, 0.08);
|
background: rgba(112, 117, 121, 0.08);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -240,6 +276,10 @@
|
||||||
&-buttons {
|
&-buttons {
|
||||||
margin-top: .9375rem;
|
margin-top: .9375rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
@include respond-to(handhelds) {
|
||||||
|
margin-top: 0.6875rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,4 +306,191 @@
|
||||||
.scroll-wrapper {
|
.scroll-wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-folders-container, .edit-folder-container {
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
.sticker-container {
|
||||||
|
width: 86px;
|
||||||
|
height: 86px;
|
||||||
|
margin: 1px auto 32px;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.caption {
|
||||||
|
text-align: center;
|
||||||
|
color: #707579;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-left-h2 {
|
||||||
|
color: #707579;
|
||||||
|
font-size: 15px;
|
||||||
|
padding-top: 7px;
|
||||||
|
padding-bottom: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-folders-container {
|
||||||
|
.btn-primary {
|
||||||
|
width: 160px;
|
||||||
|
height: 40px;
|
||||||
|
align-items: center;
|
||||||
|
margin: 15px auto 24px;
|
||||||
|
border-radius: 30px;
|
||||||
|
padding: 0 12px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tgico-add:before {
|
||||||
|
content: "\e903";
|
||||||
|
font-size: 24px;
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.folders-container {
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category {
|
||||||
|
padding: 7px 0 11px 0;
|
||||||
|
display: flex;
|
||||||
|
padding-bottom: 11px;
|
||||||
|
justify-content: space-between;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
p:last-child {
|
||||||
|
color: #707579;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
height: 30px;
|
||||||
|
font-size: 15px;
|
||||||
|
width: 52px;
|
||||||
|
transition: width 0.2s;
|
||||||
|
margin: 5px 0 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-folder-container {
|
||||||
|
.caption {
|
||||||
|
margin-bottom: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include respond-to(handhelds) {
|
||||||
|
.input-wrapper {
|
||||||
|
width: 328px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-field input {
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-left-h2 {
|
||||||
|
padding: 21px 0 8px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-wrapper {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.folder-list {
|
||||||
|
li {
|
||||||
|
padding-bottom: 2px;
|
||||||
|
|
||||||
|
.rp {
|
||||||
|
padding: 8px 3px !important;
|
||||||
|
height: 48px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
avatar-element {
|
||||||
|
height: 32px;
|
||||||
|
width: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-caption {
|
||||||
|
padding: 6px 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p span {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.folder-categories {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.folder-category-button {
|
||||||
|
display: flex;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
padding: 13px 16px 10px 16px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
user-select: none;
|
||||||
|
margin-left: 32px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.blue, &.blue:before {
|
||||||
|
color: #50a2e9;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
color: #797d82;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-header .tgico-check1 {
|
||||||
|
color: #50a2e9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.included-chats-container {
|
||||||
|
.sidebar-left-h2 {
|
||||||
|
color: #707579;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 6px 0 8px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
li > .rp {
|
||||||
|
margin: 0 !important;
|
||||||
|
padding: 7px 12px !important;
|
||||||
|
height: 62px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-avatar {
|
||||||
|
width: 46px;
|
||||||
|
height: 46px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.user-title {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-caption {
|
||||||
|
padding: 0px 0px 0 14px;
|
||||||
|
margin-top: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.user-last-message {
|
||||||
|
font-size: 15px;
|
||||||
|
margin-top: -1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -120,6 +120,10 @@
|
||||||
margin-bottom: 2px;
|
margin-bottom: 2px;
|
||||||
margin-top: 1px;
|
margin-top: 1px;
|
||||||
|
|
||||||
|
@include respond-to(handhelds) {
|
||||||
|
margin-top: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
&.online {
|
&.online {
|
||||||
color: $color-blue;
|
color: $color-blue;
|
||||||
}
|
}
|
||||||
|
@ -639,7 +643,7 @@
|
||||||
height: 48px;
|
height: 48px;
|
||||||
|
|
||||||
@include respond-to(not-handhelds) {
|
@include respond-to(not-handhelds) {
|
||||||
padding: 8px 13px;
|
padding: 8px 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,6 +134,10 @@
|
||||||
margin: 0px 9px 0px 8px;
|
margin: 0px 9px 0px 8px;
|
||||||
padding: 12px 8.5px;
|
padding: 12px 8.5px;
|
||||||
|
|
||||||
|
@include respond-to(handhelds) {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
@media not all and (min-resolution:.001dpcm)
|
@media not all and (min-resolution:.001dpcm)
|
||||||
{ @supports (-webkit-appearance:none) {
|
{ @supports (-webkit-appearance:none) {
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
|
|
|
@ -25,8 +25,12 @@
|
||||||
&__title {
|
&__title {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
padding-left: 23px;
|
padding-left: 22px;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
|
|
||||||
|
@include respond-to(handhelds) {
|
||||||
|
padding-left: 24px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-icon + .btn-icon {
|
.btn-icon + .btn-icon {
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
li {
|
li {
|
||||||
|
@ -24,6 +25,7 @@
|
||||||
// font-size: 1rem;
|
// font-size: 1rem;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
color: $color-blue;
|
color: $color-blue;
|
||||||
|
|
|
@ -4,10 +4,12 @@
|
||||||
#{$parent} {
|
#{$parent} {
|
||||||
&-container {
|
&-container {
|
||||||
max-height: 468px;
|
max-height: 468px;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-field {
|
.input-field {
|
||||||
|
margin-top: 25px;
|
||||||
.btn-icon {
|
.btn-icon {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: .5rem;
|
right: .5rem;
|
||||||
|
@ -30,4 +32,18 @@
|
||||||
}
|
}
|
||||||
} */
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.caption {
|
||||||
|
color: #707579;
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 16px 24px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.poll-create-questions {
|
||||||
|
padding: 0px 20px 32.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border-bottom: 1px solid #edeff1;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -53,6 +53,7 @@
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 9px;
|
margin-bottom: 9px;
|
||||||
|
padding: 12px 20px 15px;
|
||||||
|
|
||||||
.btn-primary {
|
.btn-primary {
|
||||||
width: 79px;
|
width: 79px;
|
||||||
|
@ -125,14 +126,14 @@
|
||||||
|
|
||||||
.input-field {
|
.input-field {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-top: 1rem;
|
margin-top: 25px;
|
||||||
|
|
||||||
&::placeholder {
|
&::placeholder {
|
||||||
color: #a2acb4;
|
color: #a2acb4;
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
height: 54px;
|
//height: 54px;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
padding: 0 15px;
|
padding: 0 15px;
|
||||||
border-radius: $border-radius-medium;
|
border-radius: $border-radius-medium;
|
||||||
|
@ -147,4 +148,8 @@
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-create-poll.popup-new-media .btn-primary {
|
||||||
|
width: 94px;
|
||||||
}
|
}
|
|
@ -347,6 +347,11 @@ input, textarea {
|
||||||
&.danger:before {
|
&.danger:before {
|
||||||
color: $color-error;
|
color: $color-error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@include respond-to(handhelds) {
|
||||||
|
padding: 0 30px 0 16px;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,6 +480,7 @@ avatar-element {
|
||||||
|
|
||||||
.rp {
|
.rp {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -853,6 +859,7 @@ avatar-element {
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
left: .75rem;
|
left: .75rem;
|
||||||
font-size: 0.75rem!important;
|
font-size: 0.75rem!important;
|
||||||
|
color: #666;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1386,6 +1393,26 @@ img.emoji {
|
||||||
transition: opacity .2s ease;
|
transition: opacity .2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.show-more {
|
||||||
|
padding-top: 13px;
|
||||||
|
padding-bottom: 13px;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
@include respond-to(not-handhelds) {
|
||||||
|
padding-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tgico-down {
|
||||||
|
float: left;
|
||||||
|
padding-right: 32px;
|
||||||
|
padding-left: 16px;
|
||||||
|
font-size: 24px;
|
||||||
|
color: #707579;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* .fade-in-end {
|
/* .fade-in-end {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transition: opacity .2s ease;
|
transition: opacity .2s ease;
|
||||||
|
|
|
@ -5,7 +5,7 @@ const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||||
const postcssPresetEnv = require('postcss-preset-env');
|
const postcssPresetEnv = require('postcss-preset-env');
|
||||||
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'];
|
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'];
|
||||||
const devMode = process.env.NODE_ENV !== 'production';
|
const devMode = process.env.NODE_ENV !== 'production';
|
||||||
const useLocal = false;
|
const useLocal = false;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user