Misc folder management fixes
This commit is contained in:
parent
446949daa6
commit
b148a60c8c
@ -4,12 +4,12 @@
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import type { MyDialogFilter } from "../../../lib/storages/filters";
|
||||
import type { DialogFilterSuggested } from "../../../layer";
|
||||
import type _rootScope from "../../../lib/rootScope";
|
||||
import { SliderSuperTab } from "../../slider";
|
||||
import lottieLoader, { LottieLoader } from "../../../lib/rlottie/lottieLoader";
|
||||
import { toast } from "../../toast";
|
||||
import type { MyDialogFilter } from "../../../lib/storages/filters";
|
||||
import type { DialogFilterSuggested, DialogFilter } from "../../../layer";
|
||||
import type _rootScope from "../../../lib/rootScope";
|
||||
import Button from "../../button";
|
||||
import rootScope from "../../../lib/rootScope";
|
||||
import AppEditFolderTab from "./editFolder";
|
||||
@ -22,6 +22,7 @@ import positionElementByIndex from "../../../helpers/dom/positionElementByIndex"
|
||||
import RLottiePlayer from "../../../lib/rlottie/rlottiePlayer";
|
||||
import wrapEmojiText from "../../../lib/richTextProcessor/wrapEmojiText";
|
||||
import { FOLDER_ID_ALL, FOLDER_ID_ARCHIVE, REAL_FOLDERS } from "../../../lib/mtproto/mtproto_config";
|
||||
import replaceContent from "../../../helpers/dom/replaceContent";
|
||||
|
||||
export default class AppChatFoldersTab extends SliderSuperTab {
|
||||
private createFolderBtn: HTMLElement;
|
||||
@ -33,7 +34,12 @@ export default class AppChatFoldersTab extends SliderSuperTab {
|
||||
private filtersRendered: {[filterId: number]: Row} = {};
|
||||
private loadAnimationPromise: ReturnType<LottieLoader['waitForFirstFrame']>;
|
||||
|
||||
private async renderFolder(dialogFilter: DialogFilterSuggested | MyDialogFilter, container?: HTMLElement, row?: Row) {
|
||||
private async renderFolder(
|
||||
dialogFilter: DialogFilterSuggested | MyDialogFilter,
|
||||
container?: HTMLElement,
|
||||
row?: Row,
|
||||
append?: boolean
|
||||
) {
|
||||
let filter: MyDialogFilter;
|
||||
let description = '';
|
||||
let d: HTMLElement[] = [];
|
||||
@ -86,14 +92,12 @@ export default class AppChatFoldersTab extends SliderSuperTab {
|
||||
});
|
||||
|
||||
if(d.length) {
|
||||
join(d).forEach((el) => {
|
||||
row.subtitle.append(el);
|
||||
});
|
||||
row.subtitle.append(...join(d));
|
||||
}
|
||||
|
||||
if(dialogFilter._ === 'dialogFilter') {
|
||||
const filterId = filter.id;
|
||||
if(!this.filtersRendered.hasOwnProperty(filter.id) && filter.id !== FOLDER_ID_ALL) {
|
||||
if(!this.filtersRendered[filter.id] && filter.id !== FOLDER_ID_ALL) {
|
||||
attachClickEvent(row.container, async() => {
|
||||
this.slider.createTab(AppEditFolderTab).open(await this.managers.filtersStorage.getFilter(filterId));
|
||||
}, {listenerSetter: this.listenerSetter});
|
||||
@ -102,18 +106,25 @@ export default class AppChatFoldersTab extends SliderSuperTab {
|
||||
this.filtersRendered[filter.id] = row;
|
||||
}
|
||||
} else {
|
||||
if(filter.id !== FOLDER_ID_ALL) {
|
||||
replaceContent(row.title, wrapEmojiText(filter.title));
|
||||
}
|
||||
|
||||
row.subtitle.textContent = '';
|
||||
join(d).forEach((el) => {
|
||||
row.subtitle.append(el);
|
||||
});
|
||||
row.subtitle.append(...join(d));
|
||||
}
|
||||
|
||||
div = row.container;
|
||||
|
||||
if((filter as MyDialogFilter).localId !== undefined) {
|
||||
// ! header will be at 0 index
|
||||
positionElementByIndex(div, div.parentElement || container, (filter as MyDialogFilter).localId);
|
||||
} else if(container) container.append(div);
|
||||
if(append) {
|
||||
const localId = (filter as MyDialogFilter).localId;
|
||||
if(localId !== undefined) {
|
||||
// ! header will be at 0 index
|
||||
positionElementByIndex(div, div.parentElement || container, localId);
|
||||
} else if(container) {
|
||||
container.append(div);
|
||||
}
|
||||
}
|
||||
|
||||
return div;
|
||||
}
|
||||
@ -166,17 +177,20 @@ export default class AppChatFoldersTab extends SliderSuperTab {
|
||||
continue;
|
||||
}
|
||||
|
||||
await this.renderFolder(filter, this.foldersSection.content);
|
||||
await this.renderFolder(filter, this.foldersSection.content, undefined, true);
|
||||
}
|
||||
|
||||
this.toggleAllChats();
|
||||
|
||||
onFiltersContainerUpdate();
|
||||
});
|
||||
|
||||
this.listenerSetter.add(rootScope)('filter_update', async(filter) => {
|
||||
if(this.filtersRendered.hasOwnProperty(filter.id)) {
|
||||
await this.renderFolder(filter, null, this.filtersRendered[filter.id]);
|
||||
} else {
|
||||
await this.renderFolder(filter, this.foldersSection.content);
|
||||
const filterRendered = this.filtersRendered[filter.id];
|
||||
if(filterRendered) {
|
||||
await this.renderFolder(filter, null, filterRendered);
|
||||
} else if(filter.id !== FOLDER_ID_ARCHIVE) {
|
||||
await this.renderFolder(filter, this.foldersSection.content, undefined, true);
|
||||
}
|
||||
|
||||
onFiltersContainerUpdate();
|
||||
@ -185,7 +199,8 @@ export default class AppChatFoldersTab extends SliderSuperTab {
|
||||
});
|
||||
|
||||
this.listenerSetter.add(rootScope)('filter_delete', (filter) => {
|
||||
if(this.filtersRendered.hasOwnProperty(filter.id)) {
|
||||
const filterRendered = this.filtersRendered[filter.id];
|
||||
if(filterRendered) {
|
||||
/* for(const suggested of this.suggestedFilters) {
|
||||
if(deepEqual(suggested.filter, filter)) {
|
||||
|
||||
@ -193,7 +208,7 @@ export default class AppChatFoldersTab extends SliderSuperTab {
|
||||
} */
|
||||
this.getSuggestedFilters();
|
||||
|
||||
this.filtersRendered[filter.id].container.remove();
|
||||
filterRendered.container.remove();
|
||||
delete this.filtersRendered[filter.id];
|
||||
}
|
||||
|
||||
@ -201,12 +216,17 @@ export default class AppChatFoldersTab extends SliderSuperTab {
|
||||
});
|
||||
|
||||
this.listenerSetter.add(rootScope)('filter_order', (order) => {
|
||||
order.forEach((filterId, idx) => {
|
||||
const container = this.filtersRendered[filterId].container;
|
||||
order.filter((filterId) => !!this.filtersRendered[filterId]).forEach((filterId, idx) => {
|
||||
const filterRendered = this.filtersRendered[filterId];
|
||||
const container = filterRendered.container;
|
||||
positionElementByIndex(container, container.parentElement, idx + 1); // ! + 1 due to header
|
||||
});
|
||||
});
|
||||
|
||||
this.listenerSetter.add(rootScope)('premium_toggle', () => {
|
||||
this.toggleAllChats();
|
||||
});
|
||||
|
||||
this.loadAnimationPromise = lottieLoader.loadAnimationAsAsset({
|
||||
container: this.stickerContainer,
|
||||
loop: false,
|
||||
@ -234,6 +254,11 @@ export default class AppChatFoldersTab extends SliderSuperTab {
|
||||
});
|
||||
}
|
||||
|
||||
private toggleAllChats() {
|
||||
const filterRendered = this.filtersRendered[FOLDER_ID_ALL];
|
||||
filterRendered.container.classList.toggle('hide', !rootScope.premium);
|
||||
}
|
||||
|
||||
private async canCreateFolder() {
|
||||
const [appConfig, filters] = await Promise.all([
|
||||
this.managers.apiManager.getAppConfig(),
|
||||
|
@ -20,6 +20,8 @@ import forEachReverse from "../../../helpers/array/forEachReverse";
|
||||
import setInnerHTML from "../../../helpers/dom/setInnerHTML";
|
||||
import wrapEmojiText from "../../../lib/richTextProcessor/wrapEmojiText";
|
||||
import { REAL_FOLDERS } from "../../../lib/mtproto/mtproto_config";
|
||||
import rootScope from "../../../lib/rootScope";
|
||||
import { MTAppConfig } from "../../../lib/mtproto/appConfig";
|
||||
|
||||
export default class AppIncludedChatsTab extends SliderSuperTab {
|
||||
private editFolderTab: AppEditFolderTab;
|
||||
@ -31,6 +33,7 @@ export default class AppIncludedChatsTab extends SliderSuperTab {
|
||||
private originalFilter: DialogFilter;
|
||||
|
||||
private dialogsByFilters: Map<DialogFilter, Set<PeerId>>;
|
||||
private limit: number;
|
||||
|
||||
protected init() {
|
||||
this.content.remove();
|
||||
@ -106,14 +109,26 @@ export default class AppIncludedChatsTab extends SliderSuperTab {
|
||||
this.close();
|
||||
});
|
||||
|
||||
const onAppConfig = (appConfig: MTAppConfig) => {
|
||||
this.limit = rootScope.premium ? appConfig.dialog_filters_chats_limit_premium : appConfig.dialog_filters_chats_limit_default;
|
||||
};
|
||||
|
||||
this.listenerSetter.add(rootScope)('app_config', onAppConfig);
|
||||
|
||||
this.dialogsByFilters = new Map();
|
||||
return this.managers.filtersStorage.getDialogFilters().then(async(filters) => {
|
||||
await Promise.all(filters.filter((filter) => !REAL_FOLDERS.has(filter.id)).map(async(filter) => {
|
||||
const dialogs = await this.managers.dialogsStorage.getFolderDialogs(filter.id);
|
||||
const peerIds = dialogs.map((d) => d.peerId);
|
||||
this.dialogsByFilters.set(filter, new Set(peerIds));
|
||||
}));
|
||||
});
|
||||
return Promise.all([
|
||||
this.managers.filtersStorage.getDialogFilters().then(async(filters) => {
|
||||
await Promise.all(filters.filter((filter) => !REAL_FOLDERS.has(filter.id)).map(async(filter) => {
|
||||
const dialogs = await this.managers.dialogsStorage.getFolderDialogs(filter.id);
|
||||
const peerIds = dialogs.map((d) => d.peerId);
|
||||
this.dialogsByFilters.set(filter, new Set(peerIds));
|
||||
}));
|
||||
}),
|
||||
|
||||
this.managers.apiManager.getAppConfig().then((appConfig) => {
|
||||
onAppConfig(appConfig);
|
||||
})
|
||||
]);
|
||||
}
|
||||
|
||||
checkbox(selected?: boolean) {
|
||||
@ -223,7 +238,7 @@ export default class AppIncludedChatsTab extends SliderSuperTab {
|
||||
let addedInitial = false;
|
||||
const _add = this.selector.add.bind(this.selector);
|
||||
this.selector.add = (peerId, title, scroll) => {
|
||||
if(this.selector.selected.size >= 100 && addedInitial && !details[peerId]) {
|
||||
if(this.selector.selected.size >= this.limit && addedInitial && !details[peerId]) {
|
||||
const el: HTMLInputElement = this.selector.list.querySelector(`[data-peer-id="${peerId}"] [type="checkbox"]`);
|
||||
if(el) {
|
||||
setTimeout(() => {
|
||||
|
@ -550,7 +550,6 @@ export class AppUsersManager extends AppManager {
|
||||
if(user.pFlags.self) {
|
||||
const isPremium = !!user.pFlags.premium;
|
||||
if(this.rootScope.premium !== isPremium) {
|
||||
this.rootScope.premium = isPremium;
|
||||
this.rootScope.dispatchEvent('premium_toggle', isPremium);
|
||||
}
|
||||
}
|
||||
|
@ -241,6 +241,7 @@ export default abstract class ApiManagerMethods extends AppManager {
|
||||
|
||||
this.appConfig = config;
|
||||
ignoreRestrictionReasons(config.ignore_restriction_reasons ?? []);
|
||||
this.rootScope.dispatchEvent('app_config', config);
|
||||
return config;
|
||||
});
|
||||
|
||||
|
@ -4,6 +4,8 @@
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import type { MyDialogFilter } from "../storages/filters";
|
||||
|
||||
/**
|
||||
* Legacy Webogram's format, don't change dcID to camelCase. date is timestamp
|
||||
*/
|
||||
@ -20,3 +22,4 @@ export const BOT_START_PARAM = '';
|
||||
export const FOLDER_ID_ALL: REAL_FOLDER_ID = 0;
|
||||
export const FOLDER_ID_ARCHIVE: REAL_FOLDER_ID = 1;
|
||||
export const REAL_FOLDERS: Set<number> = new Set([FOLDER_ID_ALL, FOLDER_ID_ARCHIVE]);
|
||||
export const START_LOCAL_ID = Math.max(...Array.from(REAL_FOLDERS)) + 1 as MyDialogFilter['localId'];
|
||||
|
@ -21,6 +21,7 @@ import EventListenerBase from "../helpers/eventListenerBase";
|
||||
import { MOUNT_CLASS_TO } from "../config/debug";
|
||||
import MTProtoMessagePort from "./mtproto/mtprotoMessagePort";
|
||||
import { IS_WORKER } from "../helpers/context";
|
||||
import { MTAppConfig } from "./mtproto/appConfig";
|
||||
|
||||
export type BroadcastEvents = {
|
||||
'chat_full_update': ChatId,
|
||||
@ -140,7 +141,9 @@ export type BroadcastEvents = {
|
||||
|
||||
'payment_sent': {peerId: PeerId, mid: number},
|
||||
|
||||
'premium_toggle': boolean
|
||||
'premium_toggle': boolean,
|
||||
|
||||
'app_config': MTAppConfig
|
||||
};
|
||||
|
||||
export type BroadcastEventsListeners = {
|
||||
@ -148,8 +151,8 @@ export type BroadcastEventsListeners = {
|
||||
};
|
||||
|
||||
export class RootScope extends EventListenerBase<BroadcastEventsListeners> {
|
||||
public myId: PeerId = NULL_PEER_ID;
|
||||
private connectionStatus: {[name: string]: ConnectionStatusChange} = {};
|
||||
public myId: PeerId;
|
||||
private connectionStatus: {[name: string]: ConnectionStatusChange};
|
||||
public settings: State['settings'];
|
||||
public managers: AppManagers;
|
||||
public premium: boolean;
|
||||
@ -157,12 +160,18 @@ export class RootScope extends EventListenerBase<BroadcastEventsListeners> {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.myId = NULL_PEER_ID;
|
||||
this.connectionStatus = {};
|
||||
this.premium = false;
|
||||
|
||||
this.addEventListener('user_auth', ({id}) => {
|
||||
this.myId = id.toPeerId();
|
||||
});
|
||||
|
||||
this.addEventListener('premium_toggle', (isPremium) => {
|
||||
this.premium = isPremium;
|
||||
});
|
||||
|
||||
this.addEventListener('connection_status_change', (status) => {
|
||||
this.connectionStatus[status.name] = status;
|
||||
});
|
||||
|
@ -11,7 +11,7 @@ import copy from "../../helpers/object/copy";
|
||||
import { AppManager } from "../appManagers/manager";
|
||||
import findAndSplice from "../../helpers/array/findAndSplice";
|
||||
import assumeType from "../../helpers/assumeType";
|
||||
import { FOLDER_ID_ALL, FOLDER_ID_ARCHIVE, REAL_FOLDERS, REAL_FOLDER_ID } from "../mtproto/mtproto_config";
|
||||
import { FOLDER_ID_ALL, FOLDER_ID_ARCHIVE, REAL_FOLDERS, REAL_FOLDER_ID, START_LOCAL_ID } from "../mtproto/mtproto_config";
|
||||
|
||||
export type MyDialogFilter = DialogFilter.dialogFilter;
|
||||
|
||||
@ -21,7 +21,6 @@ const convertment = [
|
||||
['include_peers', 'includePeerIds']
|
||||
] as ['pinned_peers' | 'exclude_peers' | 'include_peers', 'pinnedPeerIds' | 'excludePeerIds' | 'includePeerIds'][];
|
||||
|
||||
const START_LOCAL_ID = Math.max(...Array.from(REAL_FOLDERS)) + 1 as MyDialogFilter['localId'];
|
||||
const PREPENDED_FILTERS = REAL_FOLDERS.size;
|
||||
|
||||
const LOCAL_FILTER: MyDialogFilter = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user