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