diff --git a/src/components/popups/stickers.ts b/src/components/popups/stickers.ts index 0758156f..4651c7fd 100644 --- a/src/components/popups/stickers.ts +++ b/src/components/popups/stickers.ts @@ -5,7 +5,7 @@ */ import PopupElement from "."; -import appStickersManager from "../../lib/appManagers/appStickersManager"; +import appStickersManager, { AppStickersManager } from "../../lib/appManagers/appStickersManager"; import { RichTextProcessor } from "../../lib/richtextprocessor"; import Scrollable from "../scrollable"; import { wrapSticker } from "../wrappers"; @@ -29,11 +29,7 @@ export default class PopupStickers extends PopupElement { private set: StickerSet.stickerSet; - constructor(private stickerSetInput: { - //_: 'inputStickerSetID', - id: string, - access_hash: string - }) { + constructor(private stickerSetInput: Parameters[0]) { super('popup-stickers', null, {closable: true, overlayClosable: true, body: true}); this.h6 = document.createElement('h6'); diff --git a/src/lib/appManagers/apiUpdatesManager.ts b/src/lib/appManagers/apiUpdatesManager.ts index f70fa2b5..ee02baa4 100644 --- a/src/lib/appManagers/apiUpdatesManager.ts +++ b/src/lib/appManagers/apiUpdatesManager.ts @@ -248,7 +248,7 @@ export class ApiUpdatesManager { const promise = apiManager.invokeApi('updates.getDifference', { pts: updatesState.pts, - pts_total_limit: first/* && false */ ? 50/* 1200 */ : undefined, + pts_total_limit: first && false ? 50/* 1200 */ : undefined, date: updatesState.date, qts: -1 }, { diff --git a/src/lib/appManagers/appImManager.ts b/src/lib/appManagers/appImManager.ts index 408d7eed..5b84e9b8 100644 --- a/src/lib/appManagers/appImManager.ts +++ b/src/lib/appManagers/appImManager.ts @@ -59,6 +59,7 @@ import whichChild from '../../helpers/dom/whichChild'; import appEmojiManager from './appEmojiManager'; import PopupElement from '../../components/popups'; import singleInstance from '../mtproto/singleInstance'; +import PopupStickers from '../../components/popups/stickers'; //console.log('appImManager included33!'); @@ -223,9 +224,7 @@ export class AppImManager { stateStorage.setToCache('chatPositions', c || {}); }); - (window as any).showMaskedAlert = (element: HTMLAnchorElement, e: Event) => { - cancelEvent(null); - + this.addAnchorListener('showMaskedAlert', (params, element) => { const href = element.href; const a = element.cloneNode(true) as HTMLAnchorElement; @@ -244,19 +243,9 @@ export class AppImManager { }, }] }).show(); + }, false); - return false; - }; - - (window as any).execBotCommand = (element: HTMLAnchorElement, e: Event) => { - cancelEvent(null); - - const href = element.href; - const params = this.parseUriParams(href); - if(!params) { - return; - } - + this.addAnchorListener('execBotCommand', (params) => { const {command, bot} = params; /* const promise = bot ? this.openUsername(bot).then(() => this.chat.peerId) : Promise.resolve(this.chat.peerId); @@ -267,23 +256,35 @@ export class AppImManager { appMessagesManager.sendText(this.chat.peerId, '/' + command + (bot ? '@' + bot : '')); //console.log(command, bot); + }); - return false; - }; - - (window as any).searchByHashtag = (element: HTMLAnchorElement, e: Event) => { - cancelEvent(null); - - const href = element.href; - const params = this.parseUriParams(href); + this.addAnchorListener('searchByHashtag', (params) => { if(!params) { return; } const {hashtag} = params; this.chat.initSearch('#' + hashtag + ' '); + }); - return false; + this.addAnchorListener('addstickers', (params) => { + new PopupStickers({id: params[1]}).show(); + }, true); + } + + private addAnchorListener(name: 'showMaskedAlert' | 'execBotCommand' | 'searchByHashtag' | 'addstickers', + callback: (params: any, element: HTMLAnchorElement) => boolean | void, parseParams = true) { + (window as any)[name] = (element: HTMLAnchorElement, e: Event) => { + cancelEvent(null); + + const href = element.href; + let params: any; + if(parseParams) { + params = !element.href.includes('#') ? new URL(element.href).pathname.split('/').slice(1) : this.parseUriParams(href); + } + + const res = callback(params, element); + return res === undefined ? res : false; }; } diff --git a/src/lib/appManagers/appStickersManager.ts b/src/lib/appManagers/appStickersManager.ts index d91873e6..16f62593 100644 --- a/src/lib/appManagers/appStickersManager.ts +++ b/src/lib/appManagers/appStickersManager.ts @@ -16,6 +16,11 @@ import DATABASE_STATE from '../../config/databases/state'; const CACHE_TIME = 3600e3; +export type MyStickerSetInput = { + id: string, + access_hash?: string +}; + export class AppStickersManager { private storage = new AppStorage, typeof DATABASE_STATE>(DATABASE_STATE, 'stickerSets'); @@ -23,7 +28,7 @@ export class AppStickersManager { private getStickersByEmoticonsPromises: {[emoticon: string]: Promise} = {}; constructor() { - this.getStickerSet({id: 'emoji', access_hash: ''}); + this.getStickerSet({id: 'emoji'}, {saveById: true}); rootScope.addMultipleEventsListeners({ updateNewStickerSet: (update) => { @@ -42,24 +47,23 @@ export class AppStickersManager { }); } - public async getStickerSet(set: { - id: string, - access_hash: string - }, params: Partial<{ + public async getStickerSet(set: MyStickerSetInput, params: Partial<{ overwrite: boolean, - useCache: boolean + useCache: boolean, + saveById: boolean }> = {}): Promise { - if(this.getStickerSetPromises[set.id]) { - return this.getStickerSetPromises[set.id]; + const id = set.id; + if(this.getStickerSetPromises[id]) { + return this.getStickerSetPromises[id]; } - return this.getStickerSetPromises[set.id] = new Promise(async(resolve) => { + return this.getStickerSetPromises[id] = new Promise(async(resolve) => { if(!params.overwrite) { - const cachedSet = await this.storage.get(set.id); + const cachedSet = await this.storage.get(id); if(cachedSet && cachedSet.documents?.length && ((Date.now() - cachedSet.refreshTime) < CACHE_TIME || params.useCache)) { this.saveStickers(cachedSet.documents); resolve(cachedSet); - delete this.getStickerSetPromises[set.id]; + delete this.getStickerSetPromises[id]; return; } } @@ -69,14 +73,15 @@ export class AppStickersManager { stickerset: this.getStickerSetInput(set) }); - this.saveStickerSet(stickerSet, set.id); + const saveById = params.saveById ? id : stickerSet.set.id; + this.saveStickerSet(stickerSet, saveById); resolve(stickerSet); } catch(err) { resolve(null); } - delete this.getStickerSetPromises[set.id]; + delete this.getStickerSetPromises[id]; }); } @@ -158,14 +163,23 @@ export class AppStickersManager { //return promise; } */ - public getStickerSetInput(set: {id: string, access_hash: string}): InputStickerSet { - return set.id === 'emoji' ? { - _: 'inputStickerSetAnimatedEmoji' - } : { - _: 'inputStickerSetID', - id: set.id, - access_hash: set.access_hash - }; + public getStickerSetInput(set: MyStickerSetInput): InputStickerSet { + if(set.id === 'emoji') { + return { + _: 'inputStickerSetAnimatedEmoji' + }; + } else if(!set.access_hash) { + return { + _: 'inputStickerSetShortName', + short_name: set.id + }; + } else { + return { + _: 'inputStickerSetID', + id: set.id, + access_hash: set.access_hash + }; + } } public async getFeaturedStickers() { diff --git a/src/lib/idb.ts b/src/lib/idb.ts index 28b83aeb..ca5707b4 100644 --- a/src/lib/idb.ts +++ b/src/lib/idb.ts @@ -354,6 +354,10 @@ export default class IDBStorage> { return this.openDatabase().then((db) => { return new Promise((resolve, reject) => { + /* if(mode === 'readwrite') { + return; + } */ + const transaction = db.transaction([storeName], mode); transaction.onerror = (e) => { diff --git a/src/lib/richtextprocessor.ts b/src/lib/richtextprocessor.ts index bd00a776..dd5586ba 100644 --- a/src/lib/richtextprocessor.ts +++ b/src/lib/richtextprocessor.ts @@ -573,12 +573,15 @@ namespace RichTextProcessor { const entityText = text.substr(entity.offset, entity.length); // let inner: string; - let url: string; + let url: string = (entity as MessageEntity.messageEntityTextUrl).url || entityText; let masked = false; - if(entity._ === 'messageEntityTextUrl') { - url = (entity as MessageEntity.messageEntityTextUrl).url; - url = wrapUrl(url, true); + let onclick: string; + + const wrapped = wrapUrl(url, true); + url = wrapped.url; + onclick = wrapped.onclick; + if(entity._ === 'messageEntityTextUrl') { const nextEntity = entities[i + 1]; if(nextEntity?._ === 'messageEntityUrl' && nextEntity.length === entity.length && @@ -590,11 +593,13 @@ namespace RichTextProcessor { masked = true; } } else { - url = wrapUrl(entityText, false); //inner = encodeEntities(replaceUrlEncodings(entityText)); } const currentContext = url[0] === '#'; + if(!onclick && masked && !currentContext) { + onclick = 'showMaskedAlert'; + } const href = (currentContext || typeof electronHelpers === 'undefined') ? encodeEntities(url) @@ -603,7 +608,7 @@ namespace RichTextProcessor { const target = (currentContext || typeof electronHelpers !== 'undefined') ? '' : ' target="_blank" rel="noopener noreferrer"'; - insertPart(entity, ``, ''); + insertPart(entity, ``, ''); } break; @@ -789,13 +794,14 @@ namespace RichTextProcessor { return wrapRichText(text, {entities}); } - export function wrapUrl(url: string, unsafe?: number | boolean): string { + export function wrapUrl(url: string, unsafe?: number | boolean): {url: string, onclick: string} { if(!matchUrlProtocol(url)) { url = 'https://' + url; } let tgMeMatch; let telescoPeMatch; + let onclick: string; /* if(unsafe === 2) { url = 'tg://unsafe_url?url=' + encodeURIComponent(url); } else */if((tgMeMatch = url.match(/^(?:https?:\/\/)?t(?:elegram)?\.me\/(.+)/))) { @@ -803,12 +809,19 @@ namespace RichTextProcessor { const path = fullPath.split('/'); switch(path[0]) { case 'joinchat': + case 'addstickers': + onclick = path[0]; + break; + + /* case 'joinchat': + onclick = 'joinchat'; url = 'tg://join?invite=' + path[1]; break; case 'addstickers': + onclick = 'addstickers'; url = 'tg://addstickers?set=' + path[1]; - break; + break; */ default: if(path[1] && path[1].match(/^\d+$/)) { // https://t.me/.+/[0-9]+ (channel w/ username) @@ -846,7 +859,7 @@ namespace RichTextProcessor { url = 'tg://unsafe_url?url=' + encodeURIComponent(url); } */ - return url; + return {url, onclick}; } export function matchUrlProtocol(text: string) {