Stickers lite mode

Common chats tab
This commit is contained in:
Eduard Kuzmenko 2023-03-02 19:51:37 +04:00
parent 14e826e19e
commit 23960bf5e0
12 changed files with 157 additions and 62 deletions

View File

@ -337,6 +337,35 @@ export class AnimationIntersector {
if(lock) this.lockIntersectionGroup(group);
else this.unlockIntersectionGroup(group);
}
public setAutoplay(play: boolean, liteModeKey: LiteModeKey) {
let changed = false;
this.byPlayer.forEach((animationItem, animation) => {
if(animationItem.liteModeKey === liteModeKey) {
changed = true;
animation.autoplay = play ? !!+animationItem.el.dataset.stickerPlay : false;
animation.loop = play ? !!+animationItem.el.dataset.stickerLoop : false;
}
});
return changed;
}
public setLoop(loop: boolean) {
let changed = false;
this.byPlayer.forEach((animationItem, animation) => {
if(!!+animationItem.el.dataset.stickerLoop && animation.loop !== loop) {
changed = true;
animation.loop = loop;
// if(animation._autoplay && animation.autoplay !== animation._autoplay) {
animation.autoplay = !!+animationItem.el.dataset.stickerPlay;
// }
}
});
return changed;
}
}
const animationIntersector = new AnimationIntersector();

View File

@ -18,7 +18,7 @@ import useHeavyAnimationCheck, {getHeavyAnimationPromise} from '../hooks/useHeav
import I18n, {LangPackKey, i18n} from '../lib/langPack';
import findUpClassName from '../helpers/dom/findUpClassName';
import {getMiddleware, Middleware} from '../helpers/middleware';
import {ChannelParticipant, Chat, ChatFull, ChatParticipant, ChatParticipants, Document, Message, MessageMedia, Photo, WebPage} from '../layer';
import {ChannelParticipant, Chat, ChatFull, ChatParticipant, ChatParticipants, Document, Message, MessageMedia, Photo, User, WebPage} from '../layer';
import SortedUserList from './sortedUserList';
import findUpTag from '../helpers/dom/findUpTag';
import appSidebarRight from './sidebarRight';
@ -75,6 +75,7 @@ import wrapPhoto from './wrappers/photo';
import wrapVideo from './wrappers/video';
import noop from '../helpers/noop';
import wrapMediaSpoiler, {onMediaSpoilerClick} from './wrappers/mediaSpoiler';
import filterAsync from '../helpers/array/filterAsync';
// const testScroll = false;
@ -92,7 +93,7 @@ export type SearchSuperContext = {
maxDate?: number
};
export type SearchSuperMediaType = 'members' | 'media' | 'files' | 'links' | 'music' | 'chats' | 'voice';
export type SearchSuperMediaType = 'members' | 'media' | 'files' | 'links' | 'music' | 'chats' | 'voice' | 'groups';
export type SearchSuperMediaTab = {
inputFilter: SearchSuperType,
name: LangPackKey,
@ -1163,11 +1164,12 @@ export default class AppSearchSuper {
}
private async loadMembers(mediaTab: SearchSuperMediaTab) {
const id = this.searchContext.peerId.toChatId();
const chatId = mediaTab.type === 'members' ? this.searchContext.peerId.toChatId() : undefined;
const userId = mediaTab.type === 'groups' ? this.searchContext.peerId.toUserId() : undefined;
const middleware = this.middleware.get();
let promise: Promise<void>;
const renderParticipants = async(participants: (ChatParticipant | ChannelParticipant)[]) => {
const renderParticipants = async(participants: (ChatParticipant | ChannelParticipant | Chat)[]) => {
if(this.loadMutex) {
await this.loadMutex;
@ -1178,7 +1180,7 @@ export default class AppSearchSuper {
let membersList = this.membersList;
if(!membersList) {
membersList = new SortedUserList({
membersList = this.membersList = new SortedUserList({
lazyLoadQueue: this.lazyLoadQueue,
rippleEnabled: false,
managers: this.managers
@ -1203,28 +1205,53 @@ export default class AppSearchSuper {
this.afterPerforming(1, mediaTab.contentTab);
}
for(const participant of participants) {
const peerId = getParticipantPeerId(participant);
if(peerId.isAnyChat()) {
continue;
}
const user = await this.managers.appUsersManager.getUser(peerId);
if(!middleware()) {
const peerIds = participants.map((participant) => {
const peerId = userId ? (participant as Chat.chat).id.toPeerId(true) : getParticipantPeerId(participant as ChannelParticipant);
if(chatId ? peerId.isAnyChat() : peerId.isUser()) {
return;
}
if(user.pFlags.deleted) {
continue;
return peerId;
}).filter(Boolean);
const filtered = await filterAsync(peerIds, async(peerId) => {
const peer: User | Chat = await this.managers.appPeersManager.getPeer(peerId);
if(!middleware()) {
return false;
}
if(!peer || (peer as User.user).pFlags.deleted) {
return false;
}
return true;
});
for(const peerId of filtered) {
membersList.add(peerId);
}
};
if(await this.managers.appChatsManager.isChannel(id)) {
if(userId) {
const LOAD_COUNT = !this.membersList ? 50 : 200;
promise = this.managers.appProfileManager.getChannelParticipants(id, undefined, LOAD_COUNT, this.nextRates[mediaTab.inputFilter]).then((participants) => {
promise = this.managers.appUsersManager.getCommonChats(userId, LOAD_COUNT, this.nextRates[mediaTab.inputFilter]).then((messagesChats) => {
if(!middleware()) {
return;
}
// const list = mediaTab.contentTab.firstElementChild as HTMLUListElement;
const lastChat = messagesChats.chats[messagesChats.chats.length - 1];
this.nextRates[mediaTab.inputFilter] = lastChat?.id as number;
if(messagesChats.chats.length < LOAD_COUNT) {
this.loaded[mediaTab.inputFilter] = true;
}
return renderParticipants(messagesChats.chats);
});
} else if(await this.managers.appChatsManager.isChannel(chatId)) {
const LOAD_COUNT = !this.membersList ? 50 : 200;
promise = this.managers.appProfileManager.getChannelParticipants(chatId, undefined, LOAD_COUNT, this.nextRates[mediaTab.inputFilter]).then((participants) => {
if(!middleware()) {
return;
}
@ -1239,7 +1266,7 @@ export default class AppSearchSuper {
return renderParticipants(participants.participants);
});
} else {
promise = this.managers.appProfileManager.getChatFull(id).then((chatFull) => {
promise = this.managers.appProfileManager.getChatFull(chatId).then((chatFull) => {
if(!middleware()) {
return;
}
@ -1271,7 +1298,7 @@ export default class AppSearchSuper {
return this.loadPromises[type];
}
if(mediaTab.type === 'members') {
if(mediaTab.type === 'members' || mediaTab.type === 'groups') {
return this.loadMembers(mediaTab);
}
@ -1403,9 +1430,10 @@ export default class AppSearchSuper {
const mediaTabs = this.mediaTabs.filter((mediaTab) => mediaTab.inputFilter !== 'inputMessagesFilterEmpty');
const filters = mediaTabs.map((mediaTab) => ({_: mediaTab.inputFilter}));
const [counters, canViewMembers] = await Promise.all([
const [counters, canViewMembers, canViewGroups] = await Promise.all([
this.managers.appMessagesManager.getSearchCounters(peerId, filters, undefined, threadId),
this.canViewMembers()
this.canViewMembers(),
this.canViewGroups()
]);
if(!middleware()) {
@ -1439,11 +1467,26 @@ export default class AppSearchSuper {
});
const membersTab = this.mediaTabsMap.get('members');
membersTab.menuTab.classList.toggle('hide', !canViewMembers);
const a: [SearchSuperMediaTab, boolean][] = [
[membersTab, canViewMembers],
[this.mediaTabsMap.get('groups'), canViewGroups]
];
a.forEach(([tab, value]) => {
if(!tab) {
return;
}
tab.menuTab.classList.toggle('hide', !value);
if(value) {
++count;
}
});
if(canViewMembers) {
firstMediaTab = membersTab;
++count;
}
this.container.classList.toggle('hide', !firstMediaTab);
@ -1479,6 +1522,8 @@ export default class AppSearchSuper {
if(peerId.isUser()) {
findAndSplice(toLoad, (mediaTab) => mediaTab.type === 'members');
} else {
findAndSplice(toLoad, (mediaTab) => mediaTab.type === 'groups');
}
if(!toLoad.length) {
@ -1549,7 +1594,7 @@ export default class AppSearchSuper {
public canViewMembers() {
const {peerId} = this.searchContext;
const isAnyChat = peerId.isAnyChat();
if(!isAnyChat) return Promise.resolve(false);
if(!isAnyChat || !this.mediaTabsMap.has('members')) return Promise.resolve(false);
const chatId = peerId.toChatId();
return Promise.all([
this.managers.appChatsManager.isBroadcast(chatId),
@ -1560,6 +1605,13 @@ export default class AppSearchSuper {
});
}
public async canViewGroups() {
const {peerId} = this.searchContext;
if(!peerId.isUser() || !this.mediaTabsMap.has('groups')) return false;
const userFull = await this.managers.appProfileManager.getProfile(peerId.toUserId());
return !!userFull.common_chats_count;
}
public cleanup() {
this.loadPromises = {};
this.loaded = {};

View File

@ -3510,6 +3510,12 @@ export default class ChatBubbles {
restoreScroll?.();
pause(!this.chat.setPeerPromise ? 0 : 1000)
.then(() => getHeavyAnimationPromise())
.then(() => {
this.lazyLoadQueue.setAllSeen();
});
// this.setStickyDateManually();
};

View File

@ -64,4 +64,12 @@ export default class LazyLoadQueue extends LazyLoadQueueIntersector {
return true;
}
public setAllSeen() {
this.queue.forEach((item) => {
item.wasSeen = true;
});
this.setProcessQueueTimeout();
}
}

View File

@ -39,7 +39,7 @@ export default class AppPowerSavingTab extends SliderSuperTab {
'all',
'video',
'gif',
// ['stickers', ['stickers_panel', 'stickers_chat']],
['stickers', ['stickers_panel', 'stickers_chat']],
// ['emoji', ['emoji_panel', 'emoji_messages']],
['effects', ['effects_reactions', 'effects_premiumstickers', 'effects_emoji']],
['chat', ['chat_background', 'chat_spoilers']],

View File

@ -224,6 +224,10 @@ export default class AppSharedMediaTab extends SliderSuperTab {
inputFilter: 'inputMessagesFilterRoundVoice',
name: 'SharedVoiceTab2',
type: 'voice'
}, {
inputFilter: 'inputMessagesFilterEmpty',
name: 'ChatList.Filter.Groups',
type: 'groups'
}],
scrollable: this.scrollable,
onChangeTab: (mediaTab) => {

View File

@ -15,6 +15,7 @@ import safeAssign from '../helpers/object/safeAssign';
import {AppManagers} from '../lib/appManagers/managers';
import getUserStatusString from './wrappers/getUserStatusString';
import type LazyLoadQueue from './lazyLoadQueue';
import getChatMembersString from './wrappers/getChatMembersString';
interface SortedUser extends SortedElementBase<PeerId> {
dom: DialogDom
@ -47,14 +48,19 @@ export default class SortedUserList extends SortedList<SortedUser> {
managers: SortedUserList['managers']
}) {
super({
getIndex: options.getIndex || ((element) => this.managers.appUsersManager.getUserStatusForSort(element.id)),
getIndex: options.getIndex || ((element) => element.id.isAnyChat() ? 0 : this.managers.appUsersManager.getUserStatusForSort(element.id)),
onDelete: (element) => {
element.dom.listEl.remove();
this.onListLengthChange && this.onListLengthChange();
},
onUpdate: options.onUpdate || (async(element) => {
const status = getUserStatusString(await this.managers.appUsersManager.getUser(element.id));
replaceContent(element.dom.lastMessageSpan, status);
if(element.id.isAnyChat()) {
const status = await getChatMembersString(element.id.toChatId(), this.managers);
replaceContent(element.dom.lastMessageSpan, status);
} else {
const status = getUserStatusString(await this.managers.appUsersManager.getUser(element.id));
replaceContent(element.dom.lastMessageSpan, status);
}
}),
onSort: (element, idx) => {
const willChangeLength = element.dom.listEl.parentElement !== this.list;
@ -82,6 +88,10 @@ export default class SortedUserList extends SortedList<SortedUser> {
},
updateElementWith: fastRaf,
updateListWith: async(callback) => {
if(!Array.from(this.elements.values()).some((element) => element.id.isUser())) {
return callback(false);
}
if(!isInDOM(this.list)) {
return callback(false);
}

View File

@ -1677,8 +1677,8 @@ export class AppImManager extends EventListenerBase<{
}, liteMode.isAvailable('animations') ? 250 : 0, false, true);
const c: LiteModeKey[] = ['stickers_chat', 'stickers_panel'];
const changedLoop = lottieLoader.setLoop(rootScope.settings.stickers.loop);
const changedAutoplay = !!c.filter((key) => lottieLoader.setAutoplay(liteMode.isAvailable(key), key)).length;
const changedLoop = animationIntersector.setLoop(rootScope.settings.stickers.loop);
const changedAutoplay = !!c.filter((key) => animationIntersector.setAutoplay(liteMode.isAvailable(key), key)).length;
if(changedLoop || changedAutoplay) {
animationIntersector.checkAnimations2(false);
}

View File

@ -1056,4 +1056,19 @@ export class AppUsersManager extends AppManager {
public canSendToUser(userId: UserId) {
return canSendToUser(this.getUser(userId));
}
public getCommonChats(userId: UserId, limit = 100, maxId?: ChatId) {
return this.apiManager.invokeApiSingleProcess({
method: 'messages.getCommonChats',
params: {
user_id: this.getUserInput(userId),
limit,
max_id: maxId ?? 0
},
processResult: (messagesChats) => {
this.appChatsManager.saveApiChats(messagesChats.chats);
return messagesChats;
}
});
}
}

View File

@ -46,37 +46,6 @@ export class LottieLoader {
return null;
}
public setAutoplay(play: boolean, liteModeKey: LiteModeKey) {
let changed = false;
for(const i in this.players) {
const player = this.players[i];
if(player.liteModeKey === liteModeKey) {
changed = true;
player.autoplay = play ? !!+player.el[0].dataset.stickerPlay : false;
player.loop = play ? !!+player.el[0].dataset.stickerLoop : false;
}
}
return changed;
}
public setLoop(loop: boolean) {
let changed = false;
for(const i in this.players) {
const player = this.players[i];
if(player._loop && player.loop !== loop) {
changed = true;
player.loop = loop;
// if(player._autoplay && player.autoplay !== player._autoplay) {
player.autoplay = player._autoplay;
// }
}
}
return changed;
}
public loadLottieWorkers() {
if(this.loadPromise) {
return this.loadPromise;

View File

@ -581,6 +581,7 @@
.progress-line {
margin-top: 4px;
margin-inline-start: 0;
min-width: 11.25rem;
&__filled:after {
opacity: 0;

View File

@ -604,7 +604,8 @@
}
}
&-content-members {
&-content-members,
&-content-groups {
.chatlist {
padding-top: .5rem;
padding-bottom: .5rem;