;
+
+ constructor() {
+ this.scrollable = new Scrollable(this.contentDiv, 'y', ANIMATIONGROUP, undefined, undefined, 2);
+ this.scrollable.setVirtualContainer(this.gifsDiv);
+
+ this.masonry = new GifsMasonry(this.gifsDiv);
+
+ this.lazyLoadQueue = new LazyLoadQueue();
+
+ this.searchInput = new SearchInput('Search GIFs', (value) => {
+ this.reset();
+ this.search(value);
+ });
+
+ this.scrollable.onScrolledBottom = () => {
+ this.search(this.searchInput.value, false);
+ };
+
+ this.backBtn.parentElement.append(this.searchInput.container);
+ }
+
+ public onCloseAfterTimeout() {
+ this.reset();
+ this.gifsDiv.innerHTML = '';
+ this.searchInput.value = '';
+ animationIntersector.checkAnimations(undefined, ANIMATIONGROUP);
+ }
+
+ private reset() {
+ this.searchPromise = null;
+ this.nextOffset = '';
+ this.lazyLoadQueue.clear();
+ }
+
+ public init() {
+ appSidebarRight.selectTab(AppSidebarRight.SLIDERITEMSIDS.gifs);
+
+ appSidebarRight.toggleSidebar(true).then(() => {
+ //this.renderFeatured();
+ this.search('', true);
+ this.reset();
+ });
+ }
+
+ public async search(query: string, newSearch = true) {
+ if(this.searchPromise) return;
+
+ if(!this.gifBotPeerID) {
+ this.gifBotPeerID = (await appUsersManager.resolveUsername('gif')).id;
+ }
+
+ try {
+ this.searchPromise = appInlineBotsManager.getInlineResults(0, this.gifBotPeerID, query, this.nextOffset);
+ const { results, next_offset } = await this.searchPromise;
+
+ if(this.searchInput.value != query) {
+ return;
+ }
+
+ this.searchPromise = null;
+ this.nextOffset = next_offset;
+ if(newSearch) {
+ this.gifsDiv.innerHTML = '';
+ }
+
+ results.forEach((result) => {
+ if(result._ === 'botInlineMediaResult' && result.document) {
+ this.masonry.add(result.document, ANIMATIONGROUP, this.lazyLoadQueue);
+ }
+ });
+
+ this.scrollable.onScroll();
+ } catch (err) {
+ throw new Error(JSON.stringify(err));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/components/sidebarRight/pollResults.ts b/src/components/sidebarRight/pollResults.ts
new file mode 100644
index 00000000..7d9f3577
--- /dev/null
+++ b/src/components/sidebarRight/pollResults.ts
@@ -0,0 +1,130 @@
+import { SliderTab } from "../slider";
+import Scrollable from "../scrollable_new";
+import appSidebarRight, { AppSidebarRight } from "../../lib/appManagers/appSidebarRight";
+import appPollsManager from "../../lib/appManagers/appPollsManager";
+import { roundPercents } from "../poll";
+import { RichTextProcessor } from "../../lib/richtextprocessor";
+import appDialogsManager from "../../lib/appManagers/appDialogsManager";
+import { ripple } from "../ripple";
+
+export default class AppPollResultsTab implements SliderTab {
+ private container = document.getElementById('poll-results-container') as HTMLDivElement;
+ private contentDiv = this.container.querySelector('.sidebar-content') as HTMLDivElement;
+ private resultsDiv = this.contentDiv.firstElementChild as HTMLDivElement;
+ private scrollable: Scrollable;
+
+ private pollID: string;
+ private mid: number;
+
+ constructor() {
+ this.scrollable = new Scrollable(this.contentDiv, 'y', 'POLL-RESULTS', undefined, undefined, 2);
+ }
+
+ public cleanup() {
+ this.resultsDiv.innerHTML = '';
+ this.pollID = '';
+ this.mid = 0;
+ }
+
+ public onCloseAfterTimeout() {
+ this.cleanup();
+ }
+
+ public init(pollID: string, mid: number) {
+ if(this.pollID == pollID && this.mid == mid) return;
+
+ this.cleanup();
+
+ this.pollID = pollID;
+ this.mid = mid;
+
+ appSidebarRight.selectTab(AppSidebarRight.SLIDERITEMSIDS.pollResults);
+
+ const poll = appPollsManager.getPoll(pollID);
+
+ const title = document.createElement('h3');
+ title.innerHTML = poll.poll.rQuestion;
+
+ const percents = poll.results.results.map(v => v.voters / poll.results.total_voters * 100);
+ roundPercents(percents);
+
+ const fragment = document.createDocumentFragment();
+ poll.results.results.forEach((result, idx) => {
+ if(!result.voters) return;
+
+ const hr = document.createElement('hr');
+
+ const answer = poll.poll.answers[idx];
+
+ // Head
+ const answerEl = document.createElement('div');
+ answerEl.classList.add('poll-results-answer');
+
+ const answerTitle = document.createElement('div');
+ answerTitle.innerHTML = RichTextProcessor.wrapEmojiText(answer.text);
+
+ const answerPercents = document.createElement('div');
+ answerPercents.innerText = Math.round(percents[idx]) + '%';
+
+ answerEl.append(answerTitle, answerPercents);
+
+ // Humans
+ const list = document.createElement('ul');
+ list.classList.add('poll-results-voters');
+
+ appDialogsManager.setListClickListener(list);
+
+ list.style.minHeight = Math.min(result.voters, 4) * 50 + 'px';
+
+ fragment.append(hr, answerEl, list);
+
+ let offset: string, limit = 4, loading = false, left = result.voters - 4;
+ const load = () => {
+ if(loading) return;
+ loading = true;
+
+ appPollsManager.getVotes(mid, answer.option, offset, limit).then(votesList => {
+ votesList.votes.forEach(vote => {
+ const {dom} = appDialogsManager.addDialog(vote.user_id, list, false, false, undefined, false);
+ dom.lastMessageSpan.parentElement.remove();
+ });
+
+ if(offset) {
+ left -= votesList.votes.length;
+ (showMore.lastElementChild as HTMLElement).innerText = `Show ${Math.min(20, left)} more voter${left > 1 ? 's' : ''}`;
+ }
+
+ offset = votesList.next_offset;
+ limit = 20;
+
+ if(!left || !votesList.votes.length) {
+ showMore.remove();
+ }
+ }).finally(() => {
+ loading = false;
+ });
+ };
+
+ load();
+
+ if(left <= 0) return;
+
+ const showMore = document.createElement('div');
+ showMore.classList.add('poll-results-more', 'show-more');
+ showMore.addEventListener('click', load);
+
+ showMore.innerHTML = `Show ${Math.min(20, left)} more voter${left > 1 ? 's' : ''}
`;
+ ripple(showMore);
+
+ fragment.append(showMore);
+ });
+
+ this.resultsDiv.append(title, fragment);
+
+ appSidebarRight.toggleSidebar(true).then(() => {
+ /* appPollsManager.getVotes(mid).then(votes => {
+ console.log('gOt VotEs', votes);
+ }); */
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/components/sidebarRight/stickers.ts b/src/components/sidebarRight/stickers.ts
new file mode 100644
index 00000000..8b1c6a01
--- /dev/null
+++ b/src/components/sidebarRight/stickers.ts
@@ -0,0 +1,235 @@
+import { SliderTab } from "../slider";
+import SearchInput from "../searchInput";
+import Scrollable from "../scrollable_new";
+import LazyLoadQueue from "../lazyLoadQueue";
+import { findUpClassName } from "../../lib/utils";
+import appImManager from "../../lib/appManagers/appImManager";
+import appStickersManager, { MTStickerSet, MTStickerSetCovered, MTStickerSetMultiCovered } from "../../lib/appManagers/appStickersManager";
+import PopupStickers from "../popupStickers";
+import animationIntersector from "../animationIntersector";
+import { RichTextProcessor } from "../../lib/richtextprocessor";
+import { wrapSticker } from "../wrappers";
+import appSidebarRight, { AppSidebarRight } from "../../lib/appManagers/appSidebarRight";
+
+export default class AppStickersTab implements SliderTab {
+ private container = document.getElementById('stickers-container') as HTMLDivElement;
+ private contentDiv = this.container.querySelector('.sidebar-content') as HTMLDivElement;
+ private backBtn = this.container.querySelector('.sidebar-close-button') as HTMLButtonElement;
+ //private input = this.container.querySelector('#stickers-search') as HTMLInputElement;
+ private searchInput: SearchInput;
+ private setsDiv = this.contentDiv.firstElementChild as HTMLDivElement;
+ private scrollable: Scrollable;
+ private lazyLoadQueue: LazyLoadQueue;
+
+ constructor() {
+ this.scrollable = new Scrollable(this.contentDiv, 'y', 'STICKERS-SEARCH', undefined, undefined, 2);
+ this.scrollable.setVirtualContainer(this.setsDiv);
+
+ this.lazyLoadQueue = new LazyLoadQueue();
+
+ this.searchInput = new SearchInput('Search Stickers', (value) => {
+ this.search(value);
+ });
+
+ this.backBtn.parentElement.append(this.searchInput.container);
+
+ this.setsDiv.addEventListener('click', (e) => {
+ const sticker = findUpClassName(e.target, 'sticker-set-sticker');
+ if(sticker) {
+ const docID = sticker.dataset.docID;
+ appImManager.chatInputC.sendMessageWithDocument(docID);
+ return;
+ }
+
+ const target = findUpClassName(e.target, 'sticker-set');
+ if(!target) return;
+
+
+ const id = target.dataset.stickerSet as string;
+ const access_hash = target.dataset.stickerSet as string;
+
+ const button = findUpClassName(e.target, 'sticker-set-button') as HTMLElement;
+ if(button) {
+ e.preventDefault();
+ e.cancelBubble = true;
+
+ button.setAttribute('disabled', 'true');
+
+ appStickersManager.getStickerSet({id, access_hash}).then(full => {
+ appStickersManager.toggleStickerSet(full.set).then(changed => {
+ if(changed) {
+ button.innerText = full.set.installed_date ? 'Added' : 'Add';
+ button.classList.toggle('gray', !!full.set.installed_date);
+ }
+ }).finally(() => {
+ //button.style.width = set.installed_date ? '68px' : '52px';
+ button.removeAttribute('disabled');
+ });
+ });
+ } else {
+ appStickersManager.getStickerSet({id, access_hash}).then(full => {
+ new PopupStickers(full.set).show();
+ });
+ }
+ });
+ }
+
+ public onCloseAfterTimeout() {
+ this.setsDiv.innerHTML = '';
+ this.searchInput.value = '';
+ animationIntersector.checkAnimations(undefined, 'STICKERS-SEARCH');
+ }
+
+ public renderSet(set: MTStickerSet) {
+ //console.log('renderSet:', set);
+ const div = document.createElement('div');
+ div.classList.add('sticker-set');
+
+ const header = document.createElement('div');
+ header.classList.add('sticker-set-header');
+
+ const details = document.createElement('div');
+ details.classList.add('sticker-set-details');
+ details.innerHTML = `
+ ${RichTextProcessor.wrapEmojiText(set.title)}
+ ${set.count} stickers
+ `;
+
+ const button = document.createElement('button');
+ button.classList.add('btn-primary', 'sticker-set-button');
+ button.innerText = set.installed_date ? 'Added' : 'Add';
+ // button.style.width = set.installed_date ? '68px' : '52px';
+
+ if(set.installed_date) {
+ button.classList.add('gray');
+ }
+
+ //ripple(button);
+
+ header.append(details, button);
+
+ const stickersDiv = document.createElement('div');
+ stickersDiv.classList.add('sticker-set-stickers');
+
+ const count = Math.min(5, set.count);
+ for(let i = 0; i < count; ++i) {
+ const stickerDiv = document.createElement('div');
+ stickerDiv.classList.add('sticker-set-sticker');
+
+ stickersDiv.append(stickerDiv);
+ }
+
+ appStickersManager.getStickerSet(set).then(set => {
+ //console.log('renderSet got set:', set);
+
+ for(let i = 0; i < count; ++i) {
+ const div = stickersDiv.children[i] as HTMLDivElement;
+ wrapSticker({
+ doc: set.documents[i],
+ div,
+ lazyLoadQueue: this.lazyLoadQueue,
+ group: 'STICKERS-SEARCH',
+ /* play: false,
+ loop: false, */
+ play: true,
+ loop: true,
+ width: 68,
+ height: 68
+ });
+ }
+ });
+
+ /* const onMouseOver = () => {
+ const animations: AnimationItem['animation'][] = [];
+ for(let i = 0; i < count; ++i) {
+ const stickerDiv = stickersDiv.children[i] as HTMLElement;
+ const animationItem = animationIntersector.getAnimation(stickerDiv);
+ if(!animationItem) continue;
+
+ const animation = animationItem.animation;
+
+ animations.push(animation);
+ animation.loop = true;
+ animation.play();
+ }
+
+ div.addEventListener('mouseout', () => {
+ animations.forEach(animation => {
+ animation.loop = false;
+ });
+
+ div.addEventListener('mouseover', onMouseOver, {once: true});
+ }, {once: true});
+ };
+
+ div.addEventListener('mouseover', onMouseOver, {once: true}); */
+
+ div.dataset.stickerSet = set.id;
+ div.dataset.access_hash = set.access_hash;
+ div.dataset.title = set.title;
+
+ div.append(header, stickersDiv);
+
+ this.scrollable.append(div);
+ }
+
+ public init() {
+ appSidebarRight.selectTab(AppSidebarRight.SLIDERITEMSIDS.stickers);
+
+ appSidebarRight.toggleSidebar(true).then(() => {
+ this.renderFeatured();
+ });
+ }
+
+ public renderFeatured() {
+ return appStickersManager.getFeaturedStickers().then(coveredSets => {
+ if(this.searchInput.value) {
+ return;
+ }
+
+ coveredSets = this.filterRendered('', coveredSets);
+ coveredSets.forEach(set => {
+ this.renderSet(set.set);
+ });
+ });
+ }
+
+ private filterRendered(query: string, coveredSets: (MTStickerSetCovered | MTStickerSetMultiCovered)[]) {
+ coveredSets = coveredSets.slice();
+
+ const children = Array.from(this.setsDiv.children) as HTMLElement[];
+ children.forEachReverse(el => {
+ const id = el.dataset.stickerSet;
+ const index = coveredSets.findIndex(covered => covered.set.id == id);
+
+ if(index !== -1) {
+ coveredSets.splice(index, 1);
+ } else if(!query || !el.dataset.title.toLowerCase().includes(query.toLowerCase())) {
+ el.remove();
+ }
+ });
+
+ animationIntersector.checkAnimations(undefined, 'STICKERS-SEARCH');
+
+ return coveredSets;
+ }
+
+ public search(query: string) {
+ if(!query) {
+ return this.renderFeatured();
+ }
+
+ return appStickersManager.searchStickerSets(query, false).then(coveredSets => {
+ if(this.searchInput.value != query) {
+ return;
+ }
+
+ //console.log('search result:', coveredSets);
+
+ coveredSets = this.filterRendered(query, coveredSets);
+ coveredSets.forEach(set => {
+ this.renderSet(set.set);
+ });
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/components/wrappers.ts b/src/components/wrappers.ts
index 6b88a8c5..9203d75b 100644
--- a/src/components/wrappers.ts
+++ b/src/components/wrappers.ts
@@ -446,7 +446,7 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
}
};
- if(thumb.bytes) {
+ if(thumb.bytes || thumb.url) {
img = new Image();
if((!isSafari || doc.stickerThumbConverted)/* && false */) {
diff --git a/src/index.hbs b/src/index.hbs
index 3cbf4782..91fe23c7 100644
--- a/src/index.hbs
+++ b/src/index.hbs
@@ -672,6 +672,12 @@
+
diff --git a/src/lib/appManagers/AppInlineBotsManager.ts b/src/lib/appManagers/AppInlineBotsManager.ts
index 0b7e149b..f3b36a73 100644
--- a/src/lib/appManagers/AppInlineBotsManager.ts
+++ b/src/lib/appManagers/AppInlineBotsManager.ts
@@ -4,11 +4,99 @@ import appPeersManager from "../appManagers/appPeersManager";
import appMessagesIDsManager from "./appMessagesIDsManager";
import { RichTextProcessor } from "../richtextprocessor";
import { toast } from "../../components/toast";
+import appUsersManager, { User } from "./appUsersManager";
+import appPhotosManager, { MTPhoto } from "./appPhotosManager";
+import { MTDocument } from "../../types";
+import appDocsManager from "./appDocsManager";
+
+type botInlineResult = {
+ _: 'botInlineResult',
+ flags: number,
+ id: string,
+ type: string,
+ title?: string,
+ description?: string,
+ url?: string,
+ thumb: any,
+ content: any,
+ send_message: any
+};
+type botInlineMediaResult = {
+ _: 'botInlineMediaResult',
+ flags: number,
+ id: string,
+ type: string,
+ photo?: MTPhoto,
+ document?: MTDocument,
+ title?: string,
+ description?: string,
+ send_message: any
+};
+type BotInlineResult = (botInlineResult | botInlineMediaResult) & Partial<{
+ qID: string,
+ botID: number,
+ rTitle: string,
+ rDescription: string,
+ initials: string
+}>;
export class AppInlineBotsManager {
- /* private inlineResults: any = {};
+ private inlineResults: {[qID: string]: BotInlineResult} = {};
+
+ public getInlineResults(peerID: number, botID: number, query = '', offset = '', geo?: any) {
+ return apiManagerProxy.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
+ }, {timeout: 1, stopTime: -1, noErrorBox: true}).then((botResults: {
+ _: 'messages.botResults',
+ flags: number,
+ pFlags: Partial<{gallery: true}>,
+ query_id: string,
+ next_offset?: string,
+ switch_pm?: any,
+ results: BotInlineResult[],
+ cache_time: number,
+ users: User[]
+ }) => {
+ const 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});
+ }
+
+ botResults.results.forEach((result: BotInlineResult) => {
+ const 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 as botInlineResult).url || result.title || result.type || '').substr(0, 1);
+
+ if(result._ == 'botInlineMediaResult') {
+ if(result.document) {
+ result.document = appDocsManager.saveDoc(result.document);
+ }
+ if(result.photo) {
+ result.photo = appPhotosManager.savePhoto(result.photo);
+ }
+ }
+
+ this.inlineResults[qID] = result;
+ });
+
+ return botResults;
+ });
+ }
- function getPopularBots () {
+ /* function getPopularBots () {
return Storage.get('inline_bots_popular').then(function (bots) {
var result = []
var i, len
@@ -91,46 +179,6 @@ export class AppInlineBotsManager {
})
}
- 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] ||
diff --git a/src/lib/appManagers/appSidebarRight.ts b/src/lib/appManagers/appSidebarRight.ts
index 869f585b..b567f92e 100644
--- a/src/lib/appManagers/appSidebarRight.ts
+++ b/src/lib/appManagers/appSidebarRight.ts
@@ -18,15 +18,11 @@ import AvatarElement from "../../components/avatar";
import appForward from "../../components/appForward";
import { mediaSizes } from "../config";
import SidebarSlider, { SliderTab } from "../../components/slider";
-import appStickersManager, { MTStickerSet, MTStickerSetCovered, MTStickerSetMultiCovered } from "./appStickersManager";
-import animationIntersector from "../../components/animationIntersector";
-import PopupStickers from "../../components/popupStickers";
import SearchInput from "../../components/searchInput";
-import appPollsManager from "./appPollsManager";
-import { roundPercents } from "../../components/poll";
-import appDialogsManager from "./appDialogsManager";
-import { ripple } from "../../components/ripple";
import { horizontalMenu } from "../../components/horizontalMenu";
+import AppStickersTab from "../../components/sidebarRight/stickers";
+import AppPollResultsTab from "../../components/sidebarRight/pollResults";
+import AppGifsTab from "../../components/sidebarRight/gifs";
const testScroll = false;
@@ -44,353 +40,9 @@ let setText = (text: string, el: HTMLDivElement) => {
});
};
-class AppStickersTab implements SliderTab {
- private container = document.getElementById('stickers-container') as HTMLDivElement;
- private contentDiv = this.container.querySelector('.sidebar-content') as HTMLDivElement;
- private backBtn = this.container.querySelector('.sidebar-close-button') as HTMLButtonElement;
- //private input = this.container.querySelector('#stickers-search') as HTMLInputElement;
- private searchInput: SearchInput;
- private setsDiv = this.contentDiv.firstElementChild as HTMLDivElement;
- private scrollable: Scrollable;
- private lazyLoadQueue: LazyLoadQueue;
-
- constructor() {
- this.scrollable = new Scrollable(this.contentDiv, 'y', 'STICKERS-SEARCH', undefined, undefined, 2);
- this.scrollable.setVirtualContainer(this.setsDiv);
-
- this.lazyLoadQueue = new LazyLoadQueue();
-
- this.searchInput = new SearchInput('Search Stickers', (value) => {
- this.search(value);
- });
-
- this.backBtn.parentElement.append(this.searchInput.container);
-
- this.setsDiv.addEventListener('click', (e) => {
- const sticker = findUpClassName(e.target, 'sticker-set-sticker');
- if(sticker) {
- const docID = sticker.dataset.docID;
- appImManager.chatInputC.sendMessageWithDocument(docID);
- return;
- }
-
- const target = findUpClassName(e.target, 'sticker-set');
- if(!target) return;
-
-
- const id = target.dataset.stickerSet as string;
- const access_hash = target.dataset.stickerSet as string;
-
- const button = findUpClassName(e.target, 'sticker-set-button') as HTMLElement;
- if(button) {
- e.preventDefault();
- e.cancelBubble = true;
-
- button.setAttribute('disabled', 'true');
-
- appStickersManager.getStickerSet({id, access_hash}).then(full => {
- appStickersManager.toggleStickerSet(full.set).then(changed => {
- if(changed) {
- button.innerText = full.set.installed_date ? 'Added' : 'Add';
- button.classList.toggle('gray', !!full.set.installed_date);
- }
- }).finally(() => {
- //button.style.width = set.installed_date ? '68px' : '52px';
- button.removeAttribute('disabled');
- });
- });
- } else {
- appStickersManager.getStickerSet({id, access_hash}).then(full => {
- new PopupStickers(full.set).show();
- });
- }
- });
- }
-
- public onCloseAfterTimeout() {
- this.setsDiv.innerHTML = '';
- this.searchInput.value = '';
- animationIntersector.checkAnimations(undefined, 'STICKERS-SEARCH');
- }
-
- public renderSet(set: MTStickerSet) {
- //console.log('renderSet:', set);
- const div = document.createElement('div');
- div.classList.add('sticker-set');
-
- const header = document.createElement('div');
- header.classList.add('sticker-set-header');
-
- const details = document.createElement('div');
- details.classList.add('sticker-set-details');
- details.innerHTML = `
- ${RichTextProcessor.wrapEmojiText(set.title)}
- ${set.count} stickers
- `;
-
- const button = document.createElement('button');
- button.classList.add('btn-primary', 'sticker-set-button');
- button.innerText = set.installed_date ? 'Added' : 'Add';
- // button.style.width = set.installed_date ? '68px' : '52px';
-
- if(set.installed_date) {
- button.classList.add('gray');
- }
-
- //ripple(button);
-
- header.append(details, button);
-
- const stickersDiv = document.createElement('div');
- stickersDiv.classList.add('sticker-set-stickers');
-
- const count = Math.min(5, set.count);
- for(let i = 0; i < count; ++i) {
- const stickerDiv = document.createElement('div');
- stickerDiv.classList.add('sticker-set-sticker');
-
- stickersDiv.append(stickerDiv);
- }
-
- appStickersManager.getStickerSet(set).then(set => {
- //console.log('renderSet got set:', set);
-
- for(let i = 0; i < count; ++i) {
- const div = stickersDiv.children[i] as HTMLDivElement;
- wrapSticker({
- doc: set.documents[i],
- div,
- lazyLoadQueue: this.lazyLoadQueue,
- group: 'STICKERS-SEARCH',
- /* play: false,
- loop: false, */
- play: true,
- loop: true,
- width: 68,
- height: 68
- });
- }
- });
-
- /* const onMouseOver = () => {
- const animations: AnimationItem['animation'][] = [];
- for(let i = 0; i < count; ++i) {
- const stickerDiv = stickersDiv.children[i] as HTMLElement;
- const animationItem = animationIntersector.getAnimation(stickerDiv);
- if(!animationItem) continue;
-
- const animation = animationItem.animation;
-
- animations.push(animation);
- animation.loop = true;
- animation.play();
- }
-
- div.addEventListener('mouseout', () => {
- animations.forEach(animation => {
- animation.loop = false;
- });
-
- div.addEventListener('mouseover', onMouseOver, {once: true});
- }, {once: true});
- };
-
- div.addEventListener('mouseover', onMouseOver, {once: true}); */
-
- div.dataset.stickerSet = set.id;
- div.dataset.access_hash = set.access_hash;
- div.dataset.title = set.title;
-
- div.append(header, stickersDiv);
-
- this.scrollable.append(div);
- }
-
- public init() {
- appSidebarRight.selectTab(AppSidebarRight.SLIDERITEMSIDS.stickers);
-
- appSidebarRight.toggleSidebar(true).then(() => {
- this.renderFeatured();
- });
- }
-
- public renderFeatured() {
- return appStickersManager.getFeaturedStickers().then(coveredSets => {
- if(this.searchInput.value) {
- return;
- }
-
- coveredSets = this.filterRendered('', coveredSets);
- coveredSets.forEach(set => {
- this.renderSet(set.set);
- });
- });
- }
-
- private filterRendered(query: string, coveredSets: (MTStickerSetCovered | MTStickerSetMultiCovered)[]) {
- coveredSets = coveredSets.slice();
-
- const children = Array.from(this.setsDiv.children) as HTMLElement[];
- children.forEachReverse(el => {
- const id = el.dataset.stickerSet;
- const index = coveredSets.findIndex(covered => covered.set.id == id);
-
- if(index !== -1) {
- coveredSets.splice(index, 1);
- } else if(!query || !el.dataset.title.toLowerCase().includes(query.toLowerCase())) {
- el.remove();
- }
- });
-
- animationIntersector.checkAnimations(undefined, 'STICKERS-SEARCH');
-
- return coveredSets;
- }
-
- public search(query: string) {
- if(!query) {
- return this.renderFeatured();
- }
-
- return appStickersManager.searchStickerSets(query, false).then(coveredSets => {
- if(this.searchInput.value != query) {
- return;
- }
-
- //console.log('search result:', coveredSets);
-
- coveredSets = this.filterRendered(query, coveredSets);
- coveredSets.forEach(set => {
- this.renderSet(set.set);
- });
- });
- }
-}
-
-class AppPollResultsTab implements SliderTab {
- private container = document.getElementById('poll-results-container') as HTMLDivElement;
- private contentDiv = this.container.querySelector('.sidebar-content') as HTMLDivElement;
- private resultsDiv = this.contentDiv.firstElementChild as HTMLDivElement;
- private scrollable: Scrollable;
-
- private pollID: string;
- private mid: number;
-
- constructor() {
- this.scrollable = new Scrollable(this.contentDiv, 'y', 'POLL-RESULTS', undefined, undefined, 2);
- }
-
- public cleanup() {
- this.resultsDiv.innerHTML = '';
- this.pollID = '';
- this.mid = 0;
- }
-
- public onCloseAfterTimeout() {
- this.cleanup();
- }
-
- public init(pollID: string, mid: number) {
- if(this.pollID == pollID && this.mid == mid) return;
-
- this.cleanup();
-
- this.pollID = pollID;
- this.mid = mid;
-
- appSidebarRight.selectTab(AppSidebarRight.SLIDERITEMSIDS.pollResults);
-
- const poll = appPollsManager.getPoll(pollID);
-
- const title = document.createElement('h3');
- title.innerHTML = poll.poll.rQuestion;
-
- const percents = poll.results.results.map(v => v.voters / poll.results.total_voters * 100);
- roundPercents(percents);
-
- const fragment = document.createDocumentFragment();
- poll.results.results.forEach((result, idx) => {
- if(!result.voters) return;
-
- const hr = document.createElement('hr');
-
- const answer = poll.poll.answers[idx];
-
- // Head
- const answerEl = document.createElement('div');
- answerEl.classList.add('poll-results-answer');
-
- const answerTitle = document.createElement('div');
- answerTitle.innerHTML = RichTextProcessor.wrapEmojiText(answer.text);
-
- const answerPercents = document.createElement('div');
- answerPercents.innerText = Math.round(percents[idx]) + '%';
-
- answerEl.append(answerTitle, answerPercents);
-
- // Humans
- const list = document.createElement('ul');
- list.classList.add('poll-results-voters');
-
- appDialogsManager.setListClickListener(list);
-
- list.style.minHeight = Math.min(result.voters, 4) * 50 + 'px';
-
- fragment.append(hr, answerEl, list);
-
- let offset: string, limit = 4, loading = false, left = result.voters - 4;
- const load = () => {
- if(loading) return;
- loading = true;
-
- appPollsManager.getVotes(mid, answer.option, offset, limit).then(votesList => {
- votesList.votes.forEach(vote => {
- const {dom} = appDialogsManager.addDialog(vote.user_id, list, false, false, undefined, false);
- dom.lastMessageSpan.parentElement.remove();
- });
-
- if(offset) {
- left -= votesList.votes.length;
- (showMore.lastElementChild as HTMLElement).innerText = `Show ${Math.min(20, left)} more voter${left > 1 ? 's' : ''}`;
- }
-
- offset = votesList.next_offset;
- limit = 20;
-
- if(!left || !votesList.votes.length) {
- showMore.remove();
- }
- }).finally(() => {
- loading = false;
- });
- };
-
- load();
-
- if(left <= 0) return;
-
- const showMore = document.createElement('div');
- showMore.classList.add('poll-results-more', 'show-more');
- showMore.addEventListener('click', load);
-
- showMore.innerHTML = `Show ${Math.min(20, left)} more voter${left > 1 ? 's' : ''}
`;
- ripple(showMore);
-
- fragment.append(showMore);
- });
-
- this.resultsDiv.append(title, fragment);
-
- appSidebarRight.toggleSidebar(true).then(() => {
- /* appPollsManager.getVotes(mid).then(votes => {
- console.log('gOt VotEs', votes);
- }); */
- });
- }
-}
-
const stickersTab = new AppStickersTab();
const pollResultsTab = new AppPollResultsTab();
+const gifsTab = new AppGifsTab();
export class AppSidebarRight extends SidebarSlider {
public static SLIDERITEMSIDS = {
@@ -398,6 +50,7 @@ export class AppSidebarRight extends SidebarSlider {
forward: 2,
stickers: 3,
pollResults: 4,
+ gifs: 5,
};
public profileContainer: HTMLDivElement;
@@ -467,17 +120,20 @@ export class AppSidebarRight extends SidebarSlider {
public stickersTab: AppStickersTab;
public pollResultsTab: AppPollResultsTab;
+ public gifsTab: AppGifsTab;
constructor() {
super(document.getElementById('column-right') as HTMLElement, {
[AppSidebarRight.SLIDERITEMSIDS.stickers]: stickersTab,
[AppSidebarRight.SLIDERITEMSIDS.pollResults]: pollResultsTab,
+ [AppSidebarRight.SLIDERITEMSIDS.gifs]: gifsTab
});
//this._selectTab(3);
this.stickersTab = stickersTab;
this.pollResultsTab = pollResultsTab;
+ this.gifsTab = gifsTab;
this.profileContainer = this.sidebarEl.querySelector('.profile-container');
this.profileContentEl = this.sidebarEl.querySelector('.profile-content');
diff --git a/src/lib/appManagers/appUsersManager.ts b/src/lib/appManagers/appUsersManager.ts
index 53d7a154..83b9acf3 100644
--- a/src/lib/appManagers/appUsersManager.ts
+++ b/src/lib/appManagers/appUsersManager.ts
@@ -133,6 +133,19 @@ export class AppUsersManager {
});
}
+ public async resolveUsername(username: string) {
+ if(this.usernames[username]) {
+ return this.users[this.usernames[username]];
+ }
+
+ return await apiManager.invokeApi('contacts.resolveUsername', {username}).then(resolvedPeer => {
+ this.saveApiUser(resolvedPeer.users[0]);
+ appChatsManager.saveApiChats(resolvedPeer.chats);
+
+ return this.users[this.usernames[username]];
+ });
+ }
+
public pushContact(userID: number) {
this.contactsList.add(userID);
searchIndexManager.indexObject(userID, this.getUserSearchText(userID), this.contactsIndex);
@@ -183,9 +196,9 @@ export class AppUsersManager {
});
}
- public resolveUsername(username: string) {
+ /* public resolveUsername(username: string) {
return this.usernames[username] || 0;
- }
+ } */
public saveApiUsers(apiUsers: any[]) {
apiUsers.forEach((user) => this.saveApiUser(user));
diff --git a/src/lib/mtproto/mtproto.service.ts b/src/lib/mtproto/mtproto.service.ts
index bfcf7a80..7cc7dd64 100644
--- a/src/lib/mtproto/mtproto.service.ts
+++ b/src/lib/mtproto/mtproto.service.ts
@@ -78,7 +78,7 @@ networkerFactory.setUpdatesProcessor((obj, bool) => {
notify({update: {obj, bool}});
});
-ctx.addEventListener('message', async(e) => {
+const onMessage = async(e: ExtendableMessageEvent) => {
const taskID = e.data.taskID;
log.debug('got message:', taskID, e, e.data);
@@ -139,7 +139,9 @@ ctx.addEventListener('message', async(e) => {
//throw new Error('Unknown task: ' + e.data.task);
}
}
-});
+};
+
+ctx.onmessage = onMessage;
/**
* Service Worker Installation
@@ -195,14 +197,11 @@ function responseForSafariFirstRange(range: [number, number], mimeType: string,
return null;
}
-ctx.addEventListener('error', (error) => {
+ctx.onerror = (error) => {
log.error('error:', error);
-});
+};
-/**
- * Fetch requests
- */
-ctx.addEventListener('fetch', (event: FetchEvent): void => {
+const onFetch = (event: FetchEvent): void => {
const [, url, scope, params] = /http[:s]+\/\/.*?(\/(.*?)(?:$|\/(.*)$))/.exec(event.request.url) || [];
log.debug('[fetch]:', event);
@@ -440,11 +439,19 @@ ctx.addEventListener('fetch', (event: FetchEvent): void => {
if (url && url.endsWith('.tgs')) event.respondWith(fetchTGS(url));
else event.respondWith(fetch(event.request.url)); */
}
-});
+};
+
+/**
+ * Fetch requests
+ */
+//ctx.addEventListener('fetch', );
+ctx.onfetch = onFetch;
const DOWNLOAD_CHUNK_LIMIT = 512 * 1024;
-const STREAM_CHUNK_UPPER_LIMIT = 256 * 1024;
-const SMALLEST_CHUNK_LIMIT = 256 * 4;
+//const STREAM_CHUNK_UPPER_LIMIT = 256 * 1024;
+//const SMALLEST_CHUNK_LIMIT = 256 * 4;
+const STREAM_CHUNK_UPPER_LIMIT = 1024 * 1024;
+const SMALLEST_CHUNK_LIMIT = 1024 * 4;
function parseRange(header: string): [number, number] {
if(!header) return [0, 0];
@@ -462,3 +469,9 @@ function alignOffset(offset: number, base = SMALLEST_CHUNK_LIMIT) {
function alignLimit(limit: number) {
return 2 ** Math.ceil(Math.log(limit) / Math.log(2));
}
+
+// @ts-ignore
+if(process.env.NODE_ENV != 'production') {
+ (ctx as any).onMessage = onMessage;
+ (ctx as any).onFetch = onFetch;
+}
diff --git a/src/scss/partials/_chatBubble.scss b/src/scss/partials/_chatBubble.scss
index 3d66fe07..6e488ec1 100644
--- a/src/scss/partials/_chatBubble.scss
+++ b/src/scss/partials/_chatBubble.scss
@@ -878,7 +878,7 @@ $bubble-margin: .25rem;
padding: 0;
display: flex;
align-items: center;
- width: auto;
+ width: auto !important;
.inner {
margin-bottom: 0;
@@ -910,7 +910,7 @@ $bubble-margin: .25rem;
i {
font-size: 1.15rem;
margin-right: .4rem;
- margin-left: .1rem;
+ /* margin-left: .1rem; */
}
i.edited {
@@ -960,7 +960,8 @@ $bubble-margin: .25rem;
&.emoji-big, &.sticker {
.time {
- width: 81px !important;
+ /* width: 81px !important; */
+ min-width: unset;
}
}
}
@@ -1167,7 +1168,8 @@ $bubble-margin: .25rem;
.time {
color: #a3adb6;
- width: 36px;
+ /* width: 36px; */
+ padding-left: 36px;
.inner {
padding: 0 7px 0 5px;
diff --git a/src/scss/partials/_emojiDropdown.scss b/src/scss/partials/_emojiDropdown.scss
index e6202264..f98580c9 100644
--- a/src/scss/partials/_emojiDropdown.scss
+++ b/src/scss/partials/_emojiDropdown.scss
@@ -322,33 +322,4 @@
}
}
}
-
- #content-gifs {
- .gifs-masonry {
- display: flex;
- flex-wrap: wrap;
-
- > .gif {
- flex: 1 0 auto;
- max-width: 100%;
- height: 100px;
- margin: 2.5px;
- cursor: pointer;
- //background: #000;
- position: relative;
-
- video, img {
- object-fit: cover;
- width: 100%;
- height: 100%;
- }
-
- img {
- position: absolute;
- left: 0;
- top: 0;
- }
- }
- }
- }
}
diff --git a/src/scss/partials/_gifsMasonry.scss b/src/scss/partials/_gifsMasonry.scss
new file mode 100644
index 00000000..7a0d43e2
--- /dev/null
+++ b/src/scss/partials/_gifsMasonry.scss
@@ -0,0 +1,26 @@
+.gifs-masonry {
+ display: flex;
+ flex-wrap: wrap;
+
+ > .gif {
+ flex: 1 0 auto;
+ max-width: 100%;
+ height: 100px;
+ margin: 2.5px;
+ cursor: pointer;
+ //background: #000;
+ position: relative;
+
+ video, img {
+ object-fit: cover;
+ width: 100%;
+ height: 100%;
+ }
+
+ img {
+ position: absolute;
+ left: 0;
+ top: 0;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/scss/style.scss b/src/scss/style.scss
index bc0ec9bb..80089c68 100644
--- a/src/scss/style.scss
+++ b/src/scss/style.scss
@@ -48,6 +48,7 @@ $large-screen: 1680px;
@import "partials/scrollable";
@import "partials/slider";
@import "partials/selector";
+@import "partials/gifsMasonry";
@import "partials/popups/popup";
@import "partials/popups/editAvatar";
diff --git a/src/types.d.ts b/src/types.d.ts
index 06c6a64a..2f1b3421 100644
--- a/src/types.d.ts
+++ b/src/types.d.ts
@@ -9,6 +9,7 @@ export type MTDocument = {
mime_type: string,
size: number,
thumbs: MTPhotoSize[],
+ video_thumbs?: MTVideoSize[],
dc_id: number,
attributes: any[],
@@ -46,6 +47,8 @@ export type MTPhotoSize = {
url?: string
};
+export type MTVideoSize = Omit & {_: 'videoSize'};
+
export type InvokeApiOptions = Partial<{
dcID: number,
timeout: number,