Stickers and Emoji tab
Stickers sorting Stickers suggestion options Group creation without members Fix voting in polls Fix processing autocomplete on settings change
This commit is contained in:
parent
bb6cda7de5
commit
2408333c47
|
@ -689,7 +689,8 @@ export default class Chat extends EventListenerBase<{
|
|||
replyToMsgId: this.input.replyToMsgId,
|
||||
scheduleDate: this.input.scheduleDate,
|
||||
silent: this.input.sendSilent,
|
||||
sendAsPeerId: this.input.sendAsPeerId
|
||||
sendAsPeerId: this.input.sendAsPeerId,
|
||||
updateStickersetOrder: rootScope.settings.stickers.dynamicPackOrder
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -2277,7 +2277,8 @@ export default class ChatInput {
|
|||
private async checkAutocomplete(value?: string, caretPos?: number, entities?: MessageEntity[]) {
|
||||
// return;
|
||||
|
||||
if(value === undefined) {
|
||||
const hadValue = value !== undefined;
|
||||
if(!hadValue) {
|
||||
const r = getRichValueWithCaret(this.messageInputField.input, true, true);
|
||||
value = r.value;
|
||||
caretPos = r.caretPos;
|
||||
|
@ -2288,7 +2289,7 @@ export default class ChatInput {
|
|||
caretPos = value.length;
|
||||
}
|
||||
|
||||
if(entities === undefined) {
|
||||
if(entities === undefined || !hadValue) {
|
||||
const _value = parseMarkdown(value, entities, true);
|
||||
entities = mergeEntities(entities, parseEntities(_value));
|
||||
}
|
||||
|
@ -2310,7 +2311,7 @@ export default class ChatInput {
|
|||
const firstChar = query[0];
|
||||
|
||||
if(this.stickersHelper &&
|
||||
rootScope.settings.stickers.suggest &&
|
||||
rootScope.settings.stickers.suggest !== 'none' &&
|
||||
await this.chat.canSend('send_stickers') &&
|
||||
entity?._ === 'messageEntityEmoji' && entity.length === value.length && !entity.offset) {
|
||||
foundHelper = this.stickersHelper;
|
||||
|
@ -2731,7 +2732,7 @@ export default class ChatInput {
|
|||
}
|
||||
|
||||
private getValueAndEntities(input: HTMLElement) {
|
||||
const {entities: apiEntities, value} = getRichValueWithCaret(this.messageInput, true, false);
|
||||
const {entities: apiEntities, value} = getRichValueWithCaret(input, true, false);
|
||||
const myEntities = parseEntities(value);
|
||||
const totalEntities = mergeEntities(apiEntities, myEntities);
|
||||
|
||||
|
|
|
@ -68,12 +68,10 @@ export default class StickersHelper extends AutocompleteHelper {
|
|||
public checkEmoticon(emoticon: string) {
|
||||
const middleware = this.controller.getMiddleware();
|
||||
|
||||
if(this.lazyLoadQueue) {
|
||||
this.lazyLoadQueue.clear();
|
||||
}
|
||||
this.lazyLoadQueue?.clear();
|
||||
|
||||
preloadAnimatedEmojiSticker(emoticon);
|
||||
this.managers.appStickersManager.getStickersByEmoticon(emoticon)
|
||||
this.managers.appStickersManager.getStickersByEmoticon(emoticon, true, rootScope.settings.stickers.suggest === 'all')
|
||||
.then((stickers) => {
|
||||
if(!middleware()) {
|
||||
return;
|
||||
|
|
|
@ -789,6 +789,19 @@ export default class StickersTab extends EmoticonsTabC<StickersTabCategory<Stick
|
|||
}
|
||||
}));
|
||||
|
||||
rootScope.addEventListener('stickers_order', ({type, order}) => {
|
||||
if(type !== 'stickers') {
|
||||
return;
|
||||
}
|
||||
|
||||
order.forEach((id) => {
|
||||
const category = this.categories[id];
|
||||
if(category) {
|
||||
this.positionCategory(category, false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
rootScope.addEventListener('stickers_updated', ({type, stickers}) => {
|
||||
const category = this.categories[type === 'faved' ? 'faved' : 'recent'];
|
||||
if(category) {
|
||||
|
|
|
@ -479,7 +479,7 @@ export default class PollElement extends HTMLElement {
|
|||
}
|
||||
}
|
||||
|
||||
clickHandler(e: Event) {
|
||||
clickHandler = (e: Event) => {
|
||||
const target = findUpClassName(e.target, 'poll-answer') as HTMLElement;
|
||||
if(!target) {
|
||||
return;
|
||||
|
@ -505,7 +505,7 @@ export default class PollElement extends HTMLElement {
|
|||
this.setResults([100, 0], answerIndex);
|
||||
target.classList.remove('is-voting');
|
||||
}, 1000); */
|
||||
}
|
||||
};
|
||||
|
||||
sendVotes(indexes: number[]) {
|
||||
if(this.sendVotePromise) return this.sendVotePromise;
|
||||
|
|
|
@ -97,7 +97,7 @@ export class AppSidebarLeft extends SidebarSlider {
|
|||
const onNewGroupClick = () => {
|
||||
this.createTab(AppAddMembersTab).open({
|
||||
type: 'chat',
|
||||
skippable: false,
|
||||
skippable: true,
|
||||
takeOut: (peerIds) => this.createTab(AppNewGroupTab).open(peerIds),
|
||||
title: 'GroupAddMembers',
|
||||
placeholder: 'SendMessageTo'
|
||||
|
|
|
@ -34,7 +34,7 @@ export default class AppAddMembersTab extends SliderSuperTab {
|
|||
const peerIds = this.selector.getSelected().map((sel) => sel.toPeerId());
|
||||
const result = this.takeOut(peerIds);
|
||||
|
||||
if(this.skippable) {
|
||||
if(this.skippable && !(result instanceof Promise)) {
|
||||
this.close();
|
||||
} else if(result instanceof Promise) {
|
||||
this.attachToPromise(result);
|
||||
|
|
|
@ -98,9 +98,7 @@ export class RangeSettingSelector {
|
|||
export default class AppGeneralSettingsTab extends SliderSuperTabEventable {
|
||||
public static getInitArgs() {
|
||||
return {
|
||||
themes: rootScope.managers.appThemesManager.getThemes(),
|
||||
allStickers: rootScope.managers.appStickersManager.getAllStickers(),
|
||||
quickReaction: rootScope.managers.appReactionsManager.getQuickReaction()
|
||||
themes: rootScope.managers.appThemesManager.getThemes()
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -529,140 +527,6 @@ export default class AppGeneralSettingsTab extends SliderSuperTabEventable {
|
|||
container.append(form);
|
||||
}
|
||||
|
||||
{
|
||||
const container = section('Emoji');
|
||||
|
||||
const suggestCheckboxField = new CheckboxField({
|
||||
text: 'GeneralSettings.EmojiPrediction',
|
||||
name: 'suggest-emoji',
|
||||
stateKey: 'settings.emoji.suggest',
|
||||
listenerSetter: this.listenerSetter
|
||||
});
|
||||
const bigCheckboxField = new CheckboxField({
|
||||
text: 'GeneralSettings.BigEmoji',
|
||||
name: 'emoji-big',
|
||||
stateKey: 'settings.emoji.big',
|
||||
listenerSetter: this.listenerSetter
|
||||
});
|
||||
|
||||
container.append(
|
||||
CreateRowFromCheckboxField(suggestCheckboxField).container,
|
||||
CreateRowFromCheckboxField(bigCheckboxField).container
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
const section = new SettingSection({name: 'Telegram.InstalledStickerPacksController', caption: 'StickersBotInfo'});
|
||||
|
||||
const reactionsRow = new Row({
|
||||
titleLangKey: 'DoubleTapSetting',
|
||||
havePadding: true,
|
||||
clickable: () => {
|
||||
this.slider.createTab(AppQuickReactionTab).open();
|
||||
},
|
||||
listenerSetter: this.listenerSetter
|
||||
});
|
||||
|
||||
const renderQuickReaction = () => {
|
||||
p.quickReaction.then((reaction) => {
|
||||
if(reaction._ === 'availableReaction') {
|
||||
return reaction.static_icon;
|
||||
} else {
|
||||
return this.managers.appEmojiManager.getCustomEmojiDocument(reaction.document_id);
|
||||
}
|
||||
}).then((doc) => {
|
||||
wrapStickerToRow({
|
||||
row: reactionsRow,
|
||||
doc,
|
||||
size: 'small'
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
renderQuickReaction();
|
||||
|
||||
this.listenerSetter.add(rootScope)('quick_reaction', renderQuickReaction);
|
||||
|
||||
const suggestCheckboxField = new CheckboxField({
|
||||
text: 'Stickers.SuggestStickers',
|
||||
name: 'suggest',
|
||||
stateKey: 'settings.stickers.suggest',
|
||||
listenerSetter: this.listenerSetter
|
||||
});
|
||||
const loopCheckboxField = new CheckboxField({
|
||||
text: 'InstalledStickers.LoopAnimated',
|
||||
name: 'loop',
|
||||
stateKey: 'settings.stickers.loop',
|
||||
listenerSetter: this.listenerSetter
|
||||
});
|
||||
|
||||
const stickerSets: {[id: string]: Row} = {};
|
||||
|
||||
const stickersContent = section.generateContentElement();
|
||||
|
||||
const lazyLoadQueue = new LazyLoadQueue();
|
||||
const renderStickerSet = (stickerSet: StickerSet.stickerSet, method: 'append' | 'prepend' = 'append') => {
|
||||
const row = new Row({
|
||||
title: wrapEmojiText(stickerSet.title),
|
||||
subtitleLangKey: 'Stickers',
|
||||
subtitleLangArgs: [stickerSet.count],
|
||||
havePadding: true,
|
||||
clickable: () => {
|
||||
new PopupStickers({id: stickerSet.id, access_hash: stickerSet.access_hash}).show();
|
||||
},
|
||||
listenerSetter: this.listenerSetter
|
||||
});
|
||||
|
||||
stickerSets[stickerSet.id] = row;
|
||||
|
||||
const div = document.createElement('div');
|
||||
div.classList.add('row-media');
|
||||
|
||||
wrapStickerSetThumb({
|
||||
set: stickerSet,
|
||||
container: div,
|
||||
group: 'GENERAL-SETTINGS',
|
||||
lazyLoadQueue,
|
||||
width: 36,
|
||||
height: 36,
|
||||
autoplay: true,
|
||||
middleware: this.middlewareHelper.get()
|
||||
});
|
||||
|
||||
row.container.append(div);
|
||||
|
||||
stickersContent[method](row.container);
|
||||
};
|
||||
|
||||
const promise = p.allStickers.then((allStickers) => {
|
||||
assumeType<MessagesAllStickers.messagesAllStickers>(allStickers);
|
||||
const promises = allStickers.sets.map((stickerSet) => renderStickerSet(stickerSet));
|
||||
return Promise.all(promises);
|
||||
});
|
||||
|
||||
promises.push(promise);
|
||||
|
||||
this.listenerSetter.add(rootScope)('stickers_installed', (set) => {
|
||||
if(!stickerSets[set.id]) {
|
||||
renderStickerSet(set, 'prepend');
|
||||
}
|
||||
});
|
||||
|
||||
this.listenerSetter.add(rootScope)('stickers_deleted', (set) => {
|
||||
if(stickerSets[set.id]) {
|
||||
stickerSets[set.id].container.remove();
|
||||
delete stickerSets[set.id];
|
||||
}
|
||||
});
|
||||
|
||||
section.content.append(
|
||||
reactionsRow.container,
|
||||
CreateRowFromCheckboxField(suggestCheckboxField).container,
|
||||
CreateRowFromCheckboxField(loopCheckboxField).container
|
||||
);
|
||||
this.scrollable.append(section.container);
|
||||
}
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import appDialogsManager from '../../../lib/appManagers/appDialogsManager';
|
|||
import InputField from '../../inputField';
|
||||
import {SliderSuperTab} from '../../slider';
|
||||
import AvatarEdit from '../../avatarEdit';
|
||||
import I18n from '../../../lib/langPack';
|
||||
import I18n, {joinElementsWith} from '../../../lib/langPack';
|
||||
import ButtonCorner from '../../buttonCorner';
|
||||
import getUserStatusString from '../../wrappers/getUserStatusString';
|
||||
import appImManager from '../../../lib/appManagers/appImManager';
|
||||
|
@ -141,6 +141,10 @@ export default class AppNewGroupTab extends SliderSuperTab {
|
|||
nameArgs: [this.peerIds.length]
|
||||
});
|
||||
|
||||
if(!this.peerIds.length) {
|
||||
chatsSection.container.classList.add('hide');
|
||||
}
|
||||
|
||||
const list = this.list = appDialogsManager.createChatList({
|
||||
new: true
|
||||
});
|
||||
|
@ -161,16 +165,34 @@ export default class AppNewGroupTab extends SliderSuperTab {
|
|||
this.groupLocationInputField.container.classList.add('hide');
|
||||
}
|
||||
|
||||
return Promise.all(this.peerIds.map(async(userId) => {
|
||||
const {dom} = appDialogsManager.addDialogNew({
|
||||
peerId: userId,
|
||||
container: this.list,
|
||||
rippleEnabled: false,
|
||||
avatarSize: 'abitbigger'
|
||||
});
|
||||
const usersPromise = Promise.all(this.peerIds.map((peerId) => this.managers.appUsersManager.getUser(peerId.toUserId())));
|
||||
const myUserPromise = this.managers.appUsersManager.getSelf();
|
||||
|
||||
dom.lastMessageSpan.append(getUserStatusString(await this.managers.appUsersManager.getUser(userId)));
|
||||
}));
|
||||
const a = usersPromise.then((users) => {
|
||||
return users.map((user) => {
|
||||
const {dom} = appDialogsManager.addDialogNew({
|
||||
peerId: user.id.toPeerId(false),
|
||||
container: this.list,
|
||||
rippleEnabled: false,
|
||||
avatarSize: 'abitbigger'
|
||||
});
|
||||
|
||||
dom.lastMessageSpan.append(getUserStatusString(user));
|
||||
})
|
||||
});
|
||||
|
||||
const setTitlePromise = this.peerIds.length > 0 && this.peerIds.length < 5 ? Promise.all([usersPromise, myUserPromise]).then(([users, myUser]) => {
|
||||
const names = users.map((user) => [user.first_name, user.last_name].filter(Boolean).join(' '));
|
||||
names.unshift(myUser.first_name);
|
||||
|
||||
const joined = joinElementsWith(names, (isLast) => isLast ? ', ' : ' & ').join('');
|
||||
this.groupNameInputField.setDraftValue(joined);
|
||||
}) : Promise.resolve();
|
||||
|
||||
return Promise.all([
|
||||
a,
|
||||
setTitlePromise
|
||||
]);
|
||||
}
|
||||
|
||||
public onCloseAfterTimeout() {
|
||||
|
|
|
@ -28,6 +28,7 @@ import {AccountAuthorizations, Authorization} from '../../../layer';
|
|||
import PopupElement from '../../popups';
|
||||
import {attachClickEvent} from '../../../helpers/dom/clickEvent';
|
||||
import SettingSection from '../../settingSection';
|
||||
import AppStickersAndEmojiTab from './stickersAndEmoji';
|
||||
|
||||
export default class AppSettingsTab extends SliderSuperTab {
|
||||
private buttons: {
|
||||
|
@ -192,7 +193,8 @@ export default class AppSettingsTab extends SliderSuperTab {
|
|||
m('data', 'DataSettings', AppDataAndStorageTab),
|
||||
m('lock', 'AccountSettings.PrivacyAndSecurity', AppPrivacyAndSecurityTab),
|
||||
m('settings', 'Telegram.GeneralSettingsViewController', AppGeneralSettingsTab),
|
||||
m('folder', 'AccountSettings.Filters', AppChatFoldersTab)
|
||||
m('folder', 'AccountSettings.Filters', AppChatFoldersTab),
|
||||
m('stickers_face', 'StickersName', AppStickersAndEmojiTab)
|
||||
];
|
||||
|
||||
const rows = b.map((item) => {
|
||||
|
|
|
@ -0,0 +1,301 @@
|
|||
/*
|
||||
* https://github.com/morethanwords/tweb
|
||||
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import forEachReverse from '../../../helpers/array/forEachReverse';
|
||||
import assumeType from '../../../helpers/assumeType';
|
||||
import createContextMenu from '../../../helpers/dom/createContextMenu';
|
||||
import positionElementByIndex from '../../../helpers/dom/positionElementByIndex';
|
||||
import Sortable from '../../../helpers/dom/sortable';
|
||||
import {StickerSet, MessagesAllStickers} from '../../../layer';
|
||||
import {i18n, LangPackKey} from '../../../lib/langPack';
|
||||
import wrapEmojiText from '../../../lib/richTextProcessor/wrapEmojiText';
|
||||
import rootScope from '../../../lib/rootScope';
|
||||
import CheckboxField from '../../checkboxField';
|
||||
import LazyLoadQueue from '../../lazyLoadQueue';
|
||||
import PopupStickers from '../../popups/stickers';
|
||||
import Row, {CreateRowFromCheckboxField} from '../../row';
|
||||
import SettingSection from '../../settingSection';
|
||||
import SliderSuperTab from '../../sliderTab';
|
||||
import wrapStickerSetThumb from '../../wrappers/stickerSetThumb';
|
||||
import wrapStickerToRow from '../../wrappers/stickerToRow';
|
||||
import AppQuickReactionTab from './quickReaction';
|
||||
|
||||
export default class AppStickersAndEmojiTab extends SliderSuperTab {
|
||||
public static getInitArgs() {
|
||||
return {
|
||||
allStickers: rootScope.managers.appStickersManager.getAllStickers(),
|
||||
quickReaction: rootScope.managers.appReactionsManager.getQuickReaction()
|
||||
};
|
||||
}
|
||||
|
||||
public init(p: ReturnType<typeof AppStickersAndEmojiTab['getInitArgs']>) {
|
||||
this.container.classList.add('stickers-emoji-container');
|
||||
this.setTitle('StickersName');
|
||||
|
||||
const promises: Promise<any>[] = [];
|
||||
|
||||
{
|
||||
const section = new SettingSection({caption: 'LoopAnimatedStickersInfo'});
|
||||
|
||||
const suggestStickersRow = new Row({
|
||||
icon: 'lamp',
|
||||
titleLangKey: 'Stickers.SuggestStickers',
|
||||
clickable: true,
|
||||
listenerSetter: this.listenerSetter,
|
||||
titleRightSecondary: true
|
||||
});
|
||||
|
||||
const map: {[k in typeof rootScope.settings.stickers.suggest]: LangPackKey} = {
|
||||
all: 'SuggestStickersAll',
|
||||
installed: 'SuggestStickersInstalled',
|
||||
none: 'SuggestStickersNone'
|
||||
};
|
||||
|
||||
const setStickersSuggestDescription = () => {
|
||||
suggestStickersRow.titleRight.replaceChildren(i18n(map[rootScope.settings.stickers.suggest]));
|
||||
};
|
||||
|
||||
setStickersSuggestDescription();
|
||||
|
||||
const setStickersSuggest = (value: typeof rootScope.settings.stickers.suggest) => {
|
||||
if(rootScope.settings.stickers.suggest === value) return;
|
||||
rootScope.settings.stickers.suggest = value;
|
||||
setStickersSuggestDescription();
|
||||
return this.managers.appStateManager.setByKey('settings.stickers.suggest', value);
|
||||
};
|
||||
|
||||
createContextMenu({
|
||||
buttons: [{
|
||||
icon: 'stickers_face',
|
||||
text: 'SuggestStickersAll',
|
||||
onClick: setStickersSuggest.bind(this, 'all')
|
||||
}, {
|
||||
icon: 'newprivate',
|
||||
text: 'SuggestStickersInstalled',
|
||||
onClick: setStickersSuggest.bind(this, 'installed')
|
||||
}, {
|
||||
icon: 'stop',
|
||||
text: 'SuggestStickersNone',
|
||||
onClick: setStickersSuggest.bind(this, 'none')
|
||||
}],
|
||||
listenTo: suggestStickersRow.container,
|
||||
middleware: this.middlewareHelper.get(),
|
||||
listenForClick: true
|
||||
});
|
||||
|
||||
const reactionsRow = new Row({
|
||||
titleLangKey: 'DoubleTapSetting',
|
||||
havePadding: true,
|
||||
clickable: () => {
|
||||
this.slider.createTab(AppQuickReactionTab).open();
|
||||
},
|
||||
listenerSetter: this.listenerSetter
|
||||
});
|
||||
|
||||
const renderQuickReaction = () => {
|
||||
p.quickReaction.then((reaction) => {
|
||||
if(reaction._ === 'availableReaction') {
|
||||
return reaction.static_icon;
|
||||
} else {
|
||||
return this.managers.appEmojiManager.getCustomEmojiDocument(reaction.document_id);
|
||||
}
|
||||
}).then((doc) => {
|
||||
wrapStickerToRow({
|
||||
row: reactionsRow,
|
||||
doc,
|
||||
size: 'small'
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
renderQuickReaction();
|
||||
|
||||
this.listenerSetter.add(rootScope)('quick_reaction', () => {
|
||||
p = AppStickersAndEmojiTab.getInitArgs();
|
||||
renderQuickReaction();
|
||||
});
|
||||
|
||||
const loopStickersRow = new Row({
|
||||
icon: 'flip',
|
||||
titleLangKey: 'InstalledStickers.LoopAnimated',
|
||||
checkboxField: new CheckboxField({
|
||||
name: 'loop',
|
||||
stateKey: 'settings.stickers.loop',
|
||||
listenerSetter: this.listenerSetter,
|
||||
toggle: true
|
||||
}),
|
||||
listenerSetter: this.listenerSetter
|
||||
});
|
||||
|
||||
section.content.append(
|
||||
reactionsRow.container,
|
||||
suggestStickersRow.container,
|
||||
loopStickersRow.container
|
||||
);
|
||||
|
||||
this.scrollable.append(section.container);
|
||||
}
|
||||
|
||||
{
|
||||
const section = new SettingSection({name: 'Emoji'});
|
||||
|
||||
const suggestEmojiRow = new Row({
|
||||
icon: 'lamp',
|
||||
titleLangKey: 'GeneralSettings.EmojiPrediction',
|
||||
checkboxField: new CheckboxField({
|
||||
name: 'suggest-emoji',
|
||||
stateKey: 'settings.emoji.suggest',
|
||||
listenerSetter: this.listenerSetter,
|
||||
toggle: true
|
||||
}),
|
||||
listenerSetter: this.listenerSetter
|
||||
});
|
||||
const bigEmojiRow = new Row({
|
||||
icon: 'smile',
|
||||
titleLangKey: 'GeneralSettings.BigEmoji',
|
||||
checkboxField: new CheckboxField({
|
||||
name: 'emoji-big',
|
||||
stateKey: 'settings.emoji.big',
|
||||
listenerSetter: this.listenerSetter,
|
||||
toggle: true
|
||||
}),
|
||||
listenerSetter: this.listenerSetter
|
||||
});
|
||||
|
||||
section.content.append(
|
||||
suggestEmojiRow.container,
|
||||
bigEmojiRow.container
|
||||
);
|
||||
|
||||
this.scrollable.append(section.container);
|
||||
}
|
||||
|
||||
{
|
||||
const section = new SettingSection({name: 'DynamicPackOrder', caption: 'DynamicPackOrderInfo'});
|
||||
|
||||
const dynamicPackOrderRow = new Row({
|
||||
titleLangKey: 'DynamicPackOrder',
|
||||
checkboxField: new CheckboxField({
|
||||
name: 'dynamic-pack-order',
|
||||
stateKey: 'settings.stickers.dynamicPackOrder',
|
||||
listenerSetter: this.listenerSetter,
|
||||
toggle: true
|
||||
}),
|
||||
listenerSetter: this.listenerSetter
|
||||
});
|
||||
|
||||
section.content.append(
|
||||
dynamicPackOrderRow.container
|
||||
);
|
||||
|
||||
this.scrollable.append(section.container);
|
||||
}
|
||||
|
||||
{
|
||||
const section = new SettingSection({name: 'Telegram.InstalledStickerPacksController', caption: 'StickersBotInfo'});
|
||||
|
||||
const stickerSets: {[id: string]: Row} = {};
|
||||
|
||||
const stickersContent = section.generateContentElement();
|
||||
|
||||
const lazyLoadQueue = new LazyLoadQueue();
|
||||
const renderStickerSet = (stickerSet: StickerSet.stickerSet, method: 'append' | 'prepend' = 'append') => {
|
||||
const row = new Row({
|
||||
title: wrapEmojiText(stickerSet.title),
|
||||
subtitleLangKey: 'Stickers',
|
||||
subtitleLangArgs: [stickerSet.count],
|
||||
havePadding: true,
|
||||
clickable: () => {
|
||||
new PopupStickers({id: stickerSet.id, access_hash: stickerSet.access_hash}).show();
|
||||
},
|
||||
listenerSetter: this.listenerSetter
|
||||
});
|
||||
|
||||
row.container.dataset.id = '' + stickerSet.id;
|
||||
|
||||
row.makeSortable();
|
||||
|
||||
stickerSets[stickerSet.id] = row;
|
||||
|
||||
const div = document.createElement('div');
|
||||
div.classList.add('row-media');
|
||||
|
||||
wrapStickerSetThumb({
|
||||
set: stickerSet,
|
||||
container: div,
|
||||
group: 'GENERAL-SETTINGS',
|
||||
lazyLoadQueue,
|
||||
width: 36,
|
||||
height: 36,
|
||||
autoplay: true,
|
||||
middleware: this.middlewareHelper.get()
|
||||
});
|
||||
|
||||
row.container.append(div);
|
||||
|
||||
stickersContent[method](row.container);
|
||||
};
|
||||
|
||||
const promise = p.allStickers.then((allStickers) => {
|
||||
assumeType<MessagesAllStickers.messagesAllStickers>(allStickers);
|
||||
const promises = allStickers.sets.map((stickerSet) => renderStickerSet(stickerSet));
|
||||
return Promise.all(promises);
|
||||
});
|
||||
|
||||
promises.push(promise);
|
||||
|
||||
this.listenerSetter.add(rootScope)('stickers_installed', (set) => {
|
||||
if(!stickerSets[set.id]) {
|
||||
renderStickerSet(set, 'prepend');
|
||||
}
|
||||
});
|
||||
|
||||
this.listenerSetter.add(rootScope)('stickers_deleted', (set) => {
|
||||
if(stickerSets[set.id]) {
|
||||
stickerSets[set.id].container.remove();
|
||||
delete stickerSets[set.id];
|
||||
}
|
||||
});
|
||||
|
||||
this.listenerSetter.add(rootScope)('stickers_order', ({type, order}) => {
|
||||
if(type !== 'stickers') {
|
||||
return;
|
||||
}
|
||||
|
||||
order.forEach((id, idx) => {
|
||||
const row = stickerSets[id];
|
||||
if(!row) {
|
||||
return;
|
||||
}
|
||||
|
||||
positionElementByIndex(row.container, stickersContent, idx)
|
||||
});
|
||||
});
|
||||
|
||||
this.listenerSetter.add(rootScope)('stickers_top', (id) => {
|
||||
const row = stickerSets[id];
|
||||
if(!row) {
|
||||
return;
|
||||
}
|
||||
|
||||
positionElementByIndex(row.container, stickersContent, 0);
|
||||
});
|
||||
|
||||
new Sortable({
|
||||
list: stickersContent,
|
||||
middleware: this.middlewareHelper.get(),
|
||||
onSort: (idx, newIdx) => {
|
||||
const order = Array.from(stickersContent.children).map((el) => (el as HTMLElement).dataset.id);
|
||||
this.managers.appStickersManager.reorderStickerSets(order);
|
||||
}
|
||||
});
|
||||
|
||||
this.scrollable.append(section.container);
|
||||
}
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
}
|
|
@ -132,8 +132,8 @@ export default async function wrapSticker({doc, div, middleware, loadStickerMidd
|
|||
div.dataset.stickerEmoji = emoji;
|
||||
}
|
||||
|
||||
div.dataset.stickerPlay = '' + +play;
|
||||
div.dataset.stickerLoop = '' + +loop;
|
||||
div.dataset.stickerPlay = '' + +(play || false);
|
||||
div.dataset.stickerLoop = '' + +(loop || false);
|
||||
|
||||
div.classList.add('media-sticker-wrapper');
|
||||
});
|
||||
|
|
|
@ -21,7 +21,7 @@ const App = {
|
|||
version: process.env.VERSION,
|
||||
versionFull: process.env.VERSION_FULL,
|
||||
build: +process.env.BUILD,
|
||||
langPackVersion: '0.9.8',
|
||||
langPackVersion: '1.0.1',
|
||||
langPack: 'webk',
|
||||
langPackCode: 'en',
|
||||
domains: MAIN_DOMAINS,
|
||||
|
|
|
@ -91,7 +91,8 @@ export type State = {
|
|||
videos: boolean
|
||||
},
|
||||
stickers: {
|
||||
suggest: boolean,
|
||||
suggest: 'all' | 'installed' | 'none',
|
||||
dynamicPackOrder: boolean,
|
||||
loop: boolean
|
||||
},
|
||||
emoji: {
|
||||
|
@ -267,7 +268,8 @@ export const STATE_INIT: State = {
|
|||
video_upload_maxbitrate: 100
|
||||
},
|
||||
stickers: {
|
||||
suggest: true,
|
||||
suggest: 'all',
|
||||
dynamicPackOrder: true,
|
||||
loop: true
|
||||
},
|
||||
emoji: {
|
||||
|
|
|
@ -6,11 +6,13 @@
|
|||
|
||||
import ButtonMenu, {ButtonMenuItemOptionsVerifiable} from '../../components/buttonMenu';
|
||||
import filterAsync from '../array/filterAsync';
|
||||
import callbackify from '../callbackify';
|
||||
import contextMenuController from '../contextMenuController';
|
||||
import ListenerSetter from '../listenerSetter';
|
||||
import {getMiddleware} from '../middleware';
|
||||
import {getMiddleware, Middleware} from '../middleware';
|
||||
import positionMenu from '../positionMenu';
|
||||
import {attachContextMenuListener} from './attachContextMenuListener';
|
||||
import {attachClickEvent} from './clickEvent';
|
||||
|
||||
export default function createContextMenu<T extends ButtonMenuItemOptionsVerifiable>({
|
||||
buttons,
|
||||
|
@ -21,7 +23,9 @@ export default function createContextMenu<T extends ButtonMenuItemOptionsVerifia
|
|||
onOpen,
|
||||
onClose,
|
||||
onBeforeOpen,
|
||||
listenerSetter: attachListenerSetter
|
||||
listenerSetter: attachListenerSetter,
|
||||
middleware,
|
||||
listenForClick
|
||||
}: {
|
||||
buttons: T[],
|
||||
findElement?: (e: MouseEvent | TouchEvent) => HTMLElement,
|
||||
|
@ -31,60 +35,64 @@ export default function createContextMenu<T extends ButtonMenuItemOptionsVerifia
|
|||
onOpen?: (target: HTMLElement) => any,
|
||||
onClose?: () => any,
|
||||
onBeforeOpen?: () => any,
|
||||
listenerSetter?: ListenerSetter
|
||||
listenerSetter?: ListenerSetter,
|
||||
middleware?: Middleware,
|
||||
listenForClick?: boolean
|
||||
}) {
|
||||
appendTo ??= document.body;
|
||||
|
||||
attachListenerSetter ??= new ListenerSetter();
|
||||
const listenerSetter = new ListenerSetter();
|
||||
const middleware = getMiddleware();
|
||||
const middlewareHelper = middleware ? middleware.create() : getMiddleware();
|
||||
let element: HTMLElement;
|
||||
|
||||
attachContextMenuListener({
|
||||
element: listenTo,
|
||||
callback: (e) => {
|
||||
const target = findElement ? findElement(e as any) : listenTo;
|
||||
if(!target) {
|
||||
const open = (e: MouseEvent | TouchEvent) => {
|
||||
const target = findElement ? findElement(e as any) : listenTo;
|
||||
if(!target) {
|
||||
return;
|
||||
}
|
||||
|
||||
let _element = element;
|
||||
if(e instanceof MouseEvent || e.hasOwnProperty('preventDefault')) (e as any).preventDefault();
|
||||
if(_element && _element.classList.contains('active')) {
|
||||
return false;
|
||||
}
|
||||
if(e instanceof MouseEvent || e.hasOwnProperty('cancelBubble')) (e as any).cancelBubble = true;
|
||||
|
||||
const r = async() => {
|
||||
await onOpen?.(target);
|
||||
|
||||
const initResult = await init();
|
||||
if(!initResult) {
|
||||
return;
|
||||
}
|
||||
|
||||
let _element = element;
|
||||
if(e instanceof MouseEvent || e.hasOwnProperty('preventDefault')) (e as any).preventDefault();
|
||||
if(_element && _element.classList.contains('active')) {
|
||||
return false;
|
||||
}
|
||||
if(e instanceof MouseEvent || e.hasOwnProperty('cancelBubble')) (e as any).cancelBubble = true;
|
||||
_element = initResult.element;
|
||||
const {cleanup, destroy} = initResult;
|
||||
|
||||
const r = async() => {
|
||||
await onOpen?.(target);
|
||||
positionMenu(e, _element);
|
||||
contextMenuController.openBtnMenu(_element, () => {
|
||||
onClose?.();
|
||||
cleanup();
|
||||
|
||||
const initResult = await init();
|
||||
if(!initResult) {
|
||||
return;
|
||||
}
|
||||
setTimeout(() => {
|
||||
destroy();
|
||||
}, 300);
|
||||
});
|
||||
};
|
||||
|
||||
_element = initResult.element;
|
||||
const {cleanup, destroy} = initResult;
|
||||
r();
|
||||
};
|
||||
|
||||
positionMenu(e, _element);
|
||||
contextMenuController.openBtnMenu(_element, () => {
|
||||
onClose?.();
|
||||
cleanup();
|
||||
|
||||
setTimeout(() => {
|
||||
destroy();
|
||||
}, 300);
|
||||
});
|
||||
};
|
||||
|
||||
r();
|
||||
},
|
||||
attachContextMenuListener({
|
||||
element: listenTo,
|
||||
callback: open,
|
||||
listenerSetter: attachListenerSetter
|
||||
});
|
||||
|
||||
const cleanup = () => {
|
||||
listenerSetter.removeAll();
|
||||
middleware.clean();
|
||||
middlewareHelper.clean();
|
||||
};
|
||||
|
||||
const destroy = () => {
|
||||
|
@ -96,7 +104,9 @@ export default function createContextMenu<T extends ButtonMenuItemOptionsVerifia
|
|||
cleanup();
|
||||
|
||||
buttons.forEach((button) => button.element = undefined);
|
||||
const f = filterButtons || ((buttons: T[]) => filterAsync(buttons, (button) => button?.verify ? button.verify() : true));
|
||||
const f = filterButtons || ((buttons: T[]) => filterAsync(buttons, (button) => {
|
||||
return button?.verify ? callbackify(button.verify(), (result) => result ?? false) : true;
|
||||
}));
|
||||
|
||||
const filteredButtons = await f(buttons);
|
||||
if(!filteredButtons.length) {
|
||||
|
@ -122,5 +132,15 @@ export default function createContextMenu<T extends ButtonMenuItemOptionsVerifia
|
|||
};
|
||||
};
|
||||
|
||||
return {element, destroy};
|
||||
if(middleware) {
|
||||
middleware.onDestroy(() => {
|
||||
destroy();
|
||||
});
|
||||
}
|
||||
|
||||
if(listenForClick) {
|
||||
attachClickEvent(listenTo, open, {listenerSetter: attachListenerSetter});
|
||||
}
|
||||
|
||||
return {element, destroy, open};
|
||||
}
|
||||
|
|
|
@ -933,6 +933,13 @@ const lang = {
|
|||
'ErrorSendRestrictedPollsAll': 'Sorry, sending polls is not allowed in this group.',
|
||||
'Remove': 'Remove',
|
||||
'ChannelBlockUser': 'Remove User',
|
||||
'StickersName': 'Stickers and Emoji',
|
||||
'LoopAnimatedStickersInfo': 'Animated stickers will play continuously in chats.',
|
||||
'SuggestStickersAll': 'All Sets',
|
||||
'SuggestStickersInstalled': 'My Sets',
|
||||
'SuggestStickersNone': 'None',
|
||||
'DynamicPackOrder': 'Dynamic Pack Order',
|
||||
'DynamicPackOrderInfo': 'Automatically place recently used sticker packs at the front of the panel.',
|
||||
|
||||
// * macos
|
||||
'AccountSettings.Filters': 'Chat Folders',
|
||||
|
|
|
@ -166,14 +166,13 @@ const processAfter = (cb: () => void) => {
|
|||
cb();
|
||||
};
|
||||
|
||||
const UPDATE_STICKERSET_ORDER = true;
|
||||
|
||||
export type MessageSendingParams = Partial<{
|
||||
threadId: number,
|
||||
replyToMsgId: number,
|
||||
scheduleDate: number,
|
||||
silent: boolean,
|
||||
sendAsPeerId: number,
|
||||
updateStickersetOrder: boolean
|
||||
}>;
|
||||
|
||||
export class AppMessagesManager extends AppManager {
|
||||
|
@ -657,7 +656,7 @@ export class AppMessagesManager extends AppManager {
|
|||
schedule_date: options.scheduleDate || undefined,
|
||||
silent: options.silent,
|
||||
send_as: sendAs,
|
||||
update_stickersets_order: UPDATE_STICKERSET_ORDER
|
||||
update_stickersets_order: options.updateStickersetOrder
|
||||
}, sentRequestOptions);
|
||||
}
|
||||
|
||||
|
@ -1146,7 +1145,8 @@ export class AppMessagesManager extends AppManager {
|
|||
silent: options.silent,
|
||||
entities,
|
||||
clear_draft: options.clearDraft,
|
||||
send_as: options.sendAsPeerId ? this.appPeersManager.getInputPeerById(options.sendAsPeerId) : undefined
|
||||
send_as: options.sendAsPeerId ? this.appPeersManager.getInputPeerById(options.sendAsPeerId) : undefined,
|
||||
update_stickersets_order: options.updateStickersetOrder
|
||||
}).then((updates) => {
|
||||
this.apiUpdatesManager.processUpdateMessage(updates);
|
||||
}, (error: ApiError) => {
|
||||
|
@ -1272,7 +1272,7 @@ export class AppMessagesManager extends AppManager {
|
|||
silent: options.silent,
|
||||
clear_draft: options.clearDraft,
|
||||
send_as: options.sendAsPeerId ? this.appPeersManager.getInputPeerById(options.sendAsPeerId) : undefined,
|
||||
update_stickersets_order: UPDATE_STICKERSET_ORDER
|
||||
update_stickersets_order: options.updateStickersetOrder
|
||||
}).then((updates) => {
|
||||
this.apiUpdatesManager.processUpdateMessage(updates);
|
||||
deferred.resolve();
|
||||
|
@ -1488,7 +1488,7 @@ export class AppMessagesManager extends AppManager {
|
|||
schedule_date: options.scheduleDate,
|
||||
silent: options.silent,
|
||||
send_as: sendAs,
|
||||
update_stickersets_order: UPDATE_STICKERSET_ORDER
|
||||
update_stickersets_order: options.updateStickersetOrder
|
||||
}, sentRequestOptions);
|
||||
}
|
||||
|
||||
|
|
|
@ -72,10 +72,7 @@ export class AppStickersManager extends AppManager {
|
|||
private names: Record<string, InputStickerSet.inputStickerSetID>;
|
||||
|
||||
protected after() {
|
||||
this.getStickerSetPromises = {};
|
||||
this.getStickersByEmoticonsPromises = {};
|
||||
this.sounds = {};
|
||||
this.names = {};
|
||||
this.clear(true);
|
||||
|
||||
this.rootScope.addEventListener('user_auth', () => {
|
||||
setTimeout(() => {
|
||||
|
@ -83,8 +80,8 @@ export class AppStickersManager extends AppManager {
|
|||
// this.getFavedStickersStickers();
|
||||
}, 1000);
|
||||
|
||||
if(!this.getGreetingStickersPromise && this.getGreetingStickersTimeout === undefined) {
|
||||
this.getGreetingStickersTimeout = ctx.setTimeout(() => {
|
||||
if(!this.getGreetingStickersPromise) {
|
||||
this.getGreetingStickersTimeout ??= ctx.setTimeout(() => {
|
||||
this.getGreetingStickersTimeout = undefined;
|
||||
this.getGreetingSticker(true);
|
||||
}, 5000);
|
||||
|
@ -106,10 +103,41 @@ export class AppStickersManager extends AppManager {
|
|||
|
||||
updateMoveStickerSetToTop: (update) => {
|
||||
this.rootScope.dispatchEvent('stickers_top', update.stickerset);
|
||||
},
|
||||
|
||||
updateStickerSetsOrder: (update) => {
|
||||
this.rootScope.dispatchEvent('stickers_order', {
|
||||
type: update.pFlags.emojis ? 'emojis' : (update.pFlags.masks ? 'masks' : 'stickers'),
|
||||
order: update.order
|
||||
});
|
||||
}
|
||||
|
||||
// updateStickerSets: (update) => {
|
||||
// if(update.pFlags.masks) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// this.storage.clear(false);
|
||||
|
||||
// if(update.pFlags.emojis) {
|
||||
|
||||
// } else {
|
||||
// this.favedStickers = undefined;
|
||||
// this.recentStickers = undefined;
|
||||
// this.onStickersUpdated('recent', true);
|
||||
// this.onStickersUpdated('faved', true);
|
||||
// }
|
||||
// }
|
||||
});
|
||||
}
|
||||
|
||||
public clear = (init?: boolean) => {
|
||||
this.getStickerSetPromises = {};
|
||||
this.getStickersByEmoticonsPromises = {};
|
||||
this.sounds = {};
|
||||
this.names = {};
|
||||
};
|
||||
|
||||
private async onStickersUpdated(type: 'faved' | 'recent', overwrite: boolean) {
|
||||
const stickers = await (type === 'faved' ? this.getFavedStickersStickers(overwrite) : this.getRecentStickersStickers(overwrite));
|
||||
this.rootScope.dispatchEvent('stickers_updated', {
|
||||
|
@ -673,27 +701,29 @@ export class AppStickersManager extends AppManager {
|
|||
|
||||
public preloadStickerSets() {
|
||||
return this.getAllStickers().then((allStickers) => {
|
||||
return Promise.all((allStickers as MessagesAllStickers.messagesAllStickers).sets.map((set) => this.getStickerSet(set, {useCache: true})));
|
||||
const sets = (allStickers as MessagesAllStickers.messagesAllStickers).sets;
|
||||
return Promise.all(sets.map((set) => this.getStickerSet(set, {useCache: true})));
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: detect "🤷" by "🤷♂️"
|
||||
public getStickersByEmoticon(emoticon: string, includeOurStickers = true) {
|
||||
public getStickersByEmoticon(emoticon: string, includeOurStickers = true, includeServerStickers = true) {
|
||||
emoticon = fixEmoji(emoticon);
|
||||
if(this.getStickersByEmoticonsPromises[emoticon]) return this.getStickersByEmoticonsPromises[emoticon];
|
||||
const cacheKey = emoticon + (includeOurStickers ? '1' : '0') + (includeServerStickers ? '1' : '0');
|
||||
if(this.getStickersByEmoticonsPromises[cacheKey]) return this.getStickersByEmoticonsPromises[cacheKey];
|
||||
|
||||
return this.getStickersByEmoticonsPromises[emoticon] = Promise.all([
|
||||
this.apiManager.invokeApiHashable({
|
||||
return this.getStickersByEmoticonsPromises[cacheKey] = Promise.all([
|
||||
includeServerStickers ? this.apiManager.invokeApiHashable({
|
||||
method: 'messages.getStickers',
|
||||
params: {
|
||||
emoticon
|
||||
},
|
||||
processResult: (stickers) => stickers
|
||||
}),
|
||||
}) : undefined,
|
||||
includeOurStickers ? this.preloadStickerSets() : [],
|
||||
includeOurStickers ? this.getRecentStickers() : undefined
|
||||
]).then(([messagesStickers, installedSets, recentStickers]) => {
|
||||
const foundStickers = (messagesStickers as MessagesStickers.messagesStickers).stickers.map((sticker) => this.appDocsManager.saveDoc(sticker));
|
||||
const foundStickers = messagesStickers ? (messagesStickers as MessagesStickers.messagesStickers).stickers.map((sticker) => this.appDocsManager.saveDoc(sticker)) : [];
|
||||
const cachedStickersAnimated: Document.document[] = [], cachedStickersStatic: Document.document[] = [];
|
||||
|
||||
// console.log('getStickersByEmoticon', messagesStickers, installedSets, recentStickers);
|
||||
|
@ -755,4 +785,21 @@ export class AppStickersManager extends AppManager {
|
|||
|
||||
return this.apiManager.invokeApi('messages.clearRecentStickers');
|
||||
}
|
||||
|
||||
public reorderStickerSets(order: StickerSet.stickerSet['id'][], emojis?: boolean, masks?: boolean) {
|
||||
return this.apiManager.invokeApi('messages.reorderStickerSets', {
|
||||
emojis,
|
||||
masks,
|
||||
order
|
||||
}).then(() => {
|
||||
this.apiUpdatesManager.processLocalUpdate({
|
||||
_: 'updateStickerSetsOrder',
|
||||
order,
|
||||
pFlags: {
|
||||
emojis: emojis || undefined,
|
||||
masks: masks || undefined
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -383,6 +383,10 @@ async function loadStateInner() {
|
|||
state.settings.liteMode.gif = !state.settings.autoPlay.gifs;
|
||||
}
|
||||
|
||||
if(state.build < 312 && typeof(state.settings.stickers.suggest) === 'boolean') {
|
||||
state.settings.stickers.suggest = state.settings.stickers.suggest ? 'all' : 'none';
|
||||
}
|
||||
|
||||
if(compareVersion(state.version, STATE_VERSION) !== 0) {
|
||||
newVersion = STATE_VERSION;
|
||||
oldVersion = state.version;
|
||||
|
|
|
@ -93,6 +93,7 @@ export type BroadcastEvents = {
|
|||
'stickers_deleted': StickerSet.stickerSet,
|
||||
'stickers_updated': {type: 'recent' | 'faved', stickers: MyDocument[]},
|
||||
'stickers_top': Long,
|
||||
'stickers_order': {type: 'masks' | 'emojis' | 'stickers', order: Long[]},
|
||||
'sticker_updated': {type: 'recent' | 'faved', document: MyDocument, faved: boolean},
|
||||
|
||||
'state_cleared': void,
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
display: flex;
|
||||
max-width: calc(#{$large-screen} + 2px) !important;
|
||||
|
||||
.avatar-edit {
|
||||
.tgico-cameraadd {
|
||||
top: 52%;
|
||||
}
|
||||
}
|
||||
// .avatar-edit {
|
||||
// .tgico-cameraadd {
|
||||
// top: 52%;
|
||||
// }
|
||||
// }
|
||||
|
||||
#main-columns {
|
||||
width: 100%;
|
||||
|
|
Loading…
Reference in New Issue