Chat and sidebar load onload & media viewer supports aspects & reply markup buttons (only single answer)
This commit is contained in:
parent
448a781f8e
commit
fee0aab1d7
@ -5,7 +5,6 @@ import appDialogsManager from "../lib/appManagers/appDialogsManager";
|
||||
import appChatsManager from "../lib/appManagers/appChatsManager";
|
||||
import appUsersManager from "../lib/appManagers/appUsersManager";
|
||||
import { appPeersManager } from "../lib/services";
|
||||
import appProfileManager from "../lib/appManagers/appProfileManager";
|
||||
import appPhotosManager from "../lib/appManagers/appPhotosManager";
|
||||
|
||||
export class AppSelectPeers {
|
||||
@ -116,16 +115,18 @@ export class AppSelectPeers {
|
||||
appMessagesManager.getConversations(this.offsetIndex, 50, 0).then(value => {
|
||||
let dialogs = value.dialogs;
|
||||
|
||||
this.offsetIndex = dialogs[value.dialogs.length - 1].index || 0;
|
||||
let newOffsetIndex = dialogs[value.dialogs.length - 1].index || 0;
|
||||
|
||||
if(dialogs[0].peerID != this.myID) {
|
||||
dialogs.findAndSplice(d => d.peerID == this.myID);
|
||||
dialogs = dialogs.filter(d => d.peerID != this.myID);
|
||||
if(!this.offsetIndex) {
|
||||
dialogs.unshift({
|
||||
peerID: this.myID,
|
||||
pFlags: {}
|
||||
} as any);
|
||||
}
|
||||
|
||||
this.offsetIndex = newOffsetIndex;
|
||||
|
||||
this.renderResults(dialogs.map(dialog => dialog.peerID));
|
||||
});
|
||||
}
|
||||
|
@ -12,6 +12,8 @@ export default class BubbleGroups {
|
||||
details.group.findAndSplice(d => d == bubble);
|
||||
if(!details.group.length) {
|
||||
this.groups.findAndSplice(g => g == details.group);
|
||||
} else {
|
||||
this.updateGroup(details.group);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -49,7 +51,7 @@ export default class BubbleGroups {
|
||||
//console.log('addBubble', bubble, message.mid, fromID, reverse, group);
|
||||
|
||||
this.bubblesByGroups[reverse ? 'unshift' : 'push']({timestamp, fromID, mid: message.mid, group});
|
||||
this.updateGroup(group, reverse);
|
||||
this.updateGroup(group);
|
||||
}
|
||||
|
||||
setClipIfNeeded(bubble: HTMLDivElement, remove = false) {
|
||||
@ -100,7 +102,7 @@ export default class BubbleGroups {
|
||||
}
|
||||
}
|
||||
|
||||
updateGroup(group: HTMLDivElement[], reverse = false) {
|
||||
updateGroup(group: HTMLDivElement[]) {
|
||||
/* if(this.updateRAFs.has(group)) {
|
||||
window.cancelAnimationFrame(this.updateRAFs.get(group));
|
||||
this.updateRAFs.delete(group);
|
||||
@ -115,8 +117,6 @@ export default class BubbleGroups {
|
||||
|
||||
let first = group[0];
|
||||
|
||||
//appImManager.scrollPosition.prepareFor(reverse ? 'up' : 'down');
|
||||
|
||||
//console.log('updateGroup', group, first);
|
||||
|
||||
if(group.length == 1) {
|
||||
@ -140,8 +140,6 @@ export default class BubbleGroups {
|
||||
last.classList.remove('is-group-first');
|
||||
last.classList.add('is-group-last');
|
||||
this.setClipIfNeeded(last);
|
||||
|
||||
//appImManager.scrollPosition.restore();
|
||||
//}));
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,7 @@ export default class LazyLoadQueue {
|
||||
this.debug && this.log('will load media', this.lockPromise, item);
|
||||
|
||||
try {
|
||||
if(this.lockPromise) {
|
||||
if(this.lockPromise && false) {
|
||||
let perf = performance.now();
|
||||
await this.lockPromise;
|
||||
|
||||
|
@ -3,6 +3,8 @@ import Config from "../lib/config";
|
||||
|
||||
let rippleClickID = 0;
|
||||
export function ripple(elem: HTMLElement, callback: (id: number) => Promise<boolean | void> = () => Promise.resolve(), onEnd: (id: number) => void = null) {
|
||||
if(elem.querySelector('.c-ripple')) return;
|
||||
|
||||
let r = document.createElement('div');
|
||||
r.classList.add('c-ripple');
|
||||
|
||||
@ -99,6 +101,19 @@ export function ripple(elem: HTMLElement, callback: (id: number) => Promise<bool
|
||||
});
|
||||
}
|
||||
|
||||
const toastEl = document.createElement('div');
|
||||
toastEl.classList.add('toast');
|
||||
export function toast(html: string) {
|
||||
toastEl.innerHTML = html;
|
||||
document.body.append(toastEl);
|
||||
|
||||
if(toastEl.dataset.timeout) clearTimeout(+toastEl.dataset.timeout);
|
||||
toastEl.dataset.timeout = '' + setTimeout(() => {
|
||||
toastEl.remove();
|
||||
delete toastEl.dataset.timeout;
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
let loadedURLs: {[url: string]: boolean} = {};
|
||||
let set = (elem: HTMLElement | HTMLImageElement | SVGImageElement | HTMLSourceElement, url: string) => {
|
||||
if(elem instanceof HTMLImageElement || elem instanceof HTMLSourceElement) elem.src = url;
|
||||
@ -117,10 +132,12 @@ export function renderImageFromUrl(elem: HTMLElement | HTMLImageElement | SVGIma
|
||||
} else {
|
||||
let loader = new Image();
|
||||
loader.src = url;
|
||||
loader.onload = () => {
|
||||
//let perf = performance.now();
|
||||
loader.addEventListener('load', () => {
|
||||
set(elem, url);
|
||||
loadedURLs[url] = true;
|
||||
};
|
||||
//console.log('onload:', url, performance.now() - perf);
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -336,7 +353,7 @@ let onMouseMove = (e: MouseEvent) => {
|
||||
};
|
||||
|
||||
let onClick = (e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
//e.preventDefault();
|
||||
closeBtnMenu();
|
||||
};
|
||||
|
||||
|
@ -367,50 +367,41 @@ export default class Scrollable {
|
||||
return !!element.parentElement;
|
||||
}
|
||||
|
||||
public scrollIntoView(element: HTMLElement, smooth = true, fromUp = false) {
|
||||
public scrollIntoView(element: HTMLElement, smooth = true) {
|
||||
if(element.parentElement && !this.scrollLocked) {
|
||||
let scrollTop = this.scrollTop;
|
||||
let isFirstUnread = element.classList.contains('is-first-unread');
|
||||
let offsetTop = element.offsetTop;
|
||||
let clientHeight = this.container.clientHeight;
|
||||
|
||||
let height = element.scrollHeight;
|
||||
|
||||
let diff = (clientHeight - height) / 2;
|
||||
|
||||
/* if(scrollTop < offsetTop) {
|
||||
offsetTop += diff;
|
||||
} else { */
|
||||
offsetTop -= diff;
|
||||
//}
|
||||
|
||||
if(element.dataset.timeout) {
|
||||
clearTimeout(+element.dataset.timeout);
|
||||
element.classList.remove('is-selected');
|
||||
void element.offsetWidth; // reflow
|
||||
}
|
||||
element.classList.add('is-selected');
|
||||
element.dataset.timeout = '' + setTimeout(() => {
|
||||
element.classList.remove('is-selected');
|
||||
delete element.dataset.timeout;
|
||||
}, 2000);
|
||||
|
||||
if(scrollTop == Math.floor(offsetTop)) {
|
||||
if(!smooth && isFirstUnread) {
|
||||
this.scrollTo(offsetTop, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if(this.scrollLocked) clearTimeout(this.scrollLocked);
|
||||
this.scrollLocked = setTimeout(() => {
|
||||
this.scrollLocked = 0;
|
||||
this.onScroll();
|
||||
}, 468);
|
||||
if(fromUp) {
|
||||
this.container.scrollTo({behavior: 'auto', top: 0});
|
||||
}
|
||||
this.container.scrollTo({behavior: smooth ? 'smooth' : 'auto', top: offsetTop});
|
||||
//element.scrollIntoView({behavior: 'smooth', block: 'center'});
|
||||
let clientHeight = this.container.clientHeight;
|
||||
let height = element.scrollHeight;
|
||||
|
||||
offsetTop -= (clientHeight - height) / 2;
|
||||
|
||||
this.scrollTo(offsetTop, smooth);
|
||||
}
|
||||
}
|
||||
|
||||
public scrollTo(top: number, smooth = true) {
|
||||
if(this.scrollLocked) return;
|
||||
|
||||
let scrollTop = this.scrollTop;
|
||||
if(scrollTop == Math.floor(top)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(this.scrollLocked) clearTimeout(this.scrollLocked);
|
||||
this.scrollLocked = setTimeout(() => {
|
||||
this.scrollLocked = 0;
|
||||
this.onScroll();
|
||||
}, 468);
|
||||
|
||||
this.container.scrollTo({behavior: smooth ? 'smooth' : 'auto', top});
|
||||
}
|
||||
|
||||
public removeElement(element: Element) {
|
||||
element.remove();
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ import { CancellablePromise } from '../lib/polyfill';
|
||||
import { renderImageFromUrl } from './misc';
|
||||
import appMessagesManager from '../lib/appManagers/appMessagesManager';
|
||||
import { Layouter, RectPart } from './groupedLayout';
|
||||
import { Poll, PollResults } from '../lib/appManagers/appPollsManager';
|
||||
import PollElement from './poll';
|
||||
|
||||
export type MTDocument = {
|
||||
@ -135,47 +134,43 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
||||
}
|
||||
}
|
||||
|
||||
let loadVideo = () => {
|
||||
let promise = appDocsManager.downloadDoc(doc);
|
||||
|
||||
let loadVideo = async() => {
|
||||
if(message.media.preloader) { // means upload
|
||||
message.media.preloader.attach(container);
|
||||
} else if(!doc.downloaded) {
|
||||
let preloader = new ProgressivePreloader(container, true);
|
||||
let promise = appDocsManager.downloadDoc(doc);
|
||||
preloader.attach(container, true, promise);
|
||||
await promise;
|
||||
}
|
||||
|
||||
if(middleware && !middleware()) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('loaded doc:', doc, doc.url, container);
|
||||
|
||||
renderImageFromUrl(source, doc.url);
|
||||
source.type = doc.mime_type;
|
||||
video.append(source);
|
||||
|
||||
if(!withTail) {
|
||||
if(img && container.contains(img)) {
|
||||
container.removeChild(img);
|
||||
}
|
||||
|
||||
container.append(video);
|
||||
}
|
||||
|
||||
return promise.then(blob => {
|
||||
if(middleware && !middleware()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//return;
|
||||
|
||||
//console.log('loaded doc:', doc, doc.url, blob, container);
|
||||
|
||||
renderImageFromUrl(source, doc.url);
|
||||
source.type = doc.mime_type;
|
||||
video.append(source);
|
||||
|
||||
if(!withTail) {
|
||||
if(img && container.contains(img)) {
|
||||
container.removeChild(img);
|
||||
}
|
||||
|
||||
container.append(video);
|
||||
}
|
||||
|
||||
if(doc.type == 'gif') {
|
||||
video.autoplay = true;
|
||||
video.loop = true;
|
||||
} else if(doc.type == 'round') {
|
||||
//video.dataset.ckin = doc.type == 'round' ? 'circle' : 'default';
|
||||
video.dataset.ckin = 'circle';
|
||||
video.dataset.overlay = '1';
|
||||
let player = new VideoPlayer(video/* , doc.type != 'round' */);
|
||||
}
|
||||
});
|
||||
if(doc.type == 'gif') {
|
||||
video.autoplay = true;
|
||||
video.loop = true;
|
||||
} else if(doc.type == 'round') {
|
||||
//video.dataset.ckin = doc.type == 'round' ? 'circle' : 'default';
|
||||
video.dataset.ckin = 'circle';
|
||||
video.dataset.overlay = '1';
|
||||
let player = new VideoPlayer(video/* , doc.type != 'round' */);
|
||||
}
|
||||
};
|
||||
|
||||
if(doc.size >= 20e6 && !doc.downloaded) {
|
||||
@ -826,11 +821,11 @@ export function wrapSticker(doc: MTDocument, div: HTMLDivElement, middleware?: (
|
||||
if(!downloaded && (!div.firstElementChild || div.firstElementChild.tagName != 'IMG')) {
|
||||
img.style.opacity = '' + 0;
|
||||
|
||||
img.onload = () => {
|
||||
img.addEventListener('load', () => {
|
||||
window.requestAnimationFrame(() => {
|
||||
img.style.opacity = '';
|
||||
});
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
if(!doc.url) {
|
||||
@ -889,8 +884,8 @@ export function wrapReply(title: string, subtitle: string, message?: any) {
|
||||
}
|
||||
|
||||
appPhotosManager.preloadPhoto(photo, appPhotosManager.choosePhotoSize(photo, 32, 32))
|
||||
.then(blob => {
|
||||
renderImageFromUrl(replyMedia, photo._ == 'photo' ? photo.url : URL.createObjectURL(blob));
|
||||
.then(() => {
|
||||
renderImageFromUrl(replyMedia, photo._ == 'photo' ? photo.url : appPhotosManager.getDocumentCachedThumb(photo.id).url);
|
||||
});
|
||||
|
||||
replyContent.append(replyMedia);
|
||||
@ -1004,34 +999,6 @@ export function wrapAlbum({groupID, attachmentDiv, middleware, uploading, lazyLo
|
||||
});
|
||||
}
|
||||
|
||||
/* let load = () => appPhotosManager.preloadPhoto(media._ == 'photo' ? media.id : media, size)
|
||||
.then((blob) => {
|
||||
if(middleware && !middleware()) {
|
||||
console.warn('peer changed');
|
||||
return;
|
||||
}
|
||||
|
||||
if(!uploading) {
|
||||
preloader.detach();
|
||||
}
|
||||
|
||||
if(media && media.url) {
|
||||
renderImageFromUrl(div, media.url);
|
||||
} else {
|
||||
let url = URL.createObjectURL(blob);
|
||||
|
||||
let img = new Image();
|
||||
img.src = url;
|
||||
img.onload = () => {
|
||||
div.style.backgroundImage = 'url(' + url + ')';
|
||||
};
|
||||
}
|
||||
|
||||
//div.style.backgroundImage = 'url(' + url + ')';
|
||||
});
|
||||
|
||||
load(); */
|
||||
|
||||
// @ts-ignore
|
||||
//div.style.backgroundColor = '#' + Math.floor(Math.random() * (2 ** 24 - 1)).toString(16).padStart(6, '0');
|
||||
|
||||
|
421
src/lib/appManagers/AppInlineBotsManager.ts
Normal file
421
src/lib/appManagers/AppInlineBotsManager.ts
Normal file
@ -0,0 +1,421 @@
|
||||
import appMessagesManager from "./appMessagesManager";
|
||||
import apiManagerProxy from "../mtproto/mtprotoworker";
|
||||
import { appPeersManager } from "../services";
|
||||
import appMessagesIDsManager from "./appMessagesIDsManager";
|
||||
import { toast } from "../../components/misc";
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
|
||||
export class AppInlineBotsManager {
|
||||
/* private inlineResults: any = {};
|
||||
|
||||
function getPopularBots () {
|
||||
return Storage.get('inline_bots_popular').then(function (bots) {
|
||||
var result = []
|
||||
var i, len
|
||||
var userID
|
||||
if (bots && bots.length) {
|
||||
var now = tsNow(true)
|
||||
for (i = 0, len = bots.length; i < len; i++) {
|
||||
if ((now - bots[i][3]) > 14 * 86400) {
|
||||
continue
|
||||
}
|
||||
userID = bots[i][0]
|
||||
if (!AppUsersManager.hasUser(userID)) {
|
||||
AppUsersManager.saveApiUser(bots[i][1])
|
||||
}
|
||||
result.push({id: userID, rate: bots[i][2], date: bots[i][3]})
|
||||
}
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
function pushPopularBot (id) {
|
||||
getPopularBots().then(function (bots) {
|
||||
var exists = false
|
||||
var count = bots.length
|
||||
var result = []
|
||||
for (var i = 0; i < count; i++) {
|
||||
if (bots[i].id == id) {
|
||||
exists = true
|
||||
bots[i].rate++
|
||||
bots[i].date = tsNow(true)
|
||||
}
|
||||
var user = AppUsersManager.getUser(bots[i].id)
|
||||
result.push([bots[i].id, user, bots[i].rate, bots[i].date])
|
||||
}
|
||||
if (exists) {
|
||||
result.sort(function (a, b) {
|
||||
return b[2] - a[2]
|
||||
})
|
||||
} else {
|
||||
if (result.length > 15) {
|
||||
result = result.slice(0, 15)
|
||||
}
|
||||
result.push([id, AppUsersManager.getUser(id), 1, tsNow(true)])
|
||||
}
|
||||
ConfigStorage.set({inline_bots_popular: result})
|
||||
|
||||
$rootScope.$broadcast('inline_bots_popular')
|
||||
})
|
||||
}
|
||||
|
||||
function resolveInlineMention (username) {
|
||||
return AppPeersManager.resolveUsername(username).then(function (peerID) {
|
||||
if (peerID > 0) {
|
||||
var bot = AppUsersManager.getUser(peerID)
|
||||
if (bot.pFlags.bot && bot.bot_inline_placeholder !== undefined) {
|
||||
var resolvedBot = {
|
||||
username: username,
|
||||
id: peerID,
|
||||
placeholder: bot.bot_inline_placeholder
|
||||
}
|
||||
if (bot.pFlags.bot_inline_geo &&
|
||||
GeoLocationManager.isAvailable()) {
|
||||
return checkGeoLocationAccess(peerID).then(function () {
|
||||
return GeoLocationManager.getPosition().then(function (coords) {
|
||||
resolvedBot.geo = coords
|
||||
return qSync.when(resolvedBot)
|
||||
})
|
||||
})['catch'](function () {
|
||||
return qSync.when(resolvedBot)
|
||||
})
|
||||
}
|
||||
return qSync.when(resolvedBot)
|
||||
}
|
||||
}
|
||||
return $q.reject()
|
||||
}, function (error) {
|
||||
error.handled = true
|
||||
return $q.reject(error)
|
||||
})
|
||||
}
|
||||
|
||||
function getInlineResults (peerID, botID, query, geo, offset) {
|
||||
return MtpApiManager.invokeApi('messages.getInlineBotResults', {
|
||||
flags: 0 | (geo ? 1 : 0),
|
||||
bot: AppUsersManager.getUserInput(botID),
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
query: query,
|
||||
geo_point: geo && {_: 'inputGeoPoint', lat: geo['lat'], long: geo['long']},
|
||||
offset: offset
|
||||
}, {timeout: 1, stopTime: -1, noErrorBox: true}).then(function (botResults) {
|
||||
var queryID = botResults.query_id
|
||||
delete botResults._
|
||||
delete botResults.flags
|
||||
delete botResults.query_id
|
||||
|
||||
if (botResults.switch_pm) {
|
||||
botResults.switch_pm.rText = RichTextProcessor.wrapRichText(botResults.switch_pm.text, {noLinebreaks: true, noLinks: true})
|
||||
}
|
||||
|
||||
angular.forEach(botResults.results, function (result) {
|
||||
var qID = queryID + '_' + result.id
|
||||
result.qID = qID
|
||||
result.botID = botID
|
||||
|
||||
result.rTitle = RichTextProcessor.wrapRichText(result.title, {noLinebreaks: true, noLinks: true})
|
||||
result.rDescription = RichTextProcessor.wrapRichText(result.description, {noLinebreaks: true, noLinks: true})
|
||||
result.initials = (result.url || result.title || result.type || '').substr(0, 1)
|
||||
|
||||
if (result.document) {
|
||||
AppDocsManager.saveDoc(result.document)
|
||||
}
|
||||
if (result.photo) {
|
||||
AppPhotosManager.savePhoto(result.photo)
|
||||
}
|
||||
|
||||
inlineResults[qID] = result
|
||||
})
|
||||
return botResults
|
||||
})
|
||||
}
|
||||
|
||||
function regroupWrappedResults (results, rowW, rowH) {
|
||||
if (!results ||
|
||||
!results[0] ||
|
||||
['photo', 'gif', 'sticker'].indexOf(results[0].type) == -1) {
|
||||
return
|
||||
}
|
||||
var ratios = []
|
||||
angular.forEach(results, function (result) {
|
||||
var w
|
||||
var h, doc
|
||||
var photo
|
||||
if (result._ == 'botInlineMediaResult') {
|
||||
if (doc = result.document) {
|
||||
w = result.document.w
|
||||
h = result.document.h
|
||||
}
|
||||
else if (photo = result.photo) {
|
||||
var photoSize = (photo.sizes || [])[0]
|
||||
w = photoSize && photoSize.w
|
||||
h = photoSize && photoSize.h
|
||||
}
|
||||
}else {
|
||||
w = result.w
|
||||
h = result.h
|
||||
}
|
||||
if (!w || !h) {
|
||||
w = h = 1
|
||||
}
|
||||
ratios.push(w / h)
|
||||
})
|
||||
|
||||
var rows = []
|
||||
var curCnt = 0
|
||||
var curW = 0
|
||||
angular.forEach(ratios, function (ratio) {
|
||||
var w = ratio * rowH
|
||||
curW += w
|
||||
if (!curCnt || curCnt < 4 && curW < (rowW * 1.1)) {
|
||||
curCnt++
|
||||
} else {
|
||||
rows.push(curCnt)
|
||||
curCnt = 1
|
||||
curW = w
|
||||
}
|
||||
})
|
||||
if (curCnt) {
|
||||
rows.push(curCnt)
|
||||
}
|
||||
|
||||
var i = 0
|
||||
var thumbs = []
|
||||
var lastRowI = rows.length - 1
|
||||
angular.forEach(rows, function (rowCnt, rowI) {
|
||||
var lastRow = rowI == lastRowI
|
||||
var curRatios = ratios.slice(i, i + rowCnt)
|
||||
var sumRatios = 0
|
||||
angular.forEach(curRatios, function (ratio) {
|
||||
sumRatios += ratio
|
||||
})
|
||||
angular.forEach(curRatios, function (ratio, j) {
|
||||
var thumbH = rowH
|
||||
var thumbW = rowW * ratio / sumRatios
|
||||
var realW = thumbH * ratio
|
||||
if (lastRow && thumbW > realW) {
|
||||
thumbW = realW
|
||||
}
|
||||
var result = results[i + j]
|
||||
result.thumbW = Math.floor(thumbW) - 2
|
||||
result.thumbH = Math.floor(thumbH) - 2
|
||||
})
|
||||
|
||||
i += rowCnt
|
||||
})
|
||||
}
|
||||
|
||||
function switchToPM (fromPeerID, botID, startParam) {
|
||||
var peerString = AppPeersManager.getPeerString(fromPeerID)
|
||||
var setHash = {}
|
||||
setHash['inline_switch_pm' + botID] = {peer: peerString, time: tsNow()}
|
||||
Storage.set(setHash)
|
||||
$rootScope.$broadcast('history_focus', {peerString: AppPeersManager.getPeerString(botID)})
|
||||
AppMessagesManager.startBot(botID, 0, startParam)
|
||||
}
|
||||
|
||||
function checkSwitchReturn (botID) {
|
||||
var bot = AppUsersManager.getUser(botID)
|
||||
if (!bot || !bot.pFlags.bot || !bot.bot_inline_placeholder) {
|
||||
return qSync.when(false)
|
||||
}
|
||||
var key = 'inline_switch_pm' + botID
|
||||
return Storage.get(key).then(function (peerData) {
|
||||
if (peerData) {
|
||||
Storage.remove(key)
|
||||
if (tsNow() - peerData.time < 3600000) {
|
||||
return peerData.peer
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
function switchInlineQuery (botID, toPeerString, query) {
|
||||
$rootScope.$broadcast('history_focus', {
|
||||
peerString: toPeerString,
|
||||
attachment: {
|
||||
_: 'inline_query',
|
||||
mention: '@' + AppUsersManager.getUser(botID).username,
|
||||
query: query
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function switchInlineButtonClick (id, button) {
|
||||
var message = AppMessagesManager.getMessage(id)
|
||||
var botID = message.viaBotID || message.fromID
|
||||
if (button.pFlags && button.pFlags.same_peer) {
|
||||
var peerID = AppMessagesManager.getMessagePeer(message)
|
||||
var toPeerString = AppPeersManager.getPeerString(peerID)
|
||||
switchInlineQuery(botID, toPeerString, button.query)
|
||||
return
|
||||
}
|
||||
return checkSwitchReturn(botID).then(function (retPeerString) {
|
||||
if (retPeerString) {
|
||||
return switchInlineQuery(botID, retPeerString, button.query)
|
||||
}
|
||||
PeersSelectService.selectPeer({
|
||||
canSend: true
|
||||
}).then(function (toPeerString) {
|
||||
return switchInlineQuery(botID, toPeerString, button.query)
|
||||
})
|
||||
})
|
||||
} */
|
||||
|
||||
public callbackButtonClick(mid: number, button: any) {
|
||||
let message = appMessagesManager.getMessage(mid);
|
||||
let peerID = appMessagesManager.getMessagePeer(message);
|
||||
|
||||
return apiManagerProxy.invokeApi('messages.getBotCallbackAnswer', {
|
||||
flags: 1,
|
||||
peer: appPeersManager.getInputPeerByID(peerID),
|
||||
msg_id: appMessagesIDsManager.getMessageLocalID(mid),
|
||||
data: button.data
|
||||
}, {timeout: 1, stopTime: -1, noErrorBox: true}).then((callbackAnswer: any) => {
|
||||
if(typeof callbackAnswer.message === 'string' && callbackAnswer.message.length) {
|
||||
toast(RichTextProcessor.wrapRichText(callbackAnswer.message, {noLinks: true, noLinebreaks: true}));
|
||||
}
|
||||
|
||||
console.log('callbackButtonClick callbackAnswer:', callbackAnswer);
|
||||
});
|
||||
}
|
||||
|
||||
/* function gameButtonClick (id) {
|
||||
var message = AppMessagesManager.getMessage(id)
|
||||
var peerID = AppMessagesManager.getMessagePeer(message)
|
||||
|
||||
return MtpApiManager.invokeApi('messages.getBotCallbackAnswer', {
|
||||
flags: 2,
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
msg_id: AppMessagesIDsManager.getMessageLocalID(id)
|
||||
}, {timeout: 1, stopTime: -1, noErrorBox: true}).then(function (callbackAnswer) {
|
||||
if (typeof callbackAnswer.message === 'string' &&
|
||||
callbackAnswer.message.length) {
|
||||
showCallbackMessage(callbackAnswer.message, callbackAnswer.pFlags.alert)
|
||||
}
|
||||
else if (typeof callbackAnswer.url === 'string') {
|
||||
AppGamesManager.openGame(message.media.game.id, id, callbackAnswer.url)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function sendInlineResult (peerID, qID, options) {
|
||||
var inlineResult = inlineResults[qID]
|
||||
if (inlineResult === undefined) {
|
||||
return false
|
||||
}
|
||||
pushPopularBot(inlineResult.botID)
|
||||
var splitted = qID.split('_')
|
||||
var queryID = splitted.shift()
|
||||
var resultID = splitted.join('_')
|
||||
options = options || {}
|
||||
options.viaBotID = inlineResult.botID
|
||||
options.queryID = queryID
|
||||
options.resultID = resultID
|
||||
if (inlineResult.send_message.reply_markup) {
|
||||
options.reply_markup = inlineResult.send_message.reply_markup
|
||||
}
|
||||
|
||||
if (inlineResult.send_message._ == 'botInlineMessageText') {
|
||||
options.entities = inlineResult.send_message.entities
|
||||
AppMessagesManager.sendText(peerID, inlineResult.send_message.message, options)
|
||||
} else {
|
||||
var caption = ''
|
||||
var inputMedia = false
|
||||
switch (inlineResult.send_message._) {
|
||||
case 'botInlineMessageMediaAuto':
|
||||
caption = inlineResult.send_message.caption
|
||||
if (inlineResult._ == 'botInlineMediaResult') {
|
||||
var doc = inlineResult.document
|
||||
var photo = inlineResult.photo
|
||||
if (doc) {
|
||||
inputMedia = {
|
||||
_: 'inputMediaDocument',
|
||||
id: {_: 'inputDocument', id: doc.id, access_hash: doc.access_hash},
|
||||
caption: caption
|
||||
}
|
||||
} else {
|
||||
inputMedia = {
|
||||
_: 'inputMediaPhoto',
|
||||
id: {_: 'inputPhoto', id: photo.id, access_hash: photo.access_hash},
|
||||
caption: caption
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
|
||||
case 'botInlineMessageMediaGeo':
|
||||
inputMedia = {
|
||||
_: 'inputMediaGeoPoint',
|
||||
geo_point: {
|
||||
_: 'inputGeoPoint',
|
||||
'lat': inlineResult.send_message.geo['lat'],
|
||||
'long': inlineResult.send_message.geo['long']
|
||||
}
|
||||
}
|
||||
break
|
||||
|
||||
case 'botInlineMessageMediaVenue':
|
||||
inputMedia = {
|
||||
_: 'inputMediaVenue',
|
||||
geo_point: {
|
||||
_: 'inputGeoPoint',
|
||||
'lat': inlineResult.send_message.geo['lat'],
|
||||
'long': inlineResult.send_message.geo['long']
|
||||
},
|
||||
title: inlineResult.send_message.title,
|
||||
address: inlineResult.send_message.address,
|
||||
provider: inlineResult.send_message.provider,
|
||||
venue_id: inlineResult.send_message.venue_id
|
||||
}
|
||||
break
|
||||
|
||||
case 'botInlineMessageMediaContact':
|
||||
inputMedia = {
|
||||
_: 'inputMediaContact',
|
||||
phone_number: inlineResult.send_message.phone_number,
|
||||
first_name: inlineResult.send_message.first_name,
|
||||
last_name: inlineResult.send_message.last_name
|
||||
}
|
||||
break
|
||||
}
|
||||
if (!inputMedia) {
|
||||
inputMedia = {
|
||||
_: 'messageMediaPending',
|
||||
type: inlineResult.type,
|
||||
file_name: inlineResult.title || inlineResult.content_url || inlineResult.url,
|
||||
size: 0,
|
||||
progress: {percent: 30, total: 0}
|
||||
}
|
||||
}
|
||||
AppMessagesManager.sendOther(peerID, inputMedia, options)
|
||||
}
|
||||
}
|
||||
|
||||
function checkGeoLocationAccess (botID) {
|
||||
var key = 'bot_access_geo' + botID
|
||||
return Storage.get(key).then(function (geoAccess) {
|
||||
if (geoAccess && geoAccess.granted) {
|
||||
return true
|
||||
}
|
||||
return ErrorService.confirm({
|
||||
type: 'BOT_ACCESS_GEO_INLINE'
|
||||
}).then(function () {
|
||||
var setHash = {}
|
||||
setHash[key] = {granted: true, time: tsNow()}
|
||||
Storage.set(setHash)
|
||||
return true
|
||||
}, function () {
|
||||
var setHash = {}
|
||||
setHash[key] = {denied: true, time: tsNow()}
|
||||
Storage.set(setHash)
|
||||
return $q.reject()
|
||||
})
|
||||
})
|
||||
} */
|
||||
}
|
||||
|
||||
const appInlineBotsManager = new AppInlineBotsManager();
|
||||
export default appInlineBotsManager;
|
@ -13,9 +13,9 @@ export class ApiUpdatesManager {
|
||||
syncPending: any,
|
||||
syncLoading: any,
|
||||
|
||||
seq?: any,
|
||||
pts?: any,
|
||||
date?: any
|
||||
seq?: number,
|
||||
pts?: number,
|
||||
date?: number
|
||||
} = {
|
||||
pendingPtsUpdates: [],
|
||||
pendingSeqUpdates: {},
|
||||
@ -24,14 +24,7 @@ export class ApiUpdatesManager {
|
||||
};
|
||||
|
||||
public channelStates: any = {};
|
||||
public myID = 0;
|
||||
private attached = false;
|
||||
|
||||
constructor() {
|
||||
apiManager.getUserID().then((id) => {
|
||||
this.myID = id;
|
||||
});
|
||||
}
|
||||
|
||||
public popPendingSeqUpdate() {
|
||||
var nextSeq = this.updatesState.seq + 1;
|
||||
@ -141,10 +134,10 @@ export class ApiUpdatesManager {
|
||||
case 'updateShortMessage':
|
||||
case 'updateShortChatMessage':
|
||||
var isOut = updateMessage.flags & 2;
|
||||
var fromID = updateMessage.from_id || (isOut ? this.myID : updateMessage.user_id);
|
||||
var fromID = updateMessage.from_id || (isOut ? $rootScope.myID : updateMessage.user_id);
|
||||
var toID = updateMessage.chat_id
|
||||
? -updateMessage.chat_id
|
||||
: (isOut ? updateMessage.user_id : this.myID);
|
||||
: (isOut ? updateMessage.user_id : $rootScope.myID);
|
||||
|
||||
this.processUpdate({
|
||||
_: 'updateNewMessage',
|
||||
@ -500,24 +493,31 @@ export class ApiUpdatesManager {
|
||||
$rootScope.$broadcast('apiUpdate', update);
|
||||
}
|
||||
|
||||
public attach() {
|
||||
public attach(state: Pick<ApiUpdatesManager['updatesState'], 'seq' | 'pts' | 'date'>) {
|
||||
if(this.attached) return;
|
||||
|
||||
this.attached = true;
|
||||
apiManager.setUpdatesProcessor(this.processUpdateMessage.bind(this));
|
||||
apiManager.invokeApi('updates.getState', {}, {noErrorBox: true}).then((stateResult: any) => {
|
||||
this.updatesState.seq = stateResult.seq;
|
||||
this.updatesState.pts = stateResult.pts;
|
||||
this.updatesState.date = stateResult.date;
|
||||
setTimeout(() => {
|
||||
this.updatesState.syncLoading = false;
|
||||
}, 1000);
|
||||
|
||||
// updatesState.seq = 1
|
||||
// updatesState.pts = stateResult.pts - 5000
|
||||
// updatesState.date = 1
|
||||
// getDifference()
|
||||
});
|
||||
|
||||
if(!state) {
|
||||
apiManager.invokeApi('updates.getState', {}, {noErrorBox: true}).then((stateResult: any) => {
|
||||
this.updatesState.seq = stateResult.seq;
|
||||
this.updatesState.pts = stateResult.pts;
|
||||
this.updatesState.date = stateResult.date;
|
||||
setTimeout(() => {
|
||||
this.updatesState.syncLoading = false;
|
||||
}, 1000);
|
||||
|
||||
// updatesState.seq = 1
|
||||
// updatesState.pts = stateResult.pts - 5000
|
||||
// updatesState.date = 1
|
||||
// getDifference()
|
||||
});
|
||||
} else {
|
||||
Object.assign(this.updatesState, state);
|
||||
this.updatesState.syncLoading = false;
|
||||
this.getDifference();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ export class AppChatsManager {
|
||||
let titleWords = SearchIndexManager.cleanSearchText(apiChat.title || '', false).split(' ');
|
||||
let firstWord = titleWords.shift();
|
||||
let lastWord = titleWords.pop();
|
||||
apiChat.initials = firstWord.charAt(0) + (lastWord ? lastWord.charAt(0) : firstWord.charAt(1));
|
||||
apiChat.initials = firstWord.charAt(0) + (lastWord ? lastWord.charAt(0) : '');
|
||||
|
||||
if(apiChat.pFlags === undefined) {
|
||||
apiChat.pFlags = {};
|
||||
|
@ -384,8 +384,6 @@ export class AppDialogsManager {
|
||||
|
||||
public chatsArchivedContainer = document.getElementById('chats-archived-container') as HTMLDivElement;
|
||||
public chatsContainer = document.getElementById('chats-container') as HTMLDivElement;
|
||||
private chatsArchivedOffsetIndex = 0;
|
||||
private chatsOffsetIndex = 0;
|
||||
private chatsPreloader: HTMLDivElement;
|
||||
//private chatsLoadCount = 0;
|
||||
//private loadDialogsPromise: Promise<any>;
|
||||
@ -544,10 +542,30 @@ export class AppDialogsManager {
|
||||
}
|
||||
});
|
||||
|
||||
this.loadDialogs().then(result => {
|
||||
this.setPinnedDelimiter();
|
||||
//appSidebarLeft.onChatsScroll();
|
||||
this.loadDialogs(true);
|
||||
$rootScope.$on('peer_changed', (e: CustomEvent) => {
|
||||
let peerID = e.detail;
|
||||
|
||||
let lastPeerID = this.lastActiveListElement && +this.lastActiveListElement.getAttribute('data-peerID');
|
||||
if(this.lastActiveListElement && lastPeerID != peerID) {
|
||||
this.lastActiveListElement.classList.remove('active');
|
||||
this.lastActiveListElement = null;
|
||||
}
|
||||
|
||||
if(lastPeerID != peerID) {
|
||||
let dom = this.getDialogDom(peerID);
|
||||
if(dom) {
|
||||
this.lastActiveListElement = dom.listEl;
|
||||
dom.listEl.classList.add('active');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
appMessagesManager.loaded.then(() => {
|
||||
this.loadDialogs().then(result => {
|
||||
this.setPinnedDelimiter();
|
||||
//appSidebarLeft.onChatsScroll();
|
||||
this.loadDialogs(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -559,30 +577,30 @@ export class AppDialogsManager {
|
||||
if(this.loadDialogsPromise/* || 1 == 1 */) return this.loadDialogsPromise;
|
||||
|
||||
(archived ? this.chatsArchivedContainer : this.chatsContainer).append(this.chatsPreloader);
|
||||
|
||||
let storage = appMessagesManager.dialogsStorage[+archived] || [];
|
||||
let offsetIndex = 0;
|
||||
|
||||
//let offset = appMessagesManager.generateDialogIndex();/* appMessagesManager.dialogsNum */;
|
||||
|
||||
let offset = archived ? this.chatsArchivedOffsetIndex : this.chatsOffsetIndex;
|
||||
//let offset = 0;
|
||||
|
||||
let scroll = archived ? this.scrollArchived : this.scroll;
|
||||
for(let i = storage.length - 1; i >= 0; --i) {
|
||||
let dialog = storage[i];
|
||||
if(this.getDialogDom(dialog.peerID)) {
|
||||
offsetIndex = dialog.index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//let offset = storage[storage.length - 1]?.index || 0;
|
||||
|
||||
try {
|
||||
console.time('getDialogs time');
|
||||
|
||||
let loadCount = 50/*this.chatsLoadCount */;
|
||||
this.loadDialogsPromise = appMessagesManager.getConversations(offset, loadCount, +archived);
|
||||
this.loadDialogsPromise = appMessagesManager.getConversations(offsetIndex, loadCount, +archived);
|
||||
|
||||
let result = await this.loadDialogsPromise;
|
||||
|
||||
console.timeEnd('getDialogs time');
|
||||
|
||||
if(result && result.dialogs && result.dialogs.length) {
|
||||
let index = result.dialogs[result.dialogs.length - 1].index;
|
||||
|
||||
if(archived) this.chatsArchivedOffsetIndex = index;
|
||||
else this.chatsOffsetIndex = index;
|
||||
|
||||
result.dialogs.forEach((dialog: any) => {
|
||||
this.addDialog(dialog);
|
||||
});
|
||||
@ -598,7 +616,7 @@ export class AppDialogsManager {
|
||||
this.archivedCount.innerText = '' + count;
|
||||
} */
|
||||
|
||||
this.log('getDialogs ' + loadCount + ' dialogs by offset:', offset, result, this.scroll.length);
|
||||
this.log('getDialogs ' + loadCount + ' dialogs by offset:', offsetIndex, result, this.scroll.length, archived);
|
||||
this.scroll.onScroll();
|
||||
} catch(err) {
|
||||
this.log.error(err);
|
||||
@ -650,14 +668,14 @@ export class AppDialogsManager {
|
||||
if(onFound) onFound();
|
||||
|
||||
let peerID = +elem.getAttribute('data-peerID');
|
||||
let lastMsgID = +elem.dataset.mid;
|
||||
let lastMsgID = +elem.dataset.mid || 0;
|
||||
|
||||
if(!samePeer) {
|
||||
elem.classList.add('active');
|
||||
this.lastActiveListElement = elem;
|
||||
}
|
||||
|
||||
result = appImManager.setPeer(peerID, lastMsgID, true);
|
||||
result = appImManager.setPeer(peerID, lastMsgID);
|
||||
|
||||
if(result instanceof Promise) {
|
||||
this.lastGoodClickID = this.lastClickID;
|
||||
@ -721,7 +739,7 @@ export class AppDialogsManager {
|
||||
|
||||
public setPinnedDelimiter() {
|
||||
let index = -1;
|
||||
let dialogs = appMessagesManager.dialogsStorage.dialogs[0];
|
||||
let dialogs = appMessagesManager.dialogsStorage[0];
|
||||
for(let dialog of dialogs) {
|
||||
if(dialog.pFlags?.pinned) {
|
||||
index++;
|
||||
@ -766,7 +784,7 @@ export class AppDialogsManager {
|
||||
if(lastMessage._ == 'messageEmpty') {
|
||||
dom.lastMessageSpan.innerHTML = '';
|
||||
dom.lastTimeSpan.innerHTML = '';
|
||||
dom.listEl.removeAttribute('data-mid');
|
||||
delete dom.listEl.dataset.mid;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -853,10 +871,10 @@ export class AppDialogsManager {
|
||||
dom.lastTimeSpan.innerHTML = timeStr;
|
||||
} else dom.lastTimeSpan.innerHTML = '';
|
||||
|
||||
dom.listEl.setAttribute('data-mid', lastMessage.mid);
|
||||
|
||||
if(this.doms[peerID] || this.domsArchived[peerID]) {
|
||||
this.setUnreadMessages(dialog);
|
||||
} else { // means search
|
||||
dom.listEl.dataset.mid = lastMessage.mid;
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -171,7 +171,7 @@ export class AppMediaViewer {
|
||||
mover = this.setNewMover();
|
||||
} */
|
||||
|
||||
///////this.log('setMoverToTarget', target, closing, wasActive, fromRight);
|
||||
this.log('setMoverToTarget', target, closing, wasActive, fromRight);
|
||||
|
||||
let realParent: HTMLDivElement;
|
||||
|
||||
@ -200,13 +200,38 @@ export class AppMediaViewer {
|
||||
top = rect.top;
|
||||
}
|
||||
|
||||
let aspecter: HTMLDivElement;
|
||||
if(target instanceof HTMLImageElement || target instanceof HTMLVideoElement) {
|
||||
if(mover.firstElementChild && mover.firstElementChild.classList.contains('media-viewer-aspecter')) {
|
||||
aspecter = mover.firstElementChild as HTMLDivElement;
|
||||
|
||||
let player = aspecter.querySelector('.ckin__player');
|
||||
if(player) {
|
||||
let video = player.firstElementChild as HTMLVideoElement;
|
||||
aspecter.append(video);
|
||||
player.remove();
|
||||
}
|
||||
|
||||
if(!aspecter.style.cssText) { // всё из-за видео, элементы управления скейлятся, так бы можно было этого не делать
|
||||
mover.classList.remove('active');
|
||||
this.setFullAspect(aspecter, containerRect, rect);
|
||||
void mover.offsetLeft; // reflow
|
||||
mover.classList.add('active');
|
||||
}
|
||||
} else {
|
||||
aspecter = document.createElement('div');
|
||||
aspecter.classList.add('media-viewer-aspecter');
|
||||
mover.prepend(aspecter);
|
||||
}
|
||||
|
||||
aspecter.style.cssText = `width: ${rect.width}px; height: ${rect.height}px; transform: scale(${containerRect.width / rect.width}, ${containerRect.height / rect.height});`;
|
||||
}
|
||||
|
||||
transform += `translate(${left}px,${top}px) `;
|
||||
|
||||
mover.style.width = containerRect.width + 'px';
|
||||
mover.style.height = containerRect.height + 'px';
|
||||
|
||||
mover.classList.remove('cover');
|
||||
|
||||
let scaleX = rect.width / containerRect.width;
|
||||
let scaleY = rect.height / containerRect.height;
|
||||
if(!wasActive) {
|
||||
@ -234,19 +259,15 @@ export class AppMediaViewer {
|
||||
let video: HTMLVideoElement;
|
||||
|
||||
if(target.tagName == 'DIV') { // means backgrounded with cover
|
||||
//img.style.objectFit = 'cover';
|
||||
img = new Image();
|
||||
img.src = target.style.backgroundImage.slice(5, -2);
|
||||
//mover.classList.add('cover');
|
||||
//mover.style.backgroundImage = target.style.backgroundImage;
|
||||
} else if(target.tagName == 'IMG' || target.tagName == 'image') {
|
||||
} else if(target instanceof HTMLImageElement) {
|
||||
img = new Image();
|
||||
img.src = target instanceof SVGImageElement ? target.getAttributeNS(null, 'href') : (target as HTMLImageElement).src;
|
||||
img.style.objectFit = 'contain';
|
||||
} else if(target.tagName == 'VIDEO') {
|
||||
img.src = target.src;
|
||||
} else if(target instanceof HTMLVideoElement) {
|
||||
video = document.createElement('video');
|
||||
let source = document.createElement('source');
|
||||
source.src = target.querySelector('source').src;
|
||||
source.src = target.querySelector('source')?.src;
|
||||
video.append(source);
|
||||
} else if(target instanceof SVGSVGElement) {
|
||||
let clipID = target.dataset.clipID;
|
||||
@ -298,12 +319,9 @@ export class AppMediaViewer {
|
||||
mover.prepend(newSvg);
|
||||
}
|
||||
|
||||
if(img) {
|
||||
img.style.borderRadius = borderRadius;
|
||||
mover.prepend(img);
|
||||
} else if(video) {
|
||||
video.style.borderRadius = borderRadius;
|
||||
mover.prepend(video);
|
||||
if(aspecter) {
|
||||
aspecter.style.borderRadius = borderRadius;
|
||||
aspecter.append(img || video);
|
||||
}
|
||||
|
||||
mover.style.display = '';
|
||||
@ -330,15 +348,11 @@ export class AppMediaViewer {
|
||||
if(mover.firstElementChild) {
|
||||
(mover.firstElementChild as HTMLElement).style.borderRadius = borderRadius;
|
||||
}
|
||||
|
||||
if(target.tagName == 'DIV') {
|
||||
mover.classList.add('cover');
|
||||
}
|
||||
}, delay / 2);
|
||||
|
||||
setTimeout(() => {
|
||||
mover.innerHTML = '';
|
||||
mover.classList.remove('moving', 'active', 'cover');
|
||||
mover.classList.remove('moving', 'active');
|
||||
mover.style.display = 'none';
|
||||
}, delay);
|
||||
}
|
||||
@ -346,22 +360,60 @@ export class AppMediaViewer {
|
||||
return () => {
|
||||
mover.style.transform = `translate(${containerRect.left}px,${containerRect.top}px) scale(1,1)`;
|
||||
|
||||
if(aspecter) {
|
||||
this.setFullAspect(aspecter, containerRect, rect);
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
mover.style.borderRadius = '';
|
||||
|
||||
if(mover.firstElementChild) {
|
||||
(mover.firstElementChild as HTMLElement).style.borderRadius = '';
|
||||
}
|
||||
|
||||
mover.classList.remove('cover');
|
||||
}, delay / 2);
|
||||
|
||||
mover.dataset.timeout = '' + setTimeout(() => {
|
||||
mover.classList.remove('moving');
|
||||
|
||||
if(aspecter) { // всё из-за видео, элементы управления скейлятся, так бы можно было этого не делать
|
||||
mover.classList.remove('active');
|
||||
aspecter.style.cssText = '';
|
||||
void mover.offsetLeft; // reflow
|
||||
}
|
||||
|
||||
mover.classList.add('active');
|
||||
delete mover.dataset.timeout;
|
||||
}, delay);
|
||||
|
||||
if(path) {
|
||||
this.sizeTailPath(path, containerRect, scaleX, delay, true, isOut, borderRadius);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private setFullAspect(aspecter: HTMLDivElement, containerRect: DOMRect, rect: DOMRect) {
|
||||
let media = aspecter.firstElementChild;
|
||||
let proportion: number;
|
||||
if(media instanceof HTMLImageElement) {
|
||||
proportion = media.naturalWidth / media.naturalHeight;
|
||||
} else if(media instanceof HTMLVideoElement) {
|
||||
proportion = media.videoWidth / media.videoHeight;
|
||||
}
|
||||
|
||||
let {width, height} = rect;
|
||||
if(proportion == 1) {
|
||||
aspecter.style.cssText = '';
|
||||
} else {
|
||||
if(proportion > 0) {
|
||||
width = height * proportion;
|
||||
} else {
|
||||
height = width * proportion;
|
||||
}
|
||||
|
||||
aspecter.style.cssText = `width: ${width}px; height: ${height}px; transform: scale(${containerRect.width / width}, ${containerRect.height / height});`;
|
||||
}
|
||||
}
|
||||
|
||||
public sizeTailPath(path: SVGPathElement, rect: DOMRect, scaleX: number, delay: number, upscale: boolean, isOut: boolean, borderRadius: string) {
|
||||
let start = Date.now();
|
||||
let {width, height} = rect;
|
||||
@ -393,8 +445,13 @@ export class AppMediaViewer {
|
||||
public moveTheMover(mover: HTMLDivElement, toLeft = true) {
|
||||
let windowW = appPhotosManager.windowW;
|
||||
|
||||
//mover.classList.remove('active');
|
||||
mover.classList.add('moving');
|
||||
|
||||
if(mover.dataset.timeout) { // и это тоже всё из-за скейла видео, так бы это не нужно было
|
||||
clearTimeout(+mover.dataset.timeout);
|
||||
}
|
||||
|
||||
let rect = mover.getBoundingClientRect();
|
||||
|
||||
let newTransform = mover.style.transform.replace(/translate\((.+?),/, (match, p1) => {
|
||||
@ -617,30 +674,35 @@ export class AppMediaViewer {
|
||||
if(useContainerAsTarget) target = target.querySelector('img, video') || target;
|
||||
|
||||
let afterTimeout = this.setMoverToTarget(target, false, fromRight);
|
||||
//return; // set and don't move
|
||||
//if(wasActive) return;
|
||||
//return;
|
||||
setTimeout(() => {
|
||||
afterTimeout();
|
||||
//return;
|
||||
|
||||
let video = mover.querySelector('video') || document.createElement('video');
|
||||
let source: HTMLSourceElement;
|
||||
if(video.firstElementChild) {
|
||||
source = video.firstElementChild as HTMLSourceElement;
|
||||
}
|
||||
let source = video.firstElementChild as HTMLSourceElement || document.createElement('source');
|
||||
|
||||
if(media.type == 'gif') {
|
||||
video.autoplay = true;
|
||||
}
|
||||
|
||||
video.dataset.ckin = 'default';
|
||||
video.dataset.overlay = '1';
|
||||
let createPlayer = () => {
|
||||
if(media.type != 'gif') {
|
||||
video.dataset.ckin = 'default';
|
||||
video.dataset.overlay = '1';
|
||||
|
||||
let player = new VideoPlayer(video, true);
|
||||
/* player.wrapper.parentElement.append(video);
|
||||
mover.append(player.wrapper); */
|
||||
}
|
||||
};
|
||||
|
||||
if(!source || !source.src) {
|
||||
let promise = appDocsManager.downloadDoc(media);
|
||||
this.preloader.attach(mover, true, promise);
|
||||
|
||||
promise.then(blob => {
|
||||
promise.then(() => {
|
||||
if(this.currentMessageID != message.mid) {
|
||||
this.log.warn('media viewer changed video');
|
||||
return;
|
||||
@ -651,36 +713,27 @@ export class AppMediaViewer {
|
||||
this.updateMediaSource(mover, url, 'source');
|
||||
this.updateMediaSource(target, url, 'source');
|
||||
} else {
|
||||
let img = mover.firstElementChild;
|
||||
if(img instanceof Image) {
|
||||
mover.removeChild(img);
|
||||
let aspecter = mover.firstElementChild;
|
||||
let img = aspecter.firstElementChild;
|
||||
if(img instanceof HTMLImageElement) {
|
||||
img.remove();
|
||||
}
|
||||
|
||||
source = document.createElement('source');
|
||||
renderImageFromUrl(source, url);
|
||||
source.type = media.mime_type;
|
||||
|
||||
mover.prepend(video);
|
||||
|
||||
video.append(source);
|
||||
if(!source.parentElement) {
|
||||
video.append(source);
|
||||
}
|
||||
|
||||
if(!video.parentElement) {
|
||||
aspecter.prepend(video);
|
||||
}
|
||||
}
|
||||
|
||||
if(media.type != 'gif') {
|
||||
let player = new VideoPlayer(video, true);
|
||||
}
|
||||
createPlayer();
|
||||
});
|
||||
} else if(media.type != 'gif') {
|
||||
let player = new VideoPlayer(video, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* wrapVideo.call(this, media, mover, message, false, this.preloader).then(() => {
|
||||
if(this.currentMessageID != message.mid) {
|
||||
this.log.warn('media viewer changed video');
|
||||
return;
|
||||
}
|
||||
}); */
|
||||
} else createPlayer();
|
||||
}, 0);
|
||||
} else {
|
||||
let size = appPhotosManager.setAttachmentSize(media.id, container, maxWidth, maxHeight);
|
||||
@ -688,7 +741,7 @@ export class AppMediaViewer {
|
||||
if(useContainerAsTarget) target = target.querySelector('img, video') || target;
|
||||
|
||||
let afterTimeout = this.setMoverToTarget(target, false, fromRight);
|
||||
//return;
|
||||
//return; // set and don't move
|
||||
//if(wasActive) return;
|
||||
setTimeout(() => {
|
||||
afterTimeout();
|
||||
@ -709,10 +762,14 @@ export class AppMediaViewer {
|
||||
this.updateMediaSource(target, url, 'image');
|
||||
this.updateMediaSource(mover, url, 'image');
|
||||
} else {
|
||||
let image = mover.firstElementChild as HTMLImageElement || new Image();
|
||||
//image.src = url;
|
||||
let aspecter = mover.firstElementChild;
|
||||
let image = aspecter.firstElementChild as HTMLImageElement;
|
||||
if(!image) {
|
||||
image = new Image();
|
||||
aspecter.append(image);
|
||||
}
|
||||
|
||||
renderImageFromUrl(image, url);
|
||||
mover.prepend(image);
|
||||
}
|
||||
|
||||
this.preloader.detach();
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { SearchIndexManager, $rootScope, copy, tsNow, safeReplaceObject, dT, _, listMergeSorted, deepEqual, langPack } from "../utils";
|
||||
import { $rootScope, copy, tsNow, safeReplaceObject, dT, _, listMergeSorted, deepEqual, langPack } from "../utils";
|
||||
import appMessagesIDsManager from "./appMessagesIDsManager";
|
||||
import appChatsManager from "./appChatsManager";
|
||||
import appUsersManager from "./appUsersManager";
|
||||
@ -9,7 +9,7 @@ import apiUpdatesManager from "./apiUpdatesManager";
|
||||
import appPhotosManager from "./appPhotosManager";
|
||||
|
||||
import AppStorage from '../storage';
|
||||
import AppPeersManager from "./appPeersManager";
|
||||
import appPeersManager from "./appPeersManager";
|
||||
import ServerTimeManager from "../mtproto/serverTimeManager";
|
||||
import apiFileManager from "../mtproto/apiFileManager";
|
||||
import appDocsManager from "./appDocsManager";
|
||||
@ -64,20 +64,13 @@ export type Dialog = {
|
||||
|
||||
export class AppMessagesManager {
|
||||
public messagesStorage: any = {};
|
||||
public messagesForDialogs: any = {};
|
||||
public groupedMessagesStorage: {[groupID: string]: any} = {}; // will be used for albums
|
||||
public historiesStorage: {
|
||||
[peerID: string]: HistoryStorage
|
||||
} = {};
|
||||
public dialogsStorage: {
|
||||
count: number,
|
||||
dialogs: {
|
||||
[folderID: number]: Dialog[]
|
||||
}
|
||||
} = {
|
||||
count: null,
|
||||
dialogs: {}
|
||||
};
|
||||
[folderID: number]: Dialog[]
|
||||
} = {};
|
||||
public pendingByRandomID: {[randomID: string]: [number, number]} = {};
|
||||
public pendingByMessageID: any = {};
|
||||
public pendingAfterMsgs: any = {};
|
||||
@ -86,9 +79,6 @@ export class AppMessagesManager {
|
||||
public tempID = -1;
|
||||
public tempFinalizeCallbacks: any = {};
|
||||
|
||||
public dialogsIndex: any = SearchIndexManager.createIndex();
|
||||
public cachedResults: any = {query: false};
|
||||
|
||||
public lastSearchFilter: any = {};
|
||||
public lastSearchResults: any = [];
|
||||
|
||||
@ -96,10 +86,6 @@ export class AppMessagesManager {
|
||||
public fetchSingleMessagesTimeout = 0;
|
||||
private fetchSingleMessagesPromise: Promise<void> = null;
|
||||
|
||||
public incrementedMessageViews: any = {};
|
||||
public needIncrementMessageViews: any = [];
|
||||
public incrementMessageViewsTimeout: any = false;
|
||||
|
||||
public maxSeenID = 0;
|
||||
|
||||
public allDialogsLoaded: {[folder_id: number]: boolean} = {};
|
||||
@ -116,16 +102,9 @@ export class AppMessagesManager {
|
||||
public newDialogsToHandle: {[peerID: string]: {reload: true} | Dialog} = {};
|
||||
public newUpdatesAfterReloadToHandle: any = {};
|
||||
|
||||
public fwdMessagesPluralize = _('conversation_forwarded_X_messages');
|
||||
public gameScorePluralize = _('conversation_scored_X');
|
||||
public loaded: Promise<any> = null;
|
||||
|
||||
constructor() {
|
||||
AppStorage.get<number>('max_seen_msg').then((maxID) => {
|
||||
if(maxID && !appMessagesIDsManager.getMessageIDInfo(maxID)[1]) {
|
||||
this.maxSeenID = maxID;
|
||||
}
|
||||
});
|
||||
|
||||
$rootScope.$on('apiUpdate', (e: CustomEvent) => {
|
||||
let update: any = e.detail;
|
||||
// if(update._ != 'updateUserStatus') {
|
||||
@ -159,7 +138,7 @@ export class AppMessagesManager {
|
||||
if(draft && draft.date) {
|
||||
topDate = draft.date;
|
||||
} else {
|
||||
var channelID = AppPeersManager.isChannel(peerID) ? -peerID : 0
|
||||
var channelID = appPeersManager.isChannel(peerID) ? -peerID : 0
|
||||
var topDate = this.getMessage(dialog.top_message).date;
|
||||
|
||||
if(channelID) {
|
||||
@ -183,6 +162,94 @@ export class AppMessagesManager {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.loaded = new Promise((resolve, reject) => {
|
||||
AppStorage.get<{
|
||||
dialogs: Dialog[],
|
||||
allDialogsLoaded: AppMessagesManager['allDialogsLoaded'],
|
||||
peers: any[],
|
||||
messages: any[],
|
||||
updates: any,
|
||||
maxSeenMsgID: number
|
||||
}>('state').then(({dialogs, allDialogsLoaded, peers, messages, maxSeenMsgID, updates}) => {
|
||||
console.log('state res', dialogs, messages);
|
||||
|
||||
if(maxSeenMsgID && !appMessagesIDsManager.getMessageIDInfo(maxSeenMsgID)[1]) {
|
||||
this.maxSeenID = maxSeenMsgID;
|
||||
}
|
||||
|
||||
//return resolve();
|
||||
|
||||
if(peers) {
|
||||
for(let peerID in peers) {
|
||||
let peer = peers[peerID];
|
||||
if(+peerID < 0) appChatsManager.saveApiChat(peer);
|
||||
else appUsersManager.saveApiUser(peer);
|
||||
}
|
||||
}
|
||||
|
||||
if(messages) {
|
||||
this.saveMessages(messages);
|
||||
}
|
||||
|
||||
if(allDialogsLoaded) {
|
||||
this.allDialogsLoaded = allDialogsLoaded;
|
||||
}
|
||||
|
||||
if(dialogs) {
|
||||
dialogs.forEachReverse(dialog => {
|
||||
this.saveConversation(dialog);
|
||||
});
|
||||
}
|
||||
|
||||
apiUpdatesManager.attach(updates ?? null);
|
||||
|
||||
resolve();
|
||||
}).catch(resolve);
|
||||
});
|
||||
|
||||
setInterval(() => this.saveState(), 10000);
|
||||
}
|
||||
|
||||
public saveState() {
|
||||
let messages: any[] = [];
|
||||
let dialogs: Dialog[] = [];
|
||||
let peers: {[peerID: number]: any} = {};
|
||||
|
||||
for(let folderID in this.dialogsStorage) {
|
||||
for(let dialog of this.dialogsStorage[folderID]) {
|
||||
let message = this.getMessage(dialog.top_message);
|
||||
if(message._ != 'messageEmpty' && message.id > 0) {
|
||||
messages.push(message);
|
||||
|
||||
if(message.fromID != dialog.peerID) {
|
||||
peers[message.fromID] = appPeersManager.getPeer(message.fromID);
|
||||
}
|
||||
}
|
||||
|
||||
dialogs.push(dialog);
|
||||
|
||||
peers[dialog.peerID] = appPeersManager.getPeer(dialog.peerID);
|
||||
}
|
||||
}
|
||||
|
||||
let us = apiUpdatesManager.updatesState;
|
||||
let updates = {
|
||||
seq: us.seq,
|
||||
pts: us.pts,
|
||||
date: us.date
|
||||
};
|
||||
|
||||
AppStorage.set({
|
||||
state: {
|
||||
dialogs,
|
||||
messages,
|
||||
allDialogsLoaded: this.allDialogsLoaded,
|
||||
peers,
|
||||
updates,
|
||||
maxSeenMsgID: this.maxSeenID
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public getInputEntities(entities: any) {
|
||||
@ -240,7 +307,7 @@ export class AppMessagesManager {
|
||||
|
||||
return apiManager.invokeApi('messages.editMessage', {
|
||||
flags: flags,
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
peer: appPeersManager.getInputPeerByID(peerID),
|
||||
id: appMessagesIDsManager.getMessageLocalID(messageID),
|
||||
message: text,
|
||||
media: message.media,
|
||||
@ -260,22 +327,22 @@ export class AppMessagesManager {
|
||||
});
|
||||
}
|
||||
|
||||
public sendText(peerID: number, text: string, options: {
|
||||
entities?: any[],
|
||||
replyToMsgID?: number,
|
||||
viaBotID?: number,
|
||||
queryID?: number,
|
||||
resultID?: number,
|
||||
noWebPage?: boolean,
|
||||
reply_markup?: any,
|
||||
clearDraft?: boolean,
|
||||
webPage?: any
|
||||
} = {}) {
|
||||
public sendText(peerID: number, text: string, options: Partial<{
|
||||
entities: any[],
|
||||
replyToMsgID: number,
|
||||
viaBotID: number,
|
||||
queryID: number,
|
||||
resultID: number,
|
||||
noWebPage: boolean,
|
||||
reply_markup: any,
|
||||
clearDraft: boolean,
|
||||
webPage: any
|
||||
}> = {}) {
|
||||
if(typeof(text) != 'string') {
|
||||
return;
|
||||
}
|
||||
|
||||
peerID = AppPeersManager.getPeerMigratedTo(peerID) || peerID;
|
||||
peerID = appPeersManager.getPeerMigratedTo(peerID) || peerID;
|
||||
|
||||
var entities = options.entities || [];
|
||||
if(!options.viaBotID) {
|
||||
@ -293,8 +360,8 @@ export class AppMessagesManager {
|
||||
var flags = 0;
|
||||
var pFlags: any = {};
|
||||
var replyToMsgID = options.replyToMsgID;
|
||||
var isChannel = AppPeersManager.isChannel(peerID);
|
||||
var isMegagroup = isChannel && AppPeersManager.isMegagroup(peerID);
|
||||
var isChannel = appPeersManager.isChannel(peerID);
|
||||
var isMegagroup = isChannel && appPeersManager.isMegagroup(peerID);
|
||||
var asChannel = isChannel && !isMegagroup ? true : false;
|
||||
var message: any;
|
||||
let noWebPage = options.noWebPage || false;
|
||||
@ -329,7 +396,7 @@ export class AppMessagesManager {
|
||||
_: 'message',
|
||||
id: messageID,
|
||||
from_id: fromID,
|
||||
to_id: AppPeersManager.getOutputPeer(peerID),
|
||||
to_id: appPeersManager.getOutputPeer(peerID),
|
||||
flags: flags,
|
||||
pFlags: pFlags,
|
||||
date: tsNow(true) + serverTimeManager.serverTimeOffset,
|
||||
@ -387,7 +454,7 @@ export class AppMessagesManager {
|
||||
if(options.viaBotID) {
|
||||
apiPromise = apiManager.invokeApi('messages.sendInlineBotResult', {
|
||||
flags: flags,
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
peer: appPeersManager.getInputPeerByID(peerID),
|
||||
random_id: randomID,
|
||||
reply_to_msg_id: appMessagesIDsManager.getMessageLocalID(replyToMsgID),
|
||||
query_id: options.queryID,
|
||||
@ -401,7 +468,7 @@ export class AppMessagesManager {
|
||||
apiPromise = apiManager.invokeApi('messages.sendMessage', {
|
||||
flags: flags,
|
||||
no_webpage: noWebPage,
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
peer: appPeersManager.getInputPeerByID(peerID),
|
||||
message: text,
|
||||
random_id: randomID,
|
||||
reply_to_msg_id: appMessagesIDsManager.getMessageLocalID(replyToMsgID),
|
||||
@ -490,7 +557,7 @@ export class AppMessagesManager {
|
||||
duration: number,
|
||||
background: boolean
|
||||
}> = {}) {
|
||||
peerID = AppPeersManager.getPeerMigratedTo(peerID) || peerID;
|
||||
peerID = appPeersManager.getPeerMigratedTo(peerID) || peerID;
|
||||
var messageID = this.tempID--;
|
||||
var randomID = [nextRandomInt(0xFFFFFFFF), nextRandomInt(0xFFFFFFFF)];
|
||||
var randomIDS = bigint(randomID[0]).shiftLeft(32).add(bigint(randomID[1])).toString();
|
||||
@ -498,8 +565,8 @@ export class AppMessagesManager {
|
||||
var flags = 0;
|
||||
var pFlags: any = {};
|
||||
var replyToMsgID = options.replyToMsgID;
|
||||
var isChannel = AppPeersManager.isChannel(peerID);
|
||||
var isMegagroup = isChannel && AppPeersManager.isMegagroup(peerID);
|
||||
var isChannel = appPeersManager.isChannel(peerID);
|
||||
var isMegagroup = isChannel && appPeersManager.isMegagroup(peerID);
|
||||
var asChannel = isChannel && !isMegagroup ? true : false;
|
||||
var attachType: string, apiFileName: string;
|
||||
|
||||
@ -651,7 +718,7 @@ export class AppMessagesManager {
|
||||
_: 'message',
|
||||
id: messageID,
|
||||
from_id: fromID,
|
||||
to_id: AppPeersManager.getOutputPeer(peerID),
|
||||
to_id: appPeersManager.getOutputPeer(peerID),
|
||||
flags: flags,
|
||||
pFlags: pFlags,
|
||||
date: date,
|
||||
@ -688,7 +755,7 @@ export class AppMessagesManager {
|
||||
flags: flags,
|
||||
background: options.background,
|
||||
clear_draft: true,
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
peer: appPeersManager.getInputPeerByID(peerID),
|
||||
media: inputMedia,
|
||||
message: caption,
|
||||
random_id: randomID,
|
||||
@ -821,14 +888,14 @@ export class AppMessagesManager {
|
||||
objectURL: string,
|
||||
}>[]
|
||||
}> = {}) {
|
||||
peerID = AppPeersManager.getPeerMigratedTo(peerID) || peerID;
|
||||
peerID = appPeersManager.getPeerMigratedTo(peerID) || peerID;
|
||||
let groupID: number;
|
||||
let historyStorage = this.historiesStorage[peerID] ?? (this.historiesStorage[peerID] = {count: null, history: [], pending: []});
|
||||
let flags = 0;
|
||||
let pFlags: any = {};
|
||||
let replyToMsgID = options.replyToMsgID;
|
||||
let isChannel = AppPeersManager.isChannel(peerID);
|
||||
let isMegagroup = isChannel && AppPeersManager.isMegagroup(peerID);
|
||||
let isChannel = appPeersManager.isChannel(peerID);
|
||||
let isMegagroup = isChannel && appPeersManager.isMegagroup(peerID);
|
||||
let asChannel = isChannel && !isMegagroup ? true : false;
|
||||
|
||||
let caption = options.caption || '';
|
||||
@ -949,7 +1016,7 @@ export class AppMessagesManager {
|
||||
id: messageID,
|
||||
from_id: fromID,
|
||||
grouped_id: groupID,
|
||||
to_id: AppPeersManager.getOutputPeer(peerID),
|
||||
to_id: appPeersManager.getOutputPeer(peerID),
|
||||
flags: flags,
|
||||
pFlags: pFlags,
|
||||
date: date,
|
||||
@ -987,7 +1054,7 @@ export class AppMessagesManager {
|
||||
let uploaded = false,
|
||||
uploadPromise: ReturnType<typeof apiFileManager.uploadFile> = null;
|
||||
|
||||
let inputPeer = AppPeersManager.getInputPeerByID(peerID);
|
||||
let inputPeer = appPeersManager.getInputPeerByID(peerID);
|
||||
let invoke = (multiMedia: any[]) => {
|
||||
appImManager.setTyping('sendMessageCancelAction');
|
||||
|
||||
@ -1129,9 +1196,7 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
public getConversations(offsetIndex?: number, limit = 20, folderID = 0) {
|
||||
let curDialogStorage = this.dialogsStorage.dialogs[folderID] ?? (this.dialogsStorage.dialogs[folderID] = []);
|
||||
|
||||
this.cachedResults.query = false;
|
||||
let curDialogStorage = this.dialogsStorage[folderID] ?? (this.dialogsStorage[folderID] = []);
|
||||
|
||||
let offset = 0;
|
||||
if(offsetIndex > 0) {
|
||||
@ -1150,7 +1215,7 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
return this.getTopMessages(limit, folderID).then(count => {
|
||||
let curDialogStorage = this.dialogsStorage.dialogs[folderID];
|
||||
let curDialogStorage = this.dialogsStorage[folderID];
|
||||
|
||||
offset = 0;
|
||||
if(offsetIndex > 0) {
|
||||
@ -1171,12 +1236,12 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
public getTopMessages(limit: number, folderID: number): Promise<number> {
|
||||
var dialogs = this.dialogsStorage.dialogs[folderID];
|
||||
var offsetDate = 0;
|
||||
var offsetID = 0;
|
||||
var offsetPeerID = 0;
|
||||
var offsetIndex = 0;
|
||||
var flags = 0;
|
||||
const dialogs = this.dialogsStorage[folderID];
|
||||
let offsetID = 0;
|
||||
let offsetDate = 0;
|
||||
let offsetPeerID = 0;
|
||||
let offsetIndex = 0;
|
||||
let flags = 0;
|
||||
|
||||
if(this.dialogsOffsetDate[folderID]) {
|
||||
offsetDate = this.dialogsOffsetDate[folderID] + serverTimeManager.serverTimeOffset;
|
||||
@ -1196,7 +1261,7 @@ export class AppMessagesManager {
|
||||
folder_id: folderID,
|
||||
offset_date: offsetDate,
|
||||
offset_id: appMessagesIDsManager.getMessageLocalID(offsetID),
|
||||
offset_peer: AppPeersManager.getInputPeerByID(offsetPeerID),
|
||||
offset_peer: appPeersManager.getInputPeerByID(offsetPeerID),
|
||||
limit: limit,
|
||||
hash: hash
|
||||
}, {
|
||||
@ -1230,7 +1295,7 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
if(!maxSeenIdIncremented &&
|
||||
!AppPeersManager.isChannel(AppPeersManager.getPeerID(dialog.peer))) {
|
||||
!appPeersManager.isChannel(appPeersManager.getPeerID(dialog.peer))) {
|
||||
this.incrementMaxSeenID(dialog.top_message);
|
||||
maxSeenIdIncremented = true;
|
||||
}
|
||||
@ -1267,7 +1332,7 @@ export class AppMessagesManager {
|
||||
public forwardMessages(peerID: number, mids: number[], options: Partial<{
|
||||
withMyScore: boolean
|
||||
}> = {}) {
|
||||
peerID = AppPeersManager.getPeerMigratedTo(peerID) || peerID;
|
||||
peerID = appPeersManager.getPeerMigratedTo(peerID) || peerID;
|
||||
mids = mids.sort((a, b) => a - b);
|
||||
|
||||
var flags = 0;
|
||||
@ -1293,10 +1358,10 @@ export class AppMessagesManager {
|
||||
|
||||
let promise = apiManager.invokeApi('messages.forwardMessages', {
|
||||
flags: flags,
|
||||
from_peer: AppPeersManager.getInputPeerByID(-channelID),
|
||||
from_peer: appPeersManager.getInputPeerByID(-channelID),
|
||||
id: msgIDs,
|
||||
random_id: randomIDs,
|
||||
to_peer: AppPeersManager.getInputPeerByID(peerID)
|
||||
to_peer: appPeersManager.getInputPeerByID(peerID)
|
||||
}, sentRequestOptions).then((updates) => {
|
||||
apiUpdatesManager.processUpdateMessage(updates);
|
||||
}, () => {}).then(() => {
|
||||
@ -1329,7 +1394,7 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
public generateIndexForDialog(dialog: Dialog) {
|
||||
let channelID = AppPeersManager.isChannel(dialog.peerID) ? -dialog.peerID : 0;
|
||||
let channelID = appPeersManager.isChannel(dialog.peerID) ? -dialog.peerID : 0;
|
||||
let mid = appMessagesIDsManager.getFullMessageID(dialog.top_message, channelID);
|
||||
let message = this.getMessage(mid);
|
||||
|
||||
@ -1354,15 +1419,15 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
public pushDialogToStorage(dialog: Dialog, offsetDate?: number) {
|
||||
let dialogs = this.dialogsStorage.dialogs[dialog.folder_id] ?? (this.dialogsStorage.dialogs[dialog.folder_id] = []);
|
||||
let dialogs = this.dialogsStorage[dialog.folder_id] ?? (this.dialogsStorage[dialog.folder_id] = []);
|
||||
let pos = dialogs.findIndex(d => d.peerID == dialog.peerID);
|
||||
if(pos !== -1) {
|
||||
dialogs.splice(pos, 1);
|
||||
}
|
||||
|
||||
if(offsetDate &&
|
||||
!dialog.pFlags.pinned &&
|
||||
(!this.dialogsOffsetDate[dialog.folder_id] || offsetDate < this.dialogsOffsetDate[dialog.folder_id])) {
|
||||
!dialog.pFlags.pinned &&
|
||||
(!this.dialogsOffsetDate[dialog.folder_id] || offsetDate < this.dialogsOffsetDate[dialog.folder_id])) {
|
||||
if(pos !== -1) {
|
||||
// So the dialog jumped to the last position
|
||||
return false;
|
||||
@ -1395,7 +1460,7 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
public getMessagePeer(message: any): number {
|
||||
var toID = message.to_id && AppPeersManager.getPeerID(message.to_id) || 0;
|
||||
var toID = message.to_id && appPeersManager.getPeerID(message.to_id) || 0;
|
||||
|
||||
if(toID < 0) {
|
||||
return toID;
|
||||
@ -1406,7 +1471,7 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
public getDialogByPeerID(peerID: number): [Dialog, number] | [] {
|
||||
let dialogs = this.dialogsStorage.dialogs;
|
||||
let dialogs = this.dialogsStorage;
|
||||
for(let folderID in dialogs) {
|
||||
let index = dialogs[folderID].findIndex(dialog => dialog.peerID == peerID);
|
||||
if(index !== -1) {
|
||||
@ -1418,7 +1483,7 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
public reloadConversation(peerID: number | number[]) {
|
||||
let peers = [].concat(peerID).map(peerID => AppPeersManager.getInputPeerByID(peerID));
|
||||
let peers = [].concat(peerID).map(peerID => appPeersManager.getInputPeerByID(peerID));
|
||||
|
||||
console.log('will reloadConversation', peerID);
|
||||
|
||||
@ -1456,7 +1521,7 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
public async flushHistory(peerID: number, justClear: boolean) {
|
||||
if(AppPeersManager.isChannel(peerID)) {
|
||||
if(appPeersManager.isChannel(peerID)) {
|
||||
let promise = this.getHistory(peerID, 0, 1);
|
||||
|
||||
let historyResult = promise instanceof Promise ? await promise : promise;
|
||||
@ -1480,7 +1545,7 @@ export class AppMessagesManager {
|
||||
});
|
||||
}
|
||||
|
||||
return this.doFlushHistory(AppPeersManager.getInputPeerByID(peerID), justClear).then(() => {
|
||||
return this.doFlushHistory(appPeersManager.getInputPeerByID(peerID), justClear).then(() => {
|
||||
delete this.historiesStorage[peerID];
|
||||
for(let mid in this.messagesStorage) {
|
||||
let message = this.messagesStorage[mid];
|
||||
@ -1494,7 +1559,7 @@ export class AppMessagesManager {
|
||||
} else {
|
||||
let foundDialog = this.getDialogByPeerID(peerID);
|
||||
if(foundDialog[0]) {
|
||||
this.dialogsStorage.dialogs[foundDialog[0].folder_id].splice(foundDialog[1], 1);
|
||||
this.dialogsStorage[foundDialog[0].folder_id].splice(foundDialog[1], 1);
|
||||
}
|
||||
|
||||
$rootScope.$broadcast('dialog_drop', {peerID: peerID});
|
||||
@ -1559,9 +1624,9 @@ export class AppMessagesManager {
|
||||
if(fwdHeader) {
|
||||
if(peerID == appUsersManager.getSelf().id) {
|
||||
if(fwdHeader.saved_from_peer && fwdHeader.saved_from_msg_id) {
|
||||
var savedFromPeerID = AppPeersManager.getPeerID(fwdHeader.saved_from_peer);
|
||||
var savedFromPeerID = appPeersManager.getPeerID(fwdHeader.saved_from_peer);
|
||||
var savedFromMid = appMessagesIDsManager.getFullMessageID(fwdHeader.saved_from_msg_id,
|
||||
AppPeersManager.isChannel(savedFromPeerID) ? -savedFromPeerID : 0);
|
||||
appPeersManager.isChannel(savedFromPeerID) ? -savedFromPeerID : 0);
|
||||
apiMessage.savedFrom = savedFromPeerID + '_' + savedFromMid;
|
||||
}
|
||||
|
||||
@ -1834,7 +1899,7 @@ export class AppMessagesManager {
|
||||
folder_peers: peerIDs.map(peerID => {
|
||||
return {
|
||||
_: 'inputFolderPeer',
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
peer: appPeersManager.getInputPeerByID(peerID),
|
||||
folder_id: folderID
|
||||
};
|
||||
})
|
||||
@ -1850,7 +1915,7 @@ export class AppMessagesManager {
|
||||
|
||||
let peer = {
|
||||
_: 'inputDialogPeer',
|
||||
peer: AppPeersManager.getInputPeerByID(peerID)
|
||||
peer: appPeersManager.getInputPeerByID(peerID)
|
||||
};
|
||||
|
||||
let flags = dialog.pFlags?.pinned ? 0 : 1;
|
||||
@ -1874,7 +1939,7 @@ export class AppMessagesManager {
|
||||
|
||||
let peer = {
|
||||
_: 'inputDialogPeer',
|
||||
peer: AppPeersManager.getInputPeerByID(peerID)
|
||||
peer: appPeersManager.getInputPeerByID(peerID)
|
||||
};
|
||||
|
||||
let flags = dialog.pFlags?.unread_mark ? 0 : 1;
|
||||
@ -1906,7 +1971,7 @@ export class AppMessagesManager {
|
||||
setTimeout(() => {
|
||||
var foundDialog = this.getDialogByPeerID(migrateFrom);
|
||||
if(foundDialog.length) {
|
||||
this.dialogsStorage.dialogs[foundDialog[0].folder_id].splice(foundDialog[1], 1);
|
||||
this.dialogsStorage[foundDialog[0].folder_id].splice(foundDialog[1], 1);
|
||||
$rootScope.$broadcast('dialog_drop', {peerID: migrateFrom, dialog: foundDialog[0]});
|
||||
}
|
||||
|
||||
@ -1969,7 +2034,7 @@ export class AppMessagesManager {
|
||||
var updatedDialogs: {[peerID: number]: Dialog} = {};
|
||||
var hasUpdated = false;
|
||||
dialogsResult.dialogs.forEach((dialog: any) => {
|
||||
var peerID = AppPeersManager.getPeerID(dialog.peer);
|
||||
var peerID = appPeersManager.getPeerID(dialog.peer);
|
||||
var topMessage = dialog.top_message;
|
||||
var topPendingMesage = this.pendingTopMsgs[peerID];
|
||||
if(topPendingMesage) {
|
||||
@ -1991,7 +2056,6 @@ export class AppMessagesManager {
|
||||
this.saveConversation(dialog);
|
||||
|
||||
if(wasDialogBefore) {
|
||||
this.clearDialogCache(topMessage);
|
||||
$rootScope.$broadcast('dialog_top', dialog);
|
||||
} else {
|
||||
updatedDialogs[peerID] = dialog;
|
||||
@ -2000,7 +2064,7 @@ export class AppMessagesManager {
|
||||
} else {
|
||||
var foundDialog = this.getDialogByPeerID(peerID);
|
||||
if(foundDialog.length) {
|
||||
this.dialogsStorage.dialogs[foundDialog[0].folder_id].splice(foundDialog[1], 1);
|
||||
this.dialogsStorage[foundDialog[0].folder_id].splice(foundDialog[1], 1);
|
||||
$rootScope.$broadcast('dialog_drop', {peerID: peerID, dialog: foundDialog[0]});
|
||||
}
|
||||
}
|
||||
@ -2020,20 +2084,13 @@ export class AppMessagesManager {
|
||||
}
|
||||
}
|
||||
|
||||
public clearDialogCache(msgID: number) {
|
||||
delete this.messagesForDialogs[msgID];
|
||||
}
|
||||
|
||||
public saveConversation(dialog: Dialog) {
|
||||
var peerID = AppPeersManager.getPeerID(dialog.peer);
|
||||
var peerID = appPeersManager.getPeerID(dialog.peer);
|
||||
if(!peerID) {
|
||||
return false;
|
||||
}
|
||||
var channelID = AppPeersManager.isChannel(peerID) ? -peerID : 0;
|
||||
var peerText = AppPeersManager.getPeerSearchText(peerID);
|
||||
SearchIndexManager.indexObject(peerID, peerText, this.dialogsIndex);
|
||||
var channelID = appPeersManager.isChannel(peerID) ? -peerID : 0;
|
||||
|
||||
//var isMegagroup = AppPeersManager.isMegagroup(channelID);
|
||||
if(dialog.top_message) {
|
||||
var mid = appMessagesIDsManager.getFullMessageID(dialog.top_message, channelID);
|
||||
var message = this.getMessage(mid);
|
||||
@ -2044,7 +2101,7 @@ export class AppMessagesManager {
|
||||
id: mid,
|
||||
mid: mid,
|
||||
from_id: appUsersManager.getSelf().id,
|
||||
to_id: AppPeersManager.getOutputPeer(peerID),
|
||||
to_id: appPeersManager.getOutputPeer(peerID),
|
||||
deleted: true,
|
||||
flags: 0,
|
||||
pFlags: {unread: false, out: true},
|
||||
@ -2053,12 +2110,11 @@ export class AppMessagesManager {
|
||||
}
|
||||
this.saveMessages([message]);
|
||||
}
|
||||
var offsetDate = message.date;
|
||||
|
||||
if(!channelID && peerID < 0) {
|
||||
var chat = appChatsManager.getChat(-peerID)
|
||||
if(chat && chat.migrated_to && chat.pFlags.deactivated) {
|
||||
var migratedToPeer = AppPeersManager.getPeerID(chat.migrated_to)
|
||||
var migratedToPeer = appPeersManager.getPeerID(chat.migrated_to)
|
||||
this.migratedFromTo[peerID] = migratedToPeer;
|
||||
this.migratedToFrom[migratedToPeer] = peerID;
|
||||
return;
|
||||
@ -2073,7 +2129,7 @@ export class AppMessagesManager {
|
||||
dialog.peerID = peerID;
|
||||
|
||||
this.generateIndexForDialog(dialog);
|
||||
this.pushDialogToStorage(dialog, offsetDate);
|
||||
this.pushDialogToStorage(dialog, message.date);
|
||||
|
||||
// Because we saved message without dialog present
|
||||
if(message.mid > 0) {
|
||||
@ -2093,12 +2149,6 @@ export class AppMessagesManager {
|
||||
}
|
||||
}
|
||||
|
||||
//NotificationsManager.savePeerSettings(peerID, dialog.notify_settings); // warning
|
||||
|
||||
/* if(dialog.pts || dialog.pFlags.pts) {
|
||||
console.warn('dialog pts!', dialog, dialog.pts);
|
||||
} */
|
||||
|
||||
if(channelID && dialog.pts) {
|
||||
apiUpdatesManager.addChannelState(channelID, dialog.pts);
|
||||
}
|
||||
@ -2190,8 +2240,7 @@ export class AppMessagesManager {
|
||||
var foundMsgs: number[] = [];
|
||||
var useSearchCache = !query;
|
||||
var newSearchFilter = {peer: peerID, filter: inputFilter};
|
||||
var sameSearchCache = useSearchCache
|
||||
&& deepEqual(this.lastSearchFilter, newSearchFilter); //angular.equals(this.lastSearchFilter, newSearchFilter);
|
||||
var sameSearchCache = useSearchCache && deepEqual(this.lastSearchFilter, newSearchFilter);
|
||||
|
||||
if(useSearchCache && !sameSearchCache) {
|
||||
// console.warn(dT(), 'new search filter', lastSearchFilter, newSearchFilter)
|
||||
@ -2313,7 +2362,7 @@ export class AppMessagesManager {
|
||||
if(peerID || !query) {
|
||||
apiPromise = apiManager.invokeApi('messages.search', {
|
||||
flags: 0,
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
peer: appPeersManager.getInputPeerByID(peerID),
|
||||
q: query || '',
|
||||
filter: inputFilter || {_: 'inputMessagesFilterEmpty'},
|
||||
min_date: 0,
|
||||
@ -2342,7 +2391,7 @@ export class AppMessagesManager {
|
||||
apiPromise = apiManager.invokeApi('messages.searchGlobal', {
|
||||
q: query,
|
||||
offset_rate: offsetRate,
|
||||
offset_peer: AppPeersManager.getInputPeerByID(offsetPeerID),
|
||||
offset_peer: appPeersManager.getInputPeerByID(offsetPeerID),
|
||||
offset_id: appMessagesIDsManager.getMessageLocalID(offsetID),
|
||||
limit: limit || 20
|
||||
}, {
|
||||
@ -2396,7 +2445,7 @@ export class AppMessagesManager {
|
||||
let pinnedIndex: number;
|
||||
|
||||
if(dialog) {
|
||||
if(dialog.pinnedIndex) {
|
||||
if(dialog.hasOwnProperty('pinnedIndex')) {
|
||||
pinnedIndex = dialog.pinnedIndex;
|
||||
} else {
|
||||
dialog.pinnedIndex = pinnedIndex = this.pinnedIndex++;
|
||||
@ -2405,6 +2454,10 @@ export class AppMessagesManager {
|
||||
pinnedIndex = this.pinnedIndex++;
|
||||
}
|
||||
|
||||
if(pinnedIndex > this.pinnedIndex) {
|
||||
this.pinnedIndex = pinnedIndex;
|
||||
}
|
||||
|
||||
return 0x7fffff00 + (pinnedIndex & 0xff);
|
||||
}
|
||||
|
||||
@ -2428,13 +2481,13 @@ export class AppMessagesManager {
|
||||
delete this.newDialogsToHandle[peerID];
|
||||
} else {
|
||||
this.pushDialogToStorage(dialog);
|
||||
if(!AppPeersManager.isChannel(+peerID)) {
|
||||
if(!appPeersManager.isChannel(+peerID)) {
|
||||
newMaxSeenID = Math.max(newMaxSeenID, dialog.top_message || 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log('after order:', this.dialogsStorage.dialogs[0].map(d => d.peerID));
|
||||
//console.log('after order:', this.dialogsStorage[0].map(d => d.peerID));
|
||||
|
||||
if(newMaxSeenID != 0) {
|
||||
this.incrementMaxSeenID(newMaxSeenID);
|
||||
@ -2452,7 +2505,7 @@ export class AppMessagesManager {
|
||||
|
||||
public readHistory(peerID: number, maxID = 0, minID = 0): Promise<boolean> {
|
||||
// console.trace('start read')
|
||||
var isChannel = AppPeersManager.isChannel(peerID);
|
||||
var isChannel = appPeersManager.isChannel(peerID);
|
||||
var historyStorage = this.historiesStorage[peerID];
|
||||
var foundDialog = this.getDialogByPeerID(peerID)[0];
|
||||
|
||||
@ -2489,7 +2542,7 @@ export class AppMessagesManager {
|
||||
});
|
||||
} else {
|
||||
apiPromise = apiManager.invokeApi('messages.readHistory', {
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
peer: appPeersManager.getInputPeerByID(peerID),
|
||||
max_id: maxID
|
||||
}).then((affectedMessages: any) => {
|
||||
apiUpdatesManager.processUpdateMessage({
|
||||
@ -2539,9 +2592,6 @@ export class AppMessagesManager {
|
||||
if(message && !message.pFlags.out) {
|
||||
message.pFlags.unread = false;
|
||||
|
||||
if(this.messagesForDialogs[messageID]) {
|
||||
this.messagesForDialogs[messageID].pFlags.unread = false;
|
||||
}
|
||||
//NotificationsManager.cancel('msg' + messageID); // warning
|
||||
}
|
||||
|
||||
@ -2549,7 +2599,7 @@ export class AppMessagesManager {
|
||||
}
|
||||
}
|
||||
|
||||
// NotificationsManager.soundReset(AppPeersManager.getPeerString(peerID)) // warning
|
||||
// NotificationsManager.soundReset(appPeersManager.getPeerString(peerID)) // warning
|
||||
|
||||
return historyStorage.readPromise;
|
||||
}
|
||||
@ -2602,7 +2652,7 @@ export class AppMessagesManager {
|
||||
if(pendingData) {
|
||||
var peerID: number = pendingData[0];
|
||||
var tempID = pendingData[1];
|
||||
var channelID = AppPeersManager.isChannel(peerID) ? -peerID : 0;
|
||||
var channelID = appPeersManager.isChannel(peerID) ? -peerID : 0;
|
||||
var mid = appMessagesIDsManager.getFullMessageID(update.id, channelID);
|
||||
var message = this.messagesStorage[mid];
|
||||
if(message) {
|
||||
@ -2721,7 +2771,7 @@ export class AppMessagesManager {
|
||||
|
||||
case 'updateDialogUnreadMark': {
|
||||
console.log('updateDialogUnreadMark', update);
|
||||
let peerID = AppPeersManager.getPeerID(update.peer.peer);
|
||||
let peerID = appPeersManager.getPeerID(update.peer.peer);
|
||||
let foundDialog = this.getDialogByPeerID(peerID);
|
||||
|
||||
if(!foundDialog.length) {
|
||||
@ -2750,7 +2800,7 @@ export class AppMessagesManager {
|
||||
peers.forEach((folderPeer: any) => {
|
||||
let {folder_id, peer} = folderPeer;
|
||||
|
||||
let peerID = AppPeersManager.getPeerID(peer);
|
||||
let peerID = appPeersManager.getPeerID(peer);
|
||||
let foundDialog = this.getDialogByPeerID(peerID);
|
||||
if(!foundDialog.length) {
|
||||
this.newDialogsToHandle[peerID] = {reload: true};
|
||||
@ -2758,7 +2808,7 @@ export class AppMessagesManager {
|
||||
let dialog = foundDialog[0];
|
||||
this.newDialogsToHandle[peerID] = dialog;
|
||||
|
||||
this.dialogsStorage.dialogs[dialog.folder_id].splice(foundDialog[1], 1);
|
||||
this.dialogsStorage[dialog.folder_id].splice(foundDialog[1], 1);
|
||||
dialog.folder_id = folder_id;
|
||||
|
||||
this.generateIndexForDialog(dialog);
|
||||
@ -2770,7 +2820,7 @@ export class AppMessagesManager {
|
||||
|
||||
case 'updateDialogPinned': {
|
||||
console.log('updateDialogPinned', update);
|
||||
let peerID = AppPeersManager.getPeerID(update.peer.peer);
|
||||
let peerID = appPeersManager.getPeerID(update.peer.peer);
|
||||
let foundDialog = this.getDialogByPeerID(peerID);
|
||||
|
||||
this.scheduleHandleNewDialogs();
|
||||
@ -2806,7 +2856,7 @@ export class AppMessagesManager {
|
||||
newPinned[dialog.peerID] = true;
|
||||
});
|
||||
|
||||
this.dialogsStorage.dialogs[0].forEach((dialog: any) => {
|
||||
this.dialogsStorage[0].forEach((dialog: any) => {
|
||||
let peerID = dialog.peerID;
|
||||
if(dialog.pFlags.pinned && !newPinned[peerID]) {
|
||||
this.newDialogsToHandle[peerID] = {reload: true};
|
||||
@ -2817,13 +2867,13 @@ export class AppMessagesManager {
|
||||
break;
|
||||
}
|
||||
|
||||
console.log('before order:', this.dialogsStorage.dialogs[0].map(d => d.peerID));
|
||||
//console.log('before order:', this.dialogsStorage[0].map(d => d.peerID));
|
||||
|
||||
this.pinnedIndex = 0;
|
||||
let willHandle = false;
|
||||
update.order.reverse(); // index must be higher
|
||||
update.order.forEach((peer: any) => {
|
||||
let peerID = AppPeersManager.getPeerID(peer.peer);
|
||||
let peerID = appPeersManager.getPeerID(peer.peer);
|
||||
newPinned[peerID] = true;
|
||||
|
||||
let foundDialog = this.getDialogByPeerID(peerID);
|
||||
@ -2842,7 +2892,7 @@ export class AppMessagesManager {
|
||||
willHandle = true;
|
||||
});
|
||||
|
||||
this.dialogsStorage.dialogs[0].forEach(dialog => {
|
||||
this.dialogsStorage[0].forEach(dialog => {
|
||||
let peerID = dialog.peerID;
|
||||
if(dialog.pFlags.pinned && !newPinned[peerID]) {
|
||||
this.newDialogsToHandle[peerID] = {reload: true};
|
||||
@ -2901,7 +2951,7 @@ export class AppMessagesManager {
|
||||
var isOut = update._ == 'updateReadHistoryOutbox' || update._ == 'updateReadChannelOutbox';
|
||||
var channelID: number = update.channel_id;
|
||||
var maxID = appMessagesIDsManager.getFullMessageID(update.max_id, channelID);
|
||||
var peerID = channelID ? -channelID : AppPeersManager.getPeerID(update.peer);
|
||||
var peerID = channelID ? -channelID : appPeersManager.getPeerID(update.peer);
|
||||
var foundDialog = this.getDialogByPeerID(peerID);
|
||||
var history = (this.historiesStorage[peerID] || {}).history || [];
|
||||
var newUnreadCount = 0;
|
||||
@ -2935,9 +2985,7 @@ export class AppMessagesManager {
|
||||
if(!foundAffected) {
|
||||
foundAffected = true;
|
||||
}
|
||||
if(this.messagesForDialogs[messageID]) {
|
||||
this.messagesForDialogs[messageID].pFlags.unread = false;
|
||||
}
|
||||
|
||||
if(!message.pFlags.out) {
|
||||
if(foundDialog[0]) {
|
||||
newUnreadCount = --foundDialog[0].unread_count;
|
||||
@ -3007,33 +3055,22 @@ export class AppMessagesManager {
|
||||
|
||||
case 'updateDeleteMessages':
|
||||
case 'updateDeleteChannelMessages': {
|
||||
var historiesUpdated: any = {};
|
||||
var channelID: number = update.channel_id;
|
||||
var messageID: number;
|
||||
var message, i;
|
||||
var peerID: number, foundDialog: ReturnType<AppMessagesManager['getDialogByPeerID']>;
|
||||
let history: any;
|
||||
var peerMessagesToHandle;
|
||||
var peerMessagesHandlePos;
|
||||
let historiesUpdated: {[peerID: number]: {count: number, unread: number, msgs: {[mid: number]: true}}} = {};
|
||||
let channelID: number = update.channel_id;
|
||||
|
||||
for (i = 0; i < update.messages.length; i++) {
|
||||
messageID = appMessagesIDsManager.getFullMessageID(update.messages[i], channelID);
|
||||
message = this.messagesStorage[messageID];
|
||||
for(let i = 0; i < update.messages.length; i++) {
|
||||
let messageID = appMessagesIDsManager.getFullMessageID(update.messages[i], channelID);
|
||||
let message = this.messagesStorage[messageID];
|
||||
if(message) {
|
||||
peerID = this.getMessagePeer(message);
|
||||
history = historiesUpdated[peerID] || (historiesUpdated[peerID] = {count: 0, unread: 0, msgs: {}});
|
||||
let peerID = this.getMessagePeer(message);
|
||||
let history = historiesUpdated[peerID] || (historiesUpdated[peerID] = {count: 0, unread: 0, msgs: {}});
|
||||
|
||||
if(!message.pFlags.out && message.pFlags.unread) {
|
||||
history.unread++;
|
||||
// NotificationsManager.cancel('msg' + messageID); // warning
|
||||
}
|
||||
history.count++;
|
||||
history.msgs[messageID] = true;
|
||||
|
||||
if(this.messagesForDialogs[messageID]) {
|
||||
this.messagesForDialogs[messageID].deleted = true;
|
||||
delete this.messagesForDialogs[messageID];
|
||||
}
|
||||
message.deleted = true
|
||||
this.messagesStorage[messageID] = {
|
||||
deleted: true,
|
||||
@ -3045,9 +3082,9 @@ export class AppMessagesManager {
|
||||
date: message.date
|
||||
};
|
||||
|
||||
peerMessagesToHandle = this.newMessagesToHandle[peerID];
|
||||
let peerMessagesToHandle = this.newMessagesToHandle[peerID];
|
||||
if(peerMessagesToHandle && peerMessagesToHandle.length) {
|
||||
peerMessagesHandlePos = peerMessagesToHandle.indexOf(messageID);
|
||||
let peerMessagesHandlePos = peerMessagesToHandle.indexOf(messageID);
|
||||
if(peerMessagesHandlePos != -1) {
|
||||
peerMessagesToHandle.splice(peerMessagesHandlePos);
|
||||
}
|
||||
@ -3055,13 +3092,13 @@ export class AppMessagesManager {
|
||||
}
|
||||
}
|
||||
|
||||
Object.keys(historiesUpdated).forEach((peerID: string) => {
|
||||
let updatedData = historiesUpdated[peerID];
|
||||
var historyStorage = this.historiesStorage[peerID];
|
||||
Object.keys(historiesUpdated).forEach(peerID => {
|
||||
let updatedData = historiesUpdated[+peerID];
|
||||
let historyStorage = this.historiesStorage[peerID];
|
||||
if(historyStorage !== undefined) {
|
||||
var newHistory = []
|
||||
var newPending = []
|
||||
for(var i = 0; i < historyStorage.history.length; i++) {
|
||||
let newHistory: number[] = [];
|
||||
let newPending: number[] = [];
|
||||
for(let i = 0; i < historyStorage.history.length; i++) {
|
||||
if(!updatedData.msgs[historyStorage.history[i]]) {
|
||||
newHistory.push(historyStorage.history[i]);
|
||||
}
|
||||
@ -3070,13 +3107,13 @@ export class AppMessagesManager {
|
||||
if(updatedData.count &&
|
||||
historyStorage.count !== null &&
|
||||
historyStorage.count > 0) {
|
||||
historyStorage.count -= updatedData.count
|
||||
historyStorage.count -= updatedData.count;
|
||||
if(historyStorage.count < 0) {
|
||||
historyStorage.count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for(var i = 0; i < historyStorage.pending.length; i++) {
|
||||
for(let i = 0; i < historyStorage.pending.length; i++) {
|
||||
if(!updatedData.msgs[historyStorage.pending[i]]) {
|
||||
newPending.push(historyStorage.pending[i]);
|
||||
}
|
||||
@ -3086,7 +3123,7 @@ export class AppMessagesManager {
|
||||
$rootScope.$broadcast('history_delete', {peerID: peerID, msgs: updatedData.msgs});
|
||||
}
|
||||
|
||||
var foundDialog = this.getDialogByPeerID(+peerID)[0];
|
||||
let foundDialog = this.getDialogByPeerID(+peerID)[0];
|
||||
if(foundDialog) {
|
||||
if(updatedData.unread) {
|
||||
foundDialog.unread_count -= updatedData.unread;
|
||||
@ -3101,7 +3138,7 @@ export class AppMessagesManager {
|
||||
this.reloadConversation(+peerID);
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
@ -3127,7 +3164,7 @@ export class AppMessagesManager {
|
||||
this.reloadConversation(-channelID);
|
||||
} else {
|
||||
if(foundDialog[0]) {
|
||||
this.dialogsStorage.dialogs[foundDialog[0].folder_id].splice(foundDialog[1], 1);
|
||||
this.dialogsStorage[foundDialog[0].folder_id].splice(foundDialog[1], 1);
|
||||
$rootScope.$broadcast('dialog_drop', {peerID: peerID, dialog: foundDialog[0]});
|
||||
}
|
||||
}
|
||||
@ -3141,7 +3178,7 @@ export class AppMessagesManager {
|
||||
let peerID = -channelID;
|
||||
let foundDialog = this.getDialogByPeerID(peerID);
|
||||
if(foundDialog[0]) {
|
||||
this.dialogsStorage.dialogs[foundDialog[0].folder_id].splice(foundDialog[1], 1);
|
||||
this.dialogsStorage[foundDialog[0].folder_id].splice(foundDialog[1], 1);
|
||||
}
|
||||
|
||||
delete this.historiesStorage[peerID];
|
||||
@ -3167,8 +3204,6 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
case 'updateServiceNotification': {
|
||||
// update.inbox_date = tsNow(true)
|
||||
// update.pFlags = {popup: true}
|
||||
var fromID = 777000;
|
||||
var peerID = fromID;
|
||||
var messageID = this.tempID--;
|
||||
@ -3176,7 +3211,7 @@ export class AppMessagesManager {
|
||||
_: 'message',
|
||||
id: messageID,
|
||||
from_id: fromID,
|
||||
to_id: AppPeersManager.getOutputPeer(peerID),
|
||||
to_id: appPeersManager.getOutputPeer(peerID),
|
||||
flags: 0,
|
||||
pFlags: {unread: true},
|
||||
date: (update.inbox_date || tsNow(true)) + serverTimeManager.serverTimeOffset,
|
||||
@ -3203,9 +3238,7 @@ export class AppMessagesManager {
|
||||
message: message
|
||||
});
|
||||
}
|
||||
if(update.pFlags.popup && update.message) {
|
||||
//ErrorService.show({error: {code: 400, type: 'UPDATE_SERVICE_NOTIFICATION'}, historyMessage: historyMessage}); // warning
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -3464,14 +3497,14 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
public requestHistory(peerID: number, maxID: number, limit: number, offset = 0): Promise<any> {
|
||||
var isChannel = AppPeersManager.isChannel(peerID);
|
||||
var isChannel = appPeersManager.isChannel(peerID);
|
||||
|
||||
//console.trace('requestHistory', peerID, maxID, limit, offset);
|
||||
|
||||
$rootScope.$broadcast('history_request');
|
||||
|
||||
return apiManager.invokeApi('messages.getHistory', {
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
peer: appPeersManager.getInputPeerByID(peerID),
|
||||
offset_id: maxID ? appMessagesIDsManager.getMessageLocalID(maxID) : 0,
|
||||
offset_date: 0,
|
||||
add_offset: offset || 0,
|
||||
@ -3523,7 +3556,7 @@ export class AppMessagesManager {
|
||||
_: 'messageService',
|
||||
id: messageID,
|
||||
from_id: peerID,
|
||||
to_id: AppPeersManager.getOutputPeer(peerID),
|
||||
to_id: appPeersManager.getOutputPeer(peerID),
|
||||
flags: 0,
|
||||
pFlags: {},
|
||||
date: tsNow(true) + serverTimeManager.serverTimeOffset,
|
||||
@ -3617,16 +3650,14 @@ export class AppMessagesManager {
|
||||
|
||||
public wrapSingleMessage(msgID: number) {
|
||||
if(this.messagesStorage[msgID]) {
|
||||
//let ret = this.wrapForDialog(msgID); // hm
|
||||
$rootScope.$broadcast('messages_downloaded', [msgID]);
|
||||
//return ret;
|
||||
return {mid: msgID, loading: false};
|
||||
}
|
||||
|
||||
if(this.needSingleMessages.indexOf(msgID) == -1) {
|
||||
this.needSingleMessages.push(msgID);
|
||||
if(this.fetchSingleMessagesTimeout == 0) {
|
||||
this.fetchSingleMessagesTimeout = window.setTimeout(this.fetchSingleMessages.bind(this), 25);
|
||||
this.fetchSingleMessagesTimeout = window.setTimeout(this.fetchSingleMessages.bind(this), 10);
|
||||
}
|
||||
|
||||
return {mid: msgID, loading: true};
|
||||
|
@ -184,34 +184,47 @@ export class AppPhotosManager {
|
||||
arr[164] = bytes[1];
|
||||
arr[166] = bytes[2];
|
||||
} else {
|
||||
arr = bytes;
|
||||
arr = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
|
||||
}
|
||||
|
||||
//console.log('setAttachmentPreview', bytes, arr, div, isSticker);
|
||||
|
||||
let blob = new Blob([arr], {type: "image/jpeg"});
|
||||
|
||||
/* let reader = new FileReader();
|
||||
reader.onloadend = () => {
|
||||
let src = reader.result;
|
||||
};
|
||||
reader.readAsDataURL(blob); */
|
||||
|
||||
if(background) {
|
||||
let url = URL.createObjectURL(blob);
|
||||
let img = new Image();
|
||||
img.src = url;
|
||||
img.onload = () => {
|
||||
img.addEventListener('load', () => {
|
||||
element.style.backgroundImage = 'url(' + url + ')';
|
||||
};
|
||||
});
|
||||
|
||||
return element;
|
||||
//element.style.backgroundImage = 'url(' + url + ')';
|
||||
} else {
|
||||
if(element instanceof SVGSVGElement) {
|
||||
let image = element.firstElementChild as SVGImageElement || document.createElementNS("http://www.w3.org/2000/svg", "image");
|
||||
image.setAttributeNS(null, 'href', URL.createObjectURL(blob));
|
||||
element.append(image);
|
||||
|
||||
return image;
|
||||
} else if(element instanceof HTMLImageElement) {
|
||||
element.src = URL.createObjectURL(blob);
|
||||
return element;
|
||||
} else {
|
||||
let image = new Image();
|
||||
image.src = URL.createObjectURL(blob);
|
||||
let img = new Image();
|
||||
img.style.width = '100%';
|
||||
img.style.height = '100%';
|
||||
|
||||
image.style.width = '100%';
|
||||
image.style.height = '100%';
|
||||
element.append(image);
|
||||
img.src = URL.createObjectURL(blob);
|
||||
element.append(img);
|
||||
return img;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { horizontalMenu, formatPhoneNumber, putPreloader, renderImageFromUrl } from "../../components/misc";
|
||||
import { horizontalMenu, putPreloader, renderImageFromUrl } from "../../components/misc";
|
||||
//import Scrollable from '../../components/scrollable';
|
||||
import Scrollable from '../../components/scrollable_new';
|
||||
import { $rootScope } from "../utils";
|
||||
@ -18,6 +18,22 @@ import AvatarElement from "../../components/avatar";
|
||||
|
||||
const testScroll = false;
|
||||
|
||||
let setText = (text: string, el: HTMLDivElement) => {
|
||||
window.requestAnimationFrame(() => {
|
||||
if(el.childElementCount > 1) {
|
||||
el.firstElementChild.remove();
|
||||
}
|
||||
|
||||
let p = document.createElement('p');
|
||||
p.innerHTML = text;
|
||||
el.prepend(p);
|
||||
|
||||
el.style.display = '';
|
||||
|
||||
//this.scroll.getScrollTopOffset();
|
||||
});
|
||||
};
|
||||
|
||||
class AppSidebarRight {
|
||||
public sidebarEl = document.getElementById('column-right') as HTMLDivElement;
|
||||
public profileContainer = this.sidebarEl.querySelector('.profile-container') as HTMLDivElement;
|
||||
@ -56,7 +72,7 @@ class AppSidebarRight {
|
||||
'inputMessagesFilterUrl',
|
||||
'inputMessagesFilterMusic'
|
||||
];
|
||||
public sharedMediaType: string = '';
|
||||
public sharedMediaType: AppSidebarRight['sharedMediaTypes'][number] = '';
|
||||
private sharedMediaSelected: HTMLDivElement = null;
|
||||
|
||||
private lazyLoadQueueSidebar = new LazyLoadQueue(5);
|
||||
@ -91,6 +107,8 @@ class AppSidebarRight {
|
||||
public privateSearch = new AppSearch(this.searchContainer.querySelector('.chats-container') as HTMLDivElement, this.searchInput, {
|
||||
messages: new SearchGroup('Private Search', 'messages')
|
||||
});
|
||||
|
||||
private loadMutex: Promise<any> = Promise.resolve();
|
||||
|
||||
constructor() {
|
||||
let container = this.profileContentEl.querySelector('.content-container .tabs-container') as HTMLDivElement;
|
||||
@ -156,7 +174,7 @@ class AppSidebarRight {
|
||||
let ids = Object.keys(this.mediaDivsByIDs).map(k => +k).sort((a, b) => a - b);
|
||||
let idx = ids.findIndex(i => i == messageID);
|
||||
|
||||
let targets = ids.map(id => ({element: this.mediaDivsByIDs[id], mid: id}));
|
||||
let targets = ids.map(id => ({element: this.mediaDivsByIDs[id].firstElementChild as HTMLElement, mid: id}));
|
||||
|
||||
appMediaViewer.openMedia(message, target, false, this.sidebarEl, targets.slice(idx + 1).reverse(), targets.slice(0, idx).reverse(), true);
|
||||
});
|
||||
@ -289,12 +307,11 @@ class AppSidebarRight {
|
||||
return filtered;
|
||||
}
|
||||
|
||||
public performSearchResult(messages: any[], type: string) {
|
||||
public async performSearchResult(messages: any[], type: string) {
|
||||
let peerID = this.peerID;
|
||||
|
||||
let sharedMediaDiv: HTMLDivElement;
|
||||
|
||||
let elemsToAppend: HTMLElement[] = [];
|
||||
let promises: Promise<any>[] = [];
|
||||
|
||||
// https://core.telegram.org/type/MessagesFilter
|
||||
switch(type) {
|
||||
@ -305,22 +322,23 @@ class AppSidebarRight {
|
||||
let media = message.media.photo || message.media.document || (message.media.webpage && message.media.webpage.document);
|
||||
|
||||
let div = document.createElement('div');
|
||||
div.classList.add('media-item');
|
||||
//console.log(message, photo);
|
||||
|
||||
let isPhoto = media._ == 'photo';
|
||||
|
||||
let photo = isPhoto ? appPhotosManager.getPhoto(media.id) : null;
|
||||
let isDownloaded = (photo && photo.downloaded) || appPhotosManager.getDocumentCachedThumb(media.id);
|
||||
if(!isDownloaded) {
|
||||
//this.log('inputMessagesFilterPhotoVideo', message, media, photo, div);
|
||||
|
||||
let sizes = media.sizes || media.thumbs;
|
||||
if(sizes && sizes[0].bytes) {
|
||||
appPhotosManager.setAttachmentPreview(sizes[0].bytes, div, false, true);
|
||||
} /* else {
|
||||
this.log('no stripped size', message, media);
|
||||
} */
|
||||
let isDownloaded: boolean;
|
||||
if(photo) {
|
||||
isDownloaded = photo.downloaded > 0;
|
||||
} else {
|
||||
let cachedThumb = appPhotosManager.getDocumentCachedThumb(media.id);
|
||||
isDownloaded = cachedThumb?.downloaded > 0;
|
||||
}
|
||||
|
||||
let img = new Image();
|
||||
img.classList.add('media-image');
|
||||
div.append(img);
|
||||
|
||||
//this.log('inputMessagesFilterPhotoVideo', message, media);
|
||||
|
||||
@ -349,14 +367,37 @@ class AppSidebarRight {
|
||||
|
||||
let url = (photo && photo.url) || appPhotosManager.getDocumentCachedThumb(media.id).url;
|
||||
if(url) {
|
||||
renderImageFromUrl(div, url);
|
||||
renderImageFromUrl(img, url);
|
||||
}
|
||||
});
|
||||
|
||||
div.dataset.mid = '' + message.mid;
|
||||
img.dataset.mid = '' + message.mid;
|
||||
|
||||
let sizes = media.sizes || media.thumbs;
|
||||
if(isDownloaded || (sizes && sizes[0].bytes)) {
|
||||
let promise = new Promise((resolve, reject) => {
|
||||
img.addEventListener('load', () => {
|
||||
clearTimeout(timeout);
|
||||
resolve();
|
||||
});
|
||||
|
||||
let timeout = setTimeout(() => {
|
||||
this.log('did not loaded', img, media, isDownloaded, sizes);
|
||||
reject();
|
||||
}, 1e3);
|
||||
});
|
||||
|
||||
promises.push(promise);
|
||||
}
|
||||
|
||||
if(isDownloaded) load();
|
||||
else this.lazyLoadQueueSidebar.push({div, load});
|
||||
else {
|
||||
if(sizes && sizes[0].bytes) {
|
||||
appPhotosManager.setAttachmentPreview(sizes[0].bytes, img, false, false);
|
||||
}
|
||||
|
||||
this.lazyLoadQueueSidebar.push({div, load});
|
||||
}
|
||||
|
||||
this.lastSharedMediaDiv.append(div);
|
||||
if(this.lastSharedMediaDiv.childElementCount == 3) {
|
||||
@ -365,6 +406,7 @@ class AppSidebarRight {
|
||||
}
|
||||
|
||||
this.lastSharedMediaDiv = document.createElement('div');
|
||||
this.lastSharedMediaDiv.classList.add('media-row');
|
||||
}
|
||||
|
||||
this.mediaDivsByIDs[message.mid] = div;
|
||||
@ -397,6 +439,8 @@ class AppSidebarRight {
|
||||
|
||||
//this.log('wrapping webpage', webpage);
|
||||
|
||||
previewDiv.innerText = (webpage.title || webpage.description || webpage.url || webpage.display_url).slice(0, 1);
|
||||
previewDiv.classList.add('empty');
|
||||
if(webpage.photo) {
|
||||
let load = () => appPhotosManager.preloadPhoto(webpage.photo.id, appPhotosManager.choosePhotoSize(webpage.photo, 60, 60))
|
||||
.then(() => {
|
||||
@ -405,13 +449,12 @@ class AppSidebarRight {
|
||||
return;
|
||||
}
|
||||
|
||||
previewDiv.classList.remove('empty');
|
||||
|
||||
renderImageFromUrl(previewDiv, webpage.photo.url);
|
||||
});
|
||||
|
||||
this.lazyLoadQueueSidebar.push({div: previewDiv, load});
|
||||
} else {
|
||||
previewDiv.innerText = (webpage.title || webpage.description || webpage.url || webpage.display_url).slice(0, 1);
|
||||
previewDiv.classList.add('empty');
|
||||
}
|
||||
|
||||
let title = webpage.rTitle || '';
|
||||
@ -457,11 +500,19 @@ class AppSidebarRight {
|
||||
if(this.lastSharedMediaDiv.childElementCount && !this.scroll.contains(this.lastSharedMediaDiv)) {
|
||||
elemsToAppend.push(this.lastSharedMediaDiv);
|
||||
}
|
||||
|
||||
if(this.loadMutex) {
|
||||
promises.push(this.loadMutex);
|
||||
}
|
||||
|
||||
if(elemsToAppend.length) {
|
||||
//window.requestAnimationFrame(() => {
|
||||
//elemsToAppend.forEach(el => this.scroll.append(el, false));
|
||||
//});
|
||||
if(promises.length) {
|
||||
await Promise.all(promises);
|
||||
if(this.peerID != peerID) {
|
||||
this.log.warn('peer changed');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sharedMediaDiv.append(...elemsToAppend);
|
||||
}
|
||||
@ -521,7 +572,7 @@ class AppSidebarRight {
|
||||
|
||||
this.usedFromHistory[type] = used;
|
||||
if(messages.length) {
|
||||
this.performSearchResult(messages, type);
|
||||
return this.performSearchResult(messages, type);
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
@ -556,7 +607,7 @@ class AppSidebarRight {
|
||||
this.usedFromHistory[type] = history.length;
|
||||
|
||||
if(ids.length) {
|
||||
this.performSearchResult(this.filterMessagesByType(ids, type), type);
|
||||
return this.performSearchResult(this.filterMessagesByType(ids, type), type);
|
||||
}
|
||||
}, (err) => {
|
||||
this.log.error('load error:', err);
|
||||
@ -567,77 +618,77 @@ class AppSidebarRight {
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
public fillProfileElements() {
|
||||
let peerID = this.peerID = $rootScope.selectedPeerID;
|
||||
|
||||
public cleanup() {
|
||||
this.loadSidebarMediaPromises = {};
|
||||
this.loadedAllMedia = {};
|
||||
this.lastSharedMediaDiv = document.createElement('div');
|
||||
|
||||
//this.log('fillProfileElements');
|
||||
this.lastSharedMediaDiv.classList.add('media-row');
|
||||
|
||||
this.contentContainer.classList.remove('loaded');
|
||||
|
||||
this.profileElements.avatar.setAttribute('peer', '' + peerID);
|
||||
|
||||
window.requestAnimationFrame(() => {
|
||||
this.profileContentEl.parentElement.scrollTop = 0;
|
||||
this.profileElements.bio.style.display = 'none';
|
||||
this.profileElements.phone.style.display = 'none';
|
||||
this.profileElements.username.style.display = 'none';
|
||||
this.profileElements.notificationsRow.style.display = '';
|
||||
this.profileElements.notificationsCheckbox.checked = true;
|
||||
this.profileElements.notificationsStatus.innerText = 'Enabled';
|
||||
|
||||
Object.keys(this.sharedMedia).forEach(key => {
|
||||
this.sharedMedia[key].innerHTML = '';
|
||||
|
||||
let parent = this.sharedMedia[key].parentElement;
|
||||
if(!parent.querySelector('.preloader')) {
|
||||
putPreloader(parent, true);
|
||||
}
|
||||
});
|
||||
|
||||
this.prevTabID = -1;
|
||||
this.scroll.setVirtualContainer(null);
|
||||
(this.profileTabs.firstElementChild.children[1] as HTMLLIElement).click(); // set media
|
||||
|
||||
//this.scroll.getScrollTopOffset();
|
||||
|
||||
this.loadSidebarMedia(true);
|
||||
});
|
||||
this.prevTabID = -1;
|
||||
this.scroll.setVirtualContainer(null);
|
||||
|
||||
this.mediaDivsByIDs = {};
|
||||
|
||||
this.lazyLoadQueueSidebar.clear();
|
||||
|
||||
this.urlsToRevoke.forEach(url => {
|
||||
URL.revokeObjectURL(url);
|
||||
});
|
||||
this.urlsToRevoke.length = 0;
|
||||
|
||||
|
||||
this.sharedMediaTypes.forEach(type => {
|
||||
this.usedFromHistory[type] = 0;
|
||||
});
|
||||
|
||||
let setText = (text: string, el: HTMLDivElement) => {
|
||||
window.requestAnimationFrame(() => {
|
||||
if(el.childElementCount > 1) {
|
||||
el.firstElementChild.remove();
|
||||
}
|
||||
|
||||
let p = document.createElement('p');
|
||||
p.innerHTML = text;
|
||||
el.prepend(p);
|
||||
|
||||
el.style.display = '';
|
||||
|
||||
//this.scroll.getScrollTopOffset();
|
||||
this.sharedMediaType = 'inputMessagesFilterPhotoVideo';
|
||||
}
|
||||
|
||||
public cleanupHTML() {
|
||||
this.contentContainer.classList.remove('loaded');
|
||||
|
||||
this.profileContentEl.parentElement.scrollTop = 0;
|
||||
this.profileElements.bio.style.display = 'none';
|
||||
this.profileElements.phone.style.display = 'none';
|
||||
this.profileElements.username.style.display = 'none';
|
||||
this.profileElements.notificationsRow.style.display = '';
|
||||
this.profileElements.notificationsCheckbox.checked = true;
|
||||
this.profileElements.notificationsStatus.innerText = 'Enabled';
|
||||
|
||||
if(this.urlsToRevoke.length) {
|
||||
this.urlsToRevoke.forEach(url => {
|
||||
URL.revokeObjectURL(url);
|
||||
});
|
||||
};
|
||||
|
||||
this.urlsToRevoke.length = 0;
|
||||
}
|
||||
|
||||
Object.keys(this.sharedMedia).forEach(key => {
|
||||
this.sharedMedia[key].innerHTML = '';
|
||||
|
||||
if(!this.historiesStorage[this.peerID] || !this.historiesStorage[this.peerID][key]) {
|
||||
let parent = this.sharedMedia[key].parentElement;
|
||||
if(!parent.querySelector('.preloader')) {
|
||||
putPreloader(parent, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
(this.profileTabs.firstElementChild.children[1] as HTMLLIElement).click(); // set media
|
||||
}
|
||||
|
||||
public setLoadMutex(promise: Promise<any>) {
|
||||
this.loadMutex = promise;
|
||||
}
|
||||
|
||||
public setPeer(peerID: number) {
|
||||
this.peerID = peerID;
|
||||
this.cleanup();
|
||||
}
|
||||
|
||||
public fillProfileElements() {
|
||||
let peerID = this.peerID = $rootScope.selectedPeerID;
|
||||
|
||||
this.cleanupHTML();
|
||||
|
||||
this.profileElements.avatar.setAttribute('peer', '' + peerID);
|
||||
|
||||
// username
|
||||
if(peerID != appImManager.myID) {
|
||||
if(peerID != $rootScope.myID) {
|
||||
let username = appPeersManager.getPeerUsername(peerID);
|
||||
if(username) {
|
||||
setText(appPeersManager.getPeerUsername(peerID), this.profileElements.username);
|
||||
@ -656,13 +707,12 @@ class AppSidebarRight {
|
||||
} else {
|
||||
window.requestAnimationFrame(() => {
|
||||
this.profileElements.notificationsRow.style.display = 'none';
|
||||
//this.scroll.getScrollTopOffset();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
if(peerID > 0) {
|
||||
let user = appUsersManager.getUser(peerID);
|
||||
if(user.phone && peerID != appImManager.myID) {
|
||||
if(user.phone && peerID != $rootScope.myID) {
|
||||
setText(user.rPhone, this.profileElements.phone);
|
||||
}
|
||||
|
||||
@ -672,7 +722,7 @@ class AppSidebarRight {
|
||||
return;
|
||||
}
|
||||
|
||||
if(userFull.rAbout && peerID != appImManager.myID) {
|
||||
if(userFull.rAbout && peerID != $rootScope.myID) {
|
||||
setText(userFull.rAbout, this.profileElements.bio);
|
||||
}
|
||||
|
||||
@ -682,8 +732,6 @@ class AppSidebarRight {
|
||||
appImManager.pinnedMsgID = userFull.pinned_msg_id;
|
||||
appMessagesManager.wrapSingleMessage(userFull.pinned_msg_id);
|
||||
}
|
||||
|
||||
//this.scroll.getScrollTopOffset();
|
||||
});
|
||||
} else {
|
||||
let chat = appPeersManager.getPeer(peerID);
|
||||
@ -699,13 +747,8 @@ class AppSidebarRight {
|
||||
if(chatFull.about) {
|
||||
setText(RichTextProcessor.wrapRichText(chatFull.about), this.profileElements.bio);
|
||||
}
|
||||
|
||||
//this.scroll.getScrollTopOffset();
|
||||
});
|
||||
}
|
||||
|
||||
//this.scroll.getScrollTopOffset();
|
||||
//this.loadSidebarMedia();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,9 +60,6 @@ class AppStickersManager {
|
||||
for(let id in sets) {
|
||||
let set = sets[id];
|
||||
set.documents.forEach(doc => {
|
||||
delete doc.downloaded;
|
||||
delete doc.url;
|
||||
|
||||
this.saveSticker(doc);
|
||||
});
|
||||
}
|
||||
@ -78,13 +75,6 @@ class AppStickersManager {
|
||||
|
||||
public saveSticker(doc: MTDocument) {
|
||||
if(this.documents[doc.id]) return this.documents[doc.id];
|
||||
/* Object.keys(doc).forEach(key => {
|
||||
if(doc[key] instanceof Uint8Array) {
|
||||
doc[key] = Array.from(doc[key]);
|
||||
}
|
||||
}); */
|
||||
|
||||
doc.file_reference = Array.from(doc.file_reference);
|
||||
|
||||
doc = appDocsManager.saveDoc(doc);
|
||||
this.documents[doc.id] = doc;
|
||||
|
@ -228,7 +228,7 @@ export class AppUsersManager {
|
||||
var nameWords = apiUser.sortName.split(' ');
|
||||
var firstWord = nameWords.shift();
|
||||
var lastWord = nameWords.pop();
|
||||
apiUser.initials = firstWord.charAt(0) + (lastWord ? lastWord.charAt(0) : firstWord.charAt(1));
|
||||
apiUser.initials = firstWord.charAt(0) + (lastWord ? lastWord.charAt(0) : '');
|
||||
|
||||
if(apiUser.status) {
|
||||
if(apiUser.status.expires) {
|
||||
|
@ -84,6 +84,10 @@ Uint8Array.prototype.toString = function() {
|
||||
return String.fromCharCode.apply(null, [...this]);
|
||||
};
|
||||
|
||||
Uint8Array.prototype.toJSON = function() {
|
||||
return [...this];
|
||||
};
|
||||
|
||||
Array.prototype.forEachReverse = function<T>(callback: (value: T, index?: number, array?: Array<T>) => void) {
|
||||
let length = this.length;
|
||||
for(var i = length - 1; i >= 0; --i) {
|
||||
@ -113,7 +117,8 @@ declare global {
|
||||
hex: string;
|
||||
randomize: () => Uint8Array,
|
||||
concat: (...args: Array<Uint8Array | ArrayBuffer | number[]>) => Uint8Array,
|
||||
toString: () => string
|
||||
toString: () => string,
|
||||
toJSON: () => number[],
|
||||
}
|
||||
|
||||
interface Array<T> {
|
||||
|
@ -67,8 +67,11 @@ class ConfigStorage {
|
||||
value = obj[key];
|
||||
key = prefix + key;
|
||||
this.cache[key] = value;
|
||||
//value = value instanceof Uint8Array ? Array.from(value) : JSON.stringify(value);
|
||||
value = JSON.stringify(value);
|
||||
value = JSON.stringify(value, (key, value) => {
|
||||
if(key == 'downloaded' || (key == 'url' && value.indexOf('blob:') === 0)) return undefined;
|
||||
return value;
|
||||
});
|
||||
|
||||
if(this.useLs) {
|
||||
try {
|
||||
//console.log('setItem', key, value);
|
||||
|
@ -754,7 +754,8 @@ function versionCompare (ver1, ver2) {
|
||||
}
|
||||
|
||||
|
||||
var badCharsRe = /[`~!@#$%^&*()\-_=+\[\]\\|{}'";:\/?.>,<\s]+/g,
|
||||
//var badCharsRe = /[`~!@#$%^&*()\-_=+\[\]\\|{}'";:\/?.>,<\s]+/g,
|
||||
var badCharsRe = /[`~!@#$%^&*()\-_=+\[\]\\|{}'";:\/?.>,<]+/g,
|
||||
trimRe = /^\s+|\s$/g
|
||||
|
||||
function createIndex () {
|
||||
@ -766,7 +767,7 @@ function versionCompare (ver1, ver2) {
|
||||
|
||||
function cleanSearchText(text, latinize = true) {
|
||||
var hasTag = text.charAt(0) == '%';
|
||||
text = text.replace(badCharsRe, ' ').replace(trimRe, '');
|
||||
text = text.replace(badCharsRe, '').replace(trimRe, '');
|
||||
if(latinize) {
|
||||
text = text.replace(/[^A-Za-z0-9]/g, (ch) => {
|
||||
var latinizeCh = Config.LatinizeMap[ch];
|
||||
|
@ -14,36 +14,52 @@
|
||||
|
||||
.bubble {
|
||||
padding-top: 5px;
|
||||
/* display: grid;
|
||||
grid-template-columns: 1fr $chat-max-width 1fr;
|
||||
grid-row-gap: 0px; */
|
||||
max-width: $chat-max-width;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
|
||||
&.is-selected {
|
||||
&:before {
|
||||
&:after {
|
||||
position: absolute;
|
||||
width: 200%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 132, 255, .3);
|
||||
content: " ";
|
||||
display: block;
|
||||
left: -50%;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
content: " ";
|
||||
background-color: rgba(0, 132, 255, .3);
|
||||
animation: bubbleSelected 2s linear;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&:not(.is-group-last):before {
|
||||
&:not(.is-group-last):after {
|
||||
height: calc(100% + 5px);
|
||||
}
|
||||
}
|
||||
|
||||
&.is-first-unread {
|
||||
&:before {
|
||||
content: "Unread messages";
|
||||
height: 30px;
|
||||
margin-bottom: 5px;
|
||||
margin-left: -50%;
|
||||
text-align: center;
|
||||
color: #538BCC;
|
||||
line-height: 2.1;
|
||||
font-weight: 500;
|
||||
font-size: 15px;
|
||||
background-color: rgba(255, 255, 255, 0.95);
|
||||
}
|
||||
}
|
||||
|
||||
&.is-selected:after, &.is-first-unread:before {
|
||||
width: 200%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
&.is-date {
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
top: 5px;
|
||||
z-index: 2;
|
||||
z-index: 3;
|
||||
pointer-events: none;
|
||||
|
||||
&.is-sticky {
|
||||
@ -53,11 +69,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* &:before, &:after {
|
||||
content: " ";
|
||||
width: 100%;
|
||||
} */
|
||||
|
||||
&__container {
|
||||
//min-width: 60px;
|
||||
min-width: 56px;
|
||||
@ -70,6 +81,7 @@
|
||||
/* font-size: 0; */
|
||||
width: max-content;
|
||||
height: fit-content;
|
||||
z-index: 2;
|
||||
|
||||
> .user-avatar {
|
||||
position: absolute;
|
||||
@ -560,6 +572,14 @@
|
||||
.emoji {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
pre, code {
|
||||
white-space: pre-wrap; /* css-3 */
|
||||
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
|
||||
white-space: -pre-wrap; /* Opera 4-6 */
|
||||
white-space: -o-pre-wrap; /* Opera 7 */
|
||||
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
||||
}
|
||||
}
|
||||
|
||||
// all for audio (not voice)
|
||||
@ -1204,7 +1224,62 @@
|
||||
}
|
||||
}
|
||||
|
||||
.reply-markup {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
|
||||
&-row {
|
||||
margin-top: 5px;
|
||||
overflow: hidden;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
|
||||
&:last-child {
|
||||
border-bottom-left-radius: $border-radius-big;
|
||||
border-bottom-right-radius: $border-radius-big;
|
||||
}
|
||||
}
|
||||
|
||||
&-button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 6px;
|
||||
background-color: rgba(0, 0, 0, 0.23);
|
||||
z-index: 2;
|
||||
font-size: 14px;
|
||||
user-select: none;
|
||||
text-align: center;
|
||||
color: white !important;
|
||||
outline: none;
|
||||
border: none;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
transition: background-color 0.35s ease;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
& + & {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
&.is-link:before {
|
||||
content: $tgico-next;
|
||||
position: absolute;
|
||||
right: 2px;
|
||||
top: 2px;
|
||||
display: block;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
/* img.emoji {
|
||||
vertical-align: middle !important;
|
||||
} */
|
||||
}
|
||||
}
|
||||
|
||||
poll-element {
|
||||
margin-top: -1px;
|
||||
|
@ -129,7 +129,7 @@
|
||||
content: "\e91f";
|
||||
}
|
||||
.tgico-next:before {
|
||||
content: "\e920";
|
||||
content: $tgico-next;
|
||||
}
|
||||
.tgico-nosound:before {
|
||||
content: "\e921";
|
||||
|
@ -5,3 +5,4 @@ $tgico-check: "\e900";
|
||||
$tgico-checks: "\e95a";
|
||||
$tgico-sending: "\e919";
|
||||
$tgico-close: "\e943";
|
||||
$tgico-next: "\e920";
|
||||
|
@ -1,3 +1,7 @@
|
||||
$open-duration: .2s;
|
||||
//$open-duration: 10s;
|
||||
$move-duration: .35s;
|
||||
|
||||
.media-viewer {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
@ -20,7 +24,7 @@
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
color: #8b8b8b;
|
||||
transition: .2s;
|
||||
transition: $open-duration;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
@ -53,7 +57,7 @@
|
||||
|
||||
.btn-icon {
|
||||
margin: 0 .25rem;
|
||||
transition: .2s;
|
||||
transition: $open-duration;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
@ -91,14 +95,6 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
visibility: hidden;
|
||||
|
||||
&.loading {
|
||||
img, video {
|
||||
object-fit: cover;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
img, video {
|
||||
@ -108,22 +104,11 @@
|
||||
max-width: 1280px; */
|
||||
}
|
||||
|
||||
img {
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/* object-fit: cover; */
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.media-viewer-caption {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
color: $color-gray;
|
||||
transition: .2s;
|
||||
transition: $open-duration;
|
||||
max-width: 50vw;
|
||||
word-break: break-word;
|
||||
overflow: hidden;
|
||||
@ -165,7 +150,7 @@
|
||||
top: 50%;
|
||||
transform: translateY(-50%) rotate(90deg);
|
||||
opacity: 0;
|
||||
transition: .2s opacity;
|
||||
transition: $open-duration opacity;
|
||||
z-index: 5;
|
||||
/* box-shadow: 0 1px 2px 0 rgba(16, 35, 47, 0.07); */
|
||||
}
|
||||
@ -189,40 +174,40 @@
|
||||
transform-origin: top left;
|
||||
overflow: hidden;
|
||||
//border-radius: 0;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
|
||||
.ckin__player {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
img, video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 1;
|
||||
transition: .2s opacity;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
&.cover {
|
||||
align-items: center;
|
||||
|
||||
img, video {
|
||||
width: auto;
|
||||
height: auto;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
}
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
&.active {
|
||||
transition: .2s transform;
|
||||
transition: $open-duration transform;
|
||||
}
|
||||
|
||||
&.moving {
|
||||
transition: 350ms transform ease;
|
||||
transition: $move-duration transform ease;
|
||||
}
|
||||
}
|
||||
|
||||
// возможно тут это вообще не нужно
|
||||
&-aspecter {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transform: scale(1);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&-mover.active &-aspecter {
|
||||
transition: $open-duration all;
|
||||
}
|
||||
}
|
||||
|
@ -211,7 +211,7 @@
|
||||
flex-direction: column;
|
||||
padding: 4px 7.5px 7.5px;
|
||||
|
||||
> div {
|
||||
.media-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
grid-auto-rows: max-content;
|
||||
@ -219,14 +219,9 @@
|
||||
place-items: start;
|
||||
padding-top: 3.5px;
|
||||
|
||||
> div {
|
||||
.media-item {
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
|
||||
display: flex;
|
||||
background-color: #000;
|
||||
position: relative;
|
||||
@ -241,8 +236,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
span.video-time {
|
||||
position: relative;
|
||||
.video-time {
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
top: 4px;
|
||||
height: 18px;
|
||||
@ -254,6 +249,12 @@
|
||||
color: white;
|
||||
}
|
||||
|
||||
.media-image {
|
||||
width: 100%;
|
||||
max-height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
/* span.video-play {
|
||||
background-color: $time-background;
|
||||
color: #fff;
|
||||
|
@ -14,9 +14,11 @@
|
||||
flex-direction: column;
|
||||
|
||||
&-search-container {
|
||||
flex: 1 1 auto;
|
||||
flex: 0 0 auto;
|
||||
//flex: 1 1 auto;
|
||||
position: relative;
|
||||
max-height: 132px;
|
||||
overflow: hidden;
|
||||
|
||||
.scrollable {
|
||||
position: relative;
|
||||
|
@ -276,6 +276,37 @@ input {
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInFadeOut {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
10% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.toast {
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
padding: .5rem 1rem;
|
||||
background-color: rgba(0, 0, 0, .66);
|
||||
color: #fff;
|
||||
font-size: 1rem;
|
||||
border-radius: $border-radius-medium;
|
||||
animation: fadeInFadeOut 3s linear forwards;
|
||||
}
|
||||
|
||||
hr {
|
||||
width: 100%;
|
||||
border: none;
|
||||
|
@ -115,6 +115,7 @@ module.exports = {
|
||||
filename: `index.html`,
|
||||
template: 'public/index_template.html',
|
||||
inject: true,
|
||||
//inject: 'head',
|
||||
/* minify: {
|
||||
removeComments: true,
|
||||
collapseWhitespace: true,
|
||||
|
Loading…
x
Reference in New Issue
Block a user